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