Commit 8218f1ac authored by Linus Torvalds's avatar Linus Torvalds

Merge http://linux-isdn.bkbits.net/linux-2.5.make

into penguin.transmeta.com:/home/penguin/torvalds/repositories/kernel/linux
parents 7a569667 0c686811
......@@ -206,26 +206,15 @@ LC0: .word __bss_start
* r7 = architecture number
* r8 = run-time address of "start"
* On exit,
* r0, r1, r2, r3, r8, r9 corrupted
* r1, r2, r3, r8, r9, r12 corrupted
* This routine must preserve:
* r4, r5, r6, r7
*/
.align 5
cache_on: ldr r1, proc_sa110_type
eor r1, r1, r6
movs r1, r1, lsr #5 @ catch SA110 and SA1100
beq 1f
ldr r1, proc_sa1110_type
eor r1, r1, r6
movs r1, r1, lsr #4
beq 1f
ldr r1, proc_xscale_type
eor r1, r1, r6
movs r1, r1, lsr #16
@ movne pc, lr
bne cache_off
1:
sub r3, r4, #16384 @ Page directory size
cache_on: mov r3, #8 @ cache_on function
b call_cache_fn
__cache_on: sub r3, r4, #16384 @ Page directory size
bic r3, r3, #0xff @ Align the pointer
bic r3, r3, #0x3f00
/*
......@@ -277,8 +266,9 @@ cache_on: ldr r1, proc_sa110_type
mov pc, lr
/*
* This code is relocatable. It is relocated by the above code to the end
* of the kernel and executed there. During this time, we have no stacks.
* All code following this line is relocatable. It is relocated by
* the above code to the end of the decompressed kernel image and
* executed there. During this time, we have no stacks.
*
* r0 = decompressed kernel length
* r1-r3 = unused
......@@ -309,47 +299,101 @@ call_kernel: bl cache_clean_flush
mov pc, r4 @ call kernel
/*
* Here follow the relocatable cache support functions for
* the various processors.
* Here follow the relocatable cache support functions for the
* various processors. This is a generic hook for locating an
* entry and jumping to an instruction at the specified offset
* from the start of the block. Please note this is all position
* independent code.
*
* r1 = corrupted
* r2 = corrupted
* r3 = block offset
* r6 = CPU ID
* r12 = corrupted
*/
call_cache_fn: adr r12, proc_types
1: ldr r1, [r12, #0] @ get value
ldr r2, [r12, #4] @ get mask
eor r1, r1, r6 @ (real ^ match)
tst r1, r2 @ & mask
addeq pc, r12, r3 @ call cache function
add r12, r12, #4*5
b 1b
/*
* Table for cache operations. This is basically:
* - CPU ID match
* - CPU ID mask
* - 'cache on' method instruction
* - 'cache off' method instruction
* - 'cache flush' method instruction
*
* We match an entry using: ((real_id ^ match) & mask) == 0
*
* Writethrough caches generally only need 'on' and 'off'
* methods. Writeback caches _must_ have the flush method
* defined.
*/
.type proc_types,#object
proc_types:
.word 0x41560600 @ ARM6/610
.word 0xffffffe0
b __arm6_cache_off
b __arm6_cache_off
mov pc, lr
.type proc_sa110_type,#object
proc_sa110_type:
.word 0x4401a100
.size proc_sa110_type, . - proc_sa110_type
.word 0x41007000 @ ARM7/710
.word 0xfff8fe00
b __arm7_cache_off
b __arm7_cache_off
mov pc, lr
.type proc_sa1110_type,#object
proc_sa1110_type:
.word 0x6901b110
.size proc_sa1110_type, . - proc_sa1110_type
.word 0x41807200 @ ARM720T (writethrough)
.word 0xffffff00
b __cache_on
b __armv4_cache_off
mov pc, lr
.word 0x4401a100 @ sa110 / sa1100
.word 0xffffffe0
b __cache_on
b __armv4_cache_off
b __armv4_cache_flush
.word 0x6901b110 @ sa1110
.word 0xfffffff0
b __cache_on
b __armv4_cache_off
b __armv4_cache_flush
.word 0x69050000 @ xscale
.word 0xffff0000
b __cache_on
b __armv4_cache_off
b __armv4_cache_flush
.word 0 @ unrecognised type
.word 0
mov pc, lr
mov pc, lr
mov pc, lr
.size proc_types, . - proc_types
/*
* Turn off the Cache and MMU. ARMv3 does not support
* reading the control register, but ARMv4 does.
*
* On entry, r6 = processor ID
* On exit, r0, r1 corrupted
* On exit, r0, r1, r2, r3, r12 corrupted
* This routine must preserve: r4, r6, r7
*/
.align 5
cache_off:
#ifdef CONFIG_CPU_ARM610
eor r1, r6, #0x41000000
eor r1, r1, #0x00560000
bic r1, r1, #0x0000001f
teq r1, #0x00000600
mov r0, #0x00000060 @ ARM6 control reg.
beq __armv3_cache_off
#endif
#ifdef CONFIG_CPU_ARM710
eor r1, r6, #0x41000000
bic r1, r1, #0x00070000
bic r1, r1, #0x000000ff
teq r1, #0x00007000 @ ARM7
teqne r1, #0x00007100 @ ARM710
mov r0, #0x00000070 @ ARM7 control reg.
beq __armv3_cache_off
#endif
cache_off: mov r3, #12 @ cache_off function
b call_cache_fn
__armv4_cache_off:
mrc p15, 0, r0, c1, c0
bic r0, r0, #0x000d
mcr p15, 0, r0, c1, c0 @ turn MMU and cache off
......@@ -358,6 +402,14 @@ cache_off:
mcr p15, 0, r0, c8, c7 @ invalidate whole TLB v4
mov pc, lr
__arm6_cache_off:
mov r0, #0x00000060 @ ARM6 control reg.
b __armv3_cache_off
__arm7_cache_off:
mov r0, #0x00000070 @ ARM7 control reg.
b __armv3_cache_off
__armv3_cache_off:
mcr p15, 0, r0, c1, c0 @ turn MMU and cache off
mov r0, #0
......@@ -371,25 +423,16 @@ __armv3_cache_off:
* On entry,
* r6 = processor ID
* On exit,
* r1, r2, r12 corrupted
* r1, r2, r3, r12 corrupted
* This routine must preserve:
* r4, r6, r7
* r0, r4, r5, r6, r7
*/
.align 5
cache_clean_flush:
ldr r1, proc_sa110_type
eor r1, r1, r6
movs r1, r1, lsr #5 @ catch SA110 and SA1100
beq 1f
ldr r1, proc_sa1110_type
eor r1, r1, r6
movs r1, r1, lsr #4
beq 1f
ldr r1, proc_xscale_type
eor r1, r1, r6
movs r1, r1, lsr #16
movne pc, lr
1:
mov r3, #16
b call_cache_fn
__armv4_cache_flush:
bic r1, pc, #31
add r2, r1, #65536 @ 2x the largest dcache size
1: ldr r12, [r1], #32 @ s/w flush D cache
......@@ -400,12 +443,6 @@ cache_clean_flush:
mcr p15, 0, r1, c7, c10, 4 @ drain WB
mov pc, lr
.type proc_xscale_type,#object
proc_xscale_type:
.word 0x69050000
.size proc_xscale_type, . - proc_xscale_type
/*
* Various debugging routines for printing hex characters and
* memory, which again must be relocatable.
......
......@@ -15,7 +15,14 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
# CONFIG_OBSOLETE is not set
#
# General setup
#
CONFIG_NET=y
CONFIG_SYSVIPC=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
#
# Loadable module support
......@@ -96,6 +103,7 @@ CONFIG_ARCH_SHARK=y
# CONFIG_SA1100_VICTOR is not set
# CONFIG_SA1100_XP860 is not set
# CONFIG_SA1100_YOPY is not set
# CONFIG_SA1100_STORK is not set
# CONFIG_SA1100_USB is not set
# CONFIG_SA1100_USB_NETLINK is not set
# CONFIG_SA1100_USB_CHAR is not set
......@@ -124,6 +132,7 @@ CONFIG_CPU_32=y
#
# CONFIG_CPU_32v3 is not set
CONFIG_CPU_32v4=y
# CONFIG_CPU_32v5 is not set
# CONFIG_CPU_ARM610 is not set
# CONFIG_CPU_ARM710 is not set
# CONFIG_CPU_ARM720T is not set
......@@ -133,13 +142,17 @@ CONFIG_CPU_32v4=y
# CONFIG_CPU_ARM1020 is not set
CONFIG_CPU_SA110=y
# CONFIG_CPU_SA1100 is not set
# CONFIG_CPU_XSCALE is not set
# CONFIG_XSCALE_PMU is not set
# CONFIG_ARM_THUMB is not set
# CONFIG_DISCONTIGMEM is not set
#
# Processor Features
#
#
# General setup
#
# CONFIG_DISCONTIGMEM is not set
CONFIG_PCI=y
# CONFIG_PCI_HOST_PLX90X0 is not set
CONFIG_PCI_HOST_VIA82C505=y
......@@ -149,10 +162,6 @@ CONFIG_ISA_DMA=y
# CONFIG_PCI_NAMES is not set
# CONFIG_HOTPLUG is not set
# CONFIG_PCMCIA is not set
CONFIG_NET=y
CONFIG_SYSVIPC=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
#
# At least one math emulation must be selected
......@@ -165,6 +174,7 @@ CONFIG_KCORE_ELF=y
CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
# CONFIG_PM is not set
# CONFIG_PREEMPT is not set
# CONFIG_APM is not set
# CONFIG_ARTHUR is not set
CONFIG_LEDS=y
......@@ -195,6 +205,7 @@ CONFIG_PARPORT_PC_CML1=y
#
# CONFIG_PNP is not set
# CONFIG_ISAPNP is not set
# CONFIG_PNPBIOS is not set
#
# Block devices
......@@ -229,7 +240,7 @@ CONFIG_BLK_DEV_RAM_SIZE=4096
#
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
# CONFIG_NETLINK is not set
# CONFIG_NETLINK_DEV is not set
# CONFIG_NETFILTER is not set
CONFIG_FILTER=y
CONFIG_UNIX=y
......@@ -239,6 +250,7 @@ CONFIG_INET=y
# CONFIG_IP_PNP is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
# CONFIG_ARPD is not set
# CONFIG_INET_ECN is not set
# CONFIG_SYN_COOKIES is not set
# CONFIG_IPV6 is not set
......@@ -280,6 +292,7 @@ CONFIG_NETDEVICES=y
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
# CONFIG_ETHERTAP is not set
#
# Ethernet (10 or 100Mbit)
......@@ -290,7 +303,6 @@ CONFIG_NET_ETHERNET=y
# CONFIG_HAPPYMEAL is not set
# CONFIG_SUNBMAC is not set
# CONFIG_SUNQE is not set
# CONFIG_SUNLANCE is not set
# CONFIG_SUNGEM is not set
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_LANCE is not set
......@@ -306,12 +318,9 @@ CONFIG_NET_PCI=y
# CONFIG_AC3200 is not set
# CONFIG_APRICOT is not set
CONFIG_CS89x0=y
# CONFIG_DE2104X is not set
# CONFIG_TULIP is not set
# CONFIG_DE4X5 is not set
# CONFIG_DGRS is not set
# CONFIG_DM9102 is not set
# CONFIG_EEPRO100 is not set
# CONFIG_E100 is not set
# CONFIG_LNE390 is not set
# CONFIG_FEALNX is not set
# CONFIG_NATSEMI is not set
......@@ -323,13 +332,13 @@ CONFIG_CS89x0=y
# CONFIG_8139TOO_PIO is not set
# CONFIG_8139TOO_TUNE_TWISTER is not set
# CONFIG_8139TOO_8129 is not set
# CONFIG_8139_NEW_RX_RESET is not set
# CONFIG_SIS900 is not set
# CONFIG_EPIC100 is not set
# CONFIG_SUNDANCE is not set
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
# CONFIG_VIA_RHINE_MMIO is not set
# CONFIG_WINBOND_840 is not set
# CONFIG_NET_POCKET is not set
#
......@@ -337,11 +346,13 @@ CONFIG_CS89x0=y
#
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
# CONFIG_E1000 is not set
# CONFIG_MYRI_SBUS is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
# CONFIG_SK98LIN is not set
# CONFIG_TIGON3 is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
# CONFIG_PLIP is not set
......@@ -366,6 +377,11 @@ CONFIG_CS89x0=y
#
# CONFIG_WAN is not set
#
# "Tulip" family network device support
#
# CONFIG_NET_TULIP is not set
#
# Amateur Radio support
#
......@@ -382,7 +398,7 @@ CONFIG_CS89x0=y
CONFIG_IDE=y
#
# IDE, ATA and ATAPI Block devices
# ATA and ATAPI Block devices
#
CONFIG_BLK_DEV_IDE=y
......@@ -393,6 +409,7 @@ CONFIG_BLK_DEV_IDE=y
# CONFIG_BLK_DEV_HD is not set
CONFIG_BLK_DEV_IDEDISK=y
# CONFIG_IDEDISK_MULTI_MODE is not set
# CONFIG_IDEDISK_STROKE is not set
# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
# CONFIG_BLK_DEV_IDEDISK_IBM is not set
......@@ -409,7 +426,7 @@ CONFIG_BLK_DEV_IDEFLOPPY=y
# CONFIG_BLK_DEV_IDESCSI is not set
#
# IDE chipset support/bugfixes
# IDE chipset support
#
# CONFIG_BLK_DEV_CMD640 is not set
# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
......@@ -420,7 +437,6 @@ CONFIG_BLK_DEV_IDEFLOPPY=y
# CONFIG_IDE_CHIPSETS is not set
# CONFIG_IDEDMA_AUTO is not set
# CONFIG_DMA_NONPCI is not set
# CONFIG_BLK_DEV_IDE_MODES is not set
# CONFIG_BLK_DEV_ATARAID is not set
# CONFIG_BLK_DEV_ATARAID_PDC is not set
# CONFIG_BLK_DEV_ATARAID_HPT is not set
......@@ -520,13 +536,23 @@ CONFIG_CHR_DEV_SG=m
# CONFIG_ISDN is not set
#
# Input core support
# Input device support
#
# CONFIG_INPUT is not set
# CONFIG_INPUT_KEYBDEV is not set
# CONFIG_INPUT_MOUSEDEV is not set
# CONFIG_INPUT_JOYDEV is not set
# CONFIG_INPUT_EVDEV is not set
# CONFIG_GAMEPORT is not set
CONFIG_SOUND_GAMEPORT=y
# CONFIG_GAMEPORT_NS558 is not set
# CONFIG_GAMEPORT_L4 is not set
# CONFIG_INPUT_EMU10K1 is not set
# CONFIG_GAMEPORT_PCIGAME is not set
# CONFIG_GAMEPORT_FM801 is not set
# CONFIG_GAMEPORT_CS461x is not set
# CONFIG_SERIO is not set
# CONFIG_SERIO_SERPORT is not set
#
# Character devices
......@@ -541,6 +567,24 @@ CONFIG_SERIAL_CONSOLE=y
#
# Serial drivers
#
# CONFIG_SERIAL_8250 is not set
# CONFIG_SERIAL_8250_CONSOLE is not set
# CONFIG_SERIAL_8250_EXTENDED is not set
# CONFIG_SERIAL_8250_MANY_PORTS is not set
# CONFIG_SERIAL_8250_SHARE_IRQ is not set
# CONFIG_SERIAL_8250_DETECT_IRQ is not set
# CONFIG_SERIAL_8250_MULTIPORT is not set
# CONFIG_SERIAL_8250_RSA is not set
#
# Non-8250 serial port support
#
#
# ARM Serial drivers
#
# CONFIG_ATOMWIDE_SERIAL is not set
# CONFIG_DUALSP_SERIAL is not set
# CONFIG_SERIAL_ANAKIN is not set
# CONFIG_SERIAL_ANAKIN_CONSOLE is not set
# CONFIG_SERIAL_AMBA is not set
......@@ -554,16 +598,6 @@ CONFIG_SERIAL_CONSOLE=y
# CONFIG_SERIAL_UART00_CONSOLE is not set
# CONFIG_SERIAL_SA1100 is not set
# CONFIG_SERIAL_SA1100_CONSOLE is not set
# CONFIG_SERIAL_8250 is not set
# CONFIG_SERIAL_8250_CONSOLE is not set
# CONFIG_ATOMWIDE_SERIAL is not set
# CONFIG_DUALSP_SERIAL is not set
# CONFIG_SERIAL_8250_EXTENDED is not set
# CONFIG_SERIAL_8250_MANY_PORTS is not set
# CONFIG_SERIAL_8250_SHARE_IRQ is not set
# CONFIG_SERIAL_8250_DETECT_IRQ is not set
# CONFIG_SERIAL_8250_MULTIPORT is not set
# CONFIG_SERIAL_8250_RSA is not set
CONFIG_UNIX98_PTYS=y
CONFIG_UNIX98_PTY_COUNT=256
CONFIG_PRINTER=m
......@@ -596,19 +630,6 @@ CONFIG_MOUSE=y
CONFIG_PSMOUSE=y
# CONFIG_82C710_MOUSE is not set
# CONFIG_PC110_PAD is not set
#
# Joysticks
#
# CONFIG_INPUT_GAMEPORT is not set
#
# Input core support is needed for gameports
#
#
# Input core support is needed for joysticks
#
# CONFIG_QIC02_TAPE is not set
#
......@@ -664,6 +685,9 @@ CONFIG_RAMFS=y
CONFIG_ISO9660_FS=y
CONFIG_JOLIET=y
# CONFIG_ZISOFS is not set
# CONFIG_JFS_FS is not set
# CONFIG_JFS_DEBUG is not set
# CONFIG_JFS_STATISTICS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
......@@ -694,6 +718,7 @@ CONFIG_NFS_FS=y
# CONFIG_ROOT_NFS is not set
# CONFIG_NFSD is not set
# CONFIG_NFSD_V3 is not set
# CONFIG_NFSD_TCP is not set
CONFIG_SUNRPC=y
CONFIG_LOCKD=y
# CONFIG_SMB_FS is not set
......@@ -707,7 +732,6 @@ CONFIG_LOCKD=y
# CONFIG_NCPFS_NLS is not set
# CONFIG_NCPFS_EXTRAS is not set
# CONFIG_ZISOFS_FS is not set
# CONFIG_ZLIB_FS_INFLATE is not set
#
# Partition Types
......@@ -797,6 +821,7 @@ CONFIG_FB_CYBER2000=y
# CONFIG_FB_RADEON is not set
# CONFIG_FB_ATY128 is not set
# CONFIG_FB_SIS is not set
# CONFIG_FB_NEOMAGIC is not set
# CONFIG_FB_3DFX is not set
# CONFIG_FB_VOODOO1 is not set
# CONFIG_FB_VIRTUAL is not set
......@@ -813,6 +838,11 @@ CONFIG_FONT_8x16=y
# Sound
#
CONFIG_SOUND=m
#
# Open Sound System
#
CONFIG_SOUND_PRIME=m
# CONFIG_SOUND_BT878 is not set
# CONFIG_SOUND_CMPCI is not set
# CONFIG_SOUND_EMU10K1 is not set
......@@ -865,6 +895,11 @@ CONFIG_SOUND_SB=m
# CONFIG_SOUND_WAVEARTIST is not set
# CONFIG_SOUND_TVMIXER is not set
#
# Advanced Linux Sound Architecture
#
# CONFIG_SND is not set
#
# Multimedia Capabilities Port drivers
#
......@@ -875,111 +910,14 @@ CONFIG_SOUND_SB=m
# CONFIG_MCP_UCB1200_TS is not set
#
# USB support
#
# CONFIG_USB is not set
#
# USB Host Controller Drivers
#
# CONFIG_USB_EHCI_HCD is not set
# CONFIG_USB_UHCI is not set
# CONFIG_USB_UHCI_ALT is not set
# CONFIG_USB_OHCI is not set
# CONFIG_USB_OHCI_SA1111 is not set
#
# USB Device Class drivers
#
# CONFIG_USB_AUDIO is not set
# CONFIG_USB_BLUETOOTH is not set
# CONFIG_USB_STORAGE is not set
# CONFIG_USB_STORAGE_DEBUG is not set
# CONFIG_USB_STORAGE_DATAFAB is not set
# CONFIG_USB_STORAGE_FREECOM is not set
# CONFIG_USB_STORAGE_ISD200 is not set
# CONFIG_USB_STORAGE_DPCM is not set
# CONFIG_USB_STORAGE_HP8200e is not set
# CONFIG_USB_STORAGE_SDDR09 is not set
# CONFIG_USB_STORAGE_JUMPSHOT is not set
# CONFIG_USB_ACM is not set
# CONFIG_USB_PRINTER is not set
#
# USB Human Interface Devices (HID)
#
#
# Input core support is needed for USB HID
#
#
# USB Imaging devices
#
# CONFIG_USB_DC2XX is not set
# CONFIG_USB_MDC800 is not set
# CONFIG_USB_SCANNER is not set
# CONFIG_USB_MICROTEK is not set
# CONFIG_USB_HPUSBSCSI is not set
#
# USB Multimedia devices
#
#
# Video4Linux support is needed for USB Multimedia device support
#
#
# USB Network adaptors
#
# CONFIG_USB_PEGASUS is not set
# CONFIG_USB_KAWETH is not set
# CONFIG_USB_CATC is not set
# CONFIG_USB_CDCETHER is not set
# CONFIG_USB_USBNET is not set
#
# USB port drivers
#
# CONFIG_USB_USS720 is not set
#
# USB Serial Converter support
# Console Switches
#
# CONFIG_USB_SERIAL is not set
# CONFIG_USB_SERIAL_GENERIC is not set
# CONFIG_USB_SERIAL_BELKIN is not set
# CONFIG_USB_SERIAL_WHITEHEAT is not set
# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
# CONFIG_USB_SERIAL_EMPEG is not set
# CONFIG_USB_SERIAL_FTDI_SIO is not set
# CONFIG_USB_SERIAL_VISOR is not set
# CONFIG_USB_SERIAL_IPAQ is not set
# CONFIG_USB_SERIAL_IR is not set
# CONFIG_USB_SERIAL_EDGEPORT is not set
# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
# CONFIG_USB_SERIAL_KEYSPAN is not set
# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set
# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set
# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set
# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set
# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set
# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set
# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set
# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
# CONFIG_USB_SERIAL_MCT_U232 is not set
# CONFIG_USB_SERIAL_KLSI is not set
# CONFIG_USB_SERIAL_PL2303 is not set
# CONFIG_USB_SERIAL_CYBERJACK is not set
# CONFIG_USB_SERIAL_XIRCOM is not set
# CONFIG_USB_SERIAL_OMNINET is not set
# CONFIG_SWITCHES is not set
#
# USB Miscellaneous drivers
# USB support
#
# CONFIG_USB_RIO500 is not set
# CONFIG_USB_AUERSWALD is not set
# CONFIG_USB is not set
#
# Bluetooth support
......@@ -992,7 +930,6 @@ CONFIG_SOUND_SB=m
CONFIG_NO_FRAME_POINTER=y
CONFIG_DEBUG_USER=y
# CONFIG_DEBUG_INFO is not set
# CONFIG_NO_PGT_CACHE is not set
# CONFIG_DEBUG_KERNEL is not set
# CONFIG_DEBUG_SLAB is not set
# CONFIG_MAGIC_SYSRQ is not set
......@@ -1008,3 +945,5 @@ CONFIG_DEBUG_USER=y
# Library routines
#
CONFIG_CRC32=y
# CONFIG_ZLIB_INFLATE is not set
# CONFIG_ZLIB_DEFLATE is not set
......@@ -68,6 +68,7 @@ extern void __umoddi3(void);
extern void __udivmoddi4(void);
extern void __udivsi3(void);
extern void __umodsi3(void);
extern void abort(void);
extern void ret_from_exception(void);
extern void fpundefinstr(void);
......
......@@ -426,6 +426,9 @@ void __init pcibios_fixup_bus(struct pci_bus *bus)
pci_read_config_word(dev, PCI_COMMAND, &cmd);
cmd |= features;
pci_write_config_word(dev, PCI_COMMAND, cmd);
pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE,
SMP_CACHE_BYTES >> 2);
}
/*
......
......@@ -31,14 +31,6 @@
#include <asm/processor.h>
#include <asm/uaccess.h>
/*
* Values for cpu_do_idle()
*/
#define IDLE_WAIT_SLOW 0
#define IDLE_WAIT_FAST 1
#define IDLE_CLOCK_SLOW 2
#define IDLE_CLOCK_FAST 3
extern const char *processor_modes[];
extern void setup_mm_for_reboot(char mode);
......@@ -77,6 +69,18 @@ __setup("hlt", hlt_setup);
void (*pm_idle)(void);
void (*pm_power_off)(void);
/*
* This is our default idle handler. We need to disable
* interrupts here to ensure we don't miss a wakeup call.
*/
static void default_idle(void)
{
__cli();
if (!need_resched() && !hlt_counter)
arch_idle();
__sti();
}
/*
* The idle thread. We try to conserve power, while trying to keep
* overall latency low. The architecture specific idle is passed
......@@ -89,7 +93,7 @@ void cpu_idle(void)
while (1) {
void (*idle)(void) = pm_idle;
if (!idle)
idle = arch_idle;
idle = default_idle;
leds_event(led_idle_start);
while (!need_resched())
idle();
......
......@@ -188,7 +188,7 @@ static inline void dump_cache(const char *prefix, unsigned int cache)
{
unsigned int mult = 2 + (CACHE_M(cache) ? 1 : 0);
printk("%s size %dK associativity %d line length %d sets %d\n",
printk("%s: %d bytes, associativity %d, %d byte lines, %d sets\n",
prefix,
mult << (8 + CACHE_SIZE(cache)),
(mult << CACHE_ASSOC(cache)) >> 1,
......
......@@ -546,12 +546,14 @@ void abort(void)
void __init trap_init(void)
{
extern void __trap_init(void *);
__trap_init((void *)vectors_base());
if (vectors_base() != 0)
printk(KERN_DEBUG "Relocating machine vectors to 0x%08x\n",
vectors_base());
extern void __trap_init(unsigned long);
unsigned long base = vectors_base();
__trap_init(base);
flush_icache_range(base, base + PAGE_SIZE);
if (base != 0)
printk(KERN_DEBUG "Relocating machine vectors to 0x%08lx\n",
base);
#ifdef CONFIG_CPU_32
modify_domain(DOMAIN_USER, DOMAIN_CLIENT);
#endif
......
......@@ -106,8 +106,10 @@ static struct irqaction irq_cascade = { handler: no_action, name: "cascade", };
static struct resource pic1_resource = { "pic1", 0x20, 0x3f };
static struct resource pic2_resource = { "pic2", 0xa0, 0xbf };
void __init isa_init_irq(unsigned int irq)
void __init isa_init_irq(unsigned int host_irq)
{
unsigned int irq;
/*
* Setup, and then probe for an ISA PIC
* If the PIC is not there, then we
......@@ -133,10 +135,10 @@ void __init isa_init_irq(unsigned int irq)
outb(0xff, PIC_MASK_HI);/* mask all IRQs */
} else {
printk(KERN_INFO "IRQ: ISA PIC not found\n");
irq = -1;
host_irq = (unsigned int)-1;
}
if (irq != -1) {
if (host_irq != (unsigned int)-1) {
for (irq = _ISA_IRQ(0); irq < _ISA_IRQ(8); irq++) {
set_irq_chip(irq, &isa_lo_chip);
set_irq_handler(irq, do_level_IRQ);
......@@ -153,7 +155,7 @@ void __init isa_init_irq(unsigned int irq)
request_resource(&ioport_resource, &pic2_resource);
setup_irq(IRQ_ISA_CASCADE, &irq_cascade);
set_irq_chained_handler(irq, isa_irq_handler);
set_irq_chained_handler(host_irq, isa_irq_handler);
/*
* On the NetWinder, don't automatically
......
......@@ -52,26 +52,10 @@ static int __init adsbitsy_init(void)
/*
* Probe for SA1111.
*/
ret = sa1111_probe(0x18000000);
ret = sa1111_init(NULL, 0x18000000, IRQ_GPIO0);
if (ret < 0)
return ret;
/*
* We found it. Wake the chip up.
*/
sa1111_wake();
/*
* The SDRAM configuration of the SA1110 and the SA1111 must
* match. This is very important to ensure that SA1111 accesses
* don't corrupt the SDRAM. Note that this ungates the SA1111's
* MBGNT signal, so we must have called sa1110_mb_disable()
* beforehand.
*/
sa1111_configure_smc(1,
FExtr(MDCNFG, MDCNFG_SA1110_DRAC0),
FExtr(MDCNFG, MDCNFG_SA1110_TDL0));
/*
* Enable PWM control for LCD
*/
......@@ -81,20 +65,6 @@ static int __init adsbitsy_init(void)
SKPWM1 = 0x01; // Backlight
SKPEN1 = 1;
/*
* We only need to turn on DCLK whenever we want to use the
* DMA. It can otherwise be held firmly in the off position.
*/
SKPCR |= SKPCR_DCLKEN;
/*
* Enable the SA1110 memory bus request and grant signals.
*/
sa1110_mb_enable();
set_GPIO_IRQ_edge(GPIO_GPIO0, GPIO_RISING_EDGE);
sa1111_init_irq(IRQ_GPIO0);
return 0;
}
......
......@@ -34,8 +34,6 @@
static int __init badge4_sa1111_init(void)
{
int ret;
/*
* Ensure that the memory bus request/grant signals are setup,
* and the grant is held in its inactive state
......@@ -45,40 +43,7 @@ static int __init badge4_sa1111_init(void)
/*
* Probe for SA1111.
*/
ret = sa1111_probe(BADGE4_SA1111_BASE);
if (ret < 0)
return ret;
/*
* We found it. Wake the chip up.
*/
sa1111_wake();
/*
* The SDRAM configuration of the SA1110 and the SA1111 must
* match. This is very important to ensure that SA1111 accesses
* don't corrupt the SDRAM. Note that this ungates the SA1111's
* MBGNT signal, so we must have called sa1110_mb_disable()
* beforehand.
*/
sa1111_configure_smc(1,
FExtr(MDCNFG, MDCNFG_SA1110_DRAC0),
FExtr(MDCNFG, MDCNFG_SA1110_TDL0));
/*
* We only need to turn on DCLK whenever we want to use the
* DMA. It can otherwise be held firmly in the off position.
*/
SKPCR |= SKPCR_DCLKEN;
/*
* Enable the SA1110 memory bus request and grant signals.
*/
sa1110_mb_enable();
sa1111_init_irq(BADGE4_IRQ_GPIO_SA1111);
return 0;
return sa1111_init(NULL, BADGE4_SA1111_BASE, BADGE4_IRQ_GPIO_SA1111);
}
static int __init badge4_init(void)
......
......@@ -42,26 +42,10 @@ static int __init graphicsmaster_init(void)
/*
* Probe for SA1111.
*/
ret = sa1111_probe(0x18000000);
ret = sa1111_init(NULL, 0x18000000, ADS_EXT_IRQ(0));
if (ret < 0)
return ret;
/*
* We found it. Wake the chip up.
*/
sa1111_wake();
/*
* The SDRAM configuration of the SA1110 and the SA1111 must
* match. This is very important to ensure that SA1111 accesses
* don't corrupt the SDRAM. Note that this ungates the SA1111's
* MBGNT signal, so we must have called sa1110_mb_disable()
* beforehand.
*/
sa1111_configure_smc(1,
FExtr(MDCNFG, MDCNFG_SA1110_DRAC0),
FExtr(MDCNFG, MDCNFG_SA1110_TDL0));
/*
* Enable PWM control for LCD
*/
......@@ -71,19 +55,6 @@ static int __init graphicsmaster_init(void)
SKPWM1 = 0x01; // Backlight
SKPEN1 = 1;
/*
* We only need to turn on DCLK whenever we want to use the
* DMA. It can otherwise be held firmly in the off position.
*/
SKPCR |= SKPCR_DCLKEN;
/*
* Enable the SA1110 memory bus request and grant signals.
*/
sa1110_mb_enable();
sa1111_init_irq(ADS_EXT_IRQ(0));
return 0;
}
......
......@@ -10,6 +10,7 @@
#include <linux/tty.h>
#include <linux/ioport.h>
#include <linux/serial_core.h>
#include <linux/device.h>
#include <asm/hardware.h>
#include <asm/irq.h>
......@@ -21,6 +22,10 @@
#include "sa1111.h"
static struct device neponset_device = {
name: "Neponset",
bus_id: "nep_bus",
};
/*
* Install handler for Neponset IRQ. Note that we have to loop here
......@@ -125,6 +130,10 @@ static int __init neponset_init(void)
return -ENODEV;
}
ret = device_register(&neponset_device);
if (ret)
return ret;
neponset_init_irq();
/*
......@@ -139,45 +148,9 @@ static int __init neponset_init(void)
/* FIXME: setup MSC2 */
/*
* Probe for a SA1111.
*/
ret = sa1111_probe(0x40000000);
if (ret < 0)
return ret;
/*
* We found it. Wake the chip up.
*/
sa1111_wake();
/*
* The SDRAM configuration of the SA1110 and the SA1111 must
* match. This is very important to ensure that SA1111 accesses
* don't corrupt the SDRAM. Note that this ungates the SA1111's
* MBGNT signal, so we must have called sa1110_mb_disable()
* beforehand.
* Probe and initialise the SA1111.
*/
sa1111_configure_smc(1,
FExtr(MDCNFG, MDCNFG_SA1110_DRAC0),
FExtr(MDCNFG, MDCNFG_SA1110_TDL0));
/*
* We only need to turn on DCLK whenever we want to use the
* DMA. It can otherwise be held firmly in the off position.
*/
SKPCR |= SKPCR_DCLKEN;
/*
* Enable the SA1110 memory bus request and grant signals.
*/
sa1110_mb_enable();
/*
* Initialise SA1111 IRQs
*/
sa1111_init_irq(IRQ_NEPONSET_SA1111);
return 0;
return sa1111_init(&neponset_device, 0x40000000, IRQ_NEPONSET_SA1111);
}
__initcall(neponset_init);
......
......@@ -35,40 +35,7 @@ static int __init pfs168_init(void)
/*
* Probe for SA1111.
*/
ret = sa1111_probe(0x40000000);
if (ret < 0)
return ret;
/*
* We found it. Wake the chip up.
*/
sa1111_wake();
/*
* The SDRAM configuration of the SA1110 and the SA1111 must
* match. This is very important to ensure that SA1111 accesses
* don't corrupt the SDRAM. Note that this ungates the SA1111's
* MBGNT signal, so we must have called sa1110_mb_disable()
* beforehand.
*/
sa1111_configure_smc(1,
FExtr(MDCNFG, MDCNFG_SA1110_DRAC0),
FExtr(MDCNFG, MDCNFG_SA1110_TDL0));
/*
* We only need to turn on DCLK whenever we want to use the
* DMA. It can otherwise be held firmly in the off position.
*/
SKPCR |= SKPCR_DCLKEN;
/*
* Enable the SA1110 memory bus request and grant signals.
*/
sa1110_mb_enable();
sa1111_init_irq(IRQ_GPIO25); /* SA1111 IRQ on GPIO 25 */
return 0;
return sa1111_init(NULL, 0x40000000, IRQ_GPIO25);
}
__initcall(pfs168_init);
......
......@@ -23,8 +23,11 @@
#include <linux/ptrace.h>
#include <linux/errno.h>
#include <linux/ioport.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/mach/irq.h>
......@@ -32,11 +35,9 @@
#include "sa1111.h"
struct resource sa1111_resource = {
name: "SA1111",
};
struct sa1111_device *sa1111;
EXPORT_SYMBOL(sa1111_resource);
EXPORT_SYMBOL(sa1111);
/*
* SA1111 interrupt support. Since clearing an IRQ while there are
......@@ -65,6 +66,9 @@ sa1111_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
for (i = IRQ_SA1111_START + 32; stat1; i++, stat1 >>= 1)
if (stat1 & 1)
do_edge_IRQ(i, irq_desc + i, regs);
/* For level-based interrupts */
desc->chip->unmask(irq);
}
#define SA1111_IRQMASK_LO(x) (1 << (x - IRQ_SA1111_START))
......@@ -198,7 +202,7 @@ static struct irqchip sa1111_high_chip = {
type: sa1111_type_highirq,
};
void __init sa1111_init_irq(int irq_nr)
static void __init sa1111_init_irq(int irq_nr)
{
unsigned int irq;
......@@ -239,6 +243,21 @@ void __init sa1111_init_irq(int irq_nr)
set_irq_chained_handler(irq_nr, sa1111_irq_handler);
}
static int sa1111_suspend(struct device *dev, u32 state, u32 level)
{
return 0;
}
static int sa1111_resume(struct device *dev, u32 level)
{
return 0;
}
static struct device_driver sa1111_device_driver = {
suspend: sa1111_suspend,
resume: sa1111_resume,
};
/**
* sa1111_probe - probe for a single SA1111 chip.
* @phys_addr: physical address of device.
......@@ -251,38 +270,71 @@ void __init sa1111_init_irq(int irq_nr)
* %-EBUSY physical address already marked in-use.
* %0 successful.
*/
int __init sa1111_probe(unsigned long phys_addr)
static int __init
sa1111_probe(struct device *parent, unsigned long phys_addr)
{
struct sa1111_device *sa;
unsigned long id;
int ret = -ENODEV;
sa1111_resource.start = phys_addr;
sa1111_resource.end = phys_addr + 0x2000;
sa = kmalloc(sizeof(struct sa1111_device), GFP_KERNEL);
if (!sa)
return -ENOMEM;
memset(sa, 0, sizeof(struct sa1111_device));
if (request_resource(&iomem_resource, &sa1111_resource)) {
sa->resource.name = "SA1111";
sa->resource.start = phys_addr;
sa->resource.end = phys_addr + 0x2000;
if (request_resource(&iomem_resource, &sa->resource)) {
ret = -EBUSY;
goto out;
}
/* eventually ioremap... */
sa->base = (void *)0xf4000000;
if (!sa->base) {
ret = -ENOMEM;
goto release;
}
/*
* Probe for the chip. Only touch the SBI registers.
*/
id = SBI_SKID;
id = readl(sa->base + SA1111_SKID);
if ((id & SKID_ID_MASK) != SKID_SA1111_ID) {
printk(KERN_DEBUG "SA1111 not detected: ID = %08lx\n", id);
ret = -ENODEV;
goto release;
goto unmap;
}
/*
* We found the chip.
*/
strcpy(sa->dev.name, "SA1111");
sprintf(sa->dev.bus_id, "%8.8lx", phys_addr);
sa->dev.parent = parent;
sa->dev.driver = &sa1111_device_driver;
ret = device_register(&sa->dev);
if (ret)
printk("sa1111 device_register failed: %d\n", ret);
printk(KERN_INFO "SA1111 Microprocessor Companion Chip: "
"silicon revision %lx, metal revision %lx\n",
(id & SKID_SIREV_MASK)>>4, (id & SKID_MTREV_MASK));
sa1111 = sa;
return 0;
unmap:
// iounmap(sa->base);
release:
release_resource(&sa1111_resource);
release_resource(&sa->resource);
out:
kfree(sa);
return ret;
}
......@@ -302,7 +354,8 @@ int __init sa1111_probe(unsigned long phys_addr)
*/
void sa1111_wake(void)
{
unsigned long flags;
struct sa1111_device *sa = sa1111;
unsigned long flags, r;
local_irq_save(flags);
......@@ -317,8 +370,11 @@ void sa1111_wake(void)
/*
* Turn VCO on, and disable PLL Bypass.
*/
SBI_SKCR &= ~SKCR_VCO_OFF;
SBI_SKCR |= SKCR_PLL_BYPASS | SKCR_OE_EN;
r = readl(sa->base + SA1111_SKCR);
r &= ~SKCR_VCO_OFF;
writel(r, sa->base + SA1111_SKCR);
r |= SKCR_PLL_BYPASS | SKCR_OE_EN;
writel(r, sa->base + SA1111_SKCR);
/*
* Wait lock time. SA1111 manual _doesn't_
......@@ -329,7 +385,8 @@ void sa1111_wake(void)
/*
* Enable RCLK. We also ensure that RDYEN is set.
*/
SBI_SKCR |= SKCR_RCLKEN | SKCR_RDYEN;
r |= SKCR_RCLKEN | SKCR_RDYEN;
writel(r, sa->base + SA1111_SKCR);
/*
* Wait 14 RCLK cycles for the chip to finish coming out
......@@ -340,18 +397,26 @@ void sa1111_wake(void)
/*
* Ensure all clocks are initially off.
*/
SKPCR = 0;
writel(0, sa->base + SA1111_SKPCR);
local_irq_restore(flags);
}
void sa1111_doze(void)
{
if (SKPCR & SKPCR_UCLKEN) {
struct sa1111_device *sa = sa1111;
unsigned long flags;
local_irq_save(flags);
if (readl(sa->base + SA1111_SKPCR) & SKPCR_UCLKEN) {
local_irq_restore(flags);
printk("SA1111 doze mode refused\n");
return;
}
SBI_SKCR &= ~SKCR_RCLKEN;
writel(readl(sa->base + SA1111_SKCR) & ~SKCR_RCLKEN, sa->base + SA1111_SKCR);
local_irq_restore(flags);
}
/*
......@@ -359,12 +424,13 @@ void sa1111_doze(void)
*/
void sa1111_configure_smc(int sdram, unsigned int drac, unsigned int cas_latency)
{
struct sa1111_device *sa = sa1111;
unsigned int smcr = SMCR_DTIM | SMCR_MBGE | FInsrt(drac, SMCR_DRAC);
if (cas_latency == 3)
smcr |= SMCR_CLAT;
SBI_SMCR = smcr;
writel(smcr, sa->base + SA1111_SMCR);
}
/* According to the "Intel StrongARM SA-1111 Microprocessor Companion
......@@ -432,3 +498,46 @@ int sa1111_check_dma_bug(dma_addr_t addr)
}
EXPORT_SYMBOL(sa1111_check_dma_bug);
int sa1111_init(struct device *parent, unsigned long phys, unsigned int irq)
{
int ret;
ret = sa1111_probe(parent, phys);
if (ret < 0)
return ret;
/*
* We found it. Wake the chip up.
*/
sa1111_wake();
/*
* The SDRAM configuration of the SA1110 and the SA1111 must
* match. This is very important to ensure that SA1111 accesses
* don't corrupt the SDRAM. Note that this ungates the SA1111's
* MBGNT signal, so we must have called sa1110_mb_disable()
* beforehand.
*/
sa1111_configure_smc(1,
FExtr(MDCNFG, MDCNFG_SA1110_DRAC0),
FExtr(MDCNFG, MDCNFG_SA1110_TDL0));
/*
* We only need to turn on DCLK whenever we want to use the
* DMA. It can otherwise be held firmly in the off position.
*/
SKPCR |= SKPCR_DCLKEN;
/*
* Enable the SA1110 memory bus request and grant signals.
*/
sa1110_mb_enable();
/*
* Initialise SA1111 IRQs
*/
sa1111_init_irq(irq);
return 0;
}
/*
* linux/arch/arm/mach-sa1100/sa1111.h
*/
struct device;
/*
* Probe for a SA1111 chip.
*/
extern int sa1111_probe(unsigned long phys);
extern int
sa1111_init(struct device *parent, unsigned long phys, unsigned int irq);
/*
* Wake up a SA1111 chip.
......@@ -16,9 +18,3 @@ extern void sa1111_wake(void);
* Doze the SA1111 chip.
*/
extern void sa1111_doze(void);
/*
* Configure the SA1111 shared memory controller.
*/
extern void sa1111_configure_smc(int sdram, unsigned int drac, unsigned int cas_latency);
extern void sa1111_init_irq(int irq_nr);
......@@ -426,45 +426,12 @@ static int __init system3_init(void)
/*
* Probe for a SA1111.
*/
ret = sa1111_probe(PT_SA1111_BASE);
ret = sa1111_init(NULL, PT_SA1111_BASE, IRQ_SYSTEM3_SA1111);
if (ret < 0) {
printk( KERN_WARNING"PT Digital Board: no SA1111 found!\n" );
goto DONE;
}
/*
* We found it. Wake the chip up.
*/
sa1111_wake();
/*
* The SDRAM configuration of the SA1110 and the SA1111 must
* match. This is very important to ensure that SA1111 accesses
* don't corrupt the SDRAM. Note that this ungates the SA1111's
* MBGNT signal, so we must have called sa1110_mb_disable()
* beforehand.
*/
sa1111_configure_smc(1,
FExtr(MDCNFG, MDCNFG_SA1110_DRAC0),
FExtr(MDCNFG, MDCNFG_SA1110_TDL0));
/*
* We only need to turn on DCLK whenever we want to use the
* DMA. It can otherwise be held firmly in the off position.
*/
SKPCR |= SKPCR_DCLKEN;
/*
* Enable the SA1110 memory bus request and grant signals.
*/
sa1110_mb_enable();
/*
* Initialise SA1111 IRQs
*/
sa1111_init_irq(IRQ_SYSTEM3_SA1111);
#if defined( CONFIG_CPU_FREQ )
ret = cpufreq_register_notifier(&system3_clkchg_block);
if ( ret != 0 ) {
......
......@@ -20,6 +20,8 @@ static int __init shark_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
else return 255;
}
extern void __init via82c505_preinit(void *sysdata);
struct hw_pci shark_pci __initdata = {
setup: via82c505_setup,
swizzle: pci_std_swizzle,
......
......@@ -28,7 +28,7 @@ ENTRY(v5ej_early_abort)
ldrneh r3, [r2] @ read aborted thumb instruction
ldreq r3, [r2] @ read aborted ARM instruction
movne r3, r3, lsl #(21 - 12) @ move thumb bit 11 to ARM bit 20
tst r2, #1 << 20 @ L = 1 -> write
tst r3, #1 << 20 @ L = 1 -> write
orreq r1, r1, #1 << 8 @ yes.
1: mov pc, lr
......
......@@ -25,10 +25,12 @@
/*
* This allocates one page of cache-coherent memory space and returns
* both the virtual and a "dma" address to that space. It is not clear
* whether this could be called from an interrupt context or not. For
* now, we expressly forbid it, especially as some of the stuff we do
* here is not interrupt context safe.
* both the virtual and a "dma" address to that space.
*
* We should allow this function to be called from interrupt context.
* However, we call ioremap, which needs to fiddle around with various
* things (like the vmlist_lock, and allocating page tables). These
* things aren't interrupt safe (yet).
*
* Note that this does *not* zero the allocated area!
*/
......@@ -36,8 +38,9 @@ void *consistent_alloc(int gfp, size_t size, dma_addr_t *dma_handle)
{
struct page *page, *end, *free;
unsigned long order;
void *ret, *virt;
void *ret;
/* FIXME */
if (in_interrupt())
BUG();
......@@ -48,22 +51,22 @@ void *consistent_alloc(int gfp, size_t size, dma_addr_t *dma_handle)
if (!page)
goto no_page;
/*
* We could do with a page_to_phys and page_to_bus here.
*/
virt = page_address(page);
*dma_handle = virt_to_bus(virt);
ret = __ioremap(virt_to_phys(virt), size, 0);
*dma_handle = page_to_bus(page);
ret = __ioremap(page_to_phys(page), size, 0);
if (!ret)
goto no_remap;
#if 0 /* ioremap_does_flush_cache_all */
/*
* we need to ensure that there are no cachelines in use, or
* worse dirty in this area. Really, we don't need to do
* this since __ioremap does a flush_cache_all() anyway. --rmk
*/
invalidate_dcache_range(virt, virt + size);
{
void *virt = page_address(page);
/*
* we need to ensure that there are no cachelines in use, or
* worse dirty in this area. Really, we don't need to do
* this since __ioremap does a flush_cache_all() anyway. --rmk
*/
invalidate_dcache_range(virt, virt + size);
}
#endif
/*
......@@ -72,7 +75,6 @@ void *consistent_alloc(int gfp, size_t size, dma_addr_t *dma_handle)
* We also mark the pages in use as reserved so that
* remap_page_range works.
*/
page = virt_to_page(virt);
free = page + (size >> PAGE_SHIFT);
end = page + (1 << order);
......@@ -93,18 +95,12 @@ void *consistent_alloc(int gfp, size_t size, dma_addr_t *dma_handle)
void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, dma_addr_t *handle)
{
void *__ret;
int __gfp = GFP_KERNEL;
int gfp = GFP_KERNEL;
#ifdef CONFIG_PCI
if ((hwdev) == NULL ||
(hwdev)->dma_mask != 0xffffffff)
#endif
__gfp |= GFP_DMA;
if (hwdev == NULL || hwdev->dma_mask != 0xffffffff)
gfp |= GFP_DMA;
__ret = consistent_alloc(__gfp, (size),
(handle));
return __ret;
return consistent_alloc(gfp, size, handle);
}
/*
......@@ -114,19 +110,16 @@ void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, dma_addr_t *handl
void consistent_free(void *vaddr, size_t size, dma_addr_t handle)
{
struct page *page, *end;
void *virt;
if (in_interrupt())
BUG();
virt = bus_to_virt(handle);
/*
* More messing around with the MM internals. This is
* sick, but then so is remap_page_range().
*/
size = PAGE_ALIGN(size);
page = virt_to_page(virt);
page = virt_to_page(bus_to_virt(handle));
end = page + (size >> PAGE_SHIFT);
for (; page < end; page++)
......
......@@ -6,7 +6,7 @@
# To add an entry into this database, please see Documentation/arm/README,
# or contact rmk@arm.linux.org.uk
#
# Last update: Sun Mar 24 11:48:10 2002
# Last update: Fri Mar 29 15:51:20 2002
#
# machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number
#
......@@ -179,3 +179,4 @@ jornada56x ARCH_JORNADA56X JORNADA56X 167
active SA1100_ACTIVE ACTIVE 168
iq80321 ARCH_IQ80321 IQ80321 169
wid SA1100_WID WID 170
sabinal ARCH_SABINAL SABINAL 171
......@@ -33,9 +33,9 @@ static void inline flush_all (void)
* P4/Xeon Thermal transition interrupt handler
*/
#ifdef CONFIG_X86_LOCAL_APIC
static void intel_thermal_interrupt(struct pt_regs *regs)
{
#ifdef CONFIG_X86_LOCAL_APIC
u32 l, h;
unsigned int cpu = smp_processor_id();
......@@ -48,8 +48,8 @@ static void intel_thermal_interrupt(struct pt_regs *regs)
} else {
printk(KERN_INFO "CPU#%d: Temperature/speed normal\n", cpu);
}
#endif
}
#endif
static void unexpected_thermal_interrupt(struct pt_regs *regs)
{
......
......@@ -28,6 +28,7 @@
#include <linux/config.h>
#include <linux/smp_lock.h>
#include <linux/mc146818rtc.h>
#include <linux/compiler.h>
#include <asm/io.h>
#include <asm/smp.h>
......@@ -183,6 +184,86 @@ static void clear_IO_APIC (void)
clear_IO_APIC_pin(apic, pin);
}
static void set_ioapic_affinity (unsigned int irq, unsigned long mask)
{
unsigned long flags;
/*
* Only the first 8 bits are valid.
*/
mask = mask << 24;
spin_lock_irqsave(&ioapic_lock, flags);
__DO_ACTION(1, = mask, )
spin_unlock_irqrestore(&ioapic_lock, flags);
}
#if CONFIG_SMP
typedef struct {
unsigned int cpu;
unsigned long timestamp;
} ____cacheline_aligned irq_balance_t;
static irq_balance_t irq_balance[NR_IRQS] __cacheline_aligned
= { [ 0 ... NR_IRQS-1 ] = { 1, 0 } };
extern unsigned long irq_affinity [NR_IRQS];
#endif
#define IDLE_ENOUGH(cpu,now) \
(idle_cpu(cpu) && ((now) - irq_stat[(cpu)].idle_timestamp > 1))
#define IRQ_ALLOWED(cpu,allowed_mask) \
((1 << cpu) & (allowed_mask))
static unsigned long move(int curr_cpu, unsigned long allowed_mask, unsigned long now, int direction)
{
int search_idle = 1;
int cpu = curr_cpu;
goto inside;
do {
if (unlikely(cpu == curr_cpu))
search_idle = 0;
inside:
if (direction == 1) {
cpu++;
if (cpu >= smp_num_cpus)
cpu = 0;
} else {
cpu--;
if (cpu == -1)
cpu = smp_num_cpus-1;
}
} while (!IRQ_ALLOWED(cpu,allowed_mask) ||
(search_idle && !IDLE_ENOUGH(cpu,now)));
return cpu;
}
static inline void balance_irq(int irq)
{
#if CONFIG_SMP
irq_balance_t *entry = irq_balance + irq;
unsigned long now = jiffies;
if (unlikely(entry->timestamp != now)) {
unsigned long allowed_mask;
int random_number;
rdtscl(random_number);
random_number &= 1;
allowed_mask = cpu_online_map & irq_affinity[irq];
entry->timestamp = now;
entry->cpu = move(entry->cpu, allowed_mask, now, random_number);
set_ioapic_affinity(irq, 1 << entry->cpu);
}
#endif
}
/*
* support for broken MP BIOSs, enables hand-redirection of PIRQ0-7 to
* specific CPU-side IRQs.
......@@ -672,8 +753,7 @@ void __init setup_IO_APIC_irqs(void)
}
/*
* Set up the 8259A-master output pin as broadcast to all
* CPUs.
* Set up the 8259A-master output pin:
*/
void __init setup_ExtINT_IRQ0_pin(unsigned int pin, int vector)
{
......@@ -1193,6 +1273,7 @@ static unsigned int startup_edge_ioapic_irq(unsigned int irq)
*/
static void ack_edge_ioapic_irq(unsigned int irq)
{
balance_irq(irq);
if ((irq_desc[irq].status & (IRQ_PENDING | IRQ_DISABLED))
== (IRQ_PENDING | IRQ_DISABLED))
mask_IO_APIC_irq(irq);
......@@ -1232,6 +1313,7 @@ static void end_level_ioapic_irq (unsigned int irq)
unsigned long v;
int i;
balance_irq(irq);
/*
* It appears there is an erratum which affects at least version 0x11
* of I/O APIC (that's the 82093AA and cores integrated into various
......@@ -1288,19 +1370,6 @@ static void end_level_ioapic_irq (unsigned int irq)
static void mask_and_ack_level_ioapic_irq (unsigned int irq) { /* nothing */ }
static void set_ioapic_affinity (unsigned int irq, unsigned long mask)
{
unsigned long flags;
/*
* Only the first 8 bits are valid.
*/
mask = mask << 24;
spin_lock_irqsave(&ioapic_lock, flags);
__DO_ACTION(1, = mask, )
spin_unlock_irqrestore(&ioapic_lock, flags);
}
/*
* Level and edge triggered IO-APIC interrupts need different handling,
* so we use two separate IRQ descriptors. Edge triggered IRQs can be
......
......@@ -1073,7 +1073,7 @@ static unsigned int parse_hex_value (const char *buffer,
static struct proc_dir_entry * smp_affinity_entry [NR_IRQS];
static unsigned long irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = ~0UL };
unsigned long irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = ~0UL };
static int irq_affinity_read_proc (char *page, char **start, off_t off,
int count, int *eof, void *data)
{
......
......@@ -142,6 +142,7 @@ void cpu_idle (void)
void (*idle)(void) = pm_idle;
if (!idle)
idle = default_idle;
irq_stat[smp_processor_id()].idle_timestamp = jiffies;
while (!need_resched())
idle();
schedule();
......
......@@ -753,9 +753,17 @@ CONFIG_BLK_DEV_IDE_TCQ
If you have such a drive, say Y here.
CONFIG_BLK_DEV_IDE_TCQ_DEFAULT
Enabled tagged command queueing unconditionally on drives that report
support for it.
CONFIG_BLK_DEV_IDE_TCQ_FULL
When a command completes from the drive, the SERVICE bit is checked to
see if other queued commands are ready to be started. Doing this
immediately after a command completes has a tendency to 'starve' the
device hardware queue, since we risk emptying the queue completely
before starting any new commands. This shows up during stressing the
drive as a /\/\/\/\ queue size balance, where we could instead try and
maintain a minimum queue size and get a /---------\ graph instead.
Saying Y here will attempt to always keep the queue full when possible
at the cost of possibly increasing command turn-around latency.
Generally say Y here.
......@@ -766,6 +774,18 @@ CONFIG_BLK_DEV_IDE_TCQ_DEPTH
You probably just want the default of 32 here. If you enter an invalid
number, the default value will be used.
CONFIG_BLK_DEV_IDE_TCQ_DEFAULT
Enabled tagged command queueing unconditionally on drives that report
support for it. Regardless of the chosen value here, tagging can be
controlled at run time:
echo "using_tcq:32" > /proc/ide/hdX/settings
where any value between 1-32 selects chosen queue depth and enables
TCQ, and 0 disables it.
Generally say Y here.
CONFIG_BLK_DEV_IT8172
Say Y here to support the on-board IDE controller on the Integrated
Technology Express, Inc. ITE8172 SBC. Vendor page at
......
......@@ -48,10 +48,11 @@ if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then
dep_bool ' Enable DMA only for disks ' CONFIG_IDEDMA_ONLYDISK $CONFIG_IDEDMA_PCI_AUTO
define_bool CONFIG_BLK_DEV_IDEDMA $CONFIG_BLK_DEV_IDEDMA_PCI
dep_bool ' ATA tagged command queueing' CONFIG_BLK_DEV_IDE_TCQ $CONFIG_BLK_DEV_IDEDMA_PCI
dep_bool ' TCQ on by default' CONFIG_BLK_DEV_IDE_TCQ_DEFAULT $CONFIG_BLK_DEV_IDE_TCQ
if [ $CONFIG_BLK_DEV_IDE_TCQ_DEFAULT != "n" ]; then
int ' Default queue depth' CONFIG_BLK_DEV_IDE_TCQ_DEPTH 32
fi
dep_bool ' Attempt to keep queue full' CONFIG_BLK_DEV_IDE_TCQ_FULL $CONFIG_BLK_DEV_IDE_TCQ
dep_bool ' TCQ on by default' CONFIG_BLK_DEV_IDE_TCQ_DEFAULT $CONFIG_BLK_DEV_IDE_TCQ
if [ "$CONFIG_BLK_DEV_IDE_TCQ" != "n" ]; then
int ' Default queue depth' CONFIG_BLK_DEV_IDE_TCQ_DEPTH 8
fi
dep_bool ' ATA Work(s) In Progress (EXPERIMENTAL)' CONFIG_IDEDMA_PCI_WIP $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_EXPERIMENTAL
dep_bool ' Good-Bad DMA Model-Firmware (WIP)' CONFIG_IDEDMA_NEW_DRIVE_LISTINGS $CONFIG_IDEDMA_PCI_WIP
dep_bool ' AEC62XX chipset support' CONFIG_BLK_DEV_AEC62XX $CONFIG_BLK_DEV_IDEDMA_PCI
......
/*
* linux/drivers/ide/ide-cd.c
*
* Copyright (C) 1994, 1995, 1996 scott snyder <snyder@fnald0.fnal.gov>
* Copyright (C) 1996-1998 Erik Andersen <andersee@debian.org>
* Copyright (C) 1998-2000 Jens Axboe <axboe@suse.de>
......@@ -13,9 +11,10 @@
*
* Suggestions are welcome. Patches that work are more welcome though. ;-)
* For those wishing to work on this driver, please be sure you download
* and comply with the latest Mt. Fuji (SFF8090 version 4) and ATAPI
* (SFF-8020i rev 2.6) standards. These documents can be obtained by
* and comply with the latest Mt. Fuji (SFF8090 version 4) and ATAPI
* (SFF-8020i rev 2.6) standards. These documents can be obtained by
* anonymous ftp from:
*
* ftp://fission.dt.wdc.com/pub/standards/SFF_atapi/spec/SFF8020-r2.6/PS/8020r26.ps
* ftp://ftp.avc-pioneer.com/Mtfuji4/Spec/Fuji4r10.pdf
*
......@@ -54,18 +53,18 @@
* Aztech drives, which seem to have the same problem.
* 2.04b May 30, 1995 -- Fix to match changes in ide.c version 3.16 -ml
* 2.05 Jun 8, 1995 -- Don't attempt to retry after an illegal request
* or data protect error.
* or data protect error.
* Use HWIF and DEV_HWIF macros as in ide.c.
* Always try to do a request_sense after
* a failed command.
* a failed command.
* Include an option to give textual descriptions
* of ATAPI errors.
* of ATAPI errors.
* Fix a bug in handling the sector cache which
* showed up if the drive returned data in 512 byte
* blocks (like Pioneer drives). Thanks to
* Richard Hirst <srh@gpt.co.uk> for diagnosing this.
* showed up if the drive returned data in 512 byte
* blocks (like Pioneer drives). Thanks to
* Richard Hirst <srh@gpt.co.uk> for diagnosing this.
* Properly supply the page number field in the
* MODE_SELECT command.
* MODE_SELECT command.
* PLAYAUDIO12 is broken on the Aztech; work around it.
* 2.05x Aug 11, 1995 -- lots of data structure renaming/restructuring in ide.c
* (my apologies to Scott, but now ide-cd.c is independent)
......@@ -74,28 +73,28 @@
* Use input_ide_data() and output_ide_data().
* Add door locking.
* Fix usage count leak in cdrom_open, which happened
* when a read-write mount was attempted.
* when a read-write mount was attempted.
* Try to load the disk on open.
* Implement CDROMEJECT_SW ioctl (off by default).
* Read total cdrom capacity during open.
* Rearrange logic in cdrom_decode_status. Issue
* request sense commands for failed packet commands
* from here instead of from cdrom_queue_packet_command.
* Fix a race condition in retrieving error information.
* request sense commands for failed packet commands
* from here instead of from cdrom_queue_packet_command.
* Fix a race condition in retrieving error information.
* Suppress printing normal unit attention errors and
* some drive not ready errors.
* some drive not ready errors.
* Implement CDROMVOLREAD ioctl.
* Implement CDROMREADMODE1/2 ioctls.
* Fix race condition in setting up interrupt handlers
* when the `serialize' option is used.
* when the `serialize' option is used.
* 3.01 Sep 2, 1995 -- Fix ordering of reenabling interrupts in
* cdrom_queue_request.
* cdrom_queue_request.
* Another try at using ide_[input,output]_data.
* 3.02 Sep 16, 1995 -- Stick total disk capacity in partition table as well.
* Make VERBOSE_IDE_CD_ERRORS dump failed command again.
* Dump out more information for ILLEGAL REQUEST errs.
* Fix handling of errors occurring before the
* packet command is transferred.
* packet command is transferred.
* Fix transfers with odd bytelengths.
* 3.03 Oct 27, 1995 -- Some Creative drives have an id of just `CD'.
* `DCI-2S10' drives are broken too.
......@@ -103,17 +102,17 @@
* 3.05 Dec 1, 1995 -- Changes to go with overhaul of ide.c and ide-tape.c
* 3.06 Dec 16, 1995 -- Add support needed for partitions.
* More workarounds for Vertos bugs (based on patches
* from Holger Dietze <dietze@aix520.informatik.uni-leipzig.de>).
* from Holger Dietze <dietze@aix520.informatik.uni-leipzig.de>).
* Try to eliminate byteorder assumptions.
* Use atapi_cdrom_subchnl struct definition.
* Add STANDARD_ATAPI compilation option.
* 3.07 Jan 29, 1996 -- More twiddling for broken drives: Sony 55D,
* Vertos 300.
* Vertos 300.
* Add NO_DOOR_LOCKING configuration option.
* Handle drive_cmd requests w/NULL args (for hdparm -t).
* Work around sporadic Sony55e audio play problem.
* 3.07a Feb 11, 1996 -- check drive->id for NULL before dereferencing, to fix
* problem with "hde=cdrom" with no drive present. -ml
* problem with "hde=cdrom" with no drive present. -ml
* 3.08 Mar 6, 1996 -- More Vertos workarounds.
* 3.09 Apr 5, 1996 -- Add CDROMCLOSETRAY ioctl.
* Switch to using MSF addressing for audio commands.
......@@ -129,47 +128,47 @@
* 3.14 May 29, 1996 -- Add work-around for Vertos 600.
* (From Hennus Bergman <hennus@sky.ow.nl>.)
* 3.15 July 2, 1996 -- Added support for Sanyo 3 CD changers
* from Ben Galliart <bgallia@luc.edu> with
* special help from Jeff Lightfoot
* <jeffml@pobox.com>
* from Ben Galliart <bgallia@luc.edu> with
* special help from Jeff Lightfoot
* <jeffml@pobox.com>
* 3.15a July 9, 1996 -- Improved Sanyo 3 CD changer identification
* 3.16 Jul 28, 1996 -- Fix from Gadi to reduce kernel stack usage for ioctl.
* 3.17 Sep 17, 1996 -- Tweak audio reads for some drives.
* Start changing CDROMLOADFROMSLOT to CDROM_SELECT_DISC.
* 3.18 Oct 31, 1996 -- Added module and DMA support.
*
*
*
*
* 4.00 Nov 5, 1996 -- New ide-cd maintainer,
* Erik B. Andersen <andersee@debian.org>
* Erik B. Andersen <andersee@debian.org>
* -- Newer Creative drives don't always set the error
* register correctly. Make sure we see media changes
* regardless.
* register correctly. Make sure we see media changes
* regardless.
* -- Integrate with generic cdrom driver.
* -- CDROMGETSPINDOWN and CDROMSETSPINDOWN ioctls, based on
* a patch from Ciro Cattuto <>.
* a patch from Ciro Cattuto <>.
* -- Call set_device_ro.
* -- Implement CDROMMECHANISMSTATUS and CDROMSLOTTABLE
* ioctls, based on patch by Erik Andersen
* ioctls, based on patch by Erik Andersen
* -- Add some probes of drive capability during setup.
*
* 4.01 Nov 11, 1996 -- Split into ide-cd.c and ide-cd.h
* -- Removed CDROMMECHANISMSTATUS and CDROMSLOTTABLE
* ioctls in favor of a generalized approach
* using the generic cdrom driver.
* -- Removed CDROMMECHANISMSTATUS and CDROMSLOTTABLE
* ioctls in favor of a generalized approach
* using the generic cdrom driver.
* -- Fully integrated with the 2.1.X kernel.
* -- Other stuff that I forgot (lots of changes)
*
* 4.02 Dec 01, 1996 -- Applied patch from Gadi Oxman <gadio@netvision.net.il>
* to fix the drive door locking problems.
* to fix the drive door locking problems.
*
* 4.03 Dec 04, 1996 -- Added DSC overlap support.
* 4.04 Dec 29, 1996 -- Added CDROMREADRAW ioclt based on patch
* by Ales Makarov (xmakarov@sun.felk.cvut.cz)
* 4.04 Dec 29, 1996 -- Added CDROMREADRAW ioclt based on patch
* by Aleks Makarov (xmakarov@sun.felk.cvut.cz)
*
* 4.05 Nov 20, 1997 -- Modified to print more drive info on init
* Minor other changes
* Fix errors on CDROMSTOP (If you have a "Dolphin",
* you must define IHAVEADOLPHIN)
* you must define IHAVEADOLPHIN)
* Added identifier so new Sanyo CD-changer works
* Better detection if door locking isn't supported
*
......@@ -178,40 +177,40 @@
* 4.08 Dec 18, 1997 -- spew less noise when tray is empty
* -- fix speed display for ACER 24X, 18X
* 4.09 Jan 04, 1998 -- fix handling of the last block so we return
* an end of file instead of an I/O error (Gadi)
* an end of file instead of an I/O error (Gadi)
* 4.10 Jan 24, 1998 -- fixed a bug so now changers can change to a new
* slot when there is no disc in the current slot.
* slot when there is no disc in the current slot.
* -- Fixed a memory leak where info->changer_info was
* malloc'ed but never free'd when closing the device.
* malloc'ed but never free'd when closing the device.
* -- Cleaned up the global namespace a bit by making more
* functions static that should already have been.
* functions static that should already have been.
* 4.11 Mar 12, 1998 -- Added support for the CDROM_SELECT_SPEED ioctl
* based on a patch for 2.0.33 by Jelle Foks
* <jelle@scintilla.utwente.nl>, a patch for 2.0.33
* by Toni Giorgino <toni@pcape2.pi.infn.it>, the SCSI
* version, and my own efforts. -erik
* based on a patch for 2.0.33 by Jelle Foks
* <jelle@scintilla.utwente.nl>, a patch for 2.0.33
* by Toni Giorgino <toni@pcape2.pi.infn.it>, the SCSI
* version, and my own efforts. -erik
* -- Fixed a stupid bug which egcs was kind enough to
* inform me of where "Illegal mode for this track"
* was never returned due to a comparison on data
* types of limited range.
* 4.12 Mar 29, 1998 -- Fixed bug in CDROM_SELECT_SPEED so write speed is
* now set ionly for CD-R and CD-RW drives. I had
* removed this support because it produced errors.
* It produced errors _only_ for non-writers. duh.
* inform me of where "Illegal mode for this track"
* was never returned due to a comparison on data
* types of limited range.
* 4.12 Mar 29, 1998 -- Fixed bug in CDROM_SELECT_SPEED so write speed is
* now set ionly for CD-R and CD-RW drives. I had
* removed this support because it produced errors.
* It produced errors _only_ for non-writers. duh.
* 4.13 May 05, 1998 -- Suppress useless "in progress of becoming ready"
* messages, since this is not an error.
* messages, since this is not an error.
* -- Change error messages to be const
* -- Remove a "\t" which looks ugly in the syslogs
* 4.14 July 17, 1998 -- Change to pointing to .ps version of ATAPI spec
* since the .pdf version doesn't seem to work...
* since the .pdf version doesn't seem to work...
* -- Updated the TODO list to something more current.
*
* 4.15 Aug 25, 1998 -- Updated ide-cd.h to respect mechine endianess,
* patch thanks to "Eddie C. Dost" <ecd@skynet.be>
* 4.15 Aug 25, 1998 -- Updated ide-cd.h to respect mechine endianess,
* patch thanks to "Eddie C. Dost" <ecd@skynet.be>
*
* 4.50 Oct 19, 1998 -- New maintainers!
* Jens Axboe <axboe@image.dk>
* Chris Zwilling <chris@cloudnet.com>
* Jens Axboe <axboe@image.dk>
* Chris Zwilling <chris@cloudnet.com>
*
* 4.51 Dec 23, 1998 -- Jens Axboe <axboe@image.dk>
* - ide_cdrom_reset enabled since the ide subsystem
......@@ -224,17 +223,17 @@
* - Detect DVD-ROM/RAM drives
*
* 4.53 Feb 22, 1999 - Include other model Samsung and one Goldstar
* drive in transfer size limit.
* drive in transfer size limit.
* - Fix the I/O error when doing eject without a medium
* loaded on some drives.
* loaded on some drives.
* - CDROMREADMODE2 is now implemented through
* CDROMREADRAW, since many drives don't support
* MODE2 (even though ATAPI 2.6 says they must).
* CDROMREADRAW, since many drives don't support
* MODE2 (even though ATAPI 2.6 says they must).
* - Added ignore parameter to ide-cd (as a module), eg
* insmod ide-cd ignore='hda hdb'
* Useful when using ide-cd in conjunction with
* ide-scsi. TODO: non-modular way of doing the
* same.
* insmod ide-cd ignore='hda hdb'
* Useful when using ide-cd in conjunction with
* ide-scsi. TODO: non-modular way of doing the
* same.
*
* 4.54 Aug 5, 1999 - Support for MMC2 class commands through the generic
* packet interface to cdrom.c.
......@@ -270,7 +269,7 @@
* - Mode sense and mode select moved to the
* Uniform layer.
* - Fixed a problem with WPI CDS-32X drive - it
* failed the capabilities
* failed the capabilities
*
* 4.57 Apr 7, 2000 - Fixed sense reporting.
* - Fixed possible oops in ide_cdrom_get_last_session()
......@@ -293,7 +292,7 @@
* Michael D Johnson <johnsom@orst.edu>
*
*************************************************************************/
#define IDECD_VERSION "4.59"
#include <linux/config.h>
......@@ -326,63 +325,68 @@
static void cdrom_saw_media_change (ide_drive_t *drive)
{
struct cdrom_info *info = drive->driver_data;
CDROM_STATE_FLAGS (drive)->media_changed = 1;
CDROM_STATE_FLAGS (drive)->toc_valid = 0;
info->nsectors_buffered = 0;
}
static int cdrom_log_sense(ide_drive_t *drive, struct packet_command *pc,
struct request_sense *sense)
static
void cdrom_analyze_sense_data(ide_drive_t *drive, struct request *rq)
{
int log = 0;
/* FIXME --mdcki */
struct packet_command *pc = (struct packet_command *) rq->special;
struct packet_command *failed_command = (struct packet_command *) pc->sense;
struct request_sense *sense = (struct request_sense *) (pc->buffer - rq->cmd[4]);
unsigned char fail_cmd;
if (sense == NULL || pc == NULL || pc->quiet)
return 0;
if (sense == NULL || failed_command == NULL || failed_command->quiet)
return;
fail_cmd = rq->cmd[0];
/* Check whatever this error should be logged:
*/
switch (sense->sense_key) {
case NO_SENSE: case RECOVERED_ERROR:
case NO_SENSE:
case RECOVERED_ERROR:
break;
case NOT_READY:
/*
* don't care about tray state messages for
* e.g. capacity commands or in-progress or
* becoming ready
/* Don't care about tray state messages for e.g.
* capacity commands or in-progress or becoming ready.
*/
if (sense->asc == 0x3a || sense->asc == 0x04)
break;
log = 1;
break;
case UNIT_ATTENTION:
/*
* Make good and sure we've seen this potential media
/* Make good and sure we've seen this potential media
* change. Some drives (i.e. Creative) fail to present
* the correct sense key in the error register.
*/
cdrom_saw_media_change(drive);
break;
default:
log = 1;
break;
}
return log;
}
static
void cdrom_analyze_sense_data(ide_drive_t *drive,
struct packet_command *failed_command,
struct request_sense *sense)
{
if (!cdrom_log_sense(drive, failed_command, sense))
if (!log)
return;
/*
* If a read toc is executed for a CD-R or CD-RW medium where
* the first toc has not been recorded yet, it will fail with
* 05/24/00 (which is a confusing error)
* If a read toc is executed for a CD-R or CD-RW medium where the first
* toc has not been recorded yet, it will fail with 05/24/00 (which is
* a confusing error).
*/
if (failed_command && failed_command->c[0] == GPCMD_READ_TOC_PMA_ATIP)
if (fail_cmd == GPCMD_READ_TOC_PMA_ATIP)
if (sense->sense_key == 0x05 && sense->asc == 0x24)
return;
......@@ -445,28 +449,26 @@ void cdrom_analyze_sense_data(ide_drive_t *drive,
printk(" %s -- (asc=0x%02x, ascq=0x%02x)\n",
s, sense->asc, sense->ascq);
if (failed_command != NULL) {
{
int lo=0, mid, hi= ARY_LEN (packet_command_texts);
s = NULL;
while (hi > lo) {
mid = (lo + hi) / 2;
if (packet_command_texts[mid].packet_command ==
failed_command->c[0]) {
if (packet_command_texts[mid].packet_command == fail_cmd) {
s = packet_command_texts[mid].text;
break;
}
if (packet_command_texts[mid].packet_command >
failed_command->c[0])
if (packet_command_texts[mid].packet_command > fail_cmd)
hi = mid;
else
lo = mid+1;
}
printk (" The failed \"%s\" packet command was: \n \"", s);
for (i=0; i<sizeof (failed_command->c); i++)
printk ("%02x ", failed_command->c[i]);
for (i=0; i < CDROM_PACKET_SIZE; i++)
printk ("%02x ", rq->cmd[i]);
printk ("\"\n");
}
......@@ -495,7 +497,7 @@ void cdrom_analyze_sense_data(ide_drive_t *drive,
}
}
#else /* not VERBOSE_IDE_CD_ERRORS */
#else
/* Suppress printing unit attention and `in progress of becoming ready'
errors when we're not being verbose. */
......@@ -509,7 +511,7 @@ void cdrom_analyze_sense_data(ide_drive_t *drive,
drive->name,
sense->error_code, sense->sense_key,
sense->asc, sense->ascq);
#endif /* not VERBOSE_IDE_CD_ERRORS */
#endif
}
static void cdrom_queue_request_sense(ide_drive_t *drive,
......@@ -525,16 +527,20 @@ static void cdrom_queue_request_sense(ide_drive_t *drive,
sense = &info->sense_data;
memset(pc, 0, sizeof(struct packet_command));
pc->c[0] = GPCMD_REQUEST_SENSE;
pc->c[4] = pc->buflen = 18;
pc->buffer = (char *) sense;
pc->buffer = (void *) sense;
pc->buflen = 18;
pc->sense = (struct request_sense *) failed_command;
/* stuff the sense request in front of our current request */
rq = &info->request_sense_request;
rq->cmd[0] = GPCMD_REQUEST_SENSE;
rq->cmd[4] = pc->buflen;
ide_init_drive_cmd(rq);
rq->flags = REQ_SENSE;
/* FIXME --mdcki */
rq->special = (char *) pc;
rq->waiting = wait;
ide_do_drive_cmd(drive, rq, ide_preempt);
}
......@@ -544,16 +550,13 @@ static void cdrom_end_request(ide_drive_t *drive, int uptodate)
{
struct request *rq = HWGROUP(drive)->rq;
if ((rq->flags & REQ_SENSE) && uptodate) {
struct packet_command *pc = (struct packet_command *) rq->special;
cdrom_analyze_sense_data(drive,
(struct packet_command *) pc->sense,
(struct request_sense *) (pc->buffer - pc->c[4]));
}
if ((rq->flags & REQ_SENSE) && uptodate)
cdrom_analyze_sense_data(drive, rq);
if ((rq->flags & REQ_CMD) && !rq->current_nr_sectors)
uptodate = 1;
/* FIXME --mdcki */
HWGROUP(drive)->rq->special = NULL;
ide_end_request(drive, uptodate);
}
......@@ -567,7 +570,7 @@ static int cdrom_decode_status (ide_startstop_t *startstop, ide_drive_t *drive,
struct request *rq = HWGROUP(drive)->rq;
int stat, err, sense_key;
struct packet_command *pc;
/* Check for errors. */
stat = GET_STAT();
*stat_ret = stat;
......@@ -590,6 +593,7 @@ static int cdrom_decode_status (ide_startstop_t *startstop, ide_drive_t *drive,
from the drive (probably while trying
to recover from a former error). Just give up. */
/* FIXME --mdcki */
pc = (struct packet_command *) rq->special;
pc->stat = 1;
cdrom_end_request(drive, 1);
......@@ -598,6 +602,8 @@ static int cdrom_decode_status (ide_startstop_t *startstop, ide_drive_t *drive,
} else if (rq->flags & (REQ_PC | REQ_BLOCK_PC)) {
/* All other functions, except for READ. */
struct completion *wait = NULL;
/* FIXME --mdcki */
pc = (struct packet_command *) rq->special;
/* Check for tray open. */
......@@ -612,15 +618,14 @@ static int cdrom_decode_status (ide_startstop_t *startstop, ide_drive_t *drive,
/* Otherwise, print an error. */
ide_dump_status(drive, "packet command error", stat);
}
/* Set the error flag and complete the request.
Then, if we have a CHECK CONDITION status,
queue a request sense command. We must be careful,
though: we don't want the thread in
cdrom_queue_packet_command to wake up until
the request sense has completed. We do this
by transferring the semaphore from the packet
command request to the request sense request. */
Then, if we have a CHECK CONDITION status, queue a request
sense command. We must be careful, though: we don't want
the thread in cdrom_queue_packet_command to wake up until
the request sense has completed. We do this by transferring
the semaphore from the packet command request to the request
sense request. */
if ((stat & ERR_STAT) != 0) {
wait = rq->waiting;
......@@ -756,22 +761,15 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive,
}
}
/* Send a packet command to DRIVE described by CMD_BUF and CMD_LEN.
The device registers must have already been prepared
by cdrom_start_packet_command.
HANDLER is the interrupt handler to call when the command completes
or there's data ready. */
/*
* changed 5 parameters to 3 for dvd-ram
* struct packet_command *pc; now packet_command_t *pc;
* Send a packet command cmd to the drive. The device registers must have
* already been prepared by cdrom_start_packet_command. "handler" is the
* interrupt handler to call when the command completes or there's data ready.
*/
static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive,
struct packet_command *pc,
ide_handler_t *handler)
unsigned char *cmd, unsigned long timeout,
ide_handler_t *handler)
{
unsigned char *cmd_buf = pc->c;
int cmd_len = sizeof(pc->c);
unsigned int timeout = pc->timeout;
ide_startstop_t startstop;
if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) {
......@@ -780,20 +778,21 @@ static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive,
int stat_dum;
/* Check for errors. */
if (cdrom_decode_status (&startstop, drive, DRQ_STAT, &stat_dum))
if (cdrom_decode_status(&startstop, drive, DRQ_STAT, &stat_dum))
return startstop;
} else {
/* Otherwise, we must wait for DRQ to get set. */
if (ide_wait_stat (&startstop, drive, DRQ_STAT, BUSY_STAT, WAIT_READY))
if (ide_wait_stat(&startstop, drive, DRQ_STAT, BUSY_STAT, WAIT_READY))
return startstop;
}
/* Arm the interrupt handler. */
BUG_ON(HWGROUP(drive)->handler);
ide_set_handler (drive, handler, timeout, cdrom_timer_expiry);
ide_set_handler(drive, handler, timeout, cdrom_timer_expiry);
/* Send the command to the device. */
atapi_output_bytes (drive, cmd_buf, cmd_len);
atapi_output_bytes(drive, cmd, CDROM_PACKET_SIZE);
return ide_started;
}
......@@ -889,7 +888,7 @@ int cdrom_read_check_ireason (ide_drive_t *drive, int len, int ireason)
/*
* Interrupt routine. Called when a read request has completed.
*/
static ide_startstop_t cdrom_read_intr (ide_drive_t *drive)
static ide_startstop_t cdrom_read_intr(ide_drive_t *drive)
{
int stat;
int ireason, len, sectors_to_transfer, nskip;
......@@ -908,7 +907,7 @@ static ide_startstop_t cdrom_read_intr (ide_drive_t *drive)
if (cdrom_decode_status (&startstop, drive, 0, &stat))
return startstop;
if (dma) {
if (!dma_error) {
__ide_end_request(drive, 1, rq->nr_sectors);
......@@ -1071,14 +1070,12 @@ static int cdrom_read_from_buffer (ide_drive_t *drive)
}
/*
* Routine to send a read packet command to the drive.
* This is usually called directly from cdrom_start_read.
* However, for drq_interrupt devices, it is called from an interrupt
* when the drive is ready to accept the command.
* Routine to send a read packet command to the drive. This is usually called
* directly from cdrom_start_read. However, for drq_interrupt devices, it is
* called from an interrupt when the drive is ready to accept the command.
*/
static ide_startstop_t cdrom_start_read_continuation (ide_drive_t *drive)
static ide_startstop_t cdrom_start_read_continuation(ide_drive_t *drive)
{
struct packet_command pc;
struct request *rq = HWGROUP(drive)->rq;
int nsect, sector, nframes, frame, nskip;
......@@ -1117,15 +1114,11 @@ static ide_startstop_t cdrom_start_read_continuation (ide_drive_t *drive)
/* Largest number of frames was can transfer at once is 64k-1. For
some drives we need to limit this even more. */
nframes = MIN (nframes, (CDROM_CONFIG_FLAGS (drive)->limit_nframes) ?
nframes = MIN(nframes, (CDROM_CONFIG_FLAGS (drive)->limit_nframes) ?
(65534 / CD_FRAMESIZE) : 65535);
/* Set up the command */
memcpy(pc.c, rq->cmd, sizeof(pc.c));
pc.timeout = WAIT_CMD;
/* Send the command to the drive and return. */
return cdrom_transfer_packet_command(drive, &pc, &cdrom_read_intr);
return cdrom_transfer_packet_command(drive, rq->cmd, WAIT_CMD, &cdrom_read_intr);
}
......@@ -1161,7 +1154,7 @@ static ide_startstop_t cdrom_seek_intr (ide_drive_t *drive)
static ide_startstop_t cdrom_start_seek_continuation (ide_drive_t *drive)
{
struct packet_command pc;
unsigned char cmd[CDROM_PACKET_SIZE];
struct request *rq = HWGROUP(drive)->rq;
int sector, frame, nskip;
......@@ -1172,11 +1165,10 @@ static ide_startstop_t cdrom_start_seek_continuation (ide_drive_t *drive)
frame = sector / SECTORS_PER_FRAME;
memset(rq->cmd, 0, sizeof(rq->cmd));
pc.c[0] = GPCMD_SEEK;
put_unaligned(cpu_to_be32(frame), (unsigned int *) &pc.c[2]);
cmd[0] = GPCMD_SEEK;
put_unaligned(cpu_to_be32(frame), (unsigned int *) &cmd[2]);
pc.timeout = WAIT_CMD;
return cdrom_transfer_packet_command(drive, &pc, &cdrom_seek_intr);
return cdrom_transfer_packet_command(drive, cmd, WAIT_CMD, &cdrom_seek_intr);
}
static ide_startstop_t cdrom_start_seek (ide_drive_t *drive, unsigned int block)
......@@ -1243,15 +1235,13 @@ static ide_startstop_t cdrom_start_read (ide_drive_t *drive, unsigned int block)
* Execute all other packet commands.
*/
/* Forward declarations. */
static int cdrom_lockdoor(ide_drive_t *drive, int lockflag,
struct request_sense *sense);
/* Interrupt routine for packet command completion. */
static ide_startstop_t cdrom_pc_intr (ide_drive_t *drive)
{
int ireason, len, stat, thislen;
struct request *rq = HWGROUP(drive)->rq;
/* FIXME --mdcki */
struct packet_command *pc = (struct packet_command *) rq->special;
ide_startstop_t startstop;
......@@ -1268,7 +1258,7 @@ static ide_startstop_t cdrom_pc_intr (ide_drive_t *drive)
if ((stat & DRQ_STAT) == 0) {
/* Some of the trailing request sense fields are optional, and
some drives don't send them. Sigh. */
if (pc->c[0] == GPCMD_REQUEST_SENSE &&
if (rq->cmd[0] == GPCMD_REQUEST_SENSE &&
pc->buflen > 0 &&
pc->buflen <= 5) {
while (pc->buflen > 0) {
......@@ -1346,24 +1336,29 @@ static ide_startstop_t cdrom_pc_intr (ide_drive_t *drive)
return ide_started;
}
static ide_startstop_t cdrom_do_pc_continuation (ide_drive_t *drive)
static ide_startstop_t cdrom_do_pc_continuation(ide_drive_t *drive)
{
struct request *rq = HWGROUP(drive)->rq;
unsigned long timeout;
/* FIXME --mdcki */
struct packet_command *pc = (struct packet_command *) rq->special;
if (!pc->timeout)
pc->timeout = WAIT_CMD;
if (pc->timeout)
timeout = pc->timeout;
else
timeout = WAIT_CMD;
/* Send the command to the drive and return. */
return cdrom_transfer_packet_command(drive, pc, &cdrom_pc_intr);
return cdrom_transfer_packet_command(drive, rq->cmd, timeout, &cdrom_pc_intr);
}
static ide_startstop_t cdrom_do_packet_command (ide_drive_t *drive)
{
int len;
struct request *rq = HWGROUP(drive)->rq;
/* FIXME --mdcki */
struct packet_command *pc = (struct packet_command *) rq->special;
struct cdrom_info *info = drive->driver_data;
......@@ -1391,23 +1386,28 @@ void cdrom_sleep (int time)
}
static
int cdrom_queue_packet_command(ide_drive_t *drive, struct packet_command *pc)
int cdrom_queue_packet_command(ide_drive_t *drive, unsigned char *cmd, struct packet_command *pc)
{
struct request_sense sense;
struct request req;
struct request rq;
int retries = 10;
memcpy(rq.cmd, cmd, CDROM_PACKET_SIZE);
if (pc->sense == NULL)
pc->sense = &sense;
/* Start of retry loop. */
do {
ide_init_drive_cmd (&req);
req.flags = REQ_PC;
req.special = (char *) pc;
if (ide_do_drive_cmd (drive, &req, ide_wait)) {
ide_init_drive_cmd(&rq);
rq.flags = REQ_PC;
/* FIXME --mdcki */
rq.special = (void *) pc;
if (ide_do_drive_cmd(drive, &rq, ide_wait)) {
printk("%s: do_drive_cmd returned stat=%02x,err=%02x\n",
drive->name, req.buffer[0], req.buffer[1]);
drive->name, rq.buffer[0], rq.buffer[1]);
/* FIXME: we should probably abort/retry or something */
}
if (pc->stat != 0) {
......@@ -1493,7 +1493,7 @@ static ide_startstop_t cdrom_write_intr(ide_drive_t *drive)
printk("ide-cd: write_intr decode_status bad\n");
return startstop;
}
/*
* using dma, transfer is complete now
*/
......@@ -1573,20 +1573,9 @@ static ide_startstop_t cdrom_write_intr(ide_drive_t *drive)
static ide_startstop_t cdrom_start_write_cont(ide_drive_t *drive)
{
struct packet_command pc; /* packet_command_t pc; */
struct request *rq = HWGROUP(drive)->rq;
unsigned nframes, frame;
nframes = rq->nr_sectors >> 2;
frame = rq->sector >> 2;
memcpy(pc.c, rq->cmd, sizeof(pc.c));
#if 0 /* the immediate bit */
pc.c[1] = 1 << 3;
#endif
pc.timeout = 2 * WAIT_CMD;
return cdrom_transfer_packet_command(drive, &pc, cdrom_write_intr);
return cdrom_transfer_packet_command(drive, rq->cmd, 2 * WAIT_CMD, cdrom_write_intr);
}
static ide_startstop_t cdrom_start_write(ide_drive_t *drive, struct request *rq)
......@@ -1620,34 +1609,13 @@ static ide_startstop_t cdrom_start_write(ide_drive_t *drive, struct request *rq)
return cdrom_start_packet_command(drive, 32768, cdrom_start_write_cont);
}
/*
* just wrap this around cdrom_do_packet_command
*/
static ide_startstop_t cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
{
struct packet_command pc;
ide_startstop_t startstop;
memset(&pc, 0, sizeof(pc));
memcpy(pc.c, rq->cmd, sizeof(pc.c));
pc.quiet = 1;
pc.timeout = 60 * HZ;
rq->special = (char *) &pc;
startstop = cdrom_do_packet_command(drive);
if (pc.stat)
rq->errors++;
return startstop;
}
#define IDE_LARGE_SEEK(b1,b2,t) (((b1) > (b2) + (t)) || ((b2) > (b1) + (t)))
/****************************************************************************
* cdrom driver request routine.
*/
static ide_startstop_t
ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, unsigned long block)
ide_do_rw_cdrom(ide_drive_t *drive, struct request *rq, unsigned long block)
{
ide_startstop_t action;
struct cdrom_info *info = drive->driver_data;
......@@ -1679,18 +1647,31 @@ ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, unsigned long block)
} else if (rq->flags & (REQ_PC | REQ_SENSE)) {
return cdrom_do_packet_command(drive);
} else if (rq->flags & REQ_SPECIAL) {
/*
* FIXME: Kill REQ_SEPCIAL and replace it will command commands
* queued at the request queue instead as suggested (abd
* rightly so) by Linus.
* FIXME: Kill REQ_SEPCIAL and replace it with commands queued
* at the request queue instead as suggested by Linus.
*
* right now this can only be a reset...
*/
cdrom_end_request(drive, 1); return ide_stopped;
cdrom_end_request(drive, 1);
return ide_stopped;
} else if (rq->flags & REQ_BLOCK_PC) {
return cdrom_do_block_pc(drive, rq);
struct packet_command pc;
ide_startstop_t startstop;
memset(&pc, 0, sizeof(pc));
pc.quiet = 1;
pc.timeout = 60 * HZ;
/* FIXME --mdcki */
rq->special = (char *) &pc;
startstop = cdrom_do_packet_command(drive);
if (pc.stat)
++rq->errors;
return startstop;
}
blk_dump_rq_flags(rq, "ide-cd bad flags");
......@@ -1755,6 +1736,7 @@ int msf_to_lba (byte m, byte s, byte f)
static int cdrom_check_status(ide_drive_t *drive, struct request_sense *sense)
{
unsigned char cmd[CDROM_PACKET_SIZE];
struct packet_command pc;
struct cdrom_info *info = drive->driver_data;
struct cdrom_device_info *cdi = &info->devinfo;
......@@ -1762,16 +1744,16 @@ static int cdrom_check_status(ide_drive_t *drive, struct request_sense *sense)
memset(&pc, 0, sizeof(pc));
pc.sense = sense;
pc.c[0] = GPCMD_TEST_UNIT_READY;
cmd[0] = GPCMD_TEST_UNIT_READY;
#if ! STANDARD_ATAPI
/* the Sanyo 3 CD changer uses byte 7 of TEST_UNIT_READY to
#if !STANDARD_ATAPI
/* the Sanyo 3 CD changer uses byte 7 of TEST_UNIT_READY to
switch CDs instead of supporting the LOAD_UNLOAD opcode */
pc.c[7] = cdi->sanyo_slot % 3;
#endif /* not STANDARD_ATAPI */
cmd[7] = cdi->sanyo_slot % 3;
#endif
return cdrom_queue_packet_command(drive, &pc);
return cdrom_queue_packet_command(drive, cmd, &pc);
}
......@@ -1779,22 +1761,20 @@ static int cdrom_check_status(ide_drive_t *drive, struct request_sense *sense)
static int
cdrom_lockdoor(ide_drive_t *drive, int lockflag, struct request_sense *sense)
{
struct request_sense my_sense;
struct packet_command pc;
int stat;
if (sense == NULL)
sense = &my_sense;
/* If the drive cannot lock the door, just pretend. */
if (CDROM_CONFIG_FLAGS(drive)->no_doorlock) {
stat = 0;
} else {
unsigned char cmd[CDROM_PACKET_SIZE];
memset(&pc, 0, sizeof(pc));
pc.sense = sense;
pc.c[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL;
pc.c[4] = lockflag ? 1 : 0;
stat = cdrom_queue_packet_command (drive, &pc);
cmd[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL;
cmd[4] = lockflag ? 1 : 0;
stat = cdrom_queue_packet_command(drive, cmd, &pc);
}
/* If we got an illegal field error, the drive
......@@ -1807,7 +1787,7 @@ cdrom_lockdoor(ide_drive_t *drive, int lockflag, struct request_sense *sense)
CDROM_CONFIG_FLAGS (drive)->no_doorlock = 1;
stat = 0;
}
/* no medium, that's alright. */
if (stat != 0 && sense->sense_key == NOT_READY && sense->asc == 0x3a)
stat = 0;
......@@ -1825,10 +1805,11 @@ static int cdrom_eject(ide_drive_t *drive, int ejectflag,
struct request_sense *sense)
{
struct packet_command pc;
unsigned char cmd[CDROM_PACKET_SIZE];
if (CDROM_CONFIG_FLAGS(drive)->no_eject && !ejectflag)
return -EDRIVE_CANT_DO_THIS;
/* reload fails on some drives, if the tray is locked */
if (CDROM_STATE_FLAGS(drive)->door_locked && ejectflag)
return 0;
......@@ -1836,9 +1817,9 @@ static int cdrom_eject(ide_drive_t *drive, int ejectflag,
memset(&pc, 0, sizeof (pc));
pc.sense = sense;
pc.c[0] = GPCMD_START_STOP_UNIT;
pc.c[4] = 0x02 + (ejectflag != 0);
return cdrom_queue_packet_command (drive, &pc);
cmd[0] = GPCMD_START_STOP_UNIT;
cmd[4] = 0x02 + (ejectflag != 0);
return cdrom_queue_packet_command(drive, cmd, &pc);
}
static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity,
......@@ -1850,16 +1831,16 @@ static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity,
} capbuf;
int stat;
unsigned char cmd[CDROM_PACKET_SIZE];
struct packet_command pc;
memset(&pc, 0, sizeof(pc));
pc.sense = sense;
pc.c[0] = GPCMD_READ_CDVD_CAPACITY;
cmd[0] = GPCMD_READ_CDVD_CAPACITY;
pc.buffer = (char *)&capbuf;
pc.buflen = sizeof(capbuf);
stat = cdrom_queue_packet_command(drive, &pc);
stat = cdrom_queue_packet_command(drive, cmd, &pc);
if (stat == 0)
*capacity = 1 + be32_to_cpu(capbuf.lba);
......@@ -1870,6 +1851,7 @@ static int cdrom_read_tocentry(ide_drive_t *drive, int trackno, int msf_flag,
int format, char *buf, int buflen,
struct request_sense *sense)
{
unsigned char cmd[CDROM_PACKET_SIZE];
struct packet_command pc;
memset(&pc, 0, sizeof(pc));
......@@ -1878,16 +1860,16 @@ static int cdrom_read_tocentry(ide_drive_t *drive, int trackno, int msf_flag,
pc.buffer = buf;
pc.buflen = buflen;
pc.quiet = 1;
pc.c[0] = GPCMD_READ_TOC_PMA_ATIP;
pc.c[6] = trackno;
pc.c[7] = (buflen >> 8);
pc.c[8] = (buflen & 0xff);
pc.c[9] = (format << 6);
cmd[0] = GPCMD_READ_TOC_PMA_ATIP;
if (msf_flag)
pc.c[1] = 2;
cmd[1] = 2;
cmd[6] = trackno;
cmd[7] = (buflen >> 8);
cmd[8] = (buflen & 0xff);
cmd[9] = (format << 6);
return cdrom_queue_packet_command (drive, &pc);
return cdrom_queue_packet_command(drive, cmd, &pc);
}
......@@ -1916,7 +1898,7 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense)
/* Check to see if the existing data is still valid.
If it is, just return. */
(void) cdrom_check_status(drive, sense);
cdrom_check_status(drive, sense);
if (CDROM_STATE_FLAGS(drive)->toc_valid)
return 0;
......@@ -2049,6 +2031,7 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense)
static int cdrom_read_subchannel(ide_drive_t *drive, int format, char *buf,
int buflen, struct request_sense *sense)
{
unsigned char cmd[CDROM_PACKET_SIZE];
struct packet_command pc;
memset(&pc, 0, sizeof(pc));
......@@ -2056,13 +2039,14 @@ static int cdrom_read_subchannel(ide_drive_t *drive, int format, char *buf,
pc.buffer = buf;
pc.buflen = buflen;
pc.c[0] = GPCMD_READ_SUBCHANNEL;
pc.c[1] = 2; /* MSF addressing */
pc.c[2] = 0x40; /* request subQ data */
pc.c[3] = format;
pc.c[7] = (buflen >> 8);
pc.c[8] = (buflen & 0xff);
return cdrom_queue_packet_command(drive, &pc);
cmd[0] = GPCMD_READ_SUBCHANNEL;
cmd[1] = 2; /* MSF addressing */
cmd[2] = 0x40; /* request subQ data */
cmd[3] = format;
cmd[7] = (buflen >> 8);
cmd[8] = (buflen & 0xff);
return cdrom_queue_packet_command(drive, cmd, &pc);
}
/* ATAPI cdrom drives are free to select the speed you request or any slower
......@@ -2070,6 +2054,7 @@ static int cdrom_read_subchannel(ide_drive_t *drive, int format, char *buf,
static int cdrom_select_speed(ide_drive_t *drive, int speed,
struct request_sense *sense)
{
unsigned char cmd[CDROM_PACKET_SIZE];
struct packet_command pc;
memset(&pc, 0, sizeof(pc));
pc.sense = sense;
......@@ -2079,36 +2064,37 @@ static int cdrom_select_speed(ide_drive_t *drive, int speed,
else
speed *= 177; /* Nx to kbytes/s */
pc.c[0] = GPCMD_SET_SPEED;
cmd[0] = GPCMD_SET_SPEED;
/* Read Drive speed in kbytes/second MSB */
pc.c[2] = (speed >> 8) & 0xff;
cmd[2] = (speed >> 8) & 0xff;
/* Read Drive speed in kbytes/second LSB */
pc.c[3] = speed & 0xff;
cmd[3] = speed & 0xff;
if (CDROM_CONFIG_FLAGS(drive)->cd_r ||
CDROM_CONFIG_FLAGS(drive)->cd_rw ||
CDROM_CONFIG_FLAGS(drive)->dvd_r) {
/* Write Drive speed in kbytes/second MSB */
pc.c[4] = (speed >> 8) & 0xff;
cmd[4] = (speed >> 8) & 0xff;
/* Write Drive speed in kbytes/second LSB */
pc.c[5] = speed & 0xff;
cmd[5] = speed & 0xff;
}
return cdrom_queue_packet_command(drive, &pc);
return cdrom_queue_packet_command(drive, cmd, &pc);
}
static int cdrom_play_audio(ide_drive_t *drive, int lba_start, int lba_end)
{
struct request_sense sense;
unsigned char cmd[CDROM_PACKET_SIZE];
struct packet_command pc;
memset(&pc, 0, sizeof (pc));
pc.sense = &sense;
pc.c[0] = GPCMD_PLAY_AUDIO_MSF;
lba_to_msf(lba_start, &pc.c[3], &pc.c[4], &pc.c[5]);
lba_to_msf(lba_end-1, &pc.c[6], &pc.c[7], &pc.c[8]);
cmd[0] = GPCMD_PLAY_AUDIO_MSF;
lba_to_msf(lba_start, &cmd[3], &cmd[4], &cmd[5]);
lba_to_msf(lba_end-1, &cmd[6], &cmd[7], &cmd[8]);
return cdrom_queue_packet_command(drive, &pc);
return cdrom_queue_packet_command(drive, cmd, &pc);
}
static int cdrom_get_toc_entry(ide_drive_t *drive, int track,
......@@ -2152,15 +2138,15 @@ static int ide_cdrom_packet(struct cdrom_device_info *cdi,
layer. the packet must be complete, as we do not
touch it at all. */
memset(&pc, 0, sizeof(pc));
memcpy(pc.c, cgc->cmd, CDROM_PACKET_SIZE);
pc.buffer = cgc->buffer;
pc.buflen = cgc->buflen;
pc.quiet = cgc->quiet;
pc.timeout = cgc->timeout;
pc.sense = cgc->sense;
cgc->stat = cdrom_queue_packet_command(drive, &pc);
cgc->stat = cdrom_queue_packet_command(drive, cgc->cmd, &pc);
if (!cgc->stat)
cgc->buflen -= pc.buflen;
return cgc->stat;
}
......@@ -2177,34 +2163,34 @@ int ide_cdrom_dev_ioctl (struct cdrom_device_info *cdi,
/* These will be moved into the Uniform layer shortly... */
switch (cmd) {
case CDROMSETSPINDOWN: {
char spindown;
if (copy_from_user(&spindown, (void *) arg, sizeof(char)))
case CDROMSETSPINDOWN: {
char spindown;
if (copy_from_user(&spindown, (void *) arg, sizeof(char)))
return -EFAULT;
if ((stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CDROM_PAGE, 0)))
return stat;
buffer[11] = (buffer[11] & 0xf0) | (spindown & 0x0f);
buffer[11] = (buffer[11] & 0xf0) | (spindown & 0x0f);
return cdrom_mode_select(cdi, &cgc);
}
case CDROMGETSPINDOWN: {
char spindown;
return cdrom_mode_select(cdi, &cgc);
}
case CDROMGETSPINDOWN: {
char spindown;
if ((stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CDROM_PAGE, 0)))
return stat;
spindown = buffer[11] & 0x0f;
spindown = buffer[11] & 0x0f;
if (copy_to_user((void *) arg, &spindown, sizeof (char)))
return -EFAULT;
return 0;
}
return 0;
}
default:
return -EINVAL;
}
......@@ -2214,7 +2200,6 @@ int ide_cdrom_dev_ioctl (struct cdrom_device_info *cdi,
static
int ide_cdrom_audio_ioctl (struct cdrom_device_info *cdi,
unsigned int cmd, void *arg)
{
ide_drive_t *drive = (ide_drive_t*) cdi->handle;
struct cdrom_info *info = drive->driver_data;
......@@ -2306,31 +2291,34 @@ int ide_cdrom_reset (struct cdrom_device_info *cdi)
* lock it again.
*/
if (CDROM_STATE_FLAGS(drive)->door_locked)
(void) cdrom_lockdoor(drive, 1, &sense);
cdrom_lockdoor(drive, 1, &sense);
return ret;
}
static
int ide_cdrom_tray_move (struct cdrom_device_info *cdi, int position)
int ide_cdrom_tray_move(struct cdrom_device_info *cdi, int position)
{
ide_drive_t *drive = (ide_drive_t*) cdi->handle;
struct request_sense sense;
if (position) {
int stat = cdrom_lockdoor(drive, 0, &sense);
if (stat) return stat;
if (stat)
return stat;
}
return cdrom_eject(drive, !position, &sense);
}
static
int ide_cdrom_lock_door (struct cdrom_device_info *cdi, int lock)
int ide_cdrom_lock_door(struct cdrom_device_info *cdi, int lock)
{
ide_drive_t *drive = (ide_drive_t*) cdi->handle;
return cdrom_lockdoor(drive, lock, NULL);
struct request_sense sense;
return cdrom_lockdoor(drive, lock, &sense);
}
static
......@@ -2433,9 +2421,9 @@ int ide_cdrom_check_media_change_real (struct cdrom_device_info *cdi,
{
ide_drive_t *drive = (ide_drive_t*) cdi->handle;
int retval;
if (slot_nr == CDSL_CURRENT) {
(void) cdrom_check_status(drive, NULL);
cdrom_check_status(drive, NULL);
retval = CDROM_STATE_FLAGS (drive)->media_changed;
CDROM_STATE_FLAGS (drive)->media_changed = 0;
return retval;
......@@ -2502,7 +2490,7 @@ static int ide_cdrom_register (ide_drive_t *drive, int nslots)
*(int *)&devinfo->capacity = nslots;
devinfo->handle = (void *) drive;
strcpy(devinfo->name, drive->name);
/* set capability mask to match the probe. */
if (!CDROM_CONFIG_FLAGS (drive)->cd_r)
devinfo->mask |= CDC_CD_R;
......@@ -2578,8 +2566,8 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive)
int nslots = 1;
if (CDROM_CONFIG_FLAGS (drive)->nec260) {
CDROM_CONFIG_FLAGS (drive)->no_eject = 0;
CDROM_CONFIG_FLAGS (drive)->audio_play = 1;
CDROM_CONFIG_FLAGS (drive)->no_eject = 0;
CDROM_CONFIG_FLAGS (drive)->audio_play = 1;
return nslots;
}
......@@ -2632,14 +2620,14 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive)
/* The ACER/AOpen 24X cdrom has the speed fields byte-swapped */
if (drive->id && !drive->id->model[0] && !strncmp(drive->id->fw_rev, "241N", 4)) {
CDROM_STATE_FLAGS (drive)->current_speed =
CDROM_STATE_FLAGS (drive)->current_speed =
(((unsigned int)cap.curspeed) + (176/2)) / 176;
CDROM_CONFIG_FLAGS (drive)->max_speed =
CDROM_CONFIG_FLAGS (drive)->max_speed =
(((unsigned int)cap.maxspeed) + (176/2)) / 176;
} else {
CDROM_STATE_FLAGS (drive)->current_speed =
CDROM_STATE_FLAGS (drive)->current_speed =
(ntohs(cap.curspeed) + (176/2)) / 176;
CDROM_CONFIG_FLAGS (drive)->max_speed =
CDROM_CONFIG_FLAGS (drive)->max_speed =
(ntohs(cap.maxspeed) + (176/2)) / 176;
}
......@@ -2651,19 +2639,19 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive)
printk(" %s", CDROM_CONFIG_FLAGS(drive)->dvd ? "DVD-ROM" : "CD-ROM");
if (CDROM_CONFIG_FLAGS (drive)->dvd_r|CDROM_CONFIG_FLAGS (drive)->dvd_ram)
printk (" DVD%s%s",
(CDROM_CONFIG_FLAGS (drive)->dvd_r)? "-R" : "",
(CDROM_CONFIG_FLAGS (drive)->dvd_ram)? "-RAM" : "");
printk (" DVD%s%s",
(CDROM_CONFIG_FLAGS (drive)->dvd_r)? "-R" : "",
(CDROM_CONFIG_FLAGS (drive)->dvd_ram)? "-RAM" : "");
if (CDROM_CONFIG_FLAGS (drive)->cd_r|CDROM_CONFIG_FLAGS (drive)->cd_rw)
printk (" CD%s%s",
(CDROM_CONFIG_FLAGS (drive)->cd_r)? "-R" : "",
(CDROM_CONFIG_FLAGS (drive)->cd_rw)? "/RW" : "");
if (CDROM_CONFIG_FLAGS (drive)->cd_r|CDROM_CONFIG_FLAGS (drive)->cd_rw)
printk (" CD%s%s",
(CDROM_CONFIG_FLAGS (drive)->cd_r)? "-R" : "",
(CDROM_CONFIG_FLAGS (drive)->cd_rw)? "/RW" : "");
if (CDROM_CONFIG_FLAGS (drive)->is_changer)
printk (" changer w/%d slots", nslots);
else
printk (" drive");
if (CDROM_CONFIG_FLAGS (drive)->is_changer)
printk (" changer w/%d slots", nslots);
else
printk (" drive");
printk (", %dkB Cache", be16_to_cpu(cap.buffer_size));
......@@ -2678,7 +2666,8 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive)
static void ide_cdrom_add_settings(ide_drive_t *drive)
{
ide_add_setting(drive, "dsc_overlap", SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->dsc_overlap, NULL);
ide_add_setting(drive, "dsc_overlap",
SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->dsc_overlap, NULL);
}
static
......@@ -2728,7 +2717,7 @@ int ide_cdrom_setup (ide_drive_t *drive)
CDROM_CONFIG_FLAGS (drive)->supp_disc_present = 0;
CDROM_CONFIG_FLAGS (drive)->audio_play = 0;
CDROM_CONFIG_FLAGS (drive)->close_tray = 1;
/* limit transfer size per interrupt. */
CDROM_CONFIG_FLAGS (drive)->limit_nframes = 0;
if (drive->id != NULL) {
......@@ -2763,16 +2752,12 @@ int ide_cdrom_setup (ide_drive_t *drive)
CDROM_CONFIG_FLAGS (drive)->tocaddr_as_bcd = 1;
CDROM_CONFIG_FLAGS (drive)->playmsf_as_bcd = 1;
CDROM_CONFIG_FLAGS (drive)->subchan_as_bcd = 1;
}
else if (strcmp (drive->id->model, "V006E0DS") == 0 &&
} else if (strcmp (drive->id->model, "V006E0DS") == 0 &&
drive->id->fw_rev[4] == '1' &&
drive->id->fw_rev[6] <= '2') {
/* Vertos 600 ESD. */
CDROM_CONFIG_FLAGS (drive)->toctracks_as_bcd = 1;
}
else if (strcmp (drive->id->model,
} else if (strcmp (drive->id->model,
"NEC CD-ROM DRIVE:260") == 0 &&
strncmp (drive->id->fw_rev, "1.01", 4) == 0) { /* FIXME */
/* Old NEC260 (not R).
......@@ -2782,9 +2767,7 @@ int ide_cdrom_setup (ide_drive_t *drive)
CDROM_CONFIG_FLAGS (drive)->playmsf_as_bcd = 1;
CDROM_CONFIG_FLAGS (drive)->subchan_as_bcd = 1;
CDROM_CONFIG_FLAGS (drive)->nec260 = 1;
}
else if (strcmp (drive->id->model, "WEARNES CDD-120") == 0 &&
} else if (strcmp (drive->id->model, "WEARNES CDD-120") == 0 &&
strncmp (drive->id->fw_rev, "A1.1", 4) == 0) { /* FIXME */
/* Wearnes */
CDROM_CONFIG_FLAGS (drive)->playmsf_as_bcd = 1;
......@@ -2989,7 +2972,7 @@ int ide_cdrom_init(void)
kfree (info);
continue;
}
memset (info, 0, sizeof (struct cdrom_info));
memset(info, 0, sizeof (struct cdrom_info));
drive->driver_data = info;
MOD_INC_USE_COUNT;
......
......@@ -15,7 +15,7 @@
memory, though. */
#ifndef VERBOSE_IDE_CD_ERRORS
#define VERBOSE_IDE_CD_ERRORS 1
# define VERBOSE_IDE_CD_ERRORS 1
#endif
......@@ -24,7 +24,7 @@
this will give you a slightly smaller kernel. */
#ifndef STANDARD_ATAPI
#define STANDARD_ATAPI 0
# define STANDARD_ATAPI 0
#endif
......@@ -32,14 +32,14 @@
This is apparently needed for supermount. */
#ifndef NO_DOOR_LOCKING
#define NO_DOOR_LOCKING 0
# define NO_DOOR_LOCKING 0
#endif
/************************************************************************/
#define SECTOR_BITS 9
#define SECTOR_BITS 9
#ifndef SECTOR_SIZE
#define SECTOR_SIZE (1 << SECTOR_BITS)
# define SECTOR_SIZE (1 << SECTOR_BITS)
#endif
#define SECTORS_PER_FRAME (CD_FRAMESIZE >> SECTOR_BITS)
#define SECTOR_BUFFER_SIZE (CD_FRAMESIZE * 32)
......@@ -50,12 +50,6 @@
#define MIN(a,b) ((a) < (b) ? (a) : (b))
/* special command codes for strategy routine. */
#define PACKET_COMMAND 4315
#define REQUEST_SENSE_COMMAND 4316
#define RESET_DRIVE_COMMAND 4317
/* Configuration flags. These describe the capabilities of the drive.
They generally do not change after initialization, unless we learn
more about the drive from stuff failing. */
......@@ -90,7 +84,6 @@ struct ide_cd_config_flags {
};
#define CDROM_CONFIG_FLAGS(drive) (&(((struct cdrom_info *)(drive->driver_data))->config_flags))
/* State flags. These give information about the current state of the
drive, and will change during normal operation. */
struct ide_cd_state_flags {
......@@ -111,24 +104,23 @@ struct packet_command {
int quiet;
int timeout;
struct request_sense *sense;
unsigned char c[12];
};
/* Structure of a MSF cdrom address. */
struct atapi_msf {
byte reserved;
byte minute;
byte second;
byte frame;
};
u8 __reserved;
u8 minute;
u8 second;
u8 frame;
} __attribute__((packed));
/* Space to hold the disk TOC. */
#define MAX_TRACKS 99
struct atapi_toc_header {
unsigned short toc_length;
byte first_track;
byte last_track;
};
u16 toc_length;
u8 first_track;
u8 last_track;
} __attribute__((packed));
struct atapi_toc_entry {
byte reserved1;
......@@ -162,17 +154,17 @@ struct atapi_toc {
/* This structure is annoyingly close to, but not identical with,
the cdrom_subchnl structure from cdrom.h. */
struct atapi_cdrom_subchnl {
u_char acdsc_reserved;
u_char acdsc_audiostatus;
u_short acdsc_length;
u_char acdsc_format;
u8 acdsc_reserved;
u8 acdsc_audiostatus;
u16 acdsc_length;
u8 acdsc_format;
#if defined(__BIG_ENDIAN_BITFIELD)
u_char acdsc_ctrl: 4;
u_char acdsc_adr: 4;
u8 acdsc_ctrl: 4;
u8 acdsc_adr: 4;
#elif defined(__LITTLE_ENDIAN_BITFIELD)
u_char acdsc_adr: 4;
u_char acdsc_ctrl: 4;
u8 acdsc_adr: 4;
u8 acdsc_ctrl: 4;
#else
#error "Please fix <asm/byteorder.h>"
#endif
......
......@@ -107,10 +107,7 @@ static u8 get_command(ide_drive_t *drive, int cmd)
* 48-bit commands are pretty sanely laid out
*/
if (lba48bit) {
if (cmd == READ)
command = WIN_READ_EXT;
else
command = WIN_WRITE_EXT;
command = cmd == READ ? WIN_READ_EXT : WIN_WRITE_EXT;
if (drive->using_dma) {
command++; /* WIN_*DMA_EXT */
......@@ -118,31 +115,33 @@ static u8 get_command(ide_drive_t *drive, int cmd)
command++; /* WIN_*DMA_QUEUED_EXT */
} else if (drive->mult_count)
command += 5; /* WIN_MULT*_EXT */
} else {
/*
* 28-bit commands seem not to be, though...
*/
if (cmd == READ) {
if (drive->using_dma) {
if (drive->using_tcq)
command = WIN_READDMA_QUEUED;
else
command = WIN_READDMA;
} else if (drive->mult_count)
command = WIN_MULTREAD;
return command;
}
/*
* 28-bit commands seem not to be, though...
*/
if (cmd == READ) {
if (drive->using_dma) {
if (drive->using_tcq)
command = WIN_READDMA_QUEUED;
else
command = WIN_READ;
} else {
if (drive->using_dma) {
if (drive->using_tcq)
command = WIN_WRITEDMA_QUEUED;
else
command = WIN_WRITEDMA;
} else if (drive->mult_count)
command = WIN_MULTWRITE;
command = WIN_READDMA;
} else if (drive->mult_count)
command = WIN_MULTREAD;
else
command = WIN_READ;
} else {
if (drive->using_dma) {
if (drive->using_tcq)
command = WIN_WRITEDMA_QUEUED;
else
command = WIN_WRITE;
}
command = WIN_WRITEDMA;
} else if (drive->mult_count)
command = WIN_MULTWRITE;
else
command = WIN_WRITE;
}
return command;
......@@ -895,24 +894,24 @@ static int proc_idedisk_read_tcq
__set_bit(i, &tag_mask);
len += sprintf(out+len, "%d, ", i);
if (ar->ar_time > max_jif)
max_jif = ar->ar_time;
if (cur_jif - ar->ar_time > max_jif)
max_jif = cur_jif - ar->ar_time;
cmds++;
}
len += sprintf(out+len, "]\n");
len += sprintf(out+len, "Queue:\t\t\treleased [ %d ] - started [ %d ]\n", drive->tcq->immed_rel, drive->tcq->immed_comp);
if (drive->tcq->queued != cmds)
len += sprintf(out+len, "pending request and queue count mismatch (%d)\n", cmds);
len += sprintf(out+len, "pending request and queue count mismatch (counted: %d)\n", cmds);
if (tag_mask != drive->tcq->tag_mask)
len += sprintf(out+len, "tag masks differ (counted %lx != %lx\n", tag_mask, drive->tcq->tag_mask);
len += sprintf(out+len, "DMA status:\t\t%srunning\n", test_bit(IDE_DMA, &HWGROUP(drive)->flags) ? "" : "not ");
if (max_jif)
len += sprintf(out+len, "Oldest command:\t\t%lu\n", cur_jif - max_jif);
len += sprintf(out+len, "immed rel %d, immed comp %d\n", drive->tcq->immed_rel, drive->tcq->immed_comp);
len += sprintf(out+len, "Oldest command:\t\t%lu jiffies\n", max_jif);
len += sprintf(out+len, "Oldest command ever:\t%lu\n", drive->tcq->oldest_command);
drive->tcq->max_last_depth = 0;
......@@ -1017,8 +1016,10 @@ static int set_using_tcq(ide_drive_t *drive, int arg)
return -EPERM;
if (!drive->channel->dmaproc)
return -EPERM;
if (arg == drive->queue_depth && drive->using_tcq)
return 0;
drive->using_tcq = arg;
drive->queue_depth = arg ? arg : 1;
if (drive->channel->dmaproc(arg ? ide_dma_queued_on : ide_dma_queued_off, drive))
return -EIO;
......
......@@ -610,9 +610,6 @@ int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
case ide_dma_check:
return config_drive_for_dma (drive);
case ide_dma_begin:
#ifdef DEBUG
printk("ide_dma_begin: from %p\n", __builtin_return_address(0));
#endif
if (test_and_set_bit(IDE_DMA, &HWGROUP(drive)->flags))
BUG();
/* Note that this is done *after* the cmd has
......@@ -634,14 +631,13 @@ int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
case ide_dma_read:
reading = 1 << 3;
case ide_dma_write:
ar = HWGROUP(drive)->rq->special;
ar = IDE_CUR_AR(drive);
if (ide_start_dma(hwif, drive, func))
return 1;
if (drive->type != ATA_DISK)
return 0;
BUG_ON(HWGROUP(drive)->handler);
ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, dma_timer_expiry); /* issue cmd to drive */
if ((ar->ar_rq->flags & REQ_DRIVE_TASKFILE) &&
......@@ -655,20 +651,13 @@ int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
}
return hwif->dmaproc(ide_dma_begin, drive);
case ide_dma_end: /* returns 1 on error, 0 otherwise */
#ifdef DEBUG
printk("ide_dma_end: from %p\n", __builtin_return_address(0));
#endif
if (!test_and_clear_bit(IDE_DMA, &HWGROUP(drive)->flags)) {
printk("ide_dma_end: dma not going? %p\n", __builtin_return_address(0));
return 1;
}
if (!test_and_clear_bit(IDE_DMA, &HWGROUP(drive)->flags))
BUG();
drive->waiting_for_dma = 0;
outb(inb(dma_base)&~1, dma_base); /* stop DMA */
dma_stat = inb(dma_base+2); /* get DMA status */
outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */
ide_destroy_dmatable(drive); /* purge DMA mappings */
if (drive->tcq)
IDE_SET_CUR_TAG(drive, -1);
return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0; /* verify good DMA status */
case ide_dma_test_irq: /* returns 1 if dma irq issued, 0 otherwise */
dma_stat = inb(dma_base+2);
......
......@@ -192,19 +192,16 @@ static inline void do_identify (ide_drive_t *drive, byte cmd)
/*
* it's an ata drive, build command list
*/
#ifndef CONFIG_BLK_DEV_IDE_TCQ
drive->queue_depth = 1;
#ifdef CONFIG_BLK_DEV_IDE_TCQ_DEPTH
drive->queue_depth = CONFIG_BLK_DEV_IDE_TCQ_DEPTH;
#else
# ifndef CONFIG_BLK_DEV_IDE_TCQ_DEPTH
# define CONFIG_BLK_DEV_IDE_TCQ_DEPTH 1
# endif
drive->queue_depth = drive->id->queue_depth + 1;
if (drive->queue_depth > CONFIG_BLK_DEV_IDE_TCQ_DEPTH)
drive->queue_depth = CONFIG_BLK_DEV_IDE_TCQ_DEPTH;
#endif
if (drive->queue_depth < 1 || drive->queue_depth > IDE_MAX_TAG)
drive->queue_depth = IDE_MAX_TAG;
#endif
if (ide_build_commandlist(drive))
if (ide_init_commandlist(drive))
goto err_misc;
return;
......
......@@ -980,7 +980,7 @@ int ide_cmd_ioctl(ide_drive_t *drive, unsigned long arg)
/* FIXME: Do we really have to zero out the buffer?
*/
memset(argbuf, 0, 4 + SECTOR_WORDS * 4 * vals[3]);
memset(argbuf, 4, SECTOR_WORDS * 4 * vals[3]);
ide_init_drive_cmd(&rq);
rq.buffer = argbuf;
memcpy(argbuf, vals, 4);
......
......@@ -29,9 +29,11 @@
#include <asm/delay.h>
/*
* warning: it will be _very_ verbose if set to 1
* warning: it will be _very_ verbose if defined
*/
#if 0
#undef IDE_TCQ_DEBUG
#ifdef IDE_TCQ_DEBUG
#define TCQ_PRINTK printk
#else
#define TCQ_PRINTK(x...)
......@@ -49,13 +51,18 @@
*/
#undef IDE_TCQ_FIDDLE_SI
int ide_tcq_end(ide_drive_t *drive);
/*
* wait for data phase before starting DMA or not
*/
#undef IDE_TCQ_WAIT_DATAPHASE
ide_startstop_t ide_dmaq_intr(ide_drive_t *drive);
ide_startstop_t ide_service(ide_drive_t *drive);
static inline void drive_ctl_nien(ide_drive_t *drive, int clear)
{
#ifdef IDE_TCQ_NIEN
int mask = clear ? 0 : 2;
int mask = clear ? 0x00 : 0x02;
if (IDE_CONTROL_REG)
OUT_BYTE(drive->ctl | mask, IDE_CONTROL_REG);
......@@ -142,7 +149,7 @@ void ide_tcq_intr_timeout(unsigned long data)
spin_lock_irqsave(&ide_lock, flags);
if (test_bit(IDE_BUSY, &hwgroup->flags))
if (test_and_set_bit(IDE_BUSY, &hwgroup->flags))
printk("ide_tcq_intr_timeout: hwgroup not busy\n");
if (hwgroup->handler == NULL)
printk("ide_tcq_intr_timeout: missing isr!\n");
......@@ -151,6 +158,13 @@ void ide_tcq_intr_timeout(unsigned long data)
spin_unlock_irqrestore(&ide_lock, flags);
/*
* if pending commands, try service before giving up
*/
if (ide_pending_commands(drive) && (GET_STAT() & SERVICE_STAT))
if (ide_service(drive) == ide_started)
return;
if (drive)
ide_tcq_invalidate_queue(drive);
}
......@@ -192,6 +206,7 @@ int ide_tcq_wait_altstat(ide_drive_t *drive, byte *stat, byte busy_mask)
if (unlikely(i++ > IDE_TCQ_WAIT))
return 1;
} while ((*stat = GET_ALTSTAT()) & busy_mask);
return 0;
......@@ -206,7 +221,12 @@ int ide_tcq_wait_altstat(ide_drive_t *drive, byte *stat, byte busy_mask)
ide_startstop_t ide_service(ide_drive_t *drive)
{
struct ata_request *ar;
byte feat, tag, stat;
byte feat, stat;
int tag;
TCQ_PRINTK("%s: started service\n", drive->name);
drive->service_pending = 0;
if (test_bit(IDE_DMA, &HWGROUP(drive)->flags))
printk("ide_service: DMA in progress\n");
......@@ -238,9 +258,9 @@ ide_startstop_t ide_service(ide_drive_t *drive)
* FIXME, invalidate queue
*/
if (stat & ERR_STAT) {
printk("%s: error SERVICING drive (%x)\n", drive->name, stat);
ide_dump_status(drive, "ide_service", stat);
return ide_tcq_end(drive);
ide_tcq_invalidate_queue(drive);
return ide_stopped;
}
/*
......@@ -248,7 +268,7 @@ ide_startstop_t ide_service(ide_drive_t *drive)
*/
if ((feat = GET_FEAT()) & NSEC_REL) {
printk("%s: release in service\n", drive->name);
IDE_SET_CUR_TAG(drive, -1);
IDE_SET_CUR_TAG(drive, IDE_INACTIVE_TAG);
return ide_stopped;
}
......@@ -265,6 +285,8 @@ ide_startstop_t ide_service(ide_drive_t *drive)
return ide_stopped;
}
HWGROUP(drive)->rq = ar->ar_rq;
/*
* we'll start a dma read or write, device will trigger
* interrupt to indicate end of transfer, release is not allowed
......@@ -287,6 +309,8 @@ ide_startstop_t ide_check_service(ide_drive_t *drive)
{
byte stat;
TCQ_PRINTK("%s: ide_check_service\n", drive->name);
if (!ide_pending_commands(drive))
return ide_stopped;
......@@ -300,40 +324,14 @@ ide_startstop_t ide_check_service(ide_drive_t *drive)
return ide_started;
}
int ide_tcq_end(ide_drive_t *drive)
{
byte stat = GET_STAT();
if (stat & ERR_STAT) {
ide_dump_status(drive, "ide_tcq_end", stat);
ide_tcq_invalidate_queue(drive);
return ide_stopped;
} else if (stat & SERVICE_STAT) {
TCQ_PRINTK("ide_tcq_end: serv stat=%x\n", stat);
return ide_service(drive);
}
TCQ_PRINTK("ide_tcq_end: stat=%x, feat=%x\n", stat, GET_FEAT());
return ide_stopped;
}
ide_startstop_t ide_dmaq_complete(ide_drive_t *drive, byte stat)
{
struct ata_request *ar;
struct ata_request *ar = IDE_CUR_TAG(drive);
byte dma_stat;
#if 0
byte feat = GET_FEAT();
if ((feat & (NSEC_CD | NSEC_IO)) != (NSEC_CD | NSEC_IO))
printk("%s: C/D | I/O not set\n", drive->name);
#endif
/*
* transfer was in progress, stop DMA engine
*/
ar = IDE_CUR_TAG(drive);
dma_stat = drive->channel->dmaproc(ide_dma_end, drive);
/*
......@@ -352,7 +350,23 @@ ide_startstop_t ide_dmaq_complete(ide_drive_t *drive, byte stat)
TCQ_PRINTK("ide_dmaq_intr: ending %p, tag %d\n", ar, ar->ar_tag);
ide_end_queued_request(drive, !dma_stat, ar->ar_rq);
IDE_SET_CUR_TAG(drive, -1);
IDE_SET_CUR_TAG(drive, IDE_INACTIVE_TAG);
/*
* keep the queue full, or honor SERVICE? note that this may race
* and no new command will be started, in which case idedisk_do_request
* will notice and do the service check
*/
#if CONFIG_BLK_DEV_IDE_TCQ_FULL
if (!drive->service_pending && (ide_pending_commands(drive) > 1)) {
if (!blk_queue_empty(&drive->queue)) {
drive->service_pending = 1;
ide_tcq_set_intr(HWGROUP(drive), ide_dmaq_intr);
return ide_released;
}
}
#endif
return ide_check_service(drive);
}
......@@ -376,7 +390,7 @@ ide_startstop_t ide_dmaq_intr(ide_drive_t *drive)
* if a command completion interrupt is pending, do that first and
* check service afterwards
*/
if (drive->tcq->active_tag != -1)
if (drive->tcq->active_tag != IDE_INACTIVE_TAG)
return ide_dmaq_complete(drive, stat);
/*
......@@ -403,10 +417,8 @@ static int ide_tcq_configure(ide_drive_t *drive)
* bit 14 and 1 must be set in word 83 of the device id to indicate
* support for dma queued protocol
*/
if ((drive->id->command_set_2 & tcq_supp) != tcq_supp) {
printk("%s: queued feature set not supported\n", drive->name);
return 1;
}
if ((drive->id->command_set_2 & tcq_supp) != tcq_supp)
return -EIO;
memset(&args, 0, sizeof(args));
args.taskfile.feature = SETFEATURES_EN_WCACHE;
......@@ -446,6 +458,16 @@ static int ide_tcq_configure(ide_drive_t *drive)
return 1;
}
#endif
if (!drive->tcq) {
drive->tcq = kmalloc(sizeof(ide_tag_info_t), GFP_ATOMIC);
if (!drive->tcq)
return -ENOMEM;
memset(drive->tcq, 0, sizeof(ide_tag_info_t));
drive->tcq->active_tag = IDE_INACTIVE_TAG;
}
return 0;
}
......@@ -461,26 +483,33 @@ static int ide_enable_queued(ide_drive_t *drive, int on)
if (!on) {
printk("%s: TCQ disabled\n", drive->name);
drive->using_tcq = 0;
return 0;
} else if (drive->using_tcq) {
drive->queue_depth = drive->using_tcq;
goto out;
}
if (ide_tcq_configure(drive)) {
drive->using_tcq = 0;
return 1;
}
out:
drive->tcq->max_depth = 0;
if (ide_build_commandlist(drive))
return 1;
printk("%s: tagged command queueing enabled, command queue depth %d\n", drive->name, drive->queue_depth);
drive->using_tcq = 1;
drive->tcq->max_depth = 0;
return 0;
}
int ide_tcq_wait_dataphase(ide_drive_t *drive)
{
#ifdef IDE_TCQ_WAIT_DATAPHASE
ide_startstop_t foo;
if (ide_wait_stat(&startstop, drive, READY_STAT | DRQ_STAT, BUSY_STAT, WAIT_READY)) {
printk("%s: timeout waiting for data phase\n", drive->name);
return 1;
}
#endif
return 0;
}
......@@ -488,7 +517,6 @@ int ide_tcq_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
{
struct ata_channel *hwif = drive->channel;
unsigned int reading = 0, enable_tcq = 1;
ide_startstop_t startstop;
struct ata_request *ar;
byte stat, feat;
......@@ -501,15 +529,13 @@ int ide_tcq_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
reading = 1 << 3;
case ide_dma_write_queued:
TCQ_PRINTK("ide_dma: setting up queued %d\n", drive->tcq->active_tag);
BUG_ON(drive->tcq->active_tag == -1);
BUG_ON(drive->tcq->active_tag == IDE_INACTIVE_TAG);
if (!test_bit(IDE_BUSY, &HWGROUP(drive)->flags))
printk("queued_rw: IDE_BUSY not set\n");
if (ide_wait_stat(&startstop, drive, READY_STAT | DRQ_STAT, BUSY_STAT, WAIT_READY)) {
printk("%s: timeout waiting for data phase\n", drive->name);
return startstop;
}
if (ide_tcq_wait_dataphase(drive))
return ide_stopped;
if (ide_start_dma(hwif, drive, func))
return 1;
......@@ -521,7 +547,7 @@ int ide_tcq_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
* start a queued command from scratch
*/
case ide_dma_queued_start:
BUG_ON(drive->tcq->active_tag == -1);
BUG_ON(drive->tcq->active_tag == IDE_INACTIVE_TAG);
ar = IDE_CUR_TAG(drive);
/*
......@@ -540,14 +566,19 @@ int ide_tcq_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
drive_ctl_nien(drive, 0);
if (stat & ERR_STAT) {
printk("ide_dma_queued_start: abort (stat=%x)\n", stat);
ide_dump_status(drive, "tcq_start", stat);
return ide_stopped;
}
/*
* drive released the bus, clear active tag and
* check for service
*/
if ((feat = GET_FEAT()) & NSEC_REL) {
IDE_SET_CUR_TAG(drive, IDE_INACTIVE_TAG);
drive->tcq->immed_rel++;
TCQ_PRINTK("REL in queued_start\n");
IDE_SET_CUR_TAG(drive, -1);
if ((stat = GET_STAT()) & SERVICE_STAT)
return ide_service(drive);
......@@ -558,21 +589,24 @@ int ide_tcq_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
drive->tcq->immed_comp++;
if (ide_wait_stat(&startstop, drive, READY_STAT | DRQ_STAT, BUSY_STAT, WAIT_READY)) {
printk("%s: timeout waiting for data phase\n", drive->name);
return startstop;
}
if (ide_tcq_wait_dataphase(drive))
return ide_stopped;
if (ide_start_dma(hwif, drive, func))
return ide_stopped;
/*
* need to arm handler before starting dma engine,
* transfer could complete right away
*/
ide_tcq_set_intr(HWGROUP(drive), ide_dmaq_intr);
if (hwif->dmaproc(ide_dma_begin, drive))
return ide_stopped;
/*
* wait for SERVICE or completion interrupt
*/
ide_tcq_set_intr(HWGROUP(drive), ide_dmaq_intr);
return ide_started;
case ide_dma_queued_off:
......@@ -590,6 +624,10 @@ int ide_build_sglist (struct ata_channel *hwif, struct request *rq);
ide_startstop_t ide_start_tag(ide_dma_action_t func, ide_drive_t *drive,
struct ata_request *ar)
{
ide_startstop_t startstop;
TCQ_PRINTK("%s: ide_start_tag: begin tag %p/%d, rq %p\n", drive->name,ar,ar->ar_tag, ar->ar_rq);
/*
* do this now, no need to run that with interrupts disabled
*/
......@@ -597,5 +635,14 @@ ide_startstop_t ide_start_tag(ide_dma_action_t func, ide_drive_t *drive,
return ide_stopped;
IDE_SET_CUR_TAG(drive, ar->ar_tag);
return ide_tcq_dmaproc(func, drive);
HWGROUP(drive)->rq = ar->ar_rq;
startstop = ide_tcq_dmaproc(func, drive);
if (unlikely(startstop == ide_stopped)) {
IDE_SET_CUR_TAG(drive, IDE_INACTIVE_TAG);
HWGROUP(drive)->rq = NULL;
}
return startstop;
}
......@@ -381,8 +381,23 @@ void ide_end_queued_request(ide_drive_t *drive, int uptodate, struct request *rq
add_blkdev_randomness(major(rq->rq_dev));
spin_lock_irqsave(&ide_lock, flags);
if ((jiffies - ar->ar_time > ATA_AR_MAX_TURNAROUND) && drive->queue_depth > 1) {
printk("%s: exceeded max command turn-around time (%d seconds)\n", drive->name, ATA_AR_MAX_TURNAROUND / HZ);
drive->queue_depth >>= 1;
}
if (jiffies - ar->ar_time > drive->tcq->oldest_command)
drive->tcq->oldest_command = jiffies - ar->ar_time;
ata_ar_put(drive, ar);
end_that_request_last(rq);
/*
* IDE_SET_CUR_TAG(drive, IDE_INACTIVE_TAG) will do this
* too, but it really belongs here. assumes that the
* ended request is the active one.
*/
HWGROUP(drive)->rq = NULL;
spin_unlock_irqrestore(&ide_lock, flags);
}
}
......@@ -770,8 +785,7 @@ void ide_end_drive_cmd(ide_drive_t *drive, byte stat, byte err)
struct ata_taskfile *args = &ar->ar_task;
rq->errors = !OK_STAT(stat, READY_STAT, BAD_STAT);
if (args && args->taskfile.command == WIN_NOP)
printk(KERN_INFO "%s: NOP completed\n", __FUNCTION__);
if (args) {
args->taskfile.feature = err;
args->taskfile.sector_count = IN_BYTE(IDE_NSECTOR_REG);
......@@ -1101,11 +1115,7 @@ static ide_startstop_t start_request(ide_drive_t *drive, struct request *rq)
while ((read_timer() - hwif->last_time) < DISK_RECOVERY_TIME);
#endif
if (test_bit(IDE_DMA, &HWGROUP(drive)->flags))
printk("start_request: auch, DMA in progress 1\n");
SELECT_DRIVE(hwif, drive);
if (test_bit(IDE_DMA, &HWGROUP(drive)->flags))
printk("start_request: auch, DMA in progress 2\n");
if (ide_wait_stat(&startstop, drive, drive->ready_stat,
BUSY_STAT|DRQ_STAT, WAIT_READY)) {
printk(KERN_WARNING "%s: drive not ready for command\n", drive->name);
......@@ -1277,6 +1287,170 @@ static inline ide_drive_t *choose_drive(ide_hwgroup_t *hwgroup)
return best;
}
static ide_drive_t *ide_choose_drive(ide_hwgroup_t *hwgroup)
{
ide_drive_t *drive = choose_drive(hwgroup);
unsigned long sleep = 0;
if (drive)
return drive;
hwgroup->rq = NULL;
drive = hwgroup->drive;
do {
if (drive->PADAM_sleep && (!sleep || time_after(sleep, drive->PADAM_sleep)))
sleep = drive->PADAM_sleep;
} while ((drive = drive->next) != hwgroup->drive);
if (sleep) {
/*
* Take a short snooze, and then wake up this hwgroup
* again. This gives other hwgroups on the same a
* chance to play fairly with us, just in case there
* are big differences in relative throughputs.. don't
* want to hog the cpu too much.
*/
if (0 < (signed long)(jiffies + WAIT_MIN_SLEEP - sleep))
sleep = jiffies + WAIT_MIN_SLEEP;
if (timer_pending(&hwgroup->timer))
printk("ide_set_handler: timer already active\n");
set_bit(IDE_SLEEP, &hwgroup->flags);
mod_timer(&hwgroup->timer, sleep);
/* we purposely leave hwgroup busy while
* sleeping */
} else {
/* Ugly, but how can we sleep for the lock
* otherwise? perhaps from tq_disk? */
ide_release_lock(&ide_intr_lock);/* for atari only */
clear_bit(IDE_BUSY, &hwgroup->flags);
}
return NULL;
}
#ifdef CONFIG_BLK_DEV_IDE_TCQ
ide_startstop_t ide_check_service(ide_drive_t *drive);
#else
#define ide_check_service(drive) (ide_stopped)
#endif
/*
* feed commands to a drive until it barfs. used to be part of ide_do_request.
* called with ide_lock/DRIVE_LOCK held and busy hwgroup
*/
static void ide_queue_commands(ide_drive_t *drive, int masked_irq)
{
ide_hwgroup_t *hwgroup = HWGROUP(drive);
ide_startstop_t startstop = -1;
struct request *rq;
int do_service = 0;
do {
rq = NULL;
if (!test_bit(IDE_BUSY, &hwgroup->flags))
printk("%s: hwgroup not busy while queueing\n", drive->name);
/*
* abort early if we can't queue another command. for non
* tcq, ide_can_queue is always 1 since we never get here
* unless the drive is idle.
*/
if (!ide_can_queue(drive)) {
if (!ide_pending_commands(drive))
clear_bit(IDE_BUSY, &hwgroup->flags);
break;
}
drive->PADAM_sleep = 0;
drive->PADAM_service_start = jiffies;
if (test_bit(IDE_DMA, &hwgroup->flags)) {
printk("ide_do_request: DMA in progress...\n");
break;
}
/*
* there's a small window between where the queue could be
* replugged while we are in here when using tcq (in which
* case the queue is probably empty anyways...), so check
* and leave if appropriate. When not using tcq, this is
* still a severe BUG!
*/
if (blk_queue_plugged(&drive->queue)) {
BUG_ON(!drive->using_tcq);
break;
}
if (!(rq = elv_next_request(&drive->queue))) {
if (!ide_pending_commands(drive))
clear_bit(IDE_BUSY, &hwgroup->flags);
hwgroup->rq = NULL;
break;
}
/*
* if there are queued commands, we can't start a non-fs
* request (really, a non-queuable command) until the
* queue is empty
*/
if (!(rq->flags & REQ_CMD) && ide_pending_commands(drive))
break;
hwgroup->rq = rq;
service:
/*
* Some systems have trouble with IDE IRQs arriving while
* the driver is still setting things up. So, here we disable
* the IRQ used by this interface while the request is being
* started. This may look bad at first, but pretty much the
* same thing happens anyway when any interrupt comes in, IDE
* or otherwise -- the kernel masks the IRQ while it is being
* handled.
*/
if (masked_irq && HWIF(drive)->irq != masked_irq)
disable_irq_nosync(HWIF(drive)->irq);
spin_unlock(&ide_lock);
ide__sti(); /* allow other IRQs while we start this request */
if (!do_service)
startstop = start_request(drive, rq);
else
startstop = ide_check_service(drive);
spin_lock_irq(&ide_lock);
if (masked_irq && HWIF(drive)->irq != masked_irq)
enable_irq(HWIF(drive)->irq);
/*
* command started, we are busy
*/
if (startstop == ide_started)
break;
/*
* start_request() can return either ide_stopped (no command
* was started), ide_started (command started, don't queue
* more), or ide_released (command started, try and queue
* more).
*/
#if 0
if (startstop == ide_stopped)
set_bit(IDE_BUSY, &hwgroup->flags);
#endif
} while (1);
if (startstop == ide_started)
return;
if ((do_service = drive->service_pending))
goto service;
}
/*
* Issue a new request to a drive from hwgroup
* Caller must have already done spin_lock_irqsave(&ide_lock, ...)
......@@ -1311,115 +1485,34 @@ static void ide_do_request(ide_hwgroup_t *hwgroup, int masked_irq)
{
ide_drive_t *drive;
struct ata_channel *hwif;
ide_startstop_t startstop;
struct request *rq;
ide_get_lock(&ide_intr_lock, ide_intr, hwgroup);/* for atari only: POSSIBLY BROKEN HERE(?) */
__cli(); /* necessary paranoia: ensure IRQs are masked on local CPU */
while (!test_and_set_bit(IDE_BUSY, &hwgroup->flags)) {
drive = choose_drive(hwgroup);
if (drive == NULL) {
unsigned long sleep = 0;
hwgroup->rq = NULL;
drive = hwgroup->drive;
do {
if (drive->PADAM_sleep && (!sleep || time_after(sleep, drive->PADAM_sleep)))
sleep = drive->PADAM_sleep;
} while ((drive = drive->next) != hwgroup->drive);
if (sleep) {
/*
* Take a short snooze, and then wake up this hwgroup again.
* This gives other hwgroups on the same a chance to
* play fairly with us, just in case there are big differences
* in relative throughputs.. don't want to hog the cpu too much.
*/
if (0 < (signed long)(jiffies + WAIT_MIN_SLEEP - sleep))
sleep = jiffies + WAIT_MIN_SLEEP;
#if 1
if (timer_pending(&hwgroup->timer))
printk("ide_set_handler: timer already active\n");
#endif
set_bit(IDE_SLEEP, &hwgroup->flags);
mod_timer(&hwgroup->timer, sleep);
/* we purposely leave hwgroup busy while sleeping */
} else {
/* Ugly, but how can we sleep for the lock otherwise? perhaps from tq_disk? */
ide_release_lock(&ide_intr_lock);/* for atari only */
clear_bit(IDE_BUSY, &hwgroup->flags);
}
return; /* no more work for this hwgroup (for now) */
}
/*
* will clear IDE_BUSY, if appropriate
*/
if ((drive = ide_choose_drive(hwgroup)) == NULL)
break;
hwif = drive->channel;
if (hwgroup->hwif->sharing_irq && hwif != hwgroup->hwif && hwif->io_ports[IDE_CONTROL_OFFSET]) {
if (hwgroup->hwif->sharing_irq && hwif != hwgroup->hwif && IDE_CONTROL_REG) {
/* set nIEN for previous hwif */
if (hwif->intrproc)
hwif->intrproc(drive);
else
OUT_BYTE((drive)->ctl|2, hwif->io_ports[IDE_CONTROL_OFFSET]);
OUT_BYTE(drive->ctl|2, IDE_CONTROL_REG);
}
hwgroup->hwif = hwif;
hwgroup->drive = drive;
drive->PADAM_sleep = 0;
queue_next:
drive->PADAM_service_start = jiffies;
if (test_bit(IDE_DMA, &hwgroup->flags)) {
printk("ide_do_request: DMA in progress...\n");
break;
}
/*
* there's a small window between where the queue could be
* replugged while we are in here when using tcq (in which
* case the queue is probably empty anyways...), so check
* and leave if appropriate. When not using tcq, this is
* still a severe BUG!
* main queueing loop
*/
if (blk_queue_plugged(&drive->queue)) {
BUG_ON(!drive->using_tcq);
break;
}
/*
* just continuing an interrupted request maybe
*/
rq = hwgroup->rq = elv_next_request(&drive->queue);
if (!rq) {
if (!ide_pending_commands(drive))
clear_bit(IDE_BUSY, &HWGROUP(drive)->flags);
break;
}
/*
* Some systems have trouble with IDE IRQs arriving while
* the driver is still setting things up. So, here we disable
* the IRQ used by this interface while the request is being started.
* This may look bad at first, but pretty much the same thing
* happens anyway when any interrupt comes in, IDE or otherwise
* -- the kernel masks the IRQ while it is being handled.
*/
if (masked_irq && hwif->irq != masked_irq)
disable_irq_nosync(hwif->irq);
spin_unlock(&ide_lock);
ide__sti(); /* allow other IRQs while we start this request */
startstop = start_request(drive, rq);
spin_lock_irq(&ide_lock);
if (masked_irq && hwif->irq != masked_irq)
enable_irq(hwif->irq);
if (startstop == ide_released)
goto queue_next;
else if (startstop == ide_stopped) {
if (test_bit(IDE_DMA, &hwgroup->flags))
printk("2nd illegal clear\n");
clear_bit(IDE_BUSY, &hwgroup->flags);
}
ide_queue_commands(drive, masked_irq);
}
}
......@@ -1673,6 +1766,7 @@ void ide_intr(int irq, void *dev_id, struct pt_regs *regs)
goto out_lock;
if ((handler = hwgroup->handler) == NULL || hwgroup->poll_timeout != 0) {
printk("ide: unexpected interrupt\n");
/*
* Not expecting an interrupt from this drive.
* That means this could be:
......@@ -1751,7 +1845,8 @@ void ide_intr(int irq, void *dev_id, struct pt_regs *regs)
} else {
printk("%s: ide_intr: huh? expected NULL handler on exit\n", drive->name);
}
}
} else if (startstop == ide_released)
ide_queue_commands(drive, hwif->irq);
out_lock:
spin_unlock_irqrestore(&ide_lock, flags);
......@@ -2221,6 +2316,8 @@ void ide_unregister(struct ata_channel *channel)
channel->udma_four = old_hwif.udma_four;
#ifdef CONFIG_BLK_DEV_IDEPCI
channel->pci_dev = old_hwif.pci_dev;
#else
channel->pci_dev = NULL;
#endif
channel->straight8 = old_hwif.straight8;
abort:
......@@ -2699,42 +2796,33 @@ static int ide_ioctl (struct inode *inode, struct file *file,
}
}
void ide_teardown_commandlist(ide_drive_t *drive)
{
struct pci_dev *pdev= drive->channel->pci_dev;
struct list_head *entry;
list_for_each(entry, &drive->free_req) {
struct ata_request *ar = list_ata_entry(entry);
list_del(&ar->ar_queue);
kfree(ar->ar_sg_table);
pci_free_consistent(pdev, PRD_SEGMENTS * PRD_BYTES, ar->ar_dmatable_cpu, ar->ar_dmatable);
kfree(ar);
}
}
int ide_build_commandlist(ide_drive_t *drive)
{
struct pci_dev *pdev= drive->channel->pci_dev;
#ifdef CONFIG_BLK_DEV_IDEPCI
struct pci_dev *pdev = drive->channel->pci_dev;
#else
struct pci_dev *pdev = NULL;
#endif
struct list_head *p;
unsigned long flags;
struct ata_request *ar;
ide_tag_info_t *tcq;
int i, err;
int i, cur;
tcq = kmalloc(sizeof(ide_tag_info_t), GFP_ATOMIC);
if (!tcq)
return -ENOMEM;
spin_lock_irqsave(&ide_lock, flags);
drive->tcq = tcq;
memset(drive->tcq, 0, sizeof(ide_tag_info_t));
cur = 0;
list_for_each(p, &drive->free_req)
cur++;
INIT_LIST_HEAD(&drive->free_req);
drive->using_tcq = 0;
/*
* for now, just don't shrink it...
*/
if (drive->queue_depth <= cur) {
spin_unlock_irqrestore(&ide_lock, flags);
return 0;
}
err = -ENOMEM;
for (i = 0; i < drive->queue_depth; i++) {
/* Having kzmalloc would help reduce code size at quite
* many places in kernel. */
for (i = cur; i < drive->queue_depth; i++) {
ar = kmalloc(sizeof(*ar), GFP_ATOMIC);
if (!ar)
break;
......@@ -2759,25 +2847,33 @@ int ide_build_commandlist(ide_drive_t *drive)
* pheew, all done, add to list
*/
list_add_tail(&ar->ar_queue, &drive->free_req);
++cur;
}
drive->queue_depth = cur;
spin_unlock_irqrestore(&ide_lock, flags);
return 0;
}
if (i) {
drive->queue_depth = i;
if (i >= 1) {
drive->using_tcq = 1;
drive->tcq->queued = 0;
drive->tcq->active_tag = -1;
return 0;
}
int ide_init_commandlist(ide_drive_t *drive)
{
INIT_LIST_HEAD(&drive->free_req);
kfree(drive->tcq);
drive->tcq = NULL;
err = 0;
}
return ide_build_commandlist(drive);
}
kfree(drive->tcq);
drive->tcq = NULL;
return err;
void ide_teardown_commandlist(ide_drive_t *drive)
{
struct pci_dev *pdev= drive->channel->pci_dev;
struct list_head *entry;
list_for_each(entry, &drive->free_req) {
struct ata_request *ar = list_ata_entry(entry);
list_del(&ar->ar_queue);
kfree(ar->ar_sg_table);
pci_free_consistent(pdev, PRD_SEGMENTS * PRD_BYTES, ar->ar_dmatable_cpu, ar->ar_dmatable);
kfree(ar);
}
}
static int ide_check_media_change (kdev_t i_rdev)
......@@ -3038,7 +3134,7 @@ int __init ide_setup (char *s)
unit = unit % MAX_DRIVES;
hwif = &ide_hwifs[hw];
drive = &hwif->drives[unit];
if (strncmp(s + 4, "ide-", 4) == 0) {
if (!strncmp(s + 4, "ide-", 4)) {
strncpy(drive->driver_req, s + 4, 9);
goto done;
}
......@@ -3120,7 +3216,7 @@ int __init ide_setup (char *s)
/*
* Look for bus speed option: "idebus="
*/
if (strncmp(s, "idebus", 6)) {
if (!strncmp(s, "idebus", 6)) {
if (match_parm(&s[6], NULL, vals, 1) != 1)
goto bad_option;
if (vals[0] >= 20 && vals[0] <= 66) {
......
......@@ -648,6 +648,12 @@ ide_startstop_t promise_rw_disk (ide_drive_t *drive, struct request *rq, unsigne
memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
/* The four drives on the two logical (one physical) interfaces
are distinguished by writing the drive number (0-3) to the
Feature register.
FIXME: Is promise_selectproc now redundant??
*/
taskfile.feature = (drive->channel->unit << 1) + drive->select.b.unit;
taskfile.sector_count = rq->nr_sectors;
taskfile.sector_number = block;
taskfile.low_cylinder = (block>>=8);
......
......@@ -1704,8 +1704,8 @@ cyberpro_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
* Use MCLK from BIOS. FIXME: what about hotplug?
*/
#ifndef __arm__
cfb->mclk_mult = cyber2000_grphr(MCLK_MULT, cfb);
cfb->mclk_div = cyber2000_grphr(MCLK_DIV, cfb);
cfb->mclk_mult = cyber2000_grphr(EXT_MCLK_MULT, cfb);
cfb->mclk_div = cyber2000_grphr(EXT_MCLK_DIV, cfb);
#else
/*
* MCLK on the NetWinder and the Shark is fixed at 75MHz
......
......@@ -2365,7 +2365,7 @@ int __init neofb_setup (char *options)
if (!options || !*options)
return 0;
for (this_opt=strtok(options,","); this_opt; this_opt=strtok(NULL,","))
while ((this_opt = strsep(&options,",")) != NULL)
{
if (!*this_opt) continue;
......
......@@ -11,8 +11,7 @@
static inline void arch_idle(void)
{
#if 0
if (!hlt_counter)
cpu_do_idle(0);
cpu_do_idle();
#endif
}
......
......@@ -15,8 +15,7 @@
#ifndef __ASM_ARCH_SYSTEM_H
#define __ASM_ARCH_SYSTEM_H
static inline void
arch_idle(void)
static inline void arch_idle(void)
{
}
......
......@@ -8,9 +8,8 @@
* published by the Free Software Foundation.
*/
static void arch_idle(void)
static inline void arch_idle(void)
{
while (!need_resched() && !hlt_counter);
}
static inline void arch_reset(char mode)
......
......@@ -7,11 +7,11 @@
#define __ASM_ARCH_SYSTEM_H
#include <asm/hardware/iomd.h>
#include <asm/io.h>
static void arch_idle(void)
static inline void arch_idle(void)
{
while (!need_resched() && !hlt_counter)
iomd_writeb(0, IOMD_SUSMODE);
iomd_writeb(0, IOMD_SUSMODE);
}
#define arch_reset(mode) \
......
......@@ -22,7 +22,7 @@
#include <asm/hardware/clps7111.h>
static void arch_idle(void)
static inline void arch_idle(void)
{
clps_writel(1, HALT);
__asm__ __volatile__(
......
......@@ -20,31 +20,18 @@
* Instead, we spin, polling the IRQ_STAT register for the occurrence
* of any interrupt with core clock down to the memory clock.
*/
static void arch_idle(void)
static inline void arch_idle(void)
{
const char *irq_stat = (char *)0xff000000;
long flags;
if (!hlt_counter)
return;
/* disable clock switching */
asm volatile ("mcr%? p15, 0, ip, c15, c2, 2");
do {
/* disable interrupts */
cli();
/* check need_resched here to avoid races */
if (need_resched()) {
sti();
return;
}
/* disable clock switching */
asm volatile ("mcr%? p15, 0, ip, c15, c2, 2");
/* wait for an interrupt to occur */
while (!*irq_stat);
/* enable clock switching */
asm volatile ("mcr%? p15, 0, ip, c15, c1, 2");
/* allow the interrupt to happen */
sti();
} while (!need_resched());
/* wait for an interrupt to occur */
while (!*irq_stat);
/* enable clock switching */
asm volatile ("mcr%? p15, 0, ip, c15, c1, 2");
}
#define arch_reset(mode) cpu_reset(0x80000000)
......
......@@ -13,26 +13,9 @@
#include <asm/leds.h>
#include <asm/mach-types.h>
static void arch_idle(void)
static inline void arch_idle(void)
{
unsigned long start_idle;
start_idle = jiffies;
do {
if (need_resched() || hlt_counter)
goto slow_out;
cpu_do_idle(IDLE_WAIT_FAST);
} while (time_before(jiffies, start_idle + HZ/50));
cpu_do_idle(IDLE_CLOCK_SLOW);
while (!need_resched() && !hlt_counter) {
cpu_do_idle(IDLE_WAIT_SLOW);
}
cpu_do_idle(IDLE_CLOCK_FAST);
slow_out:
cpu_do_idle();
}
static inline void arch_reset(char mode)
......
......@@ -24,13 +24,13 @@
#include <asm/arch/platform.h>
static void arch_idle(void)
static inline void arch_idle(void)
{
/*
* This should do all the clock switching
* and wait for interrupt tricks
*/
cpu_do_idle(0);
cpu_do_idle();
}
extern __inline__ void arch_reset(char mode)
......
......@@ -23,13 +23,13 @@
#include <asm/arch/platform.h>
static void arch_idle(void)
static inline void arch_idle(void)
{
/*
* This should do all the clock switching
* and wait for interrupt tricks
*/
cpu_do_idle(0);
cpu_do_idle();
}
static inline void arch_reset(char mode)
......
......@@ -10,10 +10,7 @@
static inline void arch_idle(void)
{
if (!hlt_counter)
{
cpu_do_idle(0);
}
cpu_do_idle();
}
......
......@@ -12,9 +12,8 @@
#ifndef __ASM_ARCH_SYSTEM_H
#define __ASM_ARCH_SYSTEM_H
static void arch_idle(void)
static inline void arch_idle(void)
{
/* fixme: this needs to be cleaned up (converted from ASM code) --rmk */
*(unsigned long *)(IO_BASE + 0x50004) = 1; /* idle mode */
}
......
......@@ -14,10 +14,9 @@
#ifndef __ASM_ARCH_SYSTEM_H
#define __ASM_ARCH_SYSTEM_H
static void arch_idle(void)
static inline void arch_idle(void)
{
while (!need_resched() && !hlt_counter)
cpu_do_idle(IDLE_WAIT_SLOW);
cpu_do_idle();
}
#define arch_reset(mode) do { } while (0)
......
......@@ -14,13 +14,7 @@
static inline void arch_idle(void)
{
if (!hlt_counter) {
int flags;
local_irq_save(flags);
if(!need_resched())
cpu_do_idle(0);
local_irq_restore(flags);
}
cpu_do_idle();
}
......
......@@ -11,26 +11,9 @@
#include <asm/hardware/iomd.h>
#include <asm/io.h>
static void arch_idle(void)
static inline void arch_idle(void)
{
unsigned long start_idle;
start_idle = jiffies;
do {
if (need_resched() || hlt_counter)
goto slow_out;
cpu_do_idle(IDLE_WAIT_FAST);
} while (time_before(jiffies, start_idle + HZ/50));
cpu_do_idle(IDLE_CLOCK_SLOW);
while (!need_resched() && !hlt_counter) {
cpu_do_idle(IDLE_WAIT_SLOW);
}
cpu_do_idle(IDLE_CLOCK_FAST);
slow_out:
cpu_do_idle();
}
static inline void arch_reset(char mode)
......
......@@ -7,13 +7,7 @@
static inline void arch_idle(void)
{
if (!hlt_counter) {
int flags;
local_irq_save(flags);
if (!need_resched())
cpu_do_idle(0);
local_irq_restore(flags);
}
cpu_do_idle();
}
#ifdef CONFIG_SA1100_VICTOR
......
......@@ -38,6 +38,8 @@
#define __bus_to_virt__is_a_macro
#define __bus_to_virt(x) __phys_to_virt(x)
#define isa_virt_to_bus virt_to_bus
#define PHYS_TO_NID(addr) (0)
#endif
......@@ -21,7 +21,7 @@ static void arch_reset(char mode)
}
static void arch_idle(void)
static inline void arch_idle(void)
{
}
......
......@@ -6,26 +6,9 @@
#ifndef __ASM_ARCH_SYSTEM_H
#define __ASM_ARCH_SYSTEM_H
static void arch_idle(void)
static inline void arch_idle(void)
{
unsigned long start_idle;
start_idle = jiffies;
do {
if (need_resched() || hlt_counter)
goto slow_out;
cpu_do_idle(IDLE_WAIT_FAST);
} while (time_before(jiffies, start_idle + HZ/50));
cpu_do_idle(IDLE_CLOCK_SLOW);
while (!need_resched() && !hlt_counter) {
cpu_do_idle(IDLE_WAIT_SLOW);
}
cpu_do_idle(IDLE_CLOCK_FAST);
slow_out:
cpu_do_idle();
}
#define arch_reset(mode) do { } while (0)
......
......@@ -40,7 +40,7 @@ extern const struct processor arm3_processor_functions;
#define cpu_proc_init() processor._proc_init()
#define cpu_proc_fin() processor._proc_fin()
#define cpu_do_idle() do { } while (0)
#define cpu_switch_mm(pgd,tsk) processor._set_pgd(pgd)
#define cpu_switch_mm(pgd,mm) processor._set_pgd(pgd)
#define cpu_xchg_1(x,ptr) processor._xchg_1(x,ptr)
#define cpu_xchg_4(x,ptr) processor._xchg_4(x,ptr)
......
......@@ -12,8 +12,7 @@
#include <asm/memory.h>
#include <asm/page.h>
/* forward-declare task_struct */
struct task_struct;
struct mm_struct;
/*
* Don't change this structure - ASM code
......@@ -43,7 +42,7 @@ extern struct processor {
/*
* Idle the processor
*/
int (*_do_idle)(int mode);
int (*_do_idle)(void);
/*
* Processor architecture specific
*/
......@@ -93,7 +92,7 @@ extern struct processor {
/*
* Set the page table
*/
void (*set_pgd)(unsigned long pgd_phys);
void (*set_pgd)(unsigned long pgd_phys, struct mm_struct *mm);
/*
* Set a PMD (handling IMP bit 4)
*/
......@@ -113,7 +112,7 @@ extern const struct processor sa110_processor_functions;
#define cpu_proc_init() processor._proc_init()
#define cpu_proc_fin() processor._proc_fin()
#define cpu_reset(addr) processor.reset(addr)
#define cpu_do_idle(mode) processor._do_idle(mode)
#define cpu_do_idle() processor._do_idle()
#define cpu_cache_clean_invalidate_all() processor.cache.clean_invalidate_all()
#define cpu_cache_clean_invalidate_range(s,e,f) processor.cache.clean_invalidate_range(s,e,f)
......@@ -126,11 +125,11 @@ extern const struct processor sa110_processor_functions;
#define cpu_icache_invalidate_range(s,e) processor.icache.invalidate_range(s,e)
#define cpu_icache_invalidate_page(vp) processor.icache.invalidate_page(vp)
#define cpu_set_pgd(pgd) processor.pgtable.set_pgd(pgd)
#define cpu_set_pgd(pgd,mm) processor.pgtable.set_pgd(pgd,mm)
#define cpu_set_pmd(pmdp, pmd) processor.pgtable.set_pmd(pmdp, pmd)
#define cpu_set_pte(ptep, pte) processor.pgtable.set_pte(ptep, pte)
#define cpu_switch_mm(pgd,tsk) cpu_set_pgd(__virt_to_phys((unsigned long)(pgd)))
#define cpu_switch_mm(pgd,mm) cpu_set_pgd(__virt_to_phys((unsigned long)(pgd)),mm)
#define cpu_get_pgd() \
({ \
......
......@@ -44,15 +44,14 @@
#include <asm/memory.h>
#include <asm/page.h>
/* forward declare task_struct */
struct task_struct;
struct mm_struct;
/* declare all the functions as extern */
extern void cpu_data_abort(unsigned long pc);
extern void cpu_check_bugs(void);
extern void cpu_proc_init(void);
extern void cpu_proc_fin(void);
extern int cpu_do_idle(int mode);
extern int cpu_do_idle(void);
extern void cpu_cache_clean_invalidate_all(void);
extern void cpu_cache_clean_invalidate_range(unsigned long address, unsigned long end, int flags);
......@@ -65,13 +64,13 @@ extern void cpu_dcache_clean_entry(unsigned long address);
extern void cpu_icache_invalidate_range(unsigned long start, unsigned long end);
extern void cpu_icache_invalidate_page(void *virt_page);
extern void cpu_set_pgd(unsigned long pgd_phys);
extern void cpu_set_pgd(unsigned long pgd_phys, struct mm_struct *mm);
extern void cpu_set_pmd(pmd_t *pmdp, pmd_t pmd);
extern void cpu_set_pte(pte_t *ptep, pte_t pte);
extern volatile void cpu_reset(unsigned long addr);
#define cpu_switch_mm(pgd,tsk) cpu_set_pgd(__virt_to_phys((unsigned long)(pgd)))
#define cpu_switch_mm(pgd,mm) cpu_set_pgd(__virt_to_phys((unsigned long)(pgd)),mm)
#define cpu_get_pgd() \
({ \
......
......@@ -26,9 +26,7 @@
#define SA1111_v2p( x ) ((x) - SA1111_VBASE + SA1111_BASE)
#ifndef __ASSEMBLY__
extern struct resource sa1111_resource;
#define _SA1111(x) ((x) + sa1111_resource.start)
#define _SA1111(x) ((x) + sa1111->resource.start)
#endif
/*
......@@ -51,7 +49,8 @@ extern struct resource sa1111_resource;
*/
#define __CCREG(x) __REGP(SA1111_VBASE + (x))
/* System Bus Interface (SBI)
/*
* System Bus Interface (SBI)
*
* Registers
* SKCR Control Register
......@@ -127,28 +126,37 @@ extern struct resource sa1111_resource;
* SKPEN1 PWM1 Enable Register
* SKPWM1 PWM1 Clock Register
*/
#define _SKPCR _SA1111(0x0200)
#define _SKCDR _SA1111(0x0204)
#define _SKAUD _SA1111(0x0208)
#define _SKPMC _SA1111(0x020c)
#define _SKPTC _SA1111(0x0210)
#define _SKPEN0 _SA1111(0x0214)
#define _SKPWM0 _SA1111(0x0218)
#define _SKPEN1 _SA1111(0x021c)
#define _SKPWM1 _SA1111(0x0220)
#define SA1111_SKPCR 0x0200
#define SA1111_SKCDR 0x0204
#define SA1111_SKAUD 0x0208
#define SA1111_SKPMC 0x020c
#define SA1111_SKPTC 0x0210
#define SA1111_SKPEN0 0x0214
#define SA1111_SKPWN0 0x0218
#define SA1111_SKPEN1 0x021c
#define SA1111_SKPWM1 0x0220
#define _SKPCR _SA1111(SA1111_SKPCR)
#define _SKCDR _SA1111(SA1111_SKCDR)
#define _SKAUD _SA1111(SA1111_SKAUD)
#define _SKPMC _SA1111(SA1111_SKPMC)
#define _SKPTC _SA1111(SA1111_SKPTC)
#define _SKPEN0 _SA1111(SA1111_SKPEN0)
#define _SKPWM0 _SA1111(SA1111_SKPWM0)
#define _SKPEN1 _SA1111(SA1111_SKPEN1)
#define _SKPWM1 _SA1111(SA1111_SKPWM1)
#if LANGUAGE == C
#define SKPCR __CCREG(0x0200)
#define SKCDR __CCREG(0x0204)
#define SKAUD __CCREG(0x0208)
#define SKPMC __CCREG(0x020c)
#define SKPTC __CCREG(0x0210)
#define SKPEN0 __CCREG(0x0214)
#define SKPWM0 __CCREG(0x0218)
#define SKPEN1 __CCREG(0x021c)
#define SKPWM1 __CCREG(0x0220)
#define SKPCR __CCREG(SA1111_SKPCR)
#define SKCDR __CCREG(SA1111_SKCDR)
#define SKAUD __CCREG(SA1111_SKAUD)
#define SKPMC __CCREG(SA1111_SKPMC)
#define SKPTC __CCREG(SA1111_SKPTC)
#define SKPEN0 __CCREG(SA1111_SKPEN0)
#define SKPWM0 __CCREG(SA1111_SKPWM0)
#define SKPEN1 __CCREG(SA1111_SKPEN1)
#define SKPWM1 __CCREG(SA1111_SKPWM1)
#endif /* LANGUAGE == C */
......@@ -675,4 +683,12 @@ extern struct resource sa1111_resource;
#define PCSSR_S0_SLEEP (1<<0)
#define PCSSR_S1_SLEEP (1<<1)
struct sa1111_device {
struct device dev;
struct resource resource;
void *base;
};
extern struct sa1111_device *sa1111;
#endif /* _ASM_ARCH_SA1111 */
......@@ -22,6 +22,7 @@
#ifdef __KERNEL__
#include <linux/config.h>
#include <linux/types.h>
#include <asm/byteorder.h>
#include <asm/memory.h>
......@@ -269,13 +270,22 @@ extern void consistent_free(void *vaddr, size_t size, dma_addr_t handle);
extern void consistent_sync(void *vaddr, size_t size, int rw);
/*
* FIXME: I'm sure these will need to be changed for DISCONTIG
* Change "struct page" to physical address.
*/
#ifdef CONFIG_DISCONTIG
#define page_to_phys(page) \
((((page) - page_zone(page)->zone_mem_map) << PAGE_SHIFT) \
+ page_zone(page)->zone_start_paddr)
#else
#define page_to_phys(page) \
(PHYS_OFFSET + (((page) - mem_map) << PAGE_SHIFT))
#endif
/*
* Change "struct page" to physical address.
* We should really eliminate virt_to_bus() here - it's depreciated.
*/
#define page_to_phys(page) (PHYS_OFFSET + ((page - mem_map) << PAGE_SHIFT))
#define page_to_bus(page) (PHYS_OFFSET + ((page - mem_map) << PAGE_SHIFT))
#define page_to_bus(page) \
(virt_to_bus(page_address(page)))
/*
* can the hardware map this into one segment or not, given no other
......
......@@ -43,7 +43,7 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next,
struct task_struct *tsk, unsigned int cpu)
{
if (prev != next)
cpu_switch_mm(next->pgd, tsk);
cpu_switch_mm(next->pgd, next);
}
#define activate_mm(prev, next) \
......
......@@ -95,30 +95,25 @@ pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr, size_t size, int di
/* nothing to do */
}
/* Whether pci_unmap_{single,page} is a nop depends upon the
/*
* Whether pci_unmap_{single,page} is a nop depends upon the
* configuration.
*/
#ifdef CONFIG_SA1111
#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) \
dma_addr_t ADDR_NAME;
#define DECLARE_PCI_UNMAP_LEN(LEN_NAME) \
__u32 LEN_NAME;
#define pci_unmap_addr(PTR, ADDR_NAME) \
((PTR)->ADDR_NAME)
#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) \
(((PTR)->ADDR_NAME) = (VAL))
#define pci_unmap_len(PTR, LEN_NAME) \
((PTR)->LEN_NAME)
#define pci_unmap_len_set(PTR, LEN_NAME, VAL) \
(((PTR)->LEN_NAME) = (VAL))
#else /* !(CONFIG_SA1111) */
#ifdef CONFIG_PCI
#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) dma_addr_t ADDR_NAME;
#define DECLARE_PCI_UNMAP_LEN(LEN_NAME) __u32 LEN_NAME;
#define pci_unmap_addr(PTR, ADDR_NAME) ((PTR)->ADDR_NAME)
#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) (((PTR)->ADDR_NAME) = (VAL))
#define pci_unmap_len(PTR, LEN_NAME) ((PTR)->LEN_NAME)
#define pci_unmap_len_set(PTR, LEN_NAME, VAL) (((PTR)->LEN_NAME) = (VAL))
#else
#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)
#define DECLARE_PCI_UNMAP_LEN(LEN_NAME)
#define pci_unmap_addr(PTR, ADDR_NAME) (0)
#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) do { } while (0)
#define pci_unmap_len(PTR, LEN_NAME) (0)
#define pci_unmap_len_set(PTR, LEN_NAME, VAL) do { } while (0)
#endif /* CONFIG_SA1111 */
#endif /* CONFIG_PCI */
/* Map a set of buffers described by scatterlist in streaming
* mode for DMA. This is the scather-gather version of the
......
......@@ -12,6 +12,7 @@ typedef struct {
unsigned int __local_bh_count;
unsigned int __syscall_count;
struct task_struct * __ksoftirqd_task; /* waitqueue is too large */
unsigned long idle_timestamp;
unsigned int __nmi_count; /* arch dependent */
} ____cacheline_aligned irq_cpustat_t;
......
......@@ -273,19 +273,22 @@ typedef union {
} b;
} special_t;
#define IDE_MAX_TAG 32 /* spec says 32 max */
#define IDE_MAX_TAG (32) /* spec says 32 max */
#define IDE_INACTIVE_TAG (-1)
struct ata_request;
typedef struct ide_tag_info_s {
unsigned long tag_mask; /* next tag bit mask */
struct ata_request *ar[IDE_MAX_TAG]; /* in-progress requests */
int active_tag; /* current active tag */
int queued; /* current depth */
/*
* stats ->
*/
int max_depth; /* max depth ever */
int max_last_depth; /* max since last check */
/*
......@@ -295,14 +298,19 @@ typedef struct ide_tag_info_s {
*/
int immed_rel;
int immed_comp;
unsigned long oldest_command;
} ide_tag_info_t;
#define IDE_GET_AR(drive, tag) ((drive)->tcq->ar[(tag)])
#define IDE_CUR_TAG(drive) (IDE_GET_AR((drive), (drive)->tcq->active_tag))
#define IDE_SET_CUR_TAG(drive, tag) ((drive)->tcq->active_tag = (tag))
#define IDE_SET_CUR_TAG(drive, tag) \
do { \
((drive)->tcq->active_tag = (tag)); \
if ((tag) == IDE_INACTIVE_TAG) \
HWGROUP((drive))->rq = NULL; \
} while (0);
#define IDE_CUR_AR(drive) \
((drive)->using_tcq ? IDE_CUR_TAG((drive)) : HWGROUP((drive))->rq->special)
#define IDE_CUR_AR(drive) (HWGROUP((drive))->rq->special)
struct ide_settings_s;
......@@ -359,6 +367,7 @@ typedef struct ide_drive_s {
unsigned autotune : 2; /* 1=autotune, 2=noautotune, 0=default */
unsigned remap_0_to_1 : 2; /* 0=remap if ezdrive, 1=remap, 2=noremap */
unsigned ata_flash : 1; /* 1=present, 0=default */
unsigned service_pending: 1;
unsigned addressing; /* : 2; 0=28-bit, 1=48-bit, 2=64-bit */
byte scsi; /* 0=default, 1=skip current ide-subdriver for ide-scsi emulation */
select_t select; /* basic drive/head select reg value */
......@@ -546,7 +555,7 @@ extern void ide_unregister(struct ata_channel *hwif);
typedef enum {
ide_stopped, /* no drive operation was started */
ide_started, /* a drive operation was started, and a handler was set */
ide_released /* started and released bus */
ide_released, /* started, handler set, bus released */
} ide_startstop_t;
/*
......@@ -980,6 +989,11 @@ extern void revalidate_drives(void);
#define ATA_AR_SETUP 2
#define ATA_AR_RETURN 4
/*
* if turn-around time is longer than this, halve queue depth
*/
#define ATA_AR_MAX_TURNAROUND (3 * HZ)
#define list_ata_entry(entry) list_entry((entry), struct ata_request, ar_queue)
static inline void ata_ar_init(ide_drive_t *drive, struct ata_request *ar)
......@@ -1026,7 +1040,7 @@ static inline void ata_ar_put(ide_drive_t *drive, struct ata_request *ar)
ar->ar_rq = NULL;
}
extern inline int ide_get_tag(ide_drive_t *drive)
static inline int ide_get_tag(ide_drive_t *drive)
{
int tag = ffz(drive->tcq->tag_mask);
......@@ -1043,12 +1057,28 @@ extern inline int ide_get_tag(ide_drive_t *drive)
}
#ifdef CONFIG_BLK_DEV_IDE_TCQ
# define ide_pending_commands(drive) ((drive)->using_tcq && (drive)->tcq->queued)
static inline int ide_pending_commands(ide_drive_t *drive)
{
if (!drive->tcq)
return 0;
return drive->tcq->queued;
}
static inline int ide_can_queue(ide_drive_t *drive)
{
if (!drive->tcq)
return 1;
return drive->tcq->queued < drive->queue_depth;
}
#else
# define ide_pending_commands(drive) 0
#define ide_pending_commands(drive) (0)
#define ide_can_queue(drive) (1)
#endif
int ide_build_commandlist(ide_drive_t *);
int ide_init_commandlist(ide_drive_t *);
void ide_teardown_commandlist(ide_drive_t *);
int ide_tcq_dmaproc(ide_dma_action_t, ide_drive_t *);
ide_startstop_t ide_start_tag(ide_dma_action_t, ide_drive_t *, struct ata_request *);
......
......@@ -272,6 +272,10 @@ static void __init smp_init(void)
#define smp_init() do { } while (0)
#endif
static inline void setup_per_cpu_areas(void)
{
}
#else
#ifdef __GENERIC_PER_CPU
......@@ -296,10 +300,6 @@ static void __init setup_per_cpu_areas(void)
memcpy(ptr, __per_cpu_start, size);
}
}
#else
static inline void setup_per_cpu_areas(void)
{
}
#endif /* !__GENERIC_PER_CPU */
/* Called by boot processor to activate the rest. */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment