diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-03-19 01:28:40 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-03-19 01:28:40 +0000 |
commit | 8abb719409c9060a7c0676f76e9182c1e0b8ca46 (patch) | |
tree | b88cc5a6cd513a04a512b7e6215c873c90a1c5dd /drivers/block | |
parent | f01bd7aeafd95a08aafc9e3636bb26974df69d82 (diff) |
Merge with 2.3.99-pre1.
Diffstat (limited to 'drivers/block')
55 files changed, 253 insertions, 34073 deletions
diff --git a/drivers/block/Config.in b/drivers/block/Config.in index 0e29e3a2e..51a6db89c 100644 --- a/drivers/block/Config.in +++ b/drivers/block/Config.in @@ -16,172 +16,6 @@ if [ "$CONFIG_MAC" = "y" ]; then bool 'Macintosh IIfx/Quadra 900/Quadra 950 floppy support (EXPERIMENTAL)' CONFIG_BLK_DEV_SWIM_IOP fi fi - -tristate 'Enhanced IDE/MFM/RLL disk/cdrom/tape/floppy support' CONFIG_BLK_DEV_IDE -comment 'Please see Documentation/ide.txt for help/info on IDE drives' -if [ "$CONFIG_BLK_DEV_IDE" = "n" ]; then - bool 'Old hard disk (MFM/RLL/IDE) driver' CONFIG_BLK_DEV_HD_ONLY -else - bool ' Use old disk-only driver on primary interface' CONFIG_BLK_DEV_HD_IDE - dep_tristate ' Include IDE/ATA-2 DISK support' CONFIG_BLK_DEV_IDEDISK $CONFIG_BLK_DEV_IDE - if [ "$CONFIG_BLK_DEV_IDEDISK" != "n" ]; then - bool ' Use multi-mode by default' CONFIG_IDEDISK_MULTI_MODE - fi - dep_tristate ' PCMCIA IDE support' CONFIG_BLK_DEV_IDECS $CONFIG_BLK_DEV_IDE $CONFIG_PCMCIA - dep_tristate ' Include IDE/ATAPI CDROM support' CONFIG_BLK_DEV_IDECD $CONFIG_BLK_DEV_IDE - dep_tristate ' Include IDE/ATAPI TAPE support' CONFIG_BLK_DEV_IDETAPE $CONFIG_BLK_DEV_IDE - dep_tristate ' Include IDE/ATAPI FLOPPY support' CONFIG_BLK_DEV_IDEFLOPPY $CONFIG_BLK_DEV_IDE - dep_tristate ' SCSI emulation support' CONFIG_BLK_DEV_IDESCSI $CONFIG_BLK_DEV_IDE - comment 'IDE chipset support/bugfixes' - if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then - bool ' CMD640 chipset bugfix/support' CONFIG_BLK_DEV_CMD640 - if [ "$CONFIG_BLK_DEV_CMD640" = "y" ]; then - bool ' CMD640 enhanced support' CONFIG_BLK_DEV_CMD640_ENHANCED - fi - if [ "$CONFIG_ISAPNP" = "y" ]; then - bool ' ISA-PNP EIDE support' CONFIG_BLK_DEV_ISAPNP - fi - if [ "$CONFIG_PCI" = "y" ]; then - bool ' RZ1000 chipset bugfix/support' CONFIG_BLK_DEV_RZ1000 - bool ' Generic PCI IDE chipset support' CONFIG_BLK_DEV_IDEPCI - if [ "$CONFIG_BLK_DEV_IDEPCI" = "y" ]; then - bool ' Sharing PCI IDE interrupts support' CONFIG_IDEPCI_SHARE_IRQ - bool ' Generic PCI bus-master DMA support' CONFIG_BLK_DEV_IDEDMA_PCI - if [ "$CONFIG_BLK_DEV_IDEDMA_PCI" = "y" ]; then - bool ' Use PCI DMA by default when available' CONFIG_IDEDMA_PCI_AUTO - if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - bool ' Good-Bad DMA Model-Firmware (EXPERIMENTAL)' CONFIG_IDEDMA_NEW_DRIVE_LISTINGS - define_bool CONFIG_IDEDMA_PCI_EXPERIMENTAL y - else - define_bool CONFIG_IDEDMA_PCI_EXPERIMENTAL n - fi - fi - if [ "$CONFIG_IDEDMA_PCI_EXPERIMENTAL" = "y" ]; then - bool ' ATA Work(s) In Progress (EXPERIMENTAL)' CONFIG_IDEDMA_PCI_WIP - fi - bool ' Boot off-board chipsets first support' CONFIG_BLK_DEV_OFFBOARD - bool ' AEC6210 chipset support' CONFIG_BLK_DEV_AEC6210 - if [ "$CONFIG_IDEDMA_PCI_WIP" = "y" -a "$CONFIG_BLK_DEV_AEC6210" = "y" ]; then - bool ' AEC6210 Tuning support (WIP)' CONFIG_AEC6210_TUNING - fi - if [ "$CONFIG_BLK_DEV_IDEDMA_PCI" = "y" ]; then - bool ' ALI M15x3 chipset support' CONFIG_BLK_DEV_ALI15X3 - bool ' AMD Viper support' CONFIG_BLK_DEV_AMD7409 - if [ "$CONFIG_IDEDMA_PCI_WIP" = "y" -a "$CONFIG_BLK_DEV_AMD7409" = "y" ]; then - bool ' AMD Viper ATA-66 Override (WIP)' CONFIG_AMD7409_OVERRIDE - fi - fi - bool ' CMD64X chipset support' CONFIG_BLK_DEV_CMD64X - if [ "$CONFIG_IDEDMA_PCI_WIP" = "y" -a "$CONFIG_BLK_DEV_CMD64X" = "y" ]; then - bool ' CMD64X chipset RAID (WIP)' CONFIG_CMD64X_RAID - fi - if [ "$CONFIG_IDEDMA_PCI_EXPERIMENTAL" = "y" ]; then - bool ' CY82C693 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_CY82C693 - fi - bool ' Cyrix CS5530 MediaGX chipset support' CONFIG_BLK_DEV_CS5530 - if [ "$CONFIG_BLK_DEV_IDEDMA_PCI" = "y" ]; then - bool ' HPT34X chipset support' CONFIG_BLK_DEV_HPT34X - if [ "$CONFIG_IDEDMA_PCI_WIP" = "y" -a "$CONFIG_BLK_DEV_HPT34X" = "y" ]; then - bool ' HPT34X AUTODMA support (WIP)' CONFIG_HPT34X_AUTODMA - fi - bool ' HPT366 chipset support' CONFIG_BLK_DEV_HPT366 - if [ "$CONFIG_IDEDMA_PCI_WIP" = "y" -a "$CONFIG_BLK_DEV_HPT366" = "y" ]; then - bool ' HPT366 Fast Interrupts (WIP)' CONFIG_HPT366_FIP - bool ' HPT366 mode Three (WIP)' CONFIG_HPT366_MODE3 - fi - if [ "$CONFIG_X86" = "y" -o "$CONFIG_IA64" = "y" ]; then - bool ' Intel PIIXn chipsets support' CONFIG_BLK_DEV_PIIX - if [ "$CONFIG_BLK_DEV_PIIX" = "y" -a "$CONFIG_IDEDMA_PCI_AUTO" = "y" ]; then - bool ' PIIXn Tuning support' CONFIG_PIIX_TUNING - fi - fi - fi - if [ "$CONFIG_IDEDMA_PCI_EXPERIMENTAL" = "y" ]; then - bool ' NS87415 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_NS87415 - fi - if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - bool ' OPTi 82C621 chipset enhanced support (EXPERIMENTAL)' CONFIG_BLK_DEV_OPTI621 - fi - if [ "$CONFIG_BLK_DEV_IDEDMA_PCI" = "y" ]; then - bool ' PROMISE PDC20246/PDC20262 support' CONFIG_BLK_DEV_PDC202XX - if [ "$CONFIG_BLK_DEV_PDC202XX" = "y" ]; then - bool ' Special UDMA Feature' CONFIG_PDC202XX_BURST - if [ "$CONFIG_IDEDMA_PCI_WIP" = "y" ]; then - bool ' Special Mode Feature (WIP)' CONFIG_PDC202XX_MASTER - fi - fi - if [ "$CONFIG_X86" = "y" ]; then - bool ' SiS5513 chipset support' CONFIG_BLK_DEV_SIS5513 - fi - fi - if [ "$CONFIG_IDEDMA_PCI_EXPERIMENTAL" = "y" ]; then - bool ' Tekram TRM290 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_TRM290 - bool ' VIA82CXXX chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_VIA82CXXX - fi - fi - if [ "$CONFIG_PPC" = "y" -o "$CONFIG_ARM" = "y" ]; then - bool ' Winbond SL82c105 support' CONFIG_BLK_DEV_SL82C105 - fi - fi - if [ "$CONFIG_PMAC" = "y" -o "$CONFIG_ALL_PPC" = "y" ]; then - bool ' Builtin PowerMac IDE support' CONFIG_BLK_DEV_IDE_PMAC - if [ "$CONFIG_BLK_DEV_IDE_PMAC" != "n" ]; then - bool ' PowerMac IDE DMA support' CONFIG_BLK_DEV_IDEDMA_PMAC - if [ "$CONFIG_BLK_DEV_IDEDMA_PMAC" = "y" ]; then - bool ' Use DMA by default' CONFIG_IDEDMA_PMAC_AUTO - fi - fi - fi - if [ "$CONFIG_ARCH_ACORN" = "y" ]; then - bool ' ICS IDE interface support' CONFIG_BLK_DEV_IDE_ICSIDE - if [ "$CONFIG_BLK_DEV_IDE_ICSIDE" = "y" ]; then - bool ' ICS DMA support' CONFIG_BLK_DEV_IDEDMA_ICS - if [ "$CONFIG_BLK_DEV_IDEDMA_ICS" = "y" ]; then - bool ' Use ICS DMA by default' CONFIG_IDEDMA_ICS_AUTO - fi - fi - bool ' RapIDE interface support' CONFIG_BLK_DEV_IDE_RAPIDE - fi - if [ "$CONFIG_BLK_DEV_IDEDMA_PCI" = "y" -o \ - "$CONFIG_BLK_DEV_IDEDMA_PMAC" = "y" -o \ - "$CONFIG_BLK_DEV_IDEDMA_ICS" = "y" ]; then - define_bool CONFIG_BLK_DEV_IDEDMA y - if [ "$CONFIG_IDEDMA_PCI_AUTO" = "y" -o \ - "$CONFIG_IDEDMA_PMAC_AUTO" = "y" -o \ - "$CONFIG_IDEDMA_ICS_AUTO" = "y" ]; then - define_bool CONFIG_IDEDMA_AUTO y - fi - fi - bool ' Other IDE chipset support' CONFIG_IDE_CHIPSETS - if [ "$CONFIG_IDE_CHIPSETS" = "y" ]; then - comment 'Note: most of these also require special kernel boot parameters' - bool ' Generic 4 drives/port support' CONFIG_BLK_DEV_4DRIVES - bool ' ALI M14xx support' CONFIG_BLK_DEV_ALI14XX - bool ' DTC-2278 support' CONFIG_BLK_DEV_DTC2278 - bool ' Holtek HT6560B support' CONFIG_BLK_DEV_HT6560B - if [ "$CONFIG_BLK_DEV_IDEDISK" = "y" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then - bool ' PROMISE DC4030 support (EXPERIMENTAL)' CONFIG_BLK_DEV_PDC4030 - fi - bool ' QDI QD6580 support' CONFIG_BLK_DEV_QD6580 - bool ' UMC-8672 support' CONFIG_BLK_DEV_UMC8672 - fi - if [ "$CONFIG_AMIGA" = "y" ]; then - bool ' Amiga Gayle IDE interface support' CONFIG_BLK_DEV_GAYLE - if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - dep_tristate ' Amiga IDE Doubler support (EXPERIMENTAL)' CONFIG_BLK_DEV_IDEDOUBLER $CONFIG_BLK_DEV_GAYLE - fi - fi - if [ "$CONFIG_ZORRO" = "y" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then - bool ' Buddha/Catweasel IDE interface support (EXPERIMENTAL)' CONFIG_BLK_DEV_BUDDHA - fi - if [ "$CONFIG_ATARI" = "y" ]; then - bool ' Falcon IDE interface support' CONFIG_BLK_DEV_FALCON_IDE - fi - if [ "$CONFIG_MAC" = "y" ]; then - bool ' Macintosh Quadra/Powerbook IDE interface support' CONFIG_BLK_DEV_MAC_IDE - fi - fi -fi if [ "$CONFIG_MCA" = "y" ]; then tristate 'PS/2 ESDI hard disk support' CONFIG_BLK_DEV_PS2 fi @@ -196,8 +30,15 @@ if [ "$CONFIG_ATARI" = "y" ]; then tristate ' Atari SLM laser printer support' CONFIG_ATARI_SLM fi fi +tristate 'XT hard disk support' CONFIG_BLK_DEV_XD +dep_tristate 'Parallel port IDE device support' CONFIG_PARIDE $CONFIG_PARIDE_PARPORT +if [ "$CONFIG_PARIDE" = "y" -o "$CONFIG_PARIDE" = "m" ]; then + source drivers/block/paride/Config.in +fi + if [ "$CONFIG_PCI" = "y" ]; then tristate 'Compaq SMART2 support' CONFIG_BLK_CPQ_DA + tristate 'Mylex DAC960/DAC1100 PCI RAID Controller support' CONFIG_BLK_DEV_DAC960 fi comment 'Additional Block Devices' @@ -220,41 +61,5 @@ tristate 'RAM disk support' CONFIG_BLK_DEV_RAM if [ "$CONFIG_BLK_DEV_RAM" = "y" ]; then bool ' Initial RAM disk (initrd) support' CONFIG_BLK_DEV_INITRD fi -tristate 'XT hard disk support' CONFIG_BLK_DEV_XD -if [ "$CONFIG_PCI" = "y" ]; then - tristate 'Mylex DAC960/DAC1100 PCI RAID Controller support' CONFIG_BLK_DEV_DAC960 -fi - -dep_tristate 'Parallel port IDE device support' CONFIG_PARIDE $CONFIG_PARIDE_PARPORT -if [ "$CONFIG_PARIDE" = "y" -o "$CONFIG_PARIDE" = "m" ]; then - source drivers/block/paride/Config.in -fi - -if [ "$CONFIG_IDE_CHIPSETS" = "y" -o \ - "$CONFIG_BLK_DEV_AEC6210" = "y" -o \ - "$CONFIG_BLK_DEV_ALI15X3" = "y" -o \ - "$CONFIG_BLK_DEV_AMD7409" = "y" -o \ - "$CONFIG_BLK_DEV_CMD640" = "y" -o \ - "$CONFIG_BLK_DEV_CMD64X" = "y" -o \ - "$CONFIG_BLK_DEV_CS5530" = "y" -o \ - "$CONFIG_BLK_DEV_CY82C693" = "y" -o \ - "$CONFIG_BLK_DEV_HPT34X" = "y" -o \ - "$CONFIG_BLK_DEV_HPT366" = "y" -o \ - "$CONFIG_BLK_DEV_IDE_PMAC" = "y" -o \ - "$CONFIG_BLK_DEV_OPTI621" = "y" -o \ - "$CONFIG_BLK_DEV_PDC202XX" = "y" -o \ - "$CONFIG_BLK_DEV_PIIX" = "y" -o \ - "$CONFIG_BLK_DEV_SIS5513" = "y" -o \ - "$CONFIG_BLK_DEV_SL82C105" = "y" ]; then - define_bool CONFIG_BLK_DEV_IDE_MODES y -else - define_bool CONFIG_BLK_DEV_IDE_MODES n -fi - -if [ "$CONFIG_BLK_DEV_HD_IDE" = "y" -o "$CONFIG_BLK_DEV_HD_ONLY" = "y" ]; then - define_bool CONFIG_BLK_DEV_HD y -else - define_bool CONFIG_BLK_DEV_HD n -fi endmenu diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c index e969e2dd7..87c597c31 100644 --- a/drivers/block/DAC960.c +++ b/drivers/block/DAC960.c @@ -1021,7 +1021,7 @@ static inline int DAC_new_segment(request_queue_t *q, struct request *req, if (req->nr_segments < max_segments) { req->nr_segments++; - q->nr_segments++; + q->elevator.nr_segments++; return 1; } return 0; @@ -1051,23 +1051,23 @@ static int DAC_merge_requests_fn(request_queue_t *q, int max_segments; DAC960_Controller_T * Controller = q->queuedata; int total_segments = req->nr_segments + next->nr_segments; - int same_segment; + int same_segment; max_segments = Controller->MaxSegmentsPerRequest[MINOR(req->rq_dev)]; if (__max_segments < max_segments) max_segments = __max_segments; - same_segment = 0; + same_segment = 0; if (req->bhtail->b_data + req->bhtail->b_size == next->bh->b_data) { total_segments--; - same_segment = 1; + same_segment = 1; } if (total_segments > max_segments) return 0; - q->nr_segments -= same_segment; + q->elevator.nr_segments -= same_segment; req->nr_segments = total_segments; return 1; } diff --git a/drivers/block/Makefile b/drivers/block/Makefile index 6882d03f3..9f5c813d7 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -20,7 +20,7 @@ ALL_SUB_DIRS := $(SUB_DIRS) paride L_TARGET := block.a -L_OBJS := genhd.o ide-geometry.o +L_OBJS := genhd.o elevator.o M_OBJS := MOD_LIST_NAME := BLOCK_MODULES LX_OBJS := ll_rw_blk.o blkpg.o @@ -98,214 +98,6 @@ else endif endif -# -# IDE-STUFF -# - -ifeq ($(CONFIG_BLK_DEV_AEC6210),y) -IDE_OBJS += aec6210.o -endif - -ifeq ($(CONFIG_BLK_DEV_ALI14XX),y) -IDE_OBJS += ali14xx.o -endif - -ifeq ($(CONFIG_BLK_DEV_ALI15X3),y) -IDE_OBJS += alim15x3.o -endif - -ifeq ($(CONFIG_BLK_DEV_AMD7409),y) -IDE_OBJS += amd7409.o -endif - -ifeq ($(CONFIG_BLK_DEV_BUDDHA),y) -IDE_OBJS += buddha.o -endif - -ifeq ($(CONFIG_BLK_DEV_CMD640),y) -IDE_OBJS += cmd640.o -endif - -ifeq ($(CONFIG_BLK_DEV_CMD64X),y) -IDE_OBJS += cmd64x.o -endif - -ifeq ($(CONFIG_BLK_DEV_CS5530),y) -IDE_OBJS += cs5530.o -endif - -ifeq ($(CONFIG_BLK_DEV_CY82C693),y) -IDE_OBJS += cy82c693.o -endif - -ifeq ($(CONFIG_BLK_DEV_DTC2278),y) -IDE_OBJS += dtc2278.o -endif - -ifeq ($(CONFIG_BLK_DEV_FALCON_IDE),y) -IDE_OBJS += falconide.o -endif - -ifeq ($(CONFIG_BLK_DEV_GAYLE),y) -IDE_OBJS += gayle.o -endif - -ifeq ($(CONFIG_BLK_DEV_Q40IDE),y) -IDE_OBJS += q40ide.o -endif - -ifeq ($(CONFIG_BLK_DEV_HD),y) -L_OBJS += hd.o -endif - -ifeq ($(CONFIG_BLK_DEV_HPT34X),y) -IDE_OBJS += hpt34x.o -endif - -ifeq ($(CONFIG_BLK_DEV_HPT366),y) -IDE_OBJS += hpt366.o -endif - -ifeq ($(CONFIG_BLK_DEV_HT6560B),y) -IDE_OBJS += ht6560b.o -endif - -ifeq ($(CONFIG_BLK_DEV_IDE_ICSIDE),y) -IDE_OBJS += icside.o -endif - -ifeq ($(CONFIG_BLK_DEV_IDEDMA),y) -IDE_OBJS += ide-dma.o -endif - -ifeq ($(CONFIG_BLK_DEV_IDEPCI),y) -IDE_OBJS += ide-pci.o -endif - -ifeq ($(CONFIG_BLK_DEV_ISAPNP),y) -IDE_OBJS += ide-pnp.o -endif - -ifeq ($(CONFIG_BLK_DEV_IDE_PMAC),y) -IDE_OBJS += ide-pmac.o -endif - -ifeq ($(CONFIG_BLK_DEV_MAC_IDE),y) -IDE_OBJS += macide.o -endif - -ifeq ($(CONFIG_BLK_DEV_NS87415),y) -IDE_OBJS += ns87415.o -endif - -ifeq ($(CONFIG_BLK_DEV_OPTI621),y) -IDE_OBJS += opti621.o -endif - -ifeq ($(CONFIG_BLK_DEV_PDC202XX),y) -IDE_OBJS += pdc202xx.o -endif - -ifeq ($(CONFIG_BLK_DEV_PDC4030),y) -IDE_OBJS += pdc4030.o -endif - -ifeq ($(CONFIG_BLK_DEV_PIIX),y) -IDE_OBJS += piix.o -endif - -ifeq ($(CONFIG_BLK_DEV_QD6580),y) -IDE_OBJS += qd6580.o -endif - -ifeq ($(CONFIG_BLK_DEV_IDE_RAPIDE),y) -IDE_OBJS += rapide.o -endif - -ifeq ($(CONFIG_BLK_DEV_RZ1000),y) -IDE_OBJS += rz1000.o -endif - -ifeq ($(CONFIG_BLK_DEV_SIS5513),y) -IDE_OBJS += sis5513.o -endif - -ifeq ($(CONFIG_BLK_DEV_SL82C105),y) -IDE_OBJS += sl82c105.o -endif - -ifeq ($(CONFIG_BLK_DEV_TRM290),y) -IDE_OBJS += trm290.o -endif - -ifeq ($(CONFIG_BLK_DEV_UMC8672),y) -IDE_OBJS += umc8672.o -endif - -ifeq ($(CONFIG_BLK_DEV_VIA82CXXX),y) -IDE_OBJS += via82cxxx.o -endif - -### if CONFIG_BLK_DEV_IDE is n, IDE_OBJS will be ignored - -ifeq ($(CONFIG_PROC_FS),y) -IDE_OBJS += ide-proc.o -endif - -###Collect - -ifeq ($(CONFIG_BLK_DEV_IDE),y) - LX_OBJS += ide.o ide-features.o - L_OBJS += ide-probe.o $(IDE_OBJS) -else - ifeq ($(CONFIG_BLK_DEV_IDE),m) - MIX_OBJS += ide.o ide-features.o $(IDE_OBJS) - M_OBJS += ide-mod.o ide-probe-mod.o - endif -endif - -############ - -ifeq ($(CONFIG_BLK_DEV_IDECS),y) -L_OBJS += ide-cs.o -else - ifeq ($(CONFIG_BLK_DEV_IDECS),m) - M_OBJS += ide-cs.o - endif -endif - -ifeq ($(CONFIG_BLK_DEV_IDEDISK),y) -L_OBJS += ide-disk.o -else - ifeq ($(CONFIG_BLK_DEV_IDEDISK),m) - M_OBJS += ide-disk.o - endif -endif - -ifeq ($(CONFIG_BLK_DEV_IDECD),y) -L_OBJS += ide-cd.o -else - ifeq ($(CONFIG_BLK_DEV_IDECD),m) - M_OBJS += ide-cd.o - endif -endif - -ifeq ($(CONFIG_BLK_DEV_IDETAPE),y) -L_OBJS += ide-tape.o -else - ifeq ($(CONFIG_BLK_DEV_IDETAPE),m) - M_OBJS += ide-tape.o - endif -endif - -ifeq ($(CONFIG_BLK_DEV_IDEFLOPPY),y) -L_OBJS += ide-floppy.o -else - ifeq ($(CONFIG_BLK_DEV_IDEFLOPPY),m) - M_OBJS += ide-floppy.o - endif -endif - ifeq ($(CONFIG_BLK_DEV_PS2),y) L_OBJS += ps2esdi.o else @@ -418,11 +210,5 @@ endif include $(TOPDIR)/Rules.make -ide-mod.o: ide.o ide-features.o $(IDE_OBJS) - $(LD) $(LD_RFLAG) -r -o $@ ide.o ide-features.o $(IDE_OBJS) - -ide-probe-mod.o: ide-probe.o ide-geometry.o - $(LD) $(LD_RFLAG) -r -o $@ ide-probe.o ide-geometry.o - lvm-mod.o: lvm.o lvm-snap.o $(LD) -r -o $@ lvm.o lvm-snap.o diff --git a/drivers/block/aec6210.c b/drivers/block/aec6210.c deleted file mode 100644 index cc0aca5fd..000000000 --- a/drivers/block/aec6210.c +++ /dev/null @@ -1,372 +0,0 @@ -/* - * linux/drivers/block/aec6210.c Version 0.05 Feb. 10, 2000 - * - * Copyright (C) 1998-2000 Andre Hedrick (andre@suse.com) - * May be copied or modified under the terms of the GNU General Public License - * - * pio 0 :: 40: 00 07 00 00 00 00 00 00 02 07 a6 04 00 02 00 02 - * pio 1 :: 40: 0a 07 00 00 00 00 00 00 02 07 a6 05 00 02 00 02 - * pio 2 :: 40: 08 07 00 00 00 00 00 00 02 07 a6 05 00 02 00 02 - * pio 3 :: 40: 03 04 00 00 00 00 00 00 02 05 a6 05 00 02 00 02 - * pio 4 :: 40: 01 04 00 00 00 00 00 00 02 05 a6 05 00 02 00 02 - * dma 0 :: 40: 0a 07 00 00 00 00 00 00 02 05 a6 05 00 02 00 02 - * dma 1 :: 40: 02 04 00 00 00 00 00 00 02 05 a6 05 00 02 00 02 - * dma 2 :: 40: 01 04 00 00 00 00 00 00 02 05 a6 05 00 02 00 02 - * 50: ff ff ff ff 00 06 04 00 00 00 00 00 00 00 00 00 - * - * udma 0 :: 40: 01 04 00 00 00 00 00 00 02 05 a6 05 00 02 00 02 - * 50: ff ff ff ff 01 06 04 00 00 00 00 00 00 00 00 00 - * - * udma 1 :: 40: 01 04 00 00 00 00 00 00 02 05 a6 05 00 02 00 02 - * 50: ff ff ff ff 01 06 04 00 00 00 00 00 00 00 00 00 - * - * udma 2 :: 40: 01 04 00 00 00 00 00 00 02 05 a6 05 00 02 00 02 - * 50: ff ff ff ff 02 06 04 00 00 00 00 00 00 00 00 00 - * - * auto :: 40: 01 04 00 00 00 00 00 00 02 05 a6 05 00 02 00 02 - * 50: ff ff ff ff 02 06 04 00 00 00 00 00 00 00 00 00 - * - * auto :: 40: 01 04 01 04 01 04 01 04 02 05 a6 cf 00 02 00 02 - * 50: ff ff ff ff aa 06 04 00 00 00 00 00 00 00 00 00 - * - * NO-Devices - * 40: 00 00 00 00 00 00 00 00 02 05 a6 00 00 02 00 02 - * 50: ff ff ff ff 00 06 00 00 00 00 00 00 00 00 00 00 - */ - -#include <linux/config.h> -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/delay.h> -#include <linux/timer.h> -#include <linux/mm.h> -#include <linux/ioport.h> -#include <linux/blkdev.h> -#include <linux/hdreg.h> - -#include <linux/interrupt.h> -#include <linux/pci.h> -#include <linux/init.h> -#include <linux/ide.h> - -#include <asm/io.h> -#include <asm/irq.h> - -#include "ide_modes.h" - -#define ACARD_DEBUG_DRIVE_INFO 0 - -#undef DISPLAY_AEC6210_TIMINGS - -#if defined(DISPLAY_AEC6210_TIMINGS) && defined(CONFIG_PROC_FS) -#include <linux/stat.h> -#include <linux/proc_fs.h> - -static int aec6210_get_info(char *, char **, off_t, int); -extern int (*aec6210_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -extern char *ide_media_verbose(ide_drive_t *); -static struct pci_dev *bmide_dev; - -static int aec6210_get_info (char *buffer, char **addr, off_t offset, int count) -{ - char *p = buffer; - - u32 bibma = bmide_dev->resource[4].start; - u8 c0 = 0, c1 = 0; - - p += sprintf(p, "\n AEC6210 Chipset.\n"); - - /* - * at that point bibma+0x2 et bibma+0xa are byte registers - * to investigate: - */ - c0 = inb_p((unsigned short)bibma + 0x02); - c1 = inb_p((unsigned short)bibma + 0x0a); - - p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n"); - p += sprintf(p, " %sabled %sabled\n", - (c0&0x80) ? "dis" : " en", - (c1&0x80) ? "dis" : " en"); - p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n"); - p += sprintf(p, "DMA enabled: %s %s %s %s\n", - (c0&0x20) ? "yes" : "no ", (c0&0x40) ? "yes" : "no ", - (c1&0x20) ? "yes" : "no ", (c1&0x40) ? "yes" : "no " ); - - p += sprintf(p, "UDMA\n"); - p += sprintf(p, "DMA\n"); - p += sprintf(p, "PIO\n"); - return p-buffer;/* => must be less than 4k! */ -} -#endif /* defined(DISPLAY_AEC6210_TIMINGS) && defined(CONFIG_PROC_FS) */ - -byte aec6210_proc = 0; - -#ifdef CONFIG_AEC6210_TUNING - -struct chipset_bus_clock_list_entry { - byte xfer_speed; - unsigned short chipset_settings; - byte ultra_settings; -}; - -struct chipset_bus_clock_list_entry aec6210_base [] = { - { XFER_UDMA_2, 0x0401, 0x02 }, - { XFER_UDMA_1, 0x0401, 0x01 }, - { XFER_UDMA_0, 0x0401, 0x01 }, - - { XFER_MW_DMA_2, 0x0401, 0x00 }, - { XFER_MW_DMA_1, 0x0402, 0x00 }, - { XFER_MW_DMA_0, 0x070a, 0x00 }, - - { XFER_PIO_4, 0x0401, 0x00 }, - { XFER_PIO_3, 0x0403, 0x00 }, - { XFER_PIO_2, 0x0708, 0x00 }, - { XFER_PIO_1, 0x070a, 0x00 }, - { XFER_PIO_0, 0x0700, 0x00 }, - { 0, 0x0000, 0x00 } -}; - -extern char *ide_xfer_verbose (byte xfer_rate); - -/* - * TO DO: active tuning and correction of cards without a bios. - */ - -static unsigned short pci_bus_clock_list (byte speed, struct chipset_bus_clock_list_entry * chipset_table) -{ - for ( ; chipset_table->xfer_speed ; chipset_table++) - if (chipset_table->xfer_speed == speed) { - return chipset_table->chipset_settings; - } - return 0x0000; -} - -static byte pci_bus_clock_list_ultra (byte speed, struct chipset_bus_clock_list_entry * chipset_table) -{ - for ( ; chipset_table->xfer_speed ; chipset_table++) - if (chipset_table->xfer_speed == speed) { - return chipset_table->ultra_settings; - } - return 0x00; -} - -static int aec6210_tune_chipset (ide_drive_t *drive, byte speed) -{ - ide_hwif_t *hwif = HWIF(drive); - - int err; - byte drive_pci; - unsigned short drive_conf = 0x0000; - byte ultra = 0x00, ultra_conf = 0x00; - byte tmp1 = 0x00, tmp2 = 0x00; - - int drive_number = ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01)); - - switch(drive_number) { - case 0: drive_pci = 0x40; break; - case 1: drive_pci = 0x42; break; - case 2: drive_pci = 0x44; break; - case 3: drive_pci = 0x46; break; - default: return -1; - } - - pci_read_config_word(HWIF(drive)->pci_dev, drive_pci, &drive_conf); - drive_conf = pci_bus_clock_list(speed, aec6210_base); - pci_write_config_word(HWIF(drive)->pci_dev, drive_pci, drive_conf); - - pci_read_config_byte(HWIF(drive)->pci_dev, 0x54, &ultra); - tmp1 = ((0x00 << (2*drive_number)) | (ultra & ~(3 << (2*drive_number)))); - ultra_conf = pci_bus_clock_list_ultra(speed, aec6210_base); - tmp2 = ((ultra_conf << (2*drive_number)) | (tmp1 & ~(3 << (2*drive_number)))); - pci_write_config_byte(HWIF(drive)->pci_dev, 0x54, tmp2); - - err = ide_config_drive_speed(drive, speed); - -#if ACARD_DEBUG_DRIVE_INFO - printk("%s: %s drive%d 0x04%x 0x02%x 0x02%x 0x02%x 0x02%x\n", - drive->name, ide_xfer_verbose(speed), drive_number, - drive_conf, ultra, tmp1, ultra_conf, tmp2); -#endif /* ACARD_DEBUG_DRIVE_INFO */ - - return(err); -} - -static int config_chipset_for_dma (ide_drive_t *drive, byte ultra) -{ - struct hd_driveid *id = drive->id; - byte speed = -1; - - if (drive->media != ide_disk) - return ((int) ide_dma_off_quietly); - - if (((id->dma_ultra & 0x0010) || - (id->dma_ultra & 0x0008) || - (id->dma_ultra & 0x0004)) && (ultra)) { - speed = XFER_UDMA_2; - } else if ((id->dma_ultra & 0x0002) && (ultra)) { - speed = XFER_UDMA_1; - } else if ((id->dma_ultra & 0x0001) && (ultra)) { - speed = XFER_UDMA_0; - } else if (id->dma_mword & 0x0004) { - speed = XFER_MW_DMA_2; - } else if (id->dma_mword & 0x0002) { - speed = XFER_MW_DMA_1; - } else if (id->dma_mword & 0x0001) { - speed = XFER_MW_DMA_0; - } else if (id->dma_1word & 0x0004) { - speed = XFER_SW_DMA_2; - } else if (id->dma_1word & 0x0002) { - speed = XFER_SW_DMA_1; - } else if (id->dma_1word & 0x0001) { - speed = XFER_SW_DMA_0; - } else { - return ((int) ide_dma_off_quietly); - } - (void) aec6210_tune_chipset(drive, speed); - - return ((int) ((id->dma_ultra >> 11) & 3) ? ide_dma_off : - ((id->dma_ultra >> 8) & 7) ? ide_dma_on : - ((id->dma_mword >> 8) & 7) ? ide_dma_on : - ((id->dma_1word >> 8) & 7) ? ide_dma_on : - ide_dma_off_quietly); -} - -static void aec6210_tune_drive (ide_drive_t *drive, byte pio) -{ - byte speed; - - switch(pio) { - case 5: - speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, 5, NULL); - case 4: - speed = XFER_PIO_4; break; - case 3: - speed = XFER_PIO_3; break; - case 2: - speed = XFER_PIO_2; break; - case 1: - speed = XFER_PIO_1; break; - default: - speed = XFER_PIO_0; break; - } - (void) aec6210_tune_chipset(drive, speed); -} - -static int config_drive_xfer_rate (ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - ide_dma_action_t dma_func = ide_dma_on; - - if (id && (id->capability & 1) && HWIF(drive)->autodma) { - /* Consult the list of known "bad" drives */ - if (ide_dmaproc(ide_dma_bad_drive, drive)) { - dma_func = ide_dma_off; - goto fast_ata_pio; - } - dma_func = ide_dma_off_quietly; - if (id->field_valid & 4) { - if (id->dma_ultra & 0x001F) { - /* Force if Capable UltraDMA */ - dma_func = config_chipset_for_dma(drive, 1); - if ((id->field_valid & 2) && - (dma_func != ide_dma_on)) - goto try_dma_modes; - } - } else if (id->field_valid & 2) { -try_dma_modes: - if ((id->dma_mword & 0x0007) || - (id->dma_1word & 0x0007)) { - /* Force if Capable regular DMA modes */ - dma_func = config_chipset_for_dma(drive, 0); - if (dma_func != ide_dma_on) - goto no_dma_set; - } - } else if (ide_dmaproc(ide_dma_good_drive, drive)) { - if (id->eide_dma_time > 150) { - goto no_dma_set; - } - /* Consult the list of known "good" drives */ - dma_func = config_chipset_for_dma(drive, 0); - if (dma_func != ide_dma_on) - goto no_dma_set; - } else { - goto fast_ata_pio; - } - } else if ((id->capability & 8) || (id->field_valid & 2)) { -fast_ata_pio: - dma_func = ide_dma_off_quietly; -no_dma_set: - aec6210_tune_drive(drive, 5); - } - return HWIF(drive)->dmaproc(dma_func, drive); -} - -/* - * aec6210_dmaproc() initiates/aborts (U)DMA read/write operations on a drive. - */ -int aec6210_dmaproc (ide_dma_action_t func, ide_drive_t *drive) -{ - switch (func) { - case ide_dma_check: - return config_drive_xfer_rate(drive); - default: - break; - } - return ide_dmaproc(func, drive); /* use standard DMA stuff */ -} -#endif /* CONFIG_AEC6210_TUNING */ - -unsigned int __init pci_init_aec6210 (struct pci_dev *dev, const char *name) -{ - if (dev->resource[PCI_ROM_RESOURCE].start) { - pci_write_config_dword(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); - printk("%s: ROM enabled at 0x%08lx\n", name, dev->resource[PCI_ROM_RESOURCE].start); - } - -#if defined(DISPLAY_AEC6210_TIMINGS) && defined(CONFIG_PROC_FS) - aec6210_proc = 1; - bmide_dev = dev; - aec6210_display_info = &aec6210_get_info; -#endif /* DISPLAY_AEC6210_TIMINGS && CONFIG_PROC_FS */ - - return dev->irq; -} - -void __init ide_init_aec6210 (ide_hwif_t *hwif) -{ -#ifdef CONFIG_AEC6210_TUNING - hwif->tuneproc = &aec6210_tune_drive; - - if (hwif->dma_base) { - hwif->dmaproc = &aec6210_dmaproc; - } else { - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - } -#endif /* CONFIG_AEC6210_TUNING */ -} - -void __init ide_dmacapable_aec6210 (ide_hwif_t *hwif, unsigned long dmabase) -{ - byte dma_new = 0; - byte dma_old = inb(dmabase+2); - byte reg54h = 0; - byte masterdma = hwif->channel ? 0x30 : 0x03; - byte slavedma = hwif->channel ? 0xc0 : 0x0c; - unsigned long flags; - - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ - - dma_new = dma_old; - - pci_read_config_byte(hwif->pci_dev, 0x54, ®54h); - - if (reg54h & masterdma) dma_new |= 0x20; - if (reg54h & slavedma) dma_new |= 0x40; - if (dma_new != dma_old) outb(dma_new, dmabase+2); - - __restore_flags(flags); /* local CPU only */ - - ide_setup_dma(hwif, dmabase, 8); -} diff --git a/drivers/block/ali14xx.c b/drivers/block/ali14xx.c deleted file mode 100644 index b3ffaa529..000000000 --- a/drivers/block/ali14xx.c +++ /dev/null @@ -1,225 +0,0 @@ -/* - * linux/drivers/block/ali14xx.c Version 0.03 Feb 09, 1996 - * - * Copyright (C) 1996 Linus Torvalds & author (see below) - */ - -/* - * ALI M14xx chipset EIDE controller - * - * Works for ALI M1439/1443/1445/1487/1489 chipsets. - * - * Adapted from code developed by derekn@vw.ece.cmu.edu. -ml - * Derek's notes follow: - * - * I think the code should be pretty understandable, - * but I'll be happy to (try to) answer questions. - * - * The critical part is in the setupDrive function. The initRegisters - * function doesn't seem to be necessary, but the DOS driver does it, so - * I threw it in. - * - * I've only tested this on my system, which only has one disk. I posted - * it to comp.sys.linux.hardware, so maybe some other people will try it - * out. - * - * Derek Noonburg (derekn@ece.cmu.edu) - * 95-sep-26 - * - * Update 96-jul-13: - * - * I've since upgraded to two disks and a CD-ROM, with no trouble, and - * I've also heard from several others who have used it successfully. - * This driver appears to work with both the 1443/1445 and the 1487/1489 - * chipsets. I've added support for PIO mode 4 for the 1487. This - * seems to work just fine on the 1443 also, although I'm not sure it's - * advertised as supporting mode 4. (I've been running a WDC AC21200 in - * mode 4 for a while now with no trouble.) -Derek - */ - -#undef REALLY_SLOW_IO /* most systems can safely undef this */ - -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/delay.h> -#include <linux/timer.h> -#include <linux/mm.h> -#include <linux/ioport.h> -#include <linux/blkdev.h> -#include <linux/hdreg.h> -#include <linux/ide.h> - -#include <asm/io.h> - -#include "ide_modes.h" - -/* port addresses for auto-detection */ -#define ALI_NUM_PORTS 4 -static int ports[ALI_NUM_PORTS] __initdata = {0x074, 0x0f4, 0x034, 0x0e4}; - -/* register initialization data */ -typedef struct { byte reg, data; } RegInitializer; - -static RegInitializer initData[] __initdata = { - {0x01, 0x0f}, {0x02, 0x00}, {0x03, 0x00}, {0x04, 0x00}, - {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x2b}, {0x0a, 0x0f}, - {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00}, {0x28, 0x00}, - {0x29, 0x00}, {0x2a, 0x00}, {0x2f, 0x00}, {0x2b, 0x00}, - {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x30, 0x00}, - {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00}, {0x34, 0xff}, - {0x35, 0x03}, {0x00, 0x00} -}; - -#define ALI_MAX_PIO 4 - -/* timing parameter registers for each drive */ -static struct { byte reg1, reg2, reg3, reg4; } regTab[4] = { - {0x03, 0x26, 0x04, 0x27}, /* drive 0 */ - {0x05, 0x28, 0x06, 0x29}, /* drive 1 */ - {0x2b, 0x30, 0x2c, 0x31}, /* drive 2 */ - {0x2d, 0x32, 0x2e, 0x33}, /* drive 3 */ -}; - -static int basePort = 0; /* base port address */ -static int regPort = 0; /* port for register number */ -static int dataPort = 0; /* port for register data */ -static byte regOn; /* output to base port to access registers */ -static byte regOff; /* output to base port to close registers */ - -/*------------------------------------------------------------------------*/ - -/* - * Read a controller register. - */ -static inline byte inReg (byte reg) -{ - outb_p(reg, regPort); - return inb(dataPort); -} - -/* - * Write a controller register. - */ -static void outReg (byte data, byte reg) -{ - outb_p(reg, regPort); - outb_p(data, dataPort); -} - -/* - * Set PIO mode for the specified drive. - * This function computes timing parameters - * and sets controller registers accordingly. - */ -static void ali14xx_tune_drive (ide_drive_t *drive, byte pio) -{ - int driveNum; - int time1, time2; - byte param1, param2, param3, param4; - unsigned long flags; - ide_pio_data_t d; - int bus_speed = ide_system_bus_speed(); - - pio = ide_get_best_pio_mode(drive, pio, ALI_MAX_PIO, &d); - - /* calculate timing, according to PIO mode */ - time1 = d.cycle_time; - time2 = ide_pio_timings[pio].active_time; - param3 = param1 = (time2 * bus_speed + 999) / 1000; - param4 = param2 = (time1 * bus_speed + 999) / 1000 - param1; - if (pio < 3) { - param3 += 8; - param4 += 8; - } - printk("%s: PIO mode%d, t1=%dns, t2=%dns, cycles = %d+%d, %d+%d\n", - drive->name, pio, time1, time2, param1, param2, param3, param4); - - /* stuff timing parameters into controller registers */ - driveNum = (HWIF(drive)->index << 1) + drive->select.b.unit; - save_flags(flags); /* all CPUs */ - cli(); /* all CPUs */ - outb_p(regOn, basePort); - outReg(param1, regTab[driveNum].reg1); - outReg(param2, regTab[driveNum].reg2); - outReg(param3, regTab[driveNum].reg3); - outReg(param4, regTab[driveNum].reg4); - outb_p(regOff, basePort); - restore_flags(flags); /* all CPUs */ -} - -/* - * Auto-detect the IDE controller port. - */ -static int __init findPort (void) -{ - int i; - byte t; - unsigned long flags; - - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ - for (i = 0; i < ALI_NUM_PORTS; ++i) { - basePort = ports[i]; - regOff = inb(basePort); - for (regOn = 0x30; regOn <= 0x33; ++regOn) { - outb_p(regOn, basePort); - if (inb(basePort) == regOn) { - regPort = basePort + 4; - dataPort = basePort + 8; - t = inReg(0) & 0xf0; - outb_p(regOff, basePort); - __restore_flags(flags); /* local CPU only */ - if (t != 0x50) - return 0; - return 1; /* success */ - } - } - outb_p(regOff, basePort); - } - __restore_flags(flags); /* local CPU only */ - return 0; -} - -/* - * Initialize controller registers with default values. - */ -static int __init initRegisters (void) { - RegInitializer *p; - byte t; - unsigned long flags; - - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ - outb_p(regOn, basePort); - for (p = initData; p->reg != 0; ++p) - outReg(p->data, p->reg); - outb_p(0x01, regPort); - t = inb(regPort) & 0x01; - outb_p(regOff, basePort); - __restore_flags(flags); /* local CPU only */ - return t; -} - -void __init init_ali14xx (void) -{ - /* auto-detect IDE controller port */ - if (!findPort()) { - printk("\nali14xx: not found"); - return; - } - - printk("\nali14xx: base= 0x%03x, regOn = 0x%02x", basePort, regOn); - ide_hwifs[0].chipset = ide_ali14xx; - ide_hwifs[1].chipset = ide_ali14xx; - ide_hwifs[0].tuneproc = &ali14xx_tune_drive; - ide_hwifs[1].tuneproc = &ali14xx_tune_drive; - ide_hwifs[0].mate = &ide_hwifs[1]; - ide_hwifs[1].mate = &ide_hwifs[0]; - ide_hwifs[1].channel = 1; - - /* initialize controller registers */ - if (!initRegisters()) { - printk("\nali14xx: Chip initialization failed"); - return; - } -} diff --git a/drivers/block/alim15x3.c b/drivers/block/alim15x3.c deleted file mode 100644 index bc3d2b9e3..000000000 --- a/drivers/block/alim15x3.c +++ /dev/null @@ -1,689 +0,0 @@ -/* - * linux/drivers/block/alim15x3.c Version 0.08 Jan. 14, 2000 - * - * Copyright (C) 1998-2000 Michel Aubry, Maintainer - * Copyright (C) 1998-2000 Andrzej Krzysztofowicz, Maintainer - * - * Copyright (C) 1998-2000 Andre Hedrick (andre@suse.com) - * May be copied or modified under the terms of the GNU General Public License - * - * (U)DMA capable version of ali 1533/1543(C), 1535(D) - * - * version: 1.0 beta2 (Sep. 2, 1999) - * e-mail your problems to cjtsai@ali.com.tw - * - ********************************************************************** - * 9/7/99 --Parts from the above author are included and need to be - * converted into standard interface, once I finish the thought. - */ - -#include <linux/config.h> -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/pci.h> -#include <linux/delay.h> -#include <linux/hdreg.h> -#include <linux/ide.h> - -#include <asm/io.h> - -#include "ide_modes.h" - -#define DISPLAY_ALI_TIMINGS - -#if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) -#include <linux/stat.h> -#include <linux/proc_fs.h> - -static int ali_get_info(char *buffer, char **addr, off_t offset, int count); -extern int (*ali_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -struct pci_dev *bmide_dev; - -char *fifo[4] = { - "FIFO Off", - "FIFO On ", - "DMA mode", - "PIO mode" }; - -char *udmaT[8] = { - "1.5T", - " 2T", - "2.5T", - " 3T", - "3.5T", - " 4T", - " 6T", - " 8T" -}; - -char *channel_status[8] = { - "OK ", - "busy ", - "DRQ ", - "DRQ busy ", - "error ", - "error busy ", - "error DRQ ", - "error DRQ busy" -}; - -static int ali_get_info(char *buffer, char **addr, off_t offset, int count) -{ - byte reg53h, reg5xh, reg5yh, reg5xh1, reg5yh1; - unsigned int bibma; - byte c0, c1; - byte rev, tmp; - char *p = buffer; - char *q; - - /* fetch rev. */ - pci_read_config_byte(bmide_dev, 0x08, &rev); - if (rev >= 0xc1) /* M1543C or newer */ - udmaT[7] = " ???"; - else - fifo[3] = " ??? "; - - /* first fetch bibma: */ - pci_read_config_dword(bmide_dev, 0x20, &bibma); - bibma = (bibma & 0xfff0) ; - /* - * at that point bibma+0x2 et bibma+0xa are byte - * registers to investigate: - */ - c0 = inb((unsigned short)bibma + 0x02); - c1 = inb((unsigned short)bibma + 0x0a); - - p += sprintf(p, - "\n Ali M15x3 Chipset.\n"); - p += sprintf(p, - " ------------------\n"); - pci_read_config_byte(bmide_dev, 0x78, ®53h); - p += sprintf(p, "PCI Clock: %d.\n", reg53h); - - pci_read_config_byte(bmide_dev, 0x53, ®53h); - p += sprintf(p, - "CD_ROM FIFO:%s, CD_ROM DMA:%s\n", - (reg53h & 0x02) ? "Yes" : "No ", - (reg53h & 0x01) ? "Yes" : "No " ); - pci_read_config_byte(bmide_dev, 0x74, ®53h); - p += sprintf(p, - "FIFO Status: contains %d Words, runs%s%s\n\n", - (reg53h & 0x3f), - (reg53h & 0x40) ? " OVERWR" : "", - (reg53h & 0x80) ? " OVERRD." : "." ); - - p += sprintf(p, - "-------------------primary channel-------------------secondary channel---------\n\n"); - - pci_read_config_byte(bmide_dev, 0x09, ®53h); - p += sprintf(p, - "channel status: %s %s\n", - (reg53h & 0x20) ? "On " : "Off", - (reg53h & 0x10) ? "On " : "Off" ); - - p += sprintf(p, - "both channels togth: %s %s\n", - (c0&0x80) ? "No " : "Yes", - (c1&0x80) ? "No " : "Yes" ); - - pci_read_config_byte(bmide_dev, 0x76, ®53h); - p += sprintf(p, - "Channel state: %s %s\n", - channel_status[reg53h & 0x07], - channel_status[(reg53h & 0x70) >> 4] ); - - pci_read_config_byte(bmide_dev, 0x58, ®5xh); - pci_read_config_byte(bmide_dev, 0x5c, ®5yh); - p += sprintf(p, - "Add. Setup Timing: %dT %dT\n", - (reg5xh & 0x07) ? (reg5xh & 0x07) : 8, - (reg5yh & 0x07) ? (reg5yh & 0x07) : 8 ); - - pci_read_config_byte(bmide_dev, 0x59, ®5xh); - pci_read_config_byte(bmide_dev, 0x5d, ®5yh); - p += sprintf(p, - "Command Act. Count: %dT %dT\n" - "Command Rec. Count: %dT %dT\n\n", - (reg5xh & 0x70) ? ((reg5xh & 0x70) >> 4) : 8, - (reg5yh & 0x70) ? ((reg5yh & 0x70) >> 4) : 8, - (reg5xh & 0x0f) ? (reg5xh & 0x0f) : 16, - (reg5yh & 0x0f) ? (reg5yh & 0x0f) : 16 ); - - p += sprintf(p, - "----------------drive0-----------drive1------------drive0-----------drive1------\n\n"); - p += sprintf(p, - "DMA enabled: %s %s %s %s\n", - (c0&0x20) ? "Yes" : "No ", - (c0&0x40) ? "Yes" : "No ", - (c1&0x20) ? "Yes" : "No ", - (c1&0x40) ? "Yes" : "No " ); - - pci_read_config_byte(bmide_dev, 0x54, ®5xh); - pci_read_config_byte(bmide_dev, 0x55, ®5yh); - q = "FIFO threshold: %2d Words %2d Words %2d Words %2d Words\n"; - if (rev < 0xc1) { - if ((rev == 0x20) && (pci_read_config_byte(bmide_dev, 0x4f, &tmp), (tmp &= 0x20))) { - p += sprintf(p, q, 8, 8, 8, 8); - } else { - p += sprintf(p, q, - (reg5xh & 0x03) + 12, - ((reg5xh & 0x30)>>4) + 12, - (reg5yh & 0x03) + 12, - ((reg5yh & 0x30)>>4) + 12 ); - } - } else { - p += sprintf(p, q, - (tmp = (reg5xh & 0x03)) ? (tmp << 3) : 4, - (tmp = ((reg5xh & 0x30)>>4)) ? (tmp << 3) : 4, - (tmp = (reg5yh & 0x03)) ? (tmp << 3) : 4, - (tmp = ((reg5yh & 0x30)>>4)) ? (tmp << 3) : 4 ); - } - -#if 0 - p += sprintf(p, - "FIFO threshold: %2d Words %2d Words %2d Words %2d Words\n", - (reg5xh & 0x03) + 12, - ((reg5xh & 0x30)>>4) + 12, - (reg5yh & 0x03) + 12, - ((reg5yh & 0x30)>>4) + 12 ); -#endif - - p += sprintf(p, - "FIFO mode: %s %s %s %s\n", - fifo[((reg5xh & 0x0c) >> 2)], - fifo[((reg5xh & 0xc0) >> 6)], - fifo[((reg5yh & 0x0c) >> 2)], - fifo[((reg5yh & 0xc0) >> 6)] ); - - pci_read_config_byte(bmide_dev, 0x5a, ®5xh); - pci_read_config_byte(bmide_dev, 0x5b, ®5xh1); - pci_read_config_byte(bmide_dev, 0x5e, ®5yh); - pci_read_config_byte(bmide_dev, 0x5f, ®5yh1); - - p += sprintf(p,/* - "------------------drive0-----------drive1------------drive0-----------drive1------\n")*/ - "Dt RW act. Cnt %2dT %2dT %2dT %2dT\n" - "Dt RW rec. Cnt %2dT %2dT %2dT %2dT\n\n", - (reg5xh & 0x70) ? ((reg5xh & 0x70) >> 4) : 8, - (reg5xh1 & 0x70) ? ((reg5xh1 & 0x70) >> 4) : 8, - (reg5yh & 0x70) ? ((reg5yh & 0x70) >> 4) : 8, - (reg5yh1 & 0x70) ? ((reg5yh1 & 0x70) >> 4) : 8, - (reg5xh & 0x0f) ? (reg5xh & 0x0f) : 16, - (reg5xh1 & 0x0f) ? (reg5xh1 & 0x0f) : 16, - (reg5yh & 0x0f) ? (reg5yh & 0x0f) : 16, - (reg5yh1 & 0x0f) ? (reg5yh1 & 0x0f) : 16 ); - - p += sprintf(p, - "-----------------------------------UDMA Timings--------------------------------\n\n"); - - pci_read_config_byte(bmide_dev, 0x56, ®5xh); - pci_read_config_byte(bmide_dev, 0x57, ®5yh); - p += sprintf(p, - "UDMA: %s %s %s %s\n" - "UDMA timings: %s %s %s %s\n\n", - (reg5xh & 0x08) ? "OK" : "No", - (reg5xh & 0x80) ? "OK" : "No", - (reg5yh & 0x08) ? "OK" : "No", - (reg5yh & 0x80) ? "OK" : "No", - udmaT[(reg5xh & 0x07)], - udmaT[(reg5xh & 0x70) >> 4], - udmaT[reg5yh & 0x07], - udmaT[(reg5yh & 0x70) >> 4] ); - - return p-buffer; /* => must be less than 4k! */ -} -#endif /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) */ - -static byte m5229_revision = 0; -static byte chip_is_1543c_e = 0; -static byte cable_80_pin[2] = { 0, 0 }; - -byte ali_proc = 0; -static struct pci_dev *isa_dev; - -static void ali15x3_tune_drive (ide_drive_t *drive, byte pio) -{ - ide_pio_data_t d; - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - int s_time, a_time, c_time; - byte s_clc, a_clc, r_clc; - unsigned long flags; - int bus_speed = ide_system_bus_speed(); - int port = hwif->index ? 0x5c : 0x58; - int portFIFO = hwif->channel ? 0x55 : 0x54; - byte cd_dma_fifo = 0; - - pio = ide_get_best_pio_mode(drive, pio, 5, &d); - s_time = ide_pio_timings[pio].setup_time; - a_time = ide_pio_timings[pio].active_time; - if ((s_clc = (s_time * bus_speed + 999) / 1000) >= 8) - s_clc = 0; - if ((a_clc = (a_time * bus_speed + 999) / 1000) >= 8) - a_clc = 0; - c_time = ide_pio_timings[pio].cycle_time; - -#if 0 - if ((r_clc = ((c_time - s_time - a_time) * bus_speed + 999) / 1000) >= 16) - r_clc = 0; -#endif - - if (!(r_clc = (c_time * bus_speed + 999) / 1000 - a_clc - s_clc)) { - r_clc = 1; - } else { - if (r_clc >= 16) - r_clc = 0; - } - __save_flags(flags); - __cli(); - - /* - * PIO mode => ATA FIFO on, ATAPI FIFO off - */ - pci_read_config_byte(dev, portFIFO, &cd_dma_fifo); - if (drive->media==ide_disk) { - if (hwif->index) { - pci_write_config_byte(dev, portFIFO, (cd_dma_fifo & 0x0F) | 0x50); - } else { - pci_write_config_byte(dev, portFIFO, (cd_dma_fifo & 0xF0) | 0x05); - } - } else { - if (hwif->index) { - pci_write_config_byte(dev, portFIFO, cd_dma_fifo & 0x0F); - } else { - pci_write_config_byte(dev, portFIFO, cd_dma_fifo & 0xF0); - } - } - - pci_write_config_byte(dev, port, s_clc); - pci_write_config_byte(dev, port+drive->select.b.unit+2, (a_clc << 4) | r_clc); - __restore_flags(flags); - - /* - * setup active rec - * { 70, 165, 365 }, PIO Mode 0 - * { 50, 125, 208 }, PIO Mode 1 - * { 30, 100, 110 }, PIO Mode 2 - * { 30, 80, 70 }, PIO Mode 3 with IORDY - * { 25, 70, 25 }, PIO Mode 4 with IORDY ns - * { 20, 50, 30 } PIO Mode 5 with IORDY (nonstandard) - */ - -} - -static int ali15x3_tune_chipset (ide_drive_t *drive, byte speed) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - byte unit = (drive->select.b.unit & 0x01); - byte tmpbyte = 0x00; - int m5229_udma = hwif->channel? 0x57 : 0x56; - int err = 0; - - if (speed < XFER_UDMA_0) { - byte ultra_enable = (unit) ? 0x7f : 0xf7; - /* - * clear "ultra enable" bit - */ - pci_read_config_byte(dev, m5229_udma, &tmpbyte); - tmpbyte &= ultra_enable; - pci_write_config_byte(dev, m5229_udma, tmpbyte); - } - - err = ide_config_drive_speed(drive, speed); - - if (speed >= XFER_SW_DMA_0) { - unsigned long dma_base = hwif->dma_base; - - outb(inb(dma_base+2)|(1<<(5+unit)), dma_base+2); - } - - if (speed >= XFER_UDMA_0) { - pci_read_config_byte(dev, m5229_udma, &tmpbyte); - tmpbyte &= (0x0f << ((1-unit) << 2)); - /* - * enable ultra dma and set timing - */ - tmpbyte |= ((0x08 | (4-speed)) << (unit << 2)); - pci_write_config_byte(dev, m5229_udma, tmpbyte); - if (speed >= XFER_UDMA_3) { - pci_read_config_byte(dev, 0x4b, &tmpbyte); - tmpbyte |= 1; - pci_write_config_byte(dev, 0x4b, tmpbyte); - } - } - - return (err); -} - -static int config_chipset_for_dma (ide_drive_t *drive, byte ultra33) -{ - struct hd_driveid *id = drive->id; - ide_hwif_t *hwif = HWIF(drive); - byte speed = 0x00; - byte ultra66 = ((hwif->udma_four) && (id->hw_config & 0x2000)) ? 1 : 0; - int rval; - - if ((id->dma_ultra & 0x0010) && (ultra66) && (ultra33)) { - speed = XFER_UDMA_4; - } else if ((id->dma_ultra & 0x0008) && (ultra66) && (ultra33)) { - speed = XFER_UDMA_3; - } else if ((id->dma_ultra & 0x0004) && (ultra33)) { - speed = XFER_UDMA_2; - } else if ((id->dma_ultra & 0x0002) && (ultra33)) { - speed = XFER_UDMA_1; - } else if ((id->dma_ultra & 0x0001) && (ultra33)) { - speed = XFER_UDMA_0; - } else if (id->dma_mword & 0x0004) { - speed = XFER_MW_DMA_2; - } else if (id->dma_mword & 0x0002) { - speed = XFER_MW_DMA_1; - } else if (id->dma_mword & 0x0001) { - speed = XFER_MW_DMA_0; - } else if (id->dma_1word & 0x0004) { - speed = XFER_SW_DMA_2; - } else if (id->dma_1word & 0x0002) { - speed = XFER_SW_DMA_1; - } else if (id->dma_1word & 0x0001) { - speed = XFER_SW_DMA_0; - } else { - return ((int) ide_dma_off_quietly); - } - - (void) ali15x3_tune_chipset(drive, speed); - - rval = (int)( ((id->dma_ultra >> 11) & 3) ? ide_dma_on : - ((id->dma_ultra >> 8) & 7) ? ide_dma_on : - ((id->dma_mword >> 8) & 7) ? ide_dma_on : - ((id->dma_1word >> 8) & 7) ? ide_dma_on : - ide_dma_off_quietly); - - return rval; -} - -static void config_chipset_for_pio (ide_drive_t *drive) -{ - ali15x3_tune_drive(drive, 5); -} - - -static byte ali15x3_can_ultra (ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - -#if 0 - if (m5229_revision < 0x20) { -#else - if (m5229_revision <= 0x20) { -#endif - return 0; - } else if ((m5229_revision < 0xC2) && - ((drive->media!=ide_disk) || - (chip_is_1543c_e && - strstr(id->model, "WDC ")))) { - return 0; - } else { - return 1; - } -} - -static int ali15x3_config_drive_for_dma(ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - ide_hwif_t *hwif = HWIF(drive); - ide_dma_action_t dma_func = ide_dma_on; - byte can_ultra_dma = ali15x3_can_ultra(drive); - - if ((m5229_revision<=0x20) && (drive->media!=ide_disk)) - return hwif->dmaproc(ide_dma_off_quietly, drive); - - if ((id != NULL) && ((id->capability & 1) != 0) && hwif->autodma) { - /* Consult the list of known "bad" drives */ - if (ide_dmaproc(ide_dma_bad_drive, drive)) { - dma_func = ide_dma_off; - goto fast_ata_pio; - } - dma_func = ide_dma_off_quietly; - if ((id->field_valid & 4) && (m5229_revision >= 0xC2)) { - if (id->dma_ultra & 0x001F) { - /* Force if Capable UltraDMA */ - dma_func = config_chipset_for_dma(drive, can_ultra_dma); - if ((id->field_valid & 2) && - (dma_func != ide_dma_on)) - goto try_dma_modes; - } - } else if (id->field_valid & 2) { -try_dma_modes: - if ((id->dma_mword & 0x0007) || - (id->dma_1word & 0x0007)) { - /* Force if Capable regular DMA modes */ - dma_func = config_chipset_for_dma(drive, can_ultra_dma); - if (dma_func != ide_dma_on) - goto no_dma_set; - } - } else if (ide_dmaproc(ide_dma_good_drive, drive)) { - if (id->eide_dma_time > 150) { - goto no_dma_set; - } - /* Consult the list of known "good" drives */ - dma_func = config_chipset_for_dma(drive, can_ultra_dma); - if (dma_func != ide_dma_on) - goto no_dma_set; - } else { - goto fast_ata_pio; - } - } else if ((id->capability & 8) || (id->field_valid & 2)) { -fast_ata_pio: - dma_func = ide_dma_off_quietly; -no_dma_set: - config_chipset_for_pio(drive); - } - return hwif->dmaproc(dma_func, drive); -} - -static int ali15x3_dmaproc (ide_dma_action_t func, ide_drive_t *drive) -{ - switch(func) { - case ide_dma_check: - return ali15x3_config_drive_for_dma(drive); - case ide_dma_write: - if ((m5229_revision < 0xC2) && (drive->media != ide_disk)) - return 1; /* try PIO instead of DMA */ - break; - default: - break; - } - return ide_dmaproc(func, drive); /* use standard DMA stuff */ -} - -unsigned int __init pci_init_ali15x3 (struct pci_dev *dev, const char *name) -{ - unsigned long fixdma_base = dev->resource[4].start; - - pci_read_config_byte(dev, PCI_REVISION_ID, &m5229_revision); - - isa_dev = pci_find_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL); - - if (!fixdma_base || fixdma_base == PCI_BASE_ADDRESS_IO_MASK) { - /* - * - */ - } else { - /* - * enable DMA capable bit, and "not" simplex only - */ - outb(inb(fixdma_base+2) & 0x60, fixdma_base+2); - - if (inb(fixdma_base+2) & 0x80) - printk("%s: simplex device: DMA will fail!!\n", name); - } - -#if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) - ali_proc = 1; - bmide_dev = dev; - ali_display_info = &ali_get_info; -#endif /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) */ - - return 0; -} - -unsigned int __init ata66_ali15x3 (ide_hwif_t *hwif) -{ - struct pci_dev *dev = hwif->pci_dev; - byte ata66mask = hwif->channel ? 0x02 : 0x01; - unsigned int ata66 = 0; - - unsigned long flags; - byte tmpbyte; - - __save_flags(flags); - __cli(); - - if (m5229_revision >= 0xC2) { - /* - * 1543C-B?, 1535, 1535D, 1553 - * Note 1: not all "motherboard" support this detection - * Note 2: if no udma 66 device, the detection may "error". - * but in this case, we will not set the device to - * ultra 66, the detection result is not important - */ - - /* - * enable "Cable Detection", m5229, 0x4b, bit3 - */ - pci_read_config_byte(dev, 0x4b, &tmpbyte); - pci_write_config_byte(dev, 0x4b, tmpbyte | 0x08); - - /* - * set south-bridge's enable bit, m1533, 0x79 - */ - pci_read_config_byte(isa_dev, 0x79, &tmpbyte); - if (m5229_revision == 0xC2) { - /* - * 1543C-B0 (m1533, 0x79, bit 2) - */ - pci_write_config_byte(isa_dev, 0x79, tmpbyte | 0x04); - } else if (m5229_revision == 0xC3) { - /* - * 1553/1535 (m1533, 0x79, bit 1) - */ - pci_write_config_byte(isa_dev, 0x79, tmpbyte | 0x02); - } - /* - * Ultra66 cable detection (from Host View) - * m5229, 0x4a, bit0: primary, bit1: secondary 80 pin - */ - pci_read_config_byte(dev, 0x4a, &tmpbyte); - /* - * 0x4a, bit0 is 0 => primary channel - * has 80-pin (from host view) - */ - if (!(tmpbyte & 0x01)) cable_80_pin[0] = 1; - /* - * 0x4a, bit1 is 0 => secondary channel - * has 80-pin (from host view) - */ - if (!(tmpbyte & 0x02)) cable_80_pin[1] = 1; - } else { - /* - * revision 0x20 (1543-E, 1543-F) - * revision 0xC0, 0xC1 (1543C-C, 1543C-D, 1543C-E) - * clear CD-ROM DMA write bit, m5229, 0x4b, bit 7 - */ - pci_read_config_byte(dev, 0x4b, &tmpbyte); - /* - * clear bit 7 - */ - pci_write_config_byte(dev, 0x4b, tmpbyte & 0x7F); - /* - * check m1533, 0x5e, bit 1~4 == 1001 => & 00011110 = 00010010 - */ - pci_read_config_byte(isa_dev, 0x5e, &tmpbyte); - chip_is_1543c_e = ((tmpbyte & 0x1e) == 0x12) ? 1: 0; - } - - /* - * CD_ROM DMA on (m5229, 0x53, bit0) - * Enable this bit even if we want to use PIO - * PIO FIFO off (m5229, 0x53, bit1) - * The hardware will use 0x54h and 0x55h to control PIO FIFO - */ - pci_read_config_byte(dev, 0x53, &tmpbyte); - tmpbyte = (tmpbyte & (~0x02)) | 0x01; - - pci_write_config_byte(dev, 0x53, tmpbyte); - - /* - * Ultra66 cable detection (from Host View) - * m5229, 0x4a, bit0: primary, bit1: secondary 80 pin - * - * 0x4a, bit0 is 0 => primary channel - * has 80-pin (from host view) - * - * 0x4a, bit1 is 0 => secondary channel - * has 80-pin (from host view) - */ - pci_read_config_byte(dev, 0x4a, &tmpbyte); - ata66 = (!(tmpbyte & ata66mask)) ? 0 : 1; - __restore_flags(flags); - - return(ata66); -} - -void __init ide_init_ali15x3 (ide_hwif_t *hwif) -{ - byte ideic, inmir; - byte irq_routing_table[] = { -1, 9, 3, 10, 4, 5, 7, 6, - 1, 11, 0, 12, 0, 14, 0, 15 }; - - hwif->irq = hwif->channel ? 15 : 14; - - if (isa_dev) { - /* - * read IDE interface control - */ - pci_read_config_byte(isa_dev, 0x58, &ideic); - - /* bit0, bit1 */ - ideic = ideic & 0x03; - - /* get IRQ for IDE Controller */ - if ((hwif->channel && ideic == 0x03) || (!hwif->channel && !ideic)) { - /* - * get SIRQ1 routing table - */ - pci_read_config_byte(isa_dev, 0x44, &inmir); - inmir = inmir & 0x0f; - hwif->irq = irq_routing_table[inmir]; - } else if (hwif->channel && !(ideic & 0x01)) { - /* - * get SIRQ2 routing table - */ - pci_read_config_byte(isa_dev, 0x75, &inmir); - inmir = inmir & 0x0f; - hwif->irq = irq_routing_table[inmir]; - } - } - - hwif->tuneproc = &ali15x3_tune_drive; - if ((hwif->dma_base) && (m5229_revision >= 0x20)) { - /* - * M1543C or newer for DMAing - */ - hwif->dmaproc = &ali15x3_dmaproc; - hwif->autodma = 1; - } else { - hwif->autodma = 0; - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - } - return; -} - -void ide_dmacapable_ali15x3 (ide_hwif_t *hwif, unsigned long dmabase) -{ - if ((dmabase) && (m5229_revision < 0x20)) { - return; - } - ide_setup_dma(hwif, dmabase, 8); -} diff --git a/drivers/block/amd7409.c b/drivers/block/amd7409.c deleted file mode 100644 index 7d2018029..000000000 --- a/drivers/block/amd7409.c +++ /dev/null @@ -1,411 +0,0 @@ -/* - * linux/drivers/block/amd7409.c Version 0.03 Feb. 10, 2000 - * - * Copyright (C) 2000 Andre Hedrick <andre@suse.com> - * May be copied or modified under the terms of the GNU General Public License - * - */ - -#include <linux/config.h> -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/delay.h> -#include <linux/timer.h> -#include <linux/mm.h> -#include <linux/ioport.h> -#include <linux/blkdev.h> -#include <linux/hdreg.h> - -#include <linux/interrupt.h> -#include <linux/pci.h> -#include <linux/ide.h> - -#include <asm/io.h> -#include <asm/irq.h> - -#include "ide_modes.h" - -#define DISPLAY_VIPER_TIMINGS - -#if defined(DISPLAY_VIPER_TIMINGS) && defined(CONFIG_PROC_FS) -#include <linux/stat.h> -#include <linux/proc_fs.h> - -static int amd7409_get_info(char *, char **, off_t, int); -extern int (*amd7409_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -extern char *ide_media_verbose(ide_drive_t *); -static struct pci_dev *bmide_dev; - -static int amd7409_get_info (char *buffer, char **addr, off_t offset, int count) -{ - char *p = buffer; - u32 bibma = bmide_dev->resource[4].start; - u8 c0 = 0, c1 = 0; - - /* - * at that point bibma+0x2 et bibma+0xa are byte registers - * to investigate: - */ - c0 = inb_p((unsigned short)bibma + 0x02); - c1 = inb_p((unsigned short)bibma + 0x0a); - - p += sprintf(p, "\n AMD 7409 VIPER Chipset.\n"); - p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n"); - p += sprintf(p, " %sabled %sabled\n", - (c0&0x80) ? "dis" : " en", - (c1&0x80) ? "dis" : " en"); - p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n"); - p += sprintf(p, "DMA enabled: %s %s %s %s\n", - (c0&0x20) ? "yes" : "no ", (c0&0x40) ? "yes" : "no ", - (c1&0x20) ? "yes" : "no ", (c1&0x40) ? "yes" : "no " ); - p += sprintf(p, "UDMA\n"); - p += sprintf(p, "DMA\n"); - p += sprintf(p, "PIO\n"); - - return p-buffer; /* => must be less than 4k! */ -} -#endif /* defined(DISPLAY_VIPER_TIMINGS) && defined(CONFIG_PROC_FS) */ - -byte amd7409_proc = 0; - -extern char *ide_xfer_verbose (byte xfer_rate); - -/* - * Here is where all the hard work goes to program the chipset. - * - */ -static int amd7409_tune_chipset (ide_drive_t *drive, byte speed) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - int err = 0; - byte unit = (drive->select.b.unit & 0x01); - int drive_number = ((HWIF(drive)->channel ? 2 : 0) + unit); - unsigned long dma_base = hwif->dma_base; - byte drive_pci = 0x00; - byte drive_pci2 = 0x00; - byte ultra_timing = 0x00; - byte dma_pio_timing = 0x00; - byte pio_timing = 0x00; - - switch (drive_number) { - case 0: drive_pci = 0x53; drive_pci2 = 0x4b; break; - case 1: drive_pci = 0x52; drive_pci2 = 0x4a; break; - case 2: drive_pci = 0x51; drive_pci2 = 0x49; break; - case 3: drive_pci = 0x50; drive_pci2 = 0x48; break; - default: - return ((int) ide_dma_off_quietly); - } - - pci_read_config_byte(dev, drive_pci, &ultra_timing); - pci_read_config_byte(dev, drive_pci2, &dma_pio_timing); - pci_read_config_byte(dev, 0x4c, &pio_timing); - -#ifdef DEBUG - printk("%s: UDMA 0x%02x DMAPIO 0x%02x PIO 0x%02x ", - drive->name, ultra_timing, dma_pio_timing, pio_timing); -#endif - - ultra_timing &= ~0xC7; - dma_pio_timing &= ~0xFF; - pio_timing &= ~(0x03 << drive_number); - -#ifdef DEBUG - printk(":: UDMA 0x%02x DMAPIO 0x%02x PIO 0x%02x ", - ultra_timing, dma_pio_timing, pio_timing); -#endif - - switch(speed) { - case XFER_UDMA_4: - ultra_timing |= 0x45; - dma_pio_timing |= 0x20; - pio_timing |= (0x03 << drive_number); - break; - case XFER_UDMA_3: - ultra_timing |= 0x44; - dma_pio_timing |= 0x20; - pio_timing |= (0x03 << drive_number); - break; - case XFER_UDMA_2: - ultra_timing |= 0x40; - dma_pio_timing |= 0x20; - pio_timing |= (0x03 << drive_number); - break; - case XFER_UDMA_1: - ultra_timing |= 0x41; - dma_pio_timing |= 0x20; - pio_timing |= (0x03 << drive_number); - break; - case XFER_UDMA_0: - ultra_timing |= 0x42; - dma_pio_timing |= 0x20; - pio_timing |= (0x03 << drive_number); - break; - case XFER_MW_DMA_2: - dma_pio_timing |= 0x20; - pio_timing |= (0x03 << drive_number); - break; - case XFER_MW_DMA_1: - dma_pio_timing |= 0x21; - pio_timing |= (0x03 << drive_number); - break; - case XFER_MW_DMA_0: - dma_pio_timing |= 0x77; - pio_timing |= (0x03 << drive_number); - break; - case XFER_PIO_4: - dma_pio_timing |= 0x20; - pio_timing |= (0x03 << drive_number); - break; - case XFER_PIO_3: - dma_pio_timing |= 0x22; - pio_timing |= (0x03 << drive_number); - break; - case XFER_PIO_2: - dma_pio_timing |= 0x42; - pio_timing |= (0x03 << drive_number); - break; - case XFER_PIO_1: - dma_pio_timing |= 0x65; - pio_timing |= (0x03 << drive_number); - break; - case XFER_PIO_0: - default: - dma_pio_timing |= 0xA8; - pio_timing |= (0x03 << drive_number); - break; - } - - pci_write_config_byte(dev, drive_pci, ultra_timing); - pci_write_config_byte(dev, drive_pci2, dma_pio_timing); - pci_write_config_byte(dev, 0x4c, pio_timing); - -#ifdef DEBUG - printk(":: UDMA 0x%02x DMAPIO 0x%02x PIO 0x%02x\n", - ultra_timing, dma_pio_timing, pio_timing); -#endif - - if (speed > XFER_PIO_4) { - outb(inb(dma_base+2)|(1<<(5+unit)), dma_base+2); - } else { - outb(inb(dma_base+2) & ~(1<<(5+unit)), dma_base+2); - } - err = ide_config_drive_speed(drive, speed); - return (err); -} - -/* - * This allows the configuration of ide_pci chipset registers - * for cards that learn about the drive's UDMA, DMA, PIO capabilities - * after the drive is reported by the OS. - */ -static int config_chipset_for_dma (ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - byte udma_66 = ((id->hw_config & 0x2000) && - (HWIF(drive)->udma_four)) ? 1 : 0; - byte speed = 0x00; - int rval; - - if ((id->dma_ultra & 0x0010) && (udma_66)) { - speed = XFER_UDMA_4; - } else if ((id->dma_ultra & 0x0008) && (udma_66)) { - speed = XFER_UDMA_3; - } else if (id->dma_ultra & 0x0004) { - speed = XFER_UDMA_2; - } else if (id->dma_ultra & 0x0002) { - speed = XFER_UDMA_1; - } else if (id->dma_ultra & 0x0001) { - speed = XFER_UDMA_0; - } else if (id->dma_mword & 0x0004) { - speed = XFER_MW_DMA_2; - } else if (id->dma_mword & 0x0002) { - speed = XFER_MW_DMA_1; - } else if (id->dma_mword & 0x0001) { - speed = XFER_MW_DMA_0; - } else { - return ((int) ide_dma_off_quietly); - } - - (void) amd7409_tune_chipset(drive, speed); - - rval = (int)( ((id->dma_ultra >> 11) & 3) ? ide_dma_on : - ((id->dma_ultra >> 8) & 7) ? ide_dma_on : - ((id->dma_mword >> 8) & 7) ? ide_dma_on : - ide_dma_off_quietly); - - return rval; -} - -static void config_chipset_for_pio (ide_drive_t *drive) -{ - unsigned short eide_pio_timing[6] = {960, 480, 240, 180, 120, 90}; - unsigned short xfer_pio = drive->id->eide_pio_modes; - byte timing, speed, pio; - - pio = ide_get_best_pio_mode(drive, 255, 5, NULL); - - if (xfer_pio> 4) - xfer_pio = 0; - - if (drive->id->eide_pio_iordy > 0) { - for (xfer_pio = 5; - xfer_pio>0 && - drive->id->eide_pio_iordy>eide_pio_timing[xfer_pio]; - xfer_pio--); - } else { - xfer_pio = (drive->id->eide_pio_modes & 4) ? 0x05 : - (drive->id->eide_pio_modes & 2) ? 0x04 : - (drive->id->eide_pio_modes & 1) ? 0x03 : - (drive->id->tPIO & 2) ? 0x02 : - (drive->id->tPIO & 1) ? 0x01 : xfer_pio; - } - - timing = (xfer_pio >= pio) ? xfer_pio : pio; - - switch(timing) { - case 4: speed = XFER_PIO_4;break; - case 3: speed = XFER_PIO_3;break; - case 2: speed = XFER_PIO_2;break; - case 1: speed = XFER_PIO_1;break; - default: - speed = (!drive->id->tPIO) ? XFER_PIO_0 : XFER_PIO_SLOW; - break; - } - (void) amd7409_tune_chipset(drive, speed); -} - -static void amd7409_tune_drive (ide_drive_t *drive, byte pio) -{ - byte speed; - switch(pio) { - case 4: speed = XFER_PIO_4;break; - case 3: speed = XFER_PIO_3;break; - case 2: speed = XFER_PIO_2;break; - case 1: speed = XFER_PIO_1;break; - default: speed = XFER_PIO_0;break; - } - (void) amd7409_tune_chipset(drive, speed); -} - -static int config_drive_xfer_rate (ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - ide_dma_action_t dma_func = ide_dma_on; - - if (id && (id->capability & 1) && HWIF(drive)->autodma) { - /* Consult the list of known "bad" drives */ - if (ide_dmaproc(ide_dma_bad_drive, drive)) { - dma_func = ide_dma_off; - goto fast_ata_pio; - } - dma_func = ide_dma_off_quietly; - if (id->field_valid & 4) { - if (id->dma_ultra & 0x001F) { - /* Force if Capable UltraDMA */ - dma_func = config_chipset_for_dma(drive); - if ((id->field_valid & 2) && - (dma_func != ide_dma_on)) - goto try_dma_modes; - } - } else if (id->field_valid & 2) { -try_dma_modes: - if (id->dma_mword & 0x0007) { - /* Force if Capable regular DMA modes */ - dma_func = config_chipset_for_dma(drive); - if (dma_func != ide_dma_on) - goto no_dma_set; - } - } else if (ide_dmaproc(ide_dma_good_drive, drive)) { - if (id->eide_dma_time > 150) { - goto no_dma_set; - } - /* Consult the list of known "good" drives */ - dma_func = config_chipset_for_dma(drive); - if (dma_func != ide_dma_on) - goto no_dma_set; - } else { - goto fast_ata_pio; - } - } else if ((id->capability & 8) || (id->field_valid & 2)) { -fast_ata_pio: - dma_func = ide_dma_off_quietly; -no_dma_set: - - config_chipset_for_pio(drive); - } - return HWIF(drive)->dmaproc(dma_func, drive); -} - -/* - * amd7409_dmaproc() initiates/aborts (U)DMA read/write operations on a drive. - */ - -int amd7409_dmaproc (ide_dma_action_t func, ide_drive_t *drive) -{ - switch (func) { - case ide_dma_check: - return config_drive_xfer_rate(drive); - default: - break; - } - return ide_dmaproc(func, drive); /* use standard DMA stuff */ -} - -unsigned int __init pci_init_amd7409 (struct pci_dev *dev, const char *name) -{ - unsigned long fixdma_base = dev->resource[4].start; - - if (!fixdma_base || fixdma_base == PCI_BASE_ADDRESS_IO_MASK) { - /* - * - */ - } else { - /* - * enable DMA capable bit, and "not" simplex only - */ - outb(inb(fixdma_base+2) & 0x60, fixdma_base+2); - - if (inb(fixdma_base+2) & 0x80) - printk("%s: simplex device: DMA will fail!!\n", name); - } -#if defined(DISPLAY_VIPER_TIMINGS) && defined(CONFIG_PROC_FS) - amd7409_proc = 1; - bmide_dev = dev; - amd7409_display_info = &amd7409_get_info; -#endif /* DISPLAY_VIPER_TIMINGS && CONFIG_PROC_FS */ - - return 0; -} - -unsigned int __init ata66_amd7409 (ide_hwif_t *hwif) -{ -#ifdef CONFIG_AMD7409_OVERRIDE - byte ata66 = 1; -#else - byte ata66 = 0; -#endif /* CONFIG_AMD7409_OVERRIDE */ - -#if 0 - pci_read_config_byte(hwif->pci_dev, 0x48, &ata66); - return ((ata66 & 0x02) ? 0 : 1); -#endif - return ata66; -} - -void __init ide_init_amd7409 (ide_hwif_t *hwif) -{ - hwif->tuneproc = &amd7409_tune_drive; - if (hwif->dma_base) { - hwif->dmaproc = &amd7409_dmaproc; - } else { - hwif->autodma = 0; - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - } -} - -void ide_dmacapable_amd7409 (ide_hwif_t *hwif, unsigned long dmabase) -{ - ide_setup_dma(hwif, dmabase, 8); -} diff --git a/drivers/block/blkpg.c b/drivers/block/blkpg.c index 591ff9310..c709ebdc9 100644 --- a/drivers/block/blkpg.c +++ b/drivers/block/blkpg.c @@ -268,6 +268,13 @@ int blk_ioctl(kdev_t dev, unsigned int cmd, unsigned long arg) case BLKPG: return blkpg_ioctl(dev, (struct blkpg_ioctl_arg *) arg); + case BLKELVGET: + return blkelvget_ioctl(&blk_get_queue(dev)->elevator, + (blkelv_ioctl_arg_t *) arg); + case BLKELVSET: + return blkelvset_ioctl(&blk_get_queue(dev)->elevator, + (blkelv_ioctl_arg_t *) arg); + default: return -EINVAL; } diff --git a/drivers/block/buddha.c b/drivers/block/buddha.c deleted file mode 100644 index 3e1cfcd33..000000000 --- a/drivers/block/buddha.c +++ /dev/null @@ -1,165 +0,0 @@ -/* - * linux/drivers/block/buddha.c -- Amiga Buddha and Catweasel IDE Driver - * - * Copyright (C) 1997 by Geert Uytterhoeven - * - * This driver was written by based on the specifications in README.buddha. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive for - * more details. - * - * TODO: - * - test it :-) - * - tune the timings using the speed-register - */ - -#include <linux/types.h> -#include <linux/mm.h> -#include <linux/interrupt.h> -#include <linux/blkdev.h> -#include <linux/hdreg.h> -#include <linux/zorro.h> -#include <linux/ide.h> - -#include <asm/amigahw.h> -#include <asm/amigaints.h> - - - /* - * The Buddha has 2 IDE interfaces, the Catweasel has 3 - */ - -#define BUDDHA_NUM_HWIFS 2 -#define CATWEASEL_NUM_HWIFS 3 - - - /* - * Bases of the IDE interfaces (relative to the board address) - */ - -#define BUDDHA_BASE1 0x800 -#define BUDDHA_BASE2 0xa00 -#define BUDDHA_BASE3 0xc00 - -static const u_int __init buddha_bases[CATWEASEL_NUM_HWIFS] = { - BUDDHA_BASE1, BUDDHA_BASE2, BUDDHA_BASE3 -}; - - - /* - * Offsets from one of the above bases - */ - -#define BUDDHA_DATA 0x00 -#define BUDDHA_ERROR 0x06 /* see err-bits */ -#define BUDDHA_NSECTOR 0x0a /* nr of sectors to read/write */ -#define BUDDHA_SECTOR 0x0e /* starting sector */ -#define BUDDHA_LCYL 0x12 /* starting cylinder */ -#define BUDDHA_HCYL 0x16 /* high byte of starting cyl */ -#define BUDDHA_SELECT 0x1a /* 101dhhhh , d=drive, hhhh=head */ -#define BUDDHA_STATUS 0x1e /* see status-bits */ -#define BUDDHA_CONTROL 0x11a - -static int __init buddha_offsets[IDE_NR_PORTS] = { - BUDDHA_DATA, BUDDHA_ERROR, BUDDHA_NSECTOR, BUDDHA_SECTOR, BUDDHA_LCYL, - BUDDHA_HCYL, BUDDHA_SELECT, BUDDHA_STATUS, BUDDHA_CONTROL -}; - - - /* - * Other registers - */ - -#define BUDDHA_IRQ1 0xf00 /* MSB = 1, Harddisk is source of */ -#define BUDDHA_IRQ2 0xf40 /* interrupt */ -#define BUDDHA_IRQ3 0xf80 - -static const int __init buddha_irqports[CATWEASEL_NUM_HWIFS] = { - BUDDHA_IRQ1, BUDDHA_IRQ2, BUDDHA_IRQ3 -}; - -#define BUDDHA_IRQ_MR 0xfc0 /* master interrupt enable */ - - - /* - * Board information - */ - -static u_long buddha_board = 0; -static int buddha_num_hwifs = -1; - - - /* - * Check and acknowledge the interrupt status - */ - -static int buddha_ack_intr(ide_hwif_t *hwif) -{ - unsigned char ch; - - ch = inb(hwif->io_ports[IDE_IRQ_OFFSET]); - if (!(ch & 0x80)) - return 0; - return 1; -} - - - /* - * Any Buddha or Catweasel boards present? - */ - -static int __init find_buddha(void) -{ - struct zorro_dev *z = NULL; - - buddha_num_hwifs = 0; - while ((z = zorro_find_device(ZORRO_WILDCARD, z))) { - unsigned long board; - const char *name; - if (z->id == ZORRO_PROD_INDIVIDUAL_COMPUTERS_BUDDHA) { - buddha_num_hwifs = BUDDHA_NUM_HWIFS; - name = "Buddha IDE Interface"; - } else if (z->id == ZORRO_PROD_INDIVIDUAL_COMPUTERS_CATWEASEL) { - buddha_num_hwifs = CATWEASEL_NUM_HWIFS; - name = "Catweasel IDE Interface and Floppy Controller"; - } else - continue; - board = z->resource.start; - if (!request_mem_region(board+BUDDHA_BASE1, 0x800, "IDE")) - continue; - strcpy(z->name, name); - buddha_board = ZTWO_VADDR(board); - /* write to BUDDHA_IRQ_MR to enable the board IRQ */ - *(char *)(buddha_board+BUDDHA_IRQ_MR) = 0; - break; - } - return buddha_num_hwifs; -} - - - /* - * Probe for a Buddha or Catweasel IDE interface - * We support only _one_ of them, no multiple boards! - */ - -void __init buddha_init(void) -{ - hw_regs_t hw; - int i, index; - - if (buddha_num_hwifs < 0 && !find_buddha()) - return; - - for (i = 0; i < buddha_num_hwifs; i++) { - ide_setup_ports(&hw, (ide_ioreg_t)(buddha_board+buddha_bases[i]), - buddha_offsets, 0, - (ide_ioreg_t)(buddha_board+buddha_irqports[i]), - buddha_ack_intr, IRQ_AMIGA_PORTS); - index = ide_register_hw(&hw, NULL); - if (index != -1) - printk("ide%d: %s IDE interface\n", index, - buddha_num_hwifs == BUDDHA_NUM_HWIFS ? "Buddha" : - "Catweasel"); - } -} diff --git a/drivers/block/cmd640.c b/drivers/block/cmd640.c deleted file mode 100644 index b2077df6d..000000000 --- a/drivers/block/cmd640.c +++ /dev/null @@ -1,855 +0,0 @@ -/* - * linux/drivers/block/cmd640.c Version 1.02 Sep 01, 1996 - * - * Copyright (C) 1995-1996 Linus Torvalds & authors (see below) - */ - -/* - * Original authors: abramov@cecmow.enet.dec.com (Igor Abramov) - * mlord@pobox.com (Mark Lord) - * - * See linux/MAINTAINERS for address of current maintainer. - * - * This file provides support for the advanced features and bugs - * of IDE interfaces using the CMD Technologies 0640 IDE interface chip. - * - * These chips are basically fucked by design, and getting this driver - * to work on every motherboard design that uses this screwed chip seems - * bloody well impossible. However, we're still trying. - * - * Version 0.97 worked for everybody. - * - * User feedback is essential. Many thanks to the beta test team: - * - * A.Hartgers@stud.tue.nl, JZDQC@CUNYVM.CUNY.edu, abramov@cecmow.enet.dec.com, - * bardj@utopia.ppp.sn.no, bart@gaga.tue.nl, bbol001@cs.auckland.ac.nz, - * chrisc@dbass.demon.co.uk, dalecki@namu26.Num.Math.Uni-Goettingen.de, - * derekn@vw.ece.cmu.edu, florian@btp2x3.phy.uni-bayreuth.de, - * flynn@dei.unipd.it, gadio@netvision.net.il, godzilla@futuris.net, - * j@pobox.com, jkemp1@mises.uni-paderborn.de, jtoppe@hiwaay.net, - * kerouac@ssnet.com, meskes@informatik.rwth-aachen.de, hzoli@cs.elte.hu, - * peter@udgaard.isgtec.com, phil@tazenda.demon.co.uk, roadcapw@cfw.com, - * s0033las@sun10.vsz.bme.hu, schaffer@tam.cornell.edu, sjd@slip.net, - * steve@ei.org, ulrpeg@bigcomm.gun.de, ism@tardis.ed.ac.uk, mack@cray.com - * liug@mama.indstate.edu, and others. - * - * Version 0.01 Initial version, hacked out of ide.c, - * and #include'd rather than compiled separately. - * This will get cleaned up in a subsequent release. - * - * Version 0.02 Fixes for vlb initialization code, enable prefetch - * for versions 'B' and 'C' of chip by default, - * some code cleanup. - * - * Version 0.03 Added reset of secondary interface, - * and black list for devices which are not compatible - * with prefetch mode. Separate function for setting - * prefetch is added, possibly it will be called some - * day from ioctl processing code. - * - * Version 0.04 Now configs/compiles separate from ide.c - * - * Version 0.05 Major rewrite of interface timing code. - * Added new function cmd640_set_mode to set PIO mode - * from ioctl call. New drives added to black list. - * - * Version 0.06 More code cleanup. Prefetch is enabled only for - * detected hard drives, not included in prefetch - * black list. - * - * Version 0.07 Changed to more conservative drive tuning policy. - * Unknown drives, which report PIO < 4 are set to - * (reported_PIO - 1) if it is supported, or to PIO0. - * List of known drives extended by info provided by - * CMD at their ftp site. - * - * Version 0.08 Added autotune/noautotune support. - * - * Version 0.09 Try to be smarter about 2nd port enabling. - * Version 0.10 Be nice and don't reset 2nd port. - * Version 0.11 Try to handle more wierd situations. - * - * Version 0.12 Lots of bug fixes from Laszlo Peter - * irq unmasking disabled for reliability. - * try to be even smarter about the second port. - * tidy up source code formatting. - * Version 0.13 permit irq unmasking again. - * Version 0.90 massive code cleanup, some bugs fixed. - * defaults all drives to PIO mode0, prefetch off. - * autotune is OFF by default, with compile time flag. - * prefetch can be turned OFF/ON using "hdparm -p8/-p9" - * (requires hdparm-3.1 or newer) - * Version 0.91 first release to linux-kernel list. - * Version 0.92 move initial reg dump to separate callable function - * change "readahead" to "prefetch" to avoid confusion - * Version 0.95 respect original BIOS timings unless autotuning. - * tons of code cleanup and rearrangement. - * added CONFIG_BLK_DEV_CMD640_ENHANCED option - * prevent use of unmask when prefetch is on - * Version 0.96 prevent use of io_32bit when prefetch is off - * Version 0.97 fix VLB secondary interface for sjd@slip.net - * other minor tune-ups: 0.96 was very good. - * Version 0.98 ignore PCI version when disabled by BIOS - * Version 0.99 display setup/active/recovery clocks with PIO mode - * Version 1.00 Mmm.. cannot depend on PCMD_ENA in all systems - * Version 1.01 slow/fast devsel can be selected with "hdparm -p6/-p7" - * ("fast" is necessary for 32bit I/O in some systems) - * Version 1.02 fix bug that resulted in slow "setup times" - * (patch courtesy of Zoltan Hidvegi) - */ - -#undef REALLY_SLOW_IO /* most systems can safely undef this */ -#define CMD640_PREFETCH_MASKS 1 - -#include <linux/config.h> -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/delay.h> -#include <linux/timer.h> -#include <linux/mm.h> -#include <linux/ioport.h> -#include <linux/blkdev.h> -#include <linux/hdreg.h> -#include <linux/ide.h> - -#include <asm/io.h> - -#include "ide_modes.h" - -/* - * This flag is set in ide.c by the parameter: ide0=cmd640_vlb - */ -int cmd640_vlb = 0; - -/* - * CMD640 specific registers definition. - */ - -#define VID 0x00 -#define DID 0x02 -#define PCMD 0x04 -#define PCMD_ENA 0x01 -#define PSTTS 0x06 -#define REVID 0x08 -#define PROGIF 0x09 -#define SUBCL 0x0a -#define BASCL 0x0b -#define BaseA0 0x10 -#define BaseA1 0x14 -#define BaseA2 0x18 -#define BaseA3 0x1c -#define INTLINE 0x3c -#define INPINE 0x3d - -#define CFR 0x50 -#define CFR_DEVREV 0x03 -#define CFR_IDE01INTR 0x04 -#define CFR_DEVID 0x18 -#define CFR_AT_VESA_078h 0x20 -#define CFR_DSA1 0x40 -#define CFR_DSA0 0x80 - -#define CNTRL 0x51 -#define CNTRL_DIS_RA0 0x40 -#define CNTRL_DIS_RA1 0x80 -#define CNTRL_ENA_2ND 0x08 - -#define CMDTIM 0x52 -#define ARTTIM0 0x53 -#define DRWTIM0 0x54 -#define ARTTIM1 0x55 -#define DRWTIM1 0x56 -#define ARTTIM23 0x57 -#define ARTTIM23_DIS_RA2 0x04 -#define ARTTIM23_DIS_RA3 0x08 -#define DRWTIM23 0x58 -#define BRST 0x59 - -/* - * Registers and masks for easy access by drive index: - */ -static byte prefetch_regs[4] = {CNTRL, CNTRL, ARTTIM23, ARTTIM23}; -static byte prefetch_masks[4] = {CNTRL_DIS_RA0, CNTRL_DIS_RA1, ARTTIM23_DIS_RA2, ARTTIM23_DIS_RA3}; - -#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED - -static byte arttim_regs[4] = {ARTTIM0, ARTTIM1, ARTTIM23, ARTTIM23}; -static byte drwtim_regs[4] = {DRWTIM0, DRWTIM1, DRWTIM23, DRWTIM23}; - -/* - * Current cmd640 timing values for each drive. - * The defaults for each are the slowest possible timings. - */ -static byte setup_counts[4] = {4, 4, 4, 4}; /* Address setup count (in clocks) */ -static byte active_counts[4] = {16, 16, 16, 16}; /* Active count (encoded) */ -static byte recovery_counts[4] = {16, 16, 16, 16}; /* Recovery count (encoded) */ - -#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ - -/* - * These are initialized to point at the devices we control - */ -static ide_hwif_t *cmd_hwif0, *cmd_hwif1; -static ide_drive_t *cmd_drives[4]; - -/* - * Interface to access cmd640x registers - */ -static unsigned int cmd640_key; -static void (*put_cmd640_reg)(unsigned short reg, byte val); -static byte (*get_cmd640_reg)(unsigned short reg); - -/* - * This is read from the CFR reg, and is used in several places. - */ -static unsigned int cmd640_chip_version; - -/* - * The CMD640x chip does not support DWORD config write cycles, but some - * of the BIOSes use them to implement the config services. - * Therefore, we must use direct IO instead. - */ - -/* PCI method 1 access */ - -static void put_cmd640_reg_pci1 (unsigned short reg, byte val) -{ - unsigned long flags; - - save_flags(flags); - cli(); - outl_p((reg & 0xfc) | cmd640_key, 0xcf8); - outb_p(val, (reg & 3) | 0xcfc); - restore_flags(flags); -} - -static byte get_cmd640_reg_pci1 (unsigned short reg) -{ - byte b; - unsigned long flags; - - save_flags(flags); - cli(); - outl_p((reg & 0xfc) | cmd640_key, 0xcf8); - b = inb_p((reg & 3) | 0xcfc); - restore_flags(flags); - return b; -} - -/* PCI method 2 access (from CMD datasheet) */ - -static void put_cmd640_reg_pci2 (unsigned short reg, byte val) -{ - unsigned long flags; - - save_flags(flags); - cli(); - outb_p(0x10, 0xcf8); - outb_p(val, cmd640_key + reg); - outb_p(0, 0xcf8); - restore_flags(flags); -} - -static byte get_cmd640_reg_pci2 (unsigned short reg) -{ - byte b; - unsigned long flags; - - save_flags(flags); - cli(); - outb_p(0x10, 0xcf8); - b = inb_p(cmd640_key + reg); - outb_p(0, 0xcf8); - restore_flags(flags); - return b; -} - -/* VLB access */ - -static void put_cmd640_reg_vlb (unsigned short reg, byte val) -{ - unsigned long flags; - - save_flags(flags); - cli(); - outb_p(reg, cmd640_key); - outb_p(val, cmd640_key + 4); - restore_flags(flags); -} - -static byte get_cmd640_reg_vlb (unsigned short reg) -{ - byte b; - unsigned long flags; - - save_flags(flags); - cli(); - outb_p(reg, cmd640_key); - b = inb_p(cmd640_key + 4); - restore_flags(flags); - return b; -} - -static int __init match_pci_cmd640_device (void) -{ - const byte ven_dev[4] = {0x95, 0x10, 0x40, 0x06}; - unsigned int i; - for (i = 0; i < 4; i++) { - if (get_cmd640_reg(i) != ven_dev[i]) - return 0; - } -#ifdef STUPIDLY_TRUST_BROKEN_PCMD_ENA_BIT - if ((get_cmd640_reg(PCMD) & PCMD_ENA) == 0) { - printk("ide: cmd640 on PCI disabled by BIOS\n"); - return 0; - } -#endif /* STUPIDLY_TRUST_BROKEN_PCMD_ENA_BIT */ - return 1; /* success */ -} - -/* - * Probe for CMD640x -- pci method 1 - */ -static int __init probe_for_cmd640_pci1 (void) -{ - get_cmd640_reg = get_cmd640_reg_pci1; - put_cmd640_reg = put_cmd640_reg_pci1; - for (cmd640_key = 0x80000000; cmd640_key <= 0x8000f800; cmd640_key += 0x800) { - if (match_pci_cmd640_device()) - return 1; /* success */ - } - return 0; -} - -/* - * Probe for CMD640x -- pci method 2 - */ -static int __init probe_for_cmd640_pci2 (void) -{ - get_cmd640_reg = get_cmd640_reg_pci2; - put_cmd640_reg = put_cmd640_reg_pci2; - for (cmd640_key = 0xc000; cmd640_key <= 0xcf00; cmd640_key += 0x100) { - if (match_pci_cmd640_device()) - return 1; /* success */ - } - return 0; -} - -/* - * Probe for CMD640x -- vlb - */ -static int __init probe_for_cmd640_vlb (void) -{ - byte b; - - get_cmd640_reg = get_cmd640_reg_vlb; - put_cmd640_reg = put_cmd640_reg_vlb; - cmd640_key = 0x178; - b = get_cmd640_reg(CFR); - if (b == 0xff || b == 0x00 || (b & CFR_AT_VESA_078h)) { - cmd640_key = 0x78; - b = get_cmd640_reg(CFR); - if (b == 0xff || b == 0x00 || !(b & CFR_AT_VESA_078h)) - return 0; - } - return 1; /* success */ -} - -/* - * Returns 1 if an IDE interface/drive exists at 0x170, - * Returns 0 otherwise. - */ -static int __init secondary_port_responding (void) -{ - unsigned long flags; - - save_flags(flags); - cli(); - - outb_p(0x0a, 0x170 + IDE_SELECT_OFFSET); /* select drive0 */ - udelay(100); - if ((inb_p(0x170 + IDE_SELECT_OFFSET) & 0x1f) != 0x0a) { - outb_p(0x1a, 0x170 + IDE_SELECT_OFFSET); /* select drive1 */ - udelay(100); - if ((inb_p(0x170 + IDE_SELECT_OFFSET) & 0x1f) != 0x1a) { - restore_flags(flags); - return 0; /* nothing responded */ - } - } - restore_flags(flags); - return 1; /* success */ -} - -#ifdef CMD640_DUMP_REGS -/* - * Dump out all cmd640 registers. May be called from ide.c - */ -void cmd640_dump_regs (void) -{ - unsigned int reg = cmd640_vlb ? 0x50 : 0x00; - - /* Dump current state of chip registers */ - printk("ide: cmd640 internal register dump:"); - for (; reg <= 0x59; reg++) { - if (!(reg & 0x0f)) - printk("\n%04x:", reg); - printk(" %02x", get_cmd640_reg(reg)); - } - printk("\n"); -} -#endif - -/* - * Check whether prefetch is on for a drive, - * and initialize the unmask flags for safe operation. - */ -static void __init check_prefetch (unsigned int index) -{ - ide_drive_t *drive = cmd_drives[index]; - byte b = get_cmd640_reg(prefetch_regs[index]); - - if (b & prefetch_masks[index]) { /* is prefetch off? */ - drive->no_unmask = 0; - drive->no_io_32bit = 1; - drive->io_32bit = 0; - } else { -#if CMD640_PREFETCH_MASKS - drive->no_unmask = 1; - drive->unmask = 0; -#endif - drive->no_io_32bit = 0; - } -} - -/* - * Figure out which devices we control - */ -static void __init setup_device_ptrs (void) -{ - unsigned int i; - - cmd_hwif0 = &ide_hwifs[0]; /* default, if not found below */ - cmd_hwif1 = &ide_hwifs[1]; /* default, if not found below */ - for (i = 0; i < MAX_HWIFS; i++) { - ide_hwif_t *hwif = &ide_hwifs[i]; - if (hwif->chipset == ide_unknown || hwif->chipset == ide_generic) { - if (hwif->io_ports[IDE_DATA_OFFSET] == 0x1f0) - cmd_hwif0 = hwif; - else if (hwif->io_ports[IDE_DATA_OFFSET] == 0x170) - cmd_hwif1 = hwif; - } - } - cmd_drives[0] = &cmd_hwif0->drives[0]; - cmd_drives[1] = &cmd_hwif0->drives[1]; - cmd_drives[2] = &cmd_hwif1->drives[0]; - cmd_drives[3] = &cmd_hwif1->drives[1]; -} - -#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED - -/* - * Sets prefetch mode for a drive. - */ -static void set_prefetch_mode (unsigned int index, int mode) -{ - ide_drive_t *drive = cmd_drives[index]; - int reg = prefetch_regs[index]; - byte b; - unsigned long flags; - - save_flags(flags); - cli(); - b = get_cmd640_reg(reg); - if (mode) { /* want prefetch on? */ -#if CMD640_PREFETCH_MASKS - drive->no_unmask = 1; - drive->unmask = 0; -#endif - drive->no_io_32bit = 0; - b &= ~prefetch_masks[index]; /* enable prefetch */ - } else { - drive->no_unmask = 0; - drive->no_io_32bit = 1; - drive->io_32bit = 0; - b |= prefetch_masks[index]; /* disable prefetch */ - } - put_cmd640_reg(reg, b); - restore_flags(flags); -} - -/* - * Dump out current drive clocks settings - */ -static void display_clocks (unsigned int index) -{ - byte active_count, recovery_count; - - active_count = active_counts[index]; - if (active_count == 1) - ++active_count; - recovery_count = recovery_counts[index]; - if (active_count > 3 && recovery_count == 1) - ++recovery_count; - if (cmd640_chip_version > 1) - recovery_count += 1; /* cmd640b uses (count + 1)*/ - printk(", clocks=%d/%d/%d\n", setup_counts[index], active_count, recovery_count); -} - -/* - * Pack active and recovery counts into single byte representation - * used by controller - */ -inline static byte pack_nibbles (byte upper, byte lower) -{ - return ((upper & 0x0f) << 4) | (lower & 0x0f); -} - -/* - * This routine retrieves the initial drive timings from the chipset. - */ -static void __init retrieve_drive_counts (unsigned int index) -{ - byte b; - - /* - * Get the internal setup timing, and convert to clock count - */ - b = get_cmd640_reg(arttim_regs[index]) & ~0x3f; - switch (b) { - case 0x00: b = 4; break; - case 0x80: b = 3; break; - case 0x40: b = 2; break; - default: b = 5; break; - } - setup_counts[index] = b; - - /* - * Get the active/recovery counts - */ - b = get_cmd640_reg(drwtim_regs[index]); - active_counts[index] = (b >> 4) ? (b >> 4) : 0x10; - recovery_counts[index] = (b & 0x0f) ? (b & 0x0f) : 0x10; -} - - -/* - * This routine writes the prepared setup/active/recovery counts - * for a drive into the cmd640 chipset registers to active them. - */ -static void program_drive_counts (unsigned int index) -{ - unsigned long flags; - byte setup_count = setup_counts[index]; - byte active_count = active_counts[index]; - byte recovery_count = recovery_counts[index]; - - /* - * Set up address setup count and drive read/write timing registers. - * Primary interface has individual count/timing registers for - * each drive. Secondary interface has one common set of registers, - * so we merge the timings, using the slowest value for each timing. - */ - if (index > 1) { - unsigned int mate; - if (cmd_drives[mate = index ^ 1]->present) { - if (setup_count < setup_counts[mate]) - setup_count = setup_counts[mate]; - if (active_count < active_counts[mate]) - active_count = active_counts[mate]; - if (recovery_count < recovery_counts[mate]) - recovery_count = recovery_counts[mate]; - } - } - - /* - * Convert setup_count to internal chipset representation - */ - switch (setup_count) { - case 4: setup_count = 0x00; break; - case 3: setup_count = 0x80; break; - case 1: - case 2: setup_count = 0x40; break; - default: setup_count = 0xc0; /* case 5 */ - } - - /* - * Now that everything is ready, program the new timings - */ - save_flags (flags); - cli(); - /* - * Program the address_setup clocks into ARTTIM reg, - * and then the active/recovery counts into the DRWTIM reg - * (this converts counts of 16 into counts of zero -- okay). - */ - setup_count |= get_cmd640_reg(arttim_regs[index]) & 0x3f; - put_cmd640_reg(arttim_regs[index], setup_count); - put_cmd640_reg(drwtim_regs[index], pack_nibbles(active_count, recovery_count)); - restore_flags(flags); -} - -/* - * Set a specific pio_mode for a drive - */ -static void cmd640_set_mode (unsigned int index, byte pio_mode, unsigned int cycle_time) -{ - int setup_time, active_time, recovery_time, clock_time; - byte setup_count, active_count, recovery_count, recovery_count2, cycle_count; - int bus_speed = ide_system_bus_speed(); - - if (pio_mode > 5) - pio_mode = 5; - setup_time = ide_pio_timings[pio_mode].setup_time; - active_time = ide_pio_timings[pio_mode].active_time; - recovery_time = cycle_time - (setup_time + active_time); - clock_time = 1000 / bus_speed; - cycle_count = (cycle_time + clock_time - 1) / clock_time; - - setup_count = (setup_time + clock_time - 1) / clock_time; - - active_count = (active_time + clock_time - 1) / clock_time; - if (active_count < 2) - active_count = 2; /* minimum allowed by cmd640 */ - - recovery_count = (recovery_time + clock_time - 1) / clock_time; - recovery_count2 = cycle_count - (setup_count + active_count); - if (recovery_count2 > recovery_count) - recovery_count = recovery_count2; - if (recovery_count < 2) - recovery_count = 2; /* minimum allowed by cmd640 */ - if (recovery_count > 17) { - active_count += recovery_count - 17; - recovery_count = 17; - } - if (active_count > 16) - active_count = 16; /* maximum allowed by cmd640 */ - if (cmd640_chip_version > 1) - recovery_count -= 1; /* cmd640b uses (count + 1)*/ - if (recovery_count > 16) - recovery_count = 16; /* maximum allowed by cmd640 */ - - setup_counts[index] = setup_count; - active_counts[index] = active_count; - recovery_counts[index] = recovery_count; - - /* - * In a perfect world, we might set the drive pio mode here - * (using WIN_SETFEATURE) before continuing. - * - * But we do not, because: - * 1) this is the wrong place to do it (proper is do_special() in ide.c) - * 2) in practice this is rarely, if ever, necessary - */ - program_drive_counts (index); -} - -/* - * Drive PIO mode selection: - */ -static void cmd640_tune_drive (ide_drive_t *drive, byte mode_wanted) -{ - byte b; - ide_pio_data_t d; - unsigned int index = 0; - - while (drive != cmd_drives[index]) { - if (++index > 3) { - printk("%s: bad news in cmd640_tune_drive\n", drive->name); - return; - } - } - switch (mode_wanted) { - case 6: /* set fast-devsel off */ - case 7: /* set fast-devsel on */ - mode_wanted &= 1; - b = get_cmd640_reg(CNTRL) & ~0x27; - if (mode_wanted) - b |= 0x27; - put_cmd640_reg(CNTRL, b); - printk("%s: %sabled cmd640 fast host timing (devsel)\n", drive->name, mode_wanted ? "en" : "dis"); - return; - - case 8: /* set prefetch off */ - case 9: /* set prefetch on */ - mode_wanted &= 1; - set_prefetch_mode(index, mode_wanted); - printk("%s: %sabled cmd640 prefetch\n", drive->name, mode_wanted ? "en" : "dis"); - return; - } - - (void) ide_get_best_pio_mode (drive, mode_wanted, 5, &d); - cmd640_set_mode (index, d.pio_mode, d.cycle_time); - - printk ("%s: selected cmd640 PIO mode%d (%dns)%s", - drive->name, - d.pio_mode, - d.cycle_time, - d.overridden ? " (overriding vendor mode)" : ""); - display_clocks(index); - return; -} - -#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ - -/* - * Probe for a cmd640 chipset, and initialize it if found. Called from ide.c - */ -int __init ide_probe_for_cmd640x (void) -{ -#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED - int second_port_toggled = 0; -#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ - int second_port_cmd640 = 0; - const char *bus_type, *port2; - unsigned int index; - byte b, cfr; - - if (cmd640_vlb && probe_for_cmd640_vlb()) { - bus_type = "VLB"; - } else { - cmd640_vlb = 0; - if (probe_for_cmd640_pci1()) - bus_type = "PCI (type1)"; - else if (probe_for_cmd640_pci2()) - bus_type = "PCI (type2)"; - else - return 0; - } - /* - * Undocumented magic (there is no 0x5b reg in specs) - */ - put_cmd640_reg(0x5b, 0xbd); - if (get_cmd640_reg(0x5b) != 0xbd) { - printk("ide: cmd640 init failed: wrong value in reg 0x5b\n"); - return 0; - } - put_cmd640_reg(0x5b, 0); - -#ifdef CMD640_DUMP_REGS - CMD640_DUMP_REGS; -#endif - - /* - * Documented magic begins here - */ - cfr = get_cmd640_reg(CFR); - cmd640_chip_version = cfr & CFR_DEVREV; - if (cmd640_chip_version == 0) { - printk ("ide: bad cmd640 revision: %d\n", cmd640_chip_version); - return 0; - } - - /* - * Initialize data for primary port - */ - setup_device_ptrs (); - printk("%s: buggy cmd640%c interface on %s, config=0x%02x\n", - cmd_hwif0->name, 'a' + cmd640_chip_version - 1, bus_type, cfr); - cmd_hwif0->chipset = ide_cmd640; -#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED - cmd_hwif0->tuneproc = &cmd640_tune_drive; -#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ - - /* - * Ensure compatibility by always using the slowest timings - * for access to the drive's command register block, - * and reset the prefetch burstsize to default (512 bytes). - * - * Maybe we need a way to NOT do these on *some* systems? - */ - put_cmd640_reg(CMDTIM, 0); - put_cmd640_reg(BRST, 0x40); - - /* - * Try to enable the secondary interface, if not already enabled - */ - if (cmd_hwif1->noprobe) { - port2 = "not probed"; - } else { - b = get_cmd640_reg(CNTRL); - if (secondary_port_responding()) { - if ((b & CNTRL_ENA_2ND)) { - second_port_cmd640 = 1; - port2 = "okay"; - } else if (cmd640_vlb) { - second_port_cmd640 = 1; - port2 = "alive"; - } else - port2 = "not cmd640"; - } else { - put_cmd640_reg(CNTRL, b ^ CNTRL_ENA_2ND); /* toggle the bit */ - if (secondary_port_responding()) { - second_port_cmd640 = 1; -#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED - second_port_toggled = 1; -#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ - port2 = "enabled"; - } else { - put_cmd640_reg(CNTRL, b); /* restore original setting */ - port2 = "not responding"; - } - } - } - - /* - * Initialize data for secondary cmd640 port, if enabled - */ - if (second_port_cmd640) { - cmd_hwif0->serialized = 1; - cmd_hwif1->serialized = 1; - cmd_hwif1->chipset = ide_cmd640; - cmd_hwif0->mate = cmd_hwif1; - cmd_hwif1->mate = cmd_hwif0; - cmd_hwif1->channel = 1; -#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED - cmd_hwif1->tuneproc = &cmd640_tune_drive; -#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ - } - printk("%s: %sserialized, secondary interface %s\n", cmd_hwif1->name, - cmd_hwif0->serialized ? "" : "not ", port2); - - /* - * Establish initial timings/prefetch for all drives. - * Do not unnecessarily disturb any prior BIOS setup of these. - */ - for (index = 0; index < (2 + (second_port_cmd640 << 1)); index++) { - ide_drive_t *drive = cmd_drives[index]; -#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED - if (drive->autotune || ((index > 1) && second_port_toggled)) { - /* - * Reset timing to the slowest speed and turn off prefetch. - * This way, the drive identify code has a better chance. - */ - setup_counts [index] = 4; /* max possible */ - active_counts [index] = 16; /* max possible */ - recovery_counts [index] = 16; /* max possible */ - program_drive_counts (index); - set_prefetch_mode (index, 0); - printk("cmd640: drive%d timings/prefetch cleared\n", index); - } else { - /* - * Record timings/prefetch without changing them. - * This preserves any prior BIOS setup. - */ - retrieve_drive_counts (index); - check_prefetch (index); - printk("cmd640: drive%d timings/prefetch(%s) preserved", - index, drive->no_io_32bit ? "off" : "on"); - display_clocks(index); - } -#else - /* - * Set the drive unmask flags to match the prefetch setting - */ - check_prefetch (index); - printk("cmd640: drive%d timings/prefetch(%s) preserved\n", - index, drive->no_io_32bit ? "off" : "on"); -#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ - } - -#ifdef CMD640_DUMP_REGS - CMD640_DUMP_REGS; -#endif - return 1; -} - diff --git a/drivers/block/cmd64x.c b/drivers/block/cmd64x.c deleted file mode 100644 index 542ad44a1..000000000 --- a/drivers/block/cmd64x.c +++ /dev/null @@ -1,721 +0,0 @@ -/* $Id: cmd64x.c,v 1.21 2000/01/30 23:23:16 - * - * cmd64x.c: Enable interrupts at initialization time on Ultra/PCI machines. - * Note, this driver is not used at all on other systems because - * there the "BIOS" has done all of the following already. - * Due to massive hardware bugs, UltraDMA is only supported - * on the 646U2 and not on the 646U. - * - * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) - * Copyright (C) 1998 David S. Miller (davem@redhat.com) - * Copyright (C) 1999-2000 Andre Hedrick (andre@suse.com) - */ - -#include <linux/config.h> -#include <linux/types.h> -#include <linux/pci.h> -#include <linux/delay.h> -#include <linux/hdreg.h> -#include <linux/ide.h> - -#include <asm/io.h> -#include "ide_modes.h" - -#ifndef SPLIT_BYTE -#define SPLIT_BYTE(B,H,L) ((H)=(B>>4), (L)=(B-((B>>4)<<4))) -#endif - -#define CMD_DEBUG 0 - -#if CMD_DEBUG -#define cmdprintk(x...) printk(##x) -#else -#define cmdprintk(x...) -#endif - -/* - * CMD64x specific registers definition. - */ - -#define CNTRL 0x51 -#define CNTRL_DIS_RA0 0x40 -#define CNTRL_DIS_RA1 0x80 -#define CNTRL_ENA_2ND 0x08 - -#define CMDTIM 0x52 -#define ARTTIM0 0x53 -#define DRWTIM0 0x54 -#define ARTTIM1 0x55 -#define DRWTIM1 0x56 -#define ARTTIM23 0x57 -#define ARTTIM23_DIS_RA2 0x04 -#define ARTTIM23_DIS_RA3 0x08 -#define ARTTIM2 0x57 -#define ARTTIM3 0x57 -#define DRWTIM23 0x58 -#define DRWTIM2 0x58 -#define BRST 0x59 -#define DRWTIM3 0x5b - -#define BMIDECR0 0x70 -#define MRDMODE 0x71 -#define BMIDESR0 0x72 -#define UDIDETCR0 0x73 -#define DTPR0 0x74 -#define BMIDECR1 0x78 -#define BMIDECSR 0x79 -#define BMIDESR1 0x7A -#define UDIDETCR1 0x7B -#define DTPR1 0x7C - -#undef DISPLAY_CMD64X_TIMINGS - -#if defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS) -#include <linux/stat.h> -#include <linux/proc_fs.h> - -static int cmd64x_get_info(char *, char **, off_t, int); -extern int (*cmd64x_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -extern char *ide_media_verbose(ide_drive_t *); -static struct pci_dev *bmide_dev; - -static int cmd64x_get_info (char *buffer, char **addr, off_t offset, int count) -{ - char *p = buffer; - u8 reg53 = 0, reg54 = 0, reg55 = 0, reg56 = 0; /* primary */ - u8 reg57 = 0, reg58 = 0, reg5b; /* secondary */ - u8 reg72 = 0, reg73 = 0; /* primary */ - u8 reg7a = 0, reg7b = 0; /* secondary */ - u8 hi_byte = 0, lo_byte = 0; - - switch(bmide_dev->device) { - case PCI_DEVICE_ID_CMD_648: - p += sprintf(p, "\n CMD648 Chipset.\n"); - break; - case PCI_DEVICE_ID_CMD_646: - p += sprintf(p, "\n CMD646 Chipset.\n"); - break; - case PCI_DEVICE_ID_CMD_643: - p += sprintf(p, "\n CMD643 Chipset.\n"); - break; - default: - p += sprintf(p, "\n CMD64? Chipse.\n"); - break; - } - (void) pci_read_config_byte(bmide_dev, ARTTIM0, ®53); - (void) pci_read_config_byte(bmide_dev, DRWTIM0, ®54); - (void) pci_read_config_byte(bmide_dev, ARTTIM1, ®55); - (void) pci_read_config_byte(bmide_dev, DRWTIM1, ®56); - (void) pci_read_config_byte(bmide_dev, ARTTIM2, ®57); - (void) pci_read_config_byte(bmide_dev, DRWTIM2, ®58); - (void) pci_read_config_byte(bmide_dev, DRWTIM3, ®5b); - (void) pci_read_config_byte(bmide_dev, BMIDESR0, ®72); - (void) pci_read_config_byte(bmide_dev, UDIDETCR0, ®73); - (void) pci_read_config_byte(bmide_dev, BMIDESR1, ®7a); - (void) pci_read_config_byte(bmide_dev, UDIDETCR1, ®7b); - - p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n"); - p += sprintf(p, " %sabled %sabled\n", - (reg72&0x80) ? "dis" : " en", (reg7a&0x80) ? "dis" : " en"); - p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n"); - p += sprintf(p, "DMA enabled: %s %s %s %s\n", - (reg72&0x20) ? "yes" : "no ", (reg72&0x40) ? "yes" : "no ", (reg7a&0x20) ? "yes" : "no ", (reg7a&0x40) ? "yes" : "no " ); - p += sprintf(p, "UDMA enabled: %s %s %s %s\n", - (reg73&0x01) ? "yes" : "no ", (reg73&0x02) ? "yes" : "no ", (reg7b&0x01) ? "yes" : "no ", (reg7b&0x02) ? "yes" : "no " ); - p += sprintf(p, "UDMA enabled: %s %s %s %s\n", - (reg73&0x15) ? "4" : (reg73&0x25) ? "3" : (reg73&0x11) ? "2" : (reg73&0x21) ? "1" : (reg73&0x31) ? "0" : "X", - (reg73&0x4A) ? "4" : (reg73&0x8A) ? "3" : (reg73&0x42) ? "2" : (reg73&0x82) ? "1" : (reg73&0xC2) ? "0" : "X", - (reg7b&0x15) ? "4" : (reg7b&0x25) ? "3" : (reg7b&0x11) ? "2" : (reg7b&0x21) ? "1" : (reg7b&0x31) ? "0" : "X", - (reg7b&0x4A) ? "4" : (reg7b&0x8A) ? "3" : (reg7b&0x42) ? "2" : (reg7b&0x82) ? "1" : (reg7b&0xC2) ? "0" : "X" ); - p += sprintf(p, "DMA enabled: %s %s %s %s\n", - (reg73&0x10) ? "2" : (reg73&0x20) ? "1" : (reg73&0x30) ? "0" : "X", - (reg73&0x40) ? "2" : (reg73&0x80) ? "1" : (reg73&0xC0) ? "0" : "X", - (reg7b&0x10) ? "2" : (reg7b&0x20) ? "1" : (reg7b&0x30) ? "0" : "X", - (reg7b&0x40) ? "2" : (reg7b&0x80) ? "1" : (reg7b&0xC0) ? "0" : "X" ); - p += sprintf(p, "PIO\n"); - - SPLIT_BYTE(reg53, hi_byte, lo_byte); - p += sprintf(p, "ARTTIM0 = 0x%02x, HI = 0x%02x, LOW = 0x%02x\n", reg53, hi_byte, lo_byte); - SPLIT_BYTE(reg54, hi_byte, lo_byte); - p += sprintf(p, "DRWTIM0 = 0x%02x, HI = 0x%02x, LOW = 0x%02x\n", reg54, hi_byte, lo_byte); - SPLIT_BYTE(reg55, hi_byte, lo_byte); - p += sprintf(p, "ARTTIM1 = 0x%02x, HI = 0x%02x, LOW = 0x%02x\n", reg55, hi_byte, lo_byte); - SPLIT_BYTE(reg56, hi_byte, lo_byte); - p += sprintf(p, "DRWTIM1 = 0x%02x, HI = 0x%02x, LOW = 0x%02x\n", reg56, hi_byte, lo_byte); - SPLIT_BYTE(reg57, hi_byte, lo_byte); - p += sprintf(p, "ARTTIM23 = 0x%02x, HI = 0x%02x, LOW = 0x%02x\n", reg57, hi_byte, lo_byte); - SPLIT_BYTE(reg58, hi_byte, lo_byte); - p += sprintf(p, "DRWTIM2 = 0x%02x, HI = 0x%02x, LOW = 0x%02x\n", reg58, hi_byte, lo_byte); - SPLIT_BYTE(reg5b, hi_byte, lo_byte); - p += sprintf(p, "DRWTIM3 = 0x%02x, HI = 0x%02x, LOW = 0x%02x\n", reg5b, hi_byte, lo_byte); - SPLIT_BYTE(reg73, hi_byte, lo_byte); - p += sprintf(p, "UDIDETCR0 = 0x%02x, HI = 0x%02x, LOW = 0x%02x\n", reg73, hi_byte, lo_byte); - SPLIT_BYTE(reg7b, hi_byte, lo_byte); - p += sprintf(p, "UDIDETCR1 = 0x%02x, HI = 0x%02x, LOW = 0x%02x\n", reg7b, hi_byte, lo_byte); - - return p-buffer; /* => must be less than 4k! */ -} -#endif /* defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS) */ - -byte cmd64x_proc = 0; - -/* - * Registers and masks for easy access by drive index: - */ -#if 0 -static byte prefetch_regs[4] = {CNTRL, CNTRL, ARTTIM23, ARTTIM23}; -static byte prefetch_masks[4] = {CNTRL_DIS_RA0, CNTRL_DIS_RA1, ARTTIM23_DIS_RA2, ARTTIM23_DIS_RA3}; -#endif - -/* - * This routine writes the prepared setup/active/recovery counts - * for a drive into the cmd646 chipset registers to active them. - */ -static void program_drive_counts (ide_drive_t *drive, int setup_count, int active_count, int recovery_count) -{ - unsigned long flags; - ide_drive_t *drives = HWIF(drive)->drives; - byte temp_b; - static const byte setup_counts[] = {0x40, 0x40, 0x40, 0x80, 0, 0xc0}; - static const byte recovery_counts[] = - {15, 15, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0}; - static const byte arttim_regs[2][2] = { - { ARTTIM0, ARTTIM1 }, - { ARTTIM23, ARTTIM23 } - }; - static const byte drwtim_regs[2][2] = { - { DRWTIM0, DRWTIM1 }, - { DRWTIM2, DRWTIM3 } - }; - int channel = (int) HWIF(drive)->channel; - int slave = (drives != drive); /* Is this really the best way to determine this?? */ - - cmdprintk("program_drive_count parameters = s(%d),a(%d),r(%d),p(%d)\n", setup_count, - active_count, recovery_count, drive->present); - /* - * Set up address setup count registers. - * Primary interface has individual count/timing registers for - * each drive. Secondary interface has one common set of registers, - * for address setup so we merge these timings, using the slowest - * value. - */ - if (channel) { - drive->drive_data = setup_count; - setup_count = IDE_MAX(drives[0].drive_data, drives[1].drive_data); - cmdprintk("Secondary interface, setup_count = %d\n", setup_count); - } - - /* - * Convert values to internal chipset representation - */ - setup_count = (setup_count > 5) ? 0xc0 : (int) setup_counts[setup_count]; - active_count &= 0xf; /* Remember, max value is 16 */ - recovery_count = (int) recovery_counts[recovery_count]; - - cmdprintk("Final values = %d,%d,%d\n", setup_count, active_count, recovery_count); - - /* - * Now that everything is ready, program the new timings - */ - __save_flags (flags); - __cli(); - /* - * Program the address_setup clocks into ARTTIM reg, - * and then the active/recovery counts into the DRWTIM reg - */ - (void) pci_read_config_byte(HWIF(drive)->pci_dev, arttim_regs[channel][slave], &temp_b); - (void) pci_write_config_byte(HWIF(drive)->pci_dev, arttim_regs[channel][slave], - ((byte) setup_count) | (temp_b & 0x3f)); - (void) pci_write_config_byte(HWIF(drive)->pci_dev, drwtim_regs[channel][slave], - (byte) ((active_count << 4) | recovery_count)); - cmdprintk ("Write %x to %x\n", ((byte) setup_count) | (temp_b & 0x3f), arttim_regs[channel][slave]); - cmdprintk ("Write %x to %x\n", (byte) ((active_count << 4) | recovery_count), drwtim_regs[channel][slave]); - __restore_flags(flags); -} - -/* - * Attempts to set the interface PIO mode. - * The preferred method of selecting PIO modes (e.g. mode 4) is - * "echo 'piomode:4' > /proc/ide/hdx/settings". Special cases are - * 8: prefetch off, 9: prefetch on, 255: auto-select best mode. - * Called with 255 at boot time. - */ -static void cmd64x_tuneproc (ide_drive_t *drive, byte mode_wanted) -{ - int setup_time, active_time, recovery_time, clock_time, pio_mode, cycle_time; - byte recovery_count2, cycle_count; - int setup_count, active_count, recovery_count; - int bus_speed = ide_system_bus_speed(); - /*byte b;*/ - ide_pio_data_t d; - - switch (mode_wanted) { - case 8: /* set prefetch off */ - case 9: /* set prefetch on */ - mode_wanted &= 1; - /*set_prefetch_mode(index, mode_wanted);*/ - cmdprintk("%s: %sabled cmd640 prefetch\n", drive->name, mode_wanted ? "en" : "dis"); - return; - } - - mode_wanted = ide_get_best_pio_mode (drive, mode_wanted, 5, &d); - pio_mode = d.pio_mode; - cycle_time = d.cycle_time; - - /* - * I copied all this complicated stuff from cmd640.c and made a few minor changes. - * For now I am just going to pray that it is correct. - */ - if (pio_mode > 5) - pio_mode = 5; - setup_time = ide_pio_timings[pio_mode].setup_time; - active_time = ide_pio_timings[pio_mode].active_time; - recovery_time = cycle_time - (setup_time + active_time); - clock_time = 1000 / bus_speed; - cycle_count = (cycle_time + clock_time - 1) / clock_time; - - setup_count = (setup_time + clock_time - 1) / clock_time; - - active_count = (active_time + clock_time - 1) / clock_time; - - recovery_count = (recovery_time + clock_time - 1) / clock_time; - recovery_count2 = cycle_count - (setup_count + active_count); - if (recovery_count2 > recovery_count) - recovery_count = recovery_count2; - if (recovery_count > 16) { - active_count += recovery_count - 16; - recovery_count = 16; - } - if (active_count > 16) - active_count = 16; /* maximum allowed by cmd646 */ - - /* - * In a perfect world, we might set the drive pio mode here - * (using WIN_SETFEATURE) before continuing. - * - * But we do not, because: - * 1) this is the wrong place to do it (proper is do_special() in ide.c) - * 2) in practice this is rarely, if ever, necessary - */ - program_drive_counts (drive, setup_count, active_count, recovery_count); - - cmdprintk("%s: selected cmd646 PIO mode%d : %d (%dns)%s, clocks=%d/%d/%d\n", - drive->name, pio_mode, mode_wanted, cycle_time, - d.overridden ? " (overriding vendor mode)" : "", - setup_count, active_count, recovery_count); -} - -static int tune_chipset_for_dma (ide_drive_t *drive, byte speed) -{ -#if 0 - struct hd_driveid *id = drive->id; - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - unsigned long dma_base = hwif->dma_base; - byte unit = (drive->select.b.unit & 0x01); - - u8 reg72 = 0, reg73 = 0; /* primary */ - u8 reg7a = 0, reg7b = 0; /* secondary */ - u8 pciU = (hwif->channel) ? UDIDETCR1 : UDIDETCR0; - u8 pciD = (hwif->channel) ? BMIDESR1 : BMIDESR0; - u8 regU = (hwif->channel) ? 2 : 0; - u8 regD = (hwif->channel) ? 2 : 0; - - (void) pci_read_config_byte(dev, BMIDESR0, ®72); - (void) pci_read_config_byte(dev, UDIDETCR0, ®73); - (void) pci_read_config_byte(dev, BMIDESR1, ®7a); - (void) pci_read_config_byte(dev, UDIDETCR1, ®7b); - - switch(speed) { - case XFER_UDMA_4: - pciU = unit ? 0x4A : 0x15; - case XFER_UDMA_3: - pciU = unit ? 0x8A : 0x25; - case XFER_UDMA_2: - pciU = unit ? 0x42 : 0x11; - case XFER_UDMA_1: - pciU = unit ? 0x82 : 0x21; - case XFER_UDMA_0: - pciU = unit ? 0xC2 : 0x31 -(reg73&0x15)?"4":(reg73&0x25)?"3":(reg73&0x11)?"2":(reg73&0x21)?"1":(reg73&0x31)?"0":"X", -(reg73&0x4A)?"4":(reg73&0x8A)?"3":(reg73&0x42)?"2":(reg73&0x82)?"1":(reg73&0xC2)?"0":"X", -(reg7b&0x15)?"4":(reg7b&0x25)?"3":(reg7b&0x11)?"2":(reg7b&0x21)?"1":(reg7b&0x31)?"0":"X", -(reg7b&0x4A)?"4":(reg7b&0x8A)?"3":(reg7b&0x42)?"2":(reg7b&0x82)?"1":(reg7b&0xC2)?"0":"X", - - case XFER_MW_DMA_2: - pciD = unit ? 0x40 : 0x10; - case XFER_MW_DMA_1: - pciD = unit ? 0x80 : 0x20; - case XFER_MW_DMA_0: - pciD = unit ? 0xC0 : 0x30; - case XFER_SW_DMA_2: - case XFER_SW_DMA_1: - case XFER_SW_DMA_0: -(reg73&0x10)?"2":(reg73&0x20)?"1":(reg73&0x30)?"0":"X", -(reg73&0x40)?"2":(reg73&0x80)?"1":(reg73&0xC0)?"0":"X", -(reg7b&0x10)?"2":(reg7b&0x20)?"1":(reg7b&0x30)?"0":"X", -(reg7b&0x40)?"2":(reg7b&0x80)?"1":(reg7b&0xC0)?"0":"X" ); - - default: - return 1; - } - - (void) ide_config_drive_speed(drive, speed); - outb(inb(dma_base+2)|(1<<(5+unit)), dma_base+2); -#endif - return 0; -} - -static void config_chipset_for_pio (ide_drive_t *drive, byte set_speed) -{ - byte speed = 0x00; - byte set_pio = ide_get_best_pio_mode(drive, 4, 5, NULL); - - cmd64x_tuneproc(drive, set_pio); - speed = XFER_PIO_0 + set_pio; - if (set_speed) - (void) ide_config_drive_speed(drive, speed); -} - -static int config_chipset_for_dma (ide_drive_t *drive, unsigned int rev, byte ultra_66) -{ - struct hd_driveid *id = drive->id; - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - unsigned long dma_base = hwif->dma_base; - - byte unit = (drive->select.b.unit & 0x01); - byte speed = 0x00; - byte set_pio = 0x00; - byte udma_timing_bits = 0x00; - byte udma_33 = ((rev >= 0x05) || (ultra_66)) ? 1 : 0; - byte udma_66 = ((id->hw_config & 0x2000) && (hwif->udma_four)) ? 1 : 0; - /* int drive_number = ((hwif->channel ? 2 : 0) + unit); */ - int rval; - - switch(dev->device) { - case PCI_DEVICE_ID_CMD_643: - case PCI_DEVICE_ID_CMD_646: - case PCI_DEVICE_ID_CMD_648: - default: - break; - } - - if (drive->media != ide_disk) { - cmdprintk("CMD64X: drive->media != ide_disk at double check, inital check failed!!\n"); - return ((int) ide_dma_off); - } - - /* UltraDMA only supported on PCI646U and PCI646U2, - * which correspond to revisions 0x03, 0x05 and 0x07 respectively. - * Actually, although the CMD tech support people won't - * tell me the details, the 0x03 revision cannot support - * UDMA correctly without hardware modifications, and even - * then it only works with Quantum disks due to some - * hold time assumptions in the 646U part which are fixed - * in the 646U2. - * So we only do UltraDMA on revision 0x05 and 0x07 chipsets. - */ - - if ((id->dma_ultra & 0x0010) && (udma_66) && (udma_33)) { - speed = XFER_UDMA_4; - udma_timing_bits = 0x10; /* 2 clock */ - } else if ((id->dma_ultra & 0x0008) && (udma_66) && (udma_33)) { - speed = XFER_UDMA_3; - udma_timing_bits = 0x20; /* 3 clock */ - } else if ((id->dma_ultra & 0x0004) && (udma_33)) { - speed = XFER_UDMA_2; - udma_timing_bits = 0x10; /* 2 clock */ - } else if ((id->dma_ultra & 0x0002) && (udma_33)) { - speed = XFER_UDMA_1; - udma_timing_bits = 0x20; /* 3 clock */ - } else if ((id->dma_ultra & 0x0001) && (udma_33)) { - speed = XFER_UDMA_0; - udma_timing_bits = 0x30; /* 4 clock */ - } else if (id->dma_mword & 0x0004) { - speed = XFER_MW_DMA_2; - } else if (id->dma_mword & 0x0002) { - speed = XFER_MW_DMA_1; - } else if (id->dma_mword & 0x0001) { - speed = XFER_MW_DMA_0; - } else if (id->dma_1word & 0x0004) { - speed = XFER_SW_DMA_2; - } else if (id->dma_1word & 0x0002) { - speed = XFER_SW_DMA_1; - } else if (id->dma_1word & 0x0001) { - speed = XFER_SW_DMA_0; - } else { - set_pio = 1; - } - - config_chipset_for_pio(drive, set_pio); - - if (set_pio) - return ((int) ide_dma_off_quietly); - -#if 1 - /* - * This the alternate access method. :-( - * The correct method is to directly setup the pci-config space. - */ - (void) ide_config_drive_speed(drive, speed); - outb(inb(dma_base+2)|(1<<(5+unit)), dma_base+2); - - if (speed >= XFER_UDMA_0) { - byte udma_ctrl = inb(dma_base + 3); - /* Put this channel into UDMA mode. */ - udma_ctrl |= (1 << unit); - udma_ctrl &= ~(0x04 << unit); - if (udma_66) - udma_ctrl |= (0x04 << unit); - udma_ctrl &= ~(0x30 << (unit * 2)); - udma_ctrl |= (udma_timing_bits << (unit * 2)); - outb(udma_ctrl, dma_base+3); - } -#endif - - if (tune_chipset_for_dma(drive, speed)) - return ((int) ide_dma_off); - - rval = (int)( ((id->dma_ultra >> 11) & 3) ? ide_dma_on : - ((id->dma_ultra >> 8) & 7) ? ide_dma_on : - ((id->dma_mword >> 8) & 7) ? ide_dma_on : - ((id->dma_1word >> 8) & 7) ? ide_dma_on : - ide_dma_off_quietly); - - return rval; -} - -static int cmd64x_config_drive_for_dma (ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - unsigned int class_rev = 0; - byte can_ultra_33 = 0; - byte can_ultra_66 = 0; - ide_dma_action_t dma_func = ide_dma_on; - - pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); - class_rev &= 0xff; - - switch(dev->device) { - case PCI_DEVICE_ID_CMD_643: - can_ultra_33 = 1; - can_ultra_66 = 0; - break; - case PCI_DEVICE_ID_CMD_646: - can_ultra_33 = (class_rev >= 0x05) ? 1 : 0; - can_ultra_66 = 0; - break; - case PCI_DEVICE_ID_CMD_648: - can_ultra_33 = 1; - can_ultra_66 = 1; - break; - default: - return hwif->dmaproc(ide_dma_off, drive); - } - - if ((id != NULL) && ((id->capability & 1) != 0) && - hwif->autodma && (drive->media == ide_disk)) { - /* Consult the list of known "bad" drives */ - if (ide_dmaproc(ide_dma_bad_drive, drive)) { - dma_func = ide_dma_off; - goto fast_ata_pio; - } - dma_func = ide_dma_off_quietly; - if ((id->field_valid & 4) && (can_ultra_33)) { - if (id->dma_ultra & 0x001F) { - /* Force if Capable UltraDMA */ - dma_func = config_chipset_for_dma(drive, class_rev, can_ultra_66); - if ((id->field_valid & 2) && - (dma_func != ide_dma_on)) - goto try_dma_modes; - } - } else if (id->field_valid & 2) { -try_dma_modes: - if ((id->dma_mword & 0x0007) || - (id->dma_1word & 0x0007)) { - /* Force if Capable regular DMA modes */ - dma_func = config_chipset_for_dma(drive, class_rev, 0); - if (dma_func != ide_dma_on) - goto no_dma_set; - } - } else if (ide_dmaproc(ide_dma_good_drive, drive)) { - if (id->eide_dma_time > 150) { - goto no_dma_set; - } - /* Consult the list of known "good" drives */ - dma_func = config_chipset_for_dma(drive, class_rev, 0); - if (dma_func != ide_dma_on) - goto no_dma_set; - } else { - goto fast_ata_pio; - } - } else if ((id->capability & 8) || (id->field_valid & 2)) { -fast_ata_pio: - dma_func = ide_dma_off_quietly; -no_dma_set: - config_chipset_for_pio(drive, 1); - } - return HWIF(drive)->dmaproc(dma_func, drive); -} - -static int cmd64x_dmaproc (ide_dma_action_t func, ide_drive_t *drive) -{ - switch (func) { - case ide_dma_check: - return cmd64x_config_drive_for_dma(drive); - default: - break; - } - /* Other cases are done by generic IDE-DMA code. */ - return ide_dmaproc(func, drive); -} - -/* - * ASUS P55T2P4D with CMD646 chipset revision 0x01 requires the old - * event order for DMA transfers. - */ -static int cmd646_1_dmaproc (ide_dma_action_t func, ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - unsigned long dma_base = hwif->dma_base; - byte dma_stat; - - if (func == ide_dma_end) { - drive->waiting_for_dma = 0; - dma_stat = inb(dma_base+2); /* get DMA status */ - outb(inb(dma_base)&~1, dma_base); /* stop DMA */ - outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */ - ide_destroy_dmatable(drive); /* and free any DMA resources */ - return (dma_stat & 7) != 4; /* verify good DMA status */ - } - - /* Other cases are done by generic IDE-DMA code. */ - return cmd64x_dmaproc(func, drive); -} - -unsigned int __init pci_init_cmd64x (struct pci_dev *dev, const char *name) -{ - unsigned char mrdmode; - unsigned int class_rev; - - pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); - class_rev &= 0xff; - -#if 0 - if (dev->resource[PCI_ROM_RESOURCE].start) - pci_write_config_byte(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); -#endif - - switch(dev->device) { - case PCI_DEVICE_ID_CMD_643: - break; - case PCI_DEVICE_ID_CMD_646: - printk("%s: chipset revision 0x%02X, ", name, class_rev); - switch(class_rev) { - case 0x07: - case 0x05: - printk("UltraDMA Capable"); - break; - case 0x03: - printk("MultiWord DMA Force Limited"); - break; - case 0x01: - default: - printk("MultiWord DMA Limited, IRQ workaround enabled"); - break; - } - printk("\n"); - break; - case PCI_DEVICE_ID_CMD_648: - break; - default: - break; - } - - /* Set a good latency timer and cache line size value. */ - (void) pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64); -#ifdef __sparc_v9__ - (void) pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 0x10); -#endif - - /* Setup interrupts. */ - (void) pci_read_config_byte(dev, MRDMODE, &mrdmode); - mrdmode &= ~(0x30); - (void) pci_write_config_byte(dev, MRDMODE, mrdmode); - - /* Use MEMORY READ LINE for reads. - * NOTE: Although not mentioned in the PCI0646U specs, - * these bits are write only and won't be read - * back as set or not. The PCI0646U2 specs clarify - * this point. - */ - (void) pci_write_config_byte(dev, MRDMODE, mrdmode | 0x02); - - /* Set reasonable active/recovery/address-setup values. */ - (void) pci_write_config_byte(dev, ARTTIM0, 0x40); - (void) pci_write_config_byte(dev, DRWTIM0, 0x3f); - (void) pci_write_config_byte(dev, ARTTIM1, 0x40); - (void) pci_write_config_byte(dev, DRWTIM1, 0x3f); -#ifdef __i386__ - (void) pci_write_config_byte(dev, ARTTIM23, 0x1c); -#else - (void) pci_write_config_byte(dev, ARTTIM23, 0x5c); -#endif - (void) pci_write_config_byte(dev, DRWTIM23, 0x3f); - (void) pci_write_config_byte(dev, DRWTIM3, 0x3f); - -#if defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS) - cmd64x_proc = 1; - bmide_dev = dev; - cmd64x_display_info = &cmd64x_get_info; -#endif /* DISPLAY_CMD64X_TIMINGS && CONFIG_PROC_FS */ - - return 0; -} - -unsigned int __init ata66_cmd64x (ide_hwif_t *hwif) -{ - byte ata66 = 0; - byte mask = (hwif->channel) ? 0x02 : 0x01; - - pci_read_config_byte(hwif->pci_dev, BMIDECSR, &ata66); - return (ata66 & mask) ? 1 : 0; -} - -void __init ide_init_cmd64x (ide_hwif_t *hwif) -{ - struct pci_dev *dev = hwif->pci_dev; - unsigned int class_rev; - - pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); - class_rev &= 0xff; - - hwif->tuneproc = &cmd64x_tuneproc; - hwif->drives[0].autotune = 1; - hwif->drives[0].autotune = 1; - - if (!hwif->dma_base) - return; - - switch(dev->device) { - case PCI_DEVICE_ID_CMD_643: - hwif->dmaproc = &cmd64x_dmaproc; - break; - case PCI_DEVICE_ID_CMD_646: - hwif->chipset = ide_cmd646; - if (class_rev == 0x01) { - hwif->dmaproc = &cmd646_1_dmaproc; - } else { - hwif->dmaproc = &cmd64x_dmaproc; - } - break; - case PCI_DEVICE_ID_CMD_648: - hwif->dmaproc = &cmd64x_dmaproc; - break; - default: - break; - } -} diff --git a/drivers/block/cs5530.c b/drivers/block/cs5530.c deleted file mode 100644 index bb68f7b2e..000000000 --- a/drivers/block/cs5530.c +++ /dev/null @@ -1,361 +0,0 @@ -/* - * linux/drivers/block/cs5530.c Version 0.5 Feb 13, 2000 - * - * Copyright (C) 2000 Mark Lord <mlord@pobox.com> - * May be copied or modified under the terms of the GNU General Public License - * - * Development of this chipset driver was funded - * by the nice folks at National Semiconductor. - */ - -#include <linux/config.h> -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/delay.h> -#include <linux/timer.h> -#include <linux/mm.h> -#include <linux/ioport.h> -#include <linux/blkdev.h> -#include <linux/hdreg.h> -#include <linux/interrupt.h> -#include <linux/pci.h> -#include <linux/init.h> -#include <linux/ide.h> -#include <asm/io.h> -#include <asm/irq.h> -#include "ide_modes.h" - -#define DISPLAY_CS5530_TIMINGS - -#if defined(DISPLAY_CS5530_TIMINGS) && defined(CONFIG_PROC_FS) -#include <linux/stat.h> -#include <linux/proc_fs.h> - -static int cs5530_get_info(char *, char **, off_t, int); -extern int (*cs5530_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -extern char *ide_media_verbose(ide_drive_t *); -static struct pci_dev *bmide_dev; - -static int cs5530_get_info (char *buffer, char **addr, off_t offset, int count) -{ - char *p = buffer; - u32 bibma = bmide_dev->resource[4].start; - u8 c0 = 0, c1 = 0; - - /* - * at that point bibma+0x2 et bibma+0xa are byte registers - * to investigate: - */ - - c0 = inb_p((unsigned short)bibma + 0x02); - c1 = inb_p((unsigned short)bibma + 0x0a); - - p += sprintf(p, "\n Cyrix 5530 Chipset.\n"); - p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n"); - p += sprintf(p, " %sabled %sabled\n", - (c0&0x80) ? "dis" : " en", - (c1&0x80) ? "dis" : " en"); - p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n"); - p += sprintf(p, "DMA enabled: %s %s %s %s\n", - (c0&0x20) ? "yes" : "no ", (c0&0x40) ? "yes" : "no ", - (c1&0x20) ? "yes" : "no ", (c1&0x40) ? "yes" : "no " ); - - p += sprintf(p, "UDMA\n"); - p += sprintf(p, "DMA\n"); - p += sprintf(p, "PIO\n"); - - return p-buffer; -} -#endif /* DISPLAY_CS5530_TIMINGS && CONFIG_PROC_FS */ - -byte cs5530_proc = 0; - -extern char *ide_xfer_verbose (byte xfer_rate); - -/* - * Set a new transfer mode at the drive - */ -int cs5530_set_xfer_mode (ide_drive_t *drive, byte mode) -{ - int error = 0; - - printk("%s: cs5530_set_xfer_mode(%s)\n", drive->name, ide_xfer_verbose(mode)); - error = ide_config_drive_speed(drive, mode); - - return error; -} - -/* - * Here are the standard PIO mode 0-4 timings for each "format". - * Format-0 uses fast data reg timings, with slower command reg timings. - * Format-1 uses fast timings for all registers, but won't work with all drives. - */ -static unsigned int cs5530_pio_timings[2][5] = - {{0x00009172, 0x00012171, 0x00020080, 0x00032010, 0x00040010}, - {0xd1329172, 0x71212171, 0x30200080, 0x20102010, 0x00100010}}; - -/* - * After chip reset, the PIO timings are set to 0x0000e132, which is not valid. - */ -#define CS5530_BAD_PIO(timings) (((timings)&~0x80000000)==0x0000e132) -#define CS5530_BASEREG(hwif) (((hwif)->dma_base & ~0xf) + ((hwif)->channel ? 0x30 : 0x20)) - -/* - * cs5530_tuneproc() handles selection/setting of PIO modes - * for both the chipset and drive. - * - * The ide_init_cs5530() routine guarantees that all drives - * will have valid default PIO timings set up before we get here. - */ -static void cs5530_tuneproc (ide_drive_t *drive, byte pio) /* pio=255 means "autotune" */ -{ - ide_hwif_t *hwif = HWIF(drive); - unsigned int format, basereg = CS5530_BASEREG(hwif); - static byte modes[5] = {XFER_PIO_0, XFER_PIO_1, XFER_PIO_2, XFER_PIO_3, XFER_PIO_4}; - - pio = ide_get_best_pio_mode(drive, pio, 4, NULL); - if (!cs5530_set_xfer_mode(drive, modes[pio])) { - format = (inl(basereg+4) >> 31) & 1; - outl(cs5530_pio_timings[format][pio], basereg+(drive->select.b.unit<<3)); - } -} - -/* - * cs5530_config_dma() handles selection/setting of DMA/UDMA modes - * for both the chipset and drive. - */ -static int cs5530_config_dma (ide_drive_t *drive) -{ - int udma_ok = 1, mode = 0; - ide_hwif_t *hwif = HWIF(drive); - int unit = drive->select.b.unit; - ide_drive_t *mate = &hwif->drives[unit^1]; - struct hd_driveid *id = drive->id; - unsigned int basereg, reg, timings; - - - /* - * Default to DMA-off in case we run into trouble here. - */ - (void)hwif->dmaproc(ide_dma_off_quietly, drive); /* turn off DMA while we fiddle */ - outb(inb(hwif->dma_base+2)&~(unit?0x40:0x20), hwif->dma_base+2); /* clear DMA_capable bit */ - - /* - * The CS5530 specifies that two drives sharing a cable cannot - * mix UDMA/MDMA. It has to be one or the other, for the pair, - * though different timings can still be chosen for each drive. - * We could set the appropriate timing bits on the fly, - * but that might be a bit confusing. So, for now we statically - * handle this requirement by looking at our mate drive to see - * what it is capable of, before choosing a mode for our own drive. - */ - if (mate->present) { - struct hd_driveid *mateid = mate->id; - if (mateid && (mateid->capability & 1) && !hwif->dmaproc(ide_dma_bad_drive, mate)) { - if ((mateid->field_valid & 4) && (mateid->dma_ultra & 7)) - udma_ok = 1; - else if ((mateid->field_valid & 2) && (mateid->dma_mword & 7)) - udma_ok = 0; - else - udma_ok = 1; - } - } - - /* - * Now see what the current drive is capable of, - * selecting UDMA only if the mate said it was ok. - */ - if (id && (id->capability & 1) && hwif->autodma && !hwif->dmaproc(ide_dma_bad_drive, drive)) { - if (udma_ok && (id->field_valid & 4) && (id->dma_ultra & 7)) { - if (id->dma_ultra & 4) - mode = XFER_UDMA_2; - else if (id->dma_ultra & 2) - mode = XFER_UDMA_1; - else if (id->dma_ultra & 1) - mode = XFER_UDMA_0; - } - if (!mode && (id->field_valid & 2) && (id->dma_mword & 7)) { - if (id->dma_mword & 4) - mode = XFER_MW_DMA_2; - else if (id->dma_mword & 2) - mode = XFER_MW_DMA_1; - else if (id->dma_mword & 1) - mode = XFER_MW_DMA_0; - } - } - - /* - * Tell the drive to switch to the new mode; abort on failure. - */ - if (!mode || cs5530_set_xfer_mode(drive, mode)) - return 1; /* failure */ - - /* - * Now tune the chipset to match the drive: - */ - switch (mode) { - case XFER_UDMA_0: timings = 0x00921250; break; - case XFER_UDMA_1: timings = 0x00911140; break; - case XFER_UDMA_2: timings = 0x00911030; break; - case XFER_MW_DMA_0: timings = 0x00077771; break; - case XFER_MW_DMA_1: timings = 0x00012121; break; - case XFER_MW_DMA_2: timings = 0x00002020; break; - default: - printk("%s: cs5530_config_dma: huh? mode=%02x\n", drive->name, mode); - return 1; /* failure */ - } - basereg = CS5530_BASEREG(hwif); - reg = inl(basereg+4); /* get drive0 config register */ - timings |= reg & 0x80000000; /* preserve PIO format bit */ - if (unit == 0) { /* are we configuring drive0? */ - outl(timings, basereg+4); /* write drive0 config register */ - } else { - if (timings & 0x00100000) - reg |= 0x00100000; /* enable UDMA timings for both drives */ - else - reg &= ~0x00100000; /* disable UDMA timings for both drives */ - outl(reg, basereg+4); /* write drive0 config register */ - outl(timings, basereg+12); /* write drive1 config register */ - } - outb(inb(hwif->dma_base+2)|(unit?0x40:0x20), hwif->dma_base+2); /* set DMA_capable bit */ - - /* - * Finally, turn DMA on in software, and exit. - */ - return hwif->dmaproc(ide_dma_on, drive); /* success */ -} - -/* - * This is a CS5530-specific wrapper for the standard ide_dmaproc(). - * We need it for our custom "ide_dma_check" function. - * All other requests are forwarded to the standard ide_dmaproc(). - */ -int cs5530_dmaproc (ide_dma_action_t func, ide_drive_t *drive) -{ - switch (func) { - case ide_dma_check: - return cs5530_config_dma(drive); - default: - break; - } - /* Other cases are done by generic IDE-DMA code. */ - return ide_dmaproc(func, drive); -} - -/* - * Initialize the cs5530 bridge for reliable IDE DMA operation. - */ -unsigned int __init pci_init_cs5530 (struct pci_dev *dev, const char *name) -{ - struct pci_dev *master_0 = NULL, *cs5530_0 = NULL; - unsigned short pcicmd = 0; - unsigned long flags; - - pci_for_each_dev (dev) { - if (dev->vendor == PCI_VENDOR_ID_CYRIX) { - switch (dev->device) { - case PCI_DEVICE_ID_CYRIX_PCI_MASTER: - master_0 = dev; - break; - case PCI_DEVICE_ID_CYRIX_5530_LEGACY: - cs5530_0 = dev; - break; - } - } - } - if (!master_0) { - printk("%s: unable to locate PCI MASTER function\n", name); - return 0; - } - if (!cs5530_0) { - printk("%s: unable to locate CS5530 LEGACY function\n", name); - return 0; - } - - save_flags(flags); - cli(); /* all CPUs (there should only be one CPU with this chipset) */ - - /* - * Enable BusMaster and MemoryWriteAndInvalidate for the cs5530: - * --> OR 0x14 into 16-bit PCI COMMAND reg of function 0 of the cs5530 - */ - pci_read_config_word (cs5530_0, PCI_COMMAND, &pcicmd); - pci_write_config_word(cs5530_0, PCI_COMMAND, pcicmd | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE); - - /* - * Set PCI CacheLineSize to 16-bytes: - * --> Write 0x04 into 8-bit PCI CACHELINESIZE reg of function 0 of the cs5530 - */ - pci_write_config_byte(cs5530_0, PCI_CACHE_LINE_SIZE, 0x04); - - /* - * Disable trapping of UDMA register accesses (Win98 hack): - * --> Write 0x5006 into 16-bit reg at offset 0xd0 of function 0 of the cs5530 - */ - pci_write_config_word(cs5530_0, 0xd0, 0x5006); - - /* - * Bit-1 at 0x40 enables MemoryWriteAndInvalidate on internal X-bus: - * The other settings are what is necessary to get the register - * into a sane state for IDE DMA operation. - */ - pci_write_config_byte(master_0, 0x40, 0x1e); - - /* - * Set max PCI burst size (16-bytes seems to work best): - * 16bytes: set bit-1 at 0x41 (reg value of 0x16) - * all others: clear bit-1 at 0x41, and do: - * 128bytes: OR 0x00 at 0x41 - * 256bytes: OR 0x04 at 0x41 - * 512bytes: OR 0x08 at 0x41 - * 1024bytes: OR 0x0c at 0x41 - */ - pci_write_config_byte(master_0, 0x41, 0x14); - - /* - * These settings are necessary to get the chip - * into a sane state for IDE DMA operation. - */ - pci_write_config_byte(master_0, 0x42, 0x00); - pci_write_config_byte(master_0, 0x43, 0xc1); - - restore_flags(flags); - -#if defined(DISPLAY_CS5530_TIMINGS) && defined(CONFIG_PROC_FS) - cs5530_proc = 1; - bmide_dev = dev; - cs5530_display_info = &cs5530_get_info; -#endif /* DISPLAY_CS5530_TIMINGS && CONFIG_PROC_FS */ - - return 0; -} - -/* - * This gets invoked by the IDE driver once for each channel, - * and performs channel-specific pre-initialization before drive probing. - */ -void __init ide_init_cs5530 (ide_hwif_t *hwif) -{ - if (hwif->mate) - hwif->serialized = hwif->mate->serialized = 1; - if (!hwif->dma_base) { - hwif->autodma = 0; - } else { - unsigned int basereg, d0_timings; - - hwif->dmaproc = &cs5530_dmaproc; - hwif->tuneproc = &cs5530_tuneproc; - basereg = CS5530_BASEREG(hwif); - d0_timings = inl(basereg+0); - if (CS5530_BAD_PIO(d0_timings)) { /* PIO timings not initialized? */ - outl(cs5530_pio_timings[(d0_timings>>31)&1][0], basereg+0); - if (!hwif->drives[0].autotune) - hwif->drives[0].autotune = 1; /* needs autotuning later */ - } - if (CS5530_BAD_PIO(inl(basereg+8))) { /* PIO timings not initialized? */ - outl(cs5530_pio_timings[(d0_timings>>31)&1][0], basereg+8); - if (!hwif->drives[1].autotune) - hwif->drives[1].autotune = 1; /* needs autotuning later */ - } - } -} diff --git a/drivers/block/cy82c693.c b/drivers/block/cy82c693.c deleted file mode 100644 index cfff0381c..000000000 --- a/drivers/block/cy82c693.c +++ /dev/null @@ -1,441 +0,0 @@ -/* - * linux/drivers/block/cy82c693.c Version 0.34 Dec. 13, 1999 - * - * Copyright (C) 1998-99 Andreas S. Krebs (akrebs@altavista.net), Maintainer - * Copyright (C) 1998-99 Andre Hedrick, Integrater - * - * CYPRESS CY82C693 chipset IDE controller - * - * The CY82C693 chipset is used on Digital's PC-Alpha 164SX boards. - * Writting the driver was quite simple, since most of the job is - * done by the generic pci-ide support. - * The hard part was finding the CY82C693's datasheet on Cypress's - * web page :-(. But Altavista solved this problem :-). - * - * - * Notes: - * - I recently got a 16.8G IBM DTTA, so I was able to test it with - * a large and fast disk - the results look great, so I'd say the - * driver is working fine :-) - * hdparm -t reports 8.17 MB/sec at about 6% CPU usage for the DTTA - * - this is my first linux driver, so there's probably a lot of room - * for optimizations and bug fixing, so feel free to do it. - * - use idebus=xx parameter to set PCI bus speed - needed to calc - * timings for PIO modes (default will be 40) - * - if using PIO mode it's a good idea to set the PIO mode and - * 32-bit I/O support (if possible), e.g. hdparm -p2 -c1 /dev/hda - * - I had some problems with my IBM DHEA with PIO modes < 2 - * (lost interrupts) ????? - * - first tests with DMA look okay, they seem to work, but there is a - * problem with sound - the BusMaster IDE TimeOut should fixed this - * - * - * History: - * AMH@1999-08-24: v0.34 init_cy82c693_chip moved to pci_init_cy82c693 - * ASK@1999-01-23: v0.33 made a few minor code clean ups - * removed DMA clock speed setting by default - * added boot message - * ASK@1998-11-01: v0.32 added support to set BusMaster IDE TimeOut - * added support to set DMA Controller Clock Speed - * ASK@1998-10-31: v0.31 fixed problem with setting to high DMA modes on some drive - * ASK@1998-10-29: v0.3 added support to set DMA modes - * ASK@1998-10-28: v0.2 added support to set PIO modes - * ASK@1998-10-27: v0.1 first version - chipset detection - * - */ - -#include <linux/types.h> -#include <linux/pci.h> -#include <linux/delay.h> -#include <linux/ide.h> - -#include <asm/io.h> - -#include "ide_modes.h" - -/* the current version */ -#define CY82_VERSION "CY82C693U driver v0.34 99-13-12 Andreas S. Krebs (akrebs@altavista.net)" - -/* - * The following are used to debug the driver. - */ -#define CY82C693_DEBUG_LOGS 0 -#define CY82C693_DEBUG_INFO 0 - -/* define CY82C693_SETDMA_CLOCK to set DMA Controller Clock Speed to ATCLK */ -#undef CY82C693_SETDMA_CLOCK - -/* - * note: the value for busmaster timeout is tricky and i got it by trial and error ! - * using a to low value will cause DMA timeouts and drop IDE performance - * using a to high value will cause audio playback to scatter - * if you know a better value or how to calc it, please let me know - */ -#define BUSMASTER_TIMEOUT 0x50 /* twice the value written in cy82c693ub datasheet */ -/* - * the value above was tested on my machine and it seems to work okay - */ - -/* here are the offset definitions for the registers */ -#define CY82_IDE_CMDREG 0x04 -#define CY82_IDE_ADDRSETUP 0x48 -#define CY82_IDE_MASTER_IOR 0x4C -#define CY82_IDE_MASTER_IOW 0x4D -#define CY82_IDE_SLAVE_IOR 0x4E -#define CY82_IDE_SLAVE_IOW 0x4F -#define CY82_IDE_MASTER_8BIT 0x50 -#define CY82_IDE_SLAVE_8BIT 0x51 - -#define CY82_INDEX_PORT 0x22 -#define CY82_DATA_PORT 0x23 - -#define CY82_INDEX_CTRLREG1 0x01 -#define CY82_INDEX_CHANNEL0 0x30 -#define CY82_INDEX_CHANNEL1 0x31 -#define CY82_INDEX_TIMEOUT 0x32 - -/* the max PIO mode - from datasheet */ -#define CY82C693_MAX_PIO 4 - -/* the min and max PCI bus speed in MHz - from datasheet */ -#define CY82C963_MIN_BUS_SPEED 25 -#define CY82C963_MAX_BUS_SPEED 33 - -/* the struct for the PIO mode timings */ -typedef struct pio_clocks_s { - byte address_time; /* Address setup (clocks) */ - byte time_16r; /* clocks for 16bit IOR (0xF0=Active/data, 0x0F=Recovery) */ - byte time_16w; /* clocks for 16bit IOW (0xF0=Active/data, 0x0F=Recovery) */ - byte time_8; /* clocks for 8bit (0xF0=Active/data, 0x0F=Recovery) */ -} pio_clocks_t; - -/* - * calc clocks using bus_speed - * returns (rounded up) time in bus clocks for time in ns - */ -static int calc_clk (int time, int bus_speed) -{ - int clocks; - - clocks = (time*bus_speed+999)/1000 -1; - - if (clocks < 0) - clocks = 0; - - if (clocks > 0x0F) - clocks = 0x0F; - - return clocks; -} - -/* - * compute the values for the clock registers for PIO - * mode and pci_clk [MHz] speed - * - * NOTE: for mode 0,1 and 2 drives 8-bit IDE command control registers are used - * for mode 3 and 4 drives 8 and 16-bit timings are the same - * - */ -static void compute_clocks (byte pio, pio_clocks_t *p_pclk) -{ - int clk1, clk2; - int bus_speed; - - bus_speed = ide_system_bus_speed(); /* get speed of PCI bus */ - /* we don't check against CY82C693's min and max speed, - * so you can play with the idebus=xx parameter - */ - - if (pio > CY82C693_MAX_PIO) - pio = CY82C693_MAX_PIO; - - /* let's calc the address setup time clocks */ - p_pclk->address_time = (byte)calc_clk(ide_pio_timings[pio].setup_time, bus_speed); - - /* let's calc the active and recovery time clocks */ - clk1 = calc_clk(ide_pio_timings[pio].active_time, bus_speed); - - /* calc recovery timing */ - clk2 = ide_pio_timings[pio].cycle_time - - ide_pio_timings[pio].active_time - - ide_pio_timings[pio].setup_time; - - clk2 = calc_clk(clk2, bus_speed); - - clk1 = (clk1<<4)|clk2; /* combine active and recovery clocks */ - - /* note: we use the same values for 16bit IOR and IOW - * those are all the same, since I don't have other - * timings than those from ide_modes.h - */ - - p_pclk->time_16r = (byte)clk1; - p_pclk->time_16w = (byte)clk1; - - /* what are good values for 8bit ?? */ - p_pclk->time_8 = (byte)clk1; -} - -/* - * set DMA mode a specific channel for CY82C693 - */ -static void cy82c693_dma_enable (ide_drive_t *drive, int mode, int single) -{ - byte index; - byte data; - - if (mode>2) /* make sure we set a valid mode */ - mode = 2; - - if (mode > drive->id->tDMA) /* to be absolutly sure we have a valid mode */ - mode = drive->id->tDMA; - - index = (HWIF(drive)->channel==0) ? CY82_INDEX_CHANNEL0 : CY82_INDEX_CHANNEL1; - -#if CY82C693_DEBUG_LOGS - /* for debug let's show the previous values */ - - OUT_BYTE(index, CY82_INDEX_PORT); - data = IN_BYTE(CY82_DATA_PORT); - - printk (KERN_INFO "%s (ch=%d, dev=%d): DMA mode is %d (single=%d)\n", drive->name, HWIF(drive)->channel, drive->select.b.unit, (data&0x3), ((data>>2)&1)); -#endif /* CY82C693_DEBUG_LOGS */ - - data = (byte)mode|(byte)(single<<2); - - OUT_BYTE(index, CY82_INDEX_PORT); - OUT_BYTE(data, CY82_DATA_PORT); - -#if CY82C693_DEBUG_INFO - printk (KERN_INFO "%s (ch=%d, dev=%d): set DMA mode to %d (single=%d)\n", drive->name, HWIF(drive)->channel, drive->select.b.unit, mode, single); -#endif /* CY82C693_DEBUG_INFO */ - - /* - * note: below we set the value for Bus Master IDE TimeOut Register - * I'm not absolutly sure what this does, but it solved my problem - * with IDE DMA and sound, so I now can play sound and work with - * my IDE driver at the same time :-) - * - * If you know the correct (best) value for this register please - * let me know - ASK - */ - - data = BUSMASTER_TIMEOUT; - OUT_BYTE(CY82_INDEX_TIMEOUT, CY82_INDEX_PORT); - OUT_BYTE(data, CY82_DATA_PORT); - -#if CY82C693_DEBUG_INFO - printk (KERN_INFO "%s: Set IDE Bus Master TimeOut Register to 0x%X\n", drive->name, data); -#endif /* CY82C693_DEBUG_INFO */ -} - -/* - * used to set DMA mode for CY82C693 (single and multi modes) - */ -static int cy82c693_dmaproc(ide_dma_action_t func, ide_drive_t *drive) -{ - /* - * if the function is dma on, set dma mode for drive everything - * else is done by the defaul func - */ - if (func == ide_dma_on) { - struct hd_driveid *id = drive->id; - -#if CY82C693_DEBUG_INFO - printk (KERN_INFO "dma_on: %s\n", drive->name); -#endif /* CY82C693_DEBUG_INFO */ - - if (id != NULL) { - /* Enable DMA on any drive that has DMA (multi or single) enabled */ - if (id->field_valid & 2) { /* regular DMA */ - int mmode, smode; - - mmode = id->dma_mword & (id->dma_mword >> 8); - smode = id->dma_1word & (id->dma_1word >> 8); - - if (mmode != 0) - cy82c693_dma_enable(drive, (mmode >> 1), 0); /* enable multi */ - else if (smode != 0) - cy82c693_dma_enable(drive, (smode >> 1), 1); /* enable single */ - } - } - } - return ide_dmaproc(func, drive); -} - -/* - * tune ide drive - set PIO mode - */ -static void cy82c693_tune_drive (ide_drive_t *drive, byte pio) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - pio_clocks_t pclk; - unsigned int addrCtrl; - - /* select primary or secondary channel */ - if (hwif->index > 0) { /* drive is on the secondary channel */ - dev = pci_find_slot(dev->bus->number, dev->devfn+1); - if (!dev) { - printk(KERN_ERR "%s: tune_drive: Cannot find secondary interface!\n", drive->name); - return; - } - } - -#if CY82C693_DEBUG_LOGS - /* for debug let's show the register values */ - - if (drive->select.b.unit == 0) { - /* - * get master drive registers - * address setup control register - * is 32 bit !!! - */ - pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl); - addrCtrl &= 0x0F; - - /* now let's get the remaining registers */ - pci_read_config_byte(dev, CY82_IDE_MASTER_IOR, &pclk.time_16r); - pci_read_config_byte(dev, CY82_IDE_MASTER_IOW, &pclk.time_16w); - pci_read_config_byte(dev, CY82_IDE_MASTER_8BIT, &pclk.time_8); - } else { - /* - * set slave drive registers - * address setup control register - * is 32 bit !!! - */ - pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl); - - addrCtrl &= 0xF0; - addrCtrl >>= 4; - - /* now let's get the remaining registers */ - pci_read_config_byte(dev, CY82_IDE_SLAVE_IOR, &pclk.time_16r); - pci_read_config_byte(dev, CY82_IDE_SLAVE_IOW, &pclk.time_16w); - pci_read_config_byte(dev, CY82_IDE_SLAVE_8BIT, &pclk.time_8); - } - - printk (KERN_INFO "%s (ch=%d, dev=%d): PIO timing is (addr=0x%X, ior=0x%X, iow=0x%X, 8bit=0x%X)\n", drive->name, hwif->channel, drive->select.b.unit, addrCtrl, pclk.time_16r, pclk.time_16w, pclk.time_8); -#endif /* CY82C693_DEBUG_LOGS */ - - /* first let's calc the pio modes */ - pio = ide_get_best_pio_mode(drive, pio, CY82C693_MAX_PIO, NULL); - -#if CY82C693_DEBUG_INFO - printk (KERN_INFO "%s: Selected PIO mode %d\n", drive->name, pio); -#endif /* CY82C693_DEBUG_INFO */ - - compute_clocks(pio, &pclk); /* let's calc the values for this PIO mode */ - - /* now let's write the clocks registers */ - if (drive->select.b.unit == 0) { - /* - * set master drive - * address setup control register - * is 32 bit !!! - */ - pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl); - - addrCtrl &= (~0xF); - addrCtrl |= (unsigned int)pclk.address_time; - pci_write_config_dword(dev, CY82_IDE_ADDRSETUP, addrCtrl); - - /* now let's set the remaining registers */ - pci_write_config_byte(dev, CY82_IDE_MASTER_IOR, pclk.time_16r); - pci_write_config_byte(dev, CY82_IDE_MASTER_IOW, pclk.time_16w); - pci_write_config_byte(dev, CY82_IDE_MASTER_8BIT, pclk.time_8); - - addrCtrl &= 0xF; - } else { - /* - * set slave drive - * address setup control register - * is 32 bit !!! - */ - pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl); - - addrCtrl &= (~0xF0); - addrCtrl |= ((unsigned int)pclk.address_time<<4); - pci_write_config_dword(dev, CY82_IDE_ADDRSETUP, addrCtrl); - - /* now let's set the remaining registers */ - pci_write_config_byte(dev, CY82_IDE_SLAVE_IOR, pclk.time_16r); - pci_write_config_byte(dev, CY82_IDE_SLAVE_IOW, pclk.time_16w); - pci_write_config_byte(dev, CY82_IDE_SLAVE_8BIT, pclk.time_8); - - addrCtrl >>= 4; - addrCtrl &= 0xF; - } - -#if CY82C693_DEBUG_INFO - printk (KERN_INFO "%s (ch=%d, dev=%d): set PIO timing to (addr=0x%X, ior=0x%X, iow=0x%X, 8bit=0x%X)\n", drive->name, hwif->channel, drive->select.b.unit, addrCtrl, pclk.time_16r, pclk.time_16w, pclk.time_8); -#endif /* CY82C693_DEBUG_INFO */ -} - -/* - * this function is called during init and is used to setup the cy82c693 chip - */ -/* - * FIXME! "pci_init_cy82c693" really should replace - * the "init_cy82c693_chip", it is the correct location to tinker/setup - * the device prior to INIT. - */ - -unsigned int __init pci_init_cy82c693(struct pci_dev *dev, const char *name) -{ -#ifdef CY82C693_SETDMA_CLOCK - byte data; -#endif /* CY82C693_SETDMA_CLOCK */ - - /* write info about this verion of the driver */ - printk (KERN_INFO CY82_VERSION "\n"); - -#ifdef CY82C693_SETDMA_CLOCK - /* okay let's set the DMA clock speed */ - - OUT_BYTE(CY82_INDEX_CTRLREG1, CY82_INDEX_PORT); - data = IN_BYTE(CY82_DATA_PORT); - -#if CY82C693_DEBUG_INFO - printk (KERN_INFO "%s: Peripheral Configuration Register: 0x%X\n", name, data); -#endif /* CY82C693_DEBUG_INFO */ - - /* - * for some reason sometimes the DMA controller - * speed is set to ATCLK/2 ???? - we fix this here - * - * note: i don't know what causes this strange behaviour, - * but even changing the dma speed doesn't solve it :-( - * the ide performance is still only half the normal speed - * - * if anybody knows what goes wrong with my machine, please - * let me know - ASK - */ - - data |= 0x03; - - OUT_BYTE(CY82_INDEX_CTRLREG1, CY82_INDEX_PORT); - OUT_BYTE(data, CY82_DATA_PORT); - -#if CY82C693_DEBUG_INFO - printk (KERN_INFO "%s: New Peripheral Configuration Register: 0x%X\n", name, data); -#endif /* CY82C693_DEBUG_INFO */ - -#endif /* CY82C693_SETDMA_CLOCK */ - return 0; -} - -/* - * the init function - called for each ide channel once - */ -void __init ide_init_cy82c693(ide_hwif_t *hwif) -{ - hwif->chipset = ide_cy82c693; - hwif->tuneproc = &cy82c693_tune_drive; - if (hwif->dma_base) { - hwif->dmaproc = &cy82c693_dmaproc; - } else { - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - } -} diff --git a/drivers/block/dtc2278.c b/drivers/block/dtc2278.c deleted file mode 100644 index d8838e111..000000000 --- a/drivers/block/dtc2278.c +++ /dev/null @@ -1,133 +0,0 @@ -/* - * linux/drivers/block/dtc2278.c Version 0.02 Feb 10, 1996 - * - * Copyright (C) 1996 Linus Torvalds & author (see below) - */ - -#undef REALLY_SLOW_IO /* most systems can safely undef this */ - -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/delay.h> -#include <linux/timer.h> -#include <linux/mm.h> -#include <linux/ioport.h> -#include <linux/blkdev.h> -#include <linux/hdreg.h> -#include <linux/ide.h> - -#include <asm/io.h> - -#include "ide_modes.h" - -/* - * Changing this #undef to #define may solve start up problems in some systems. - */ -#undef ALWAYS_SET_DTC2278_PIO_MODE - -/* - * From: andy@cercle.cts.com (Dyan Wile) - * - * Below is a patch for DTC-2278 - alike software-programmable controllers - * The code enables the secondary IDE controller and the PIO4 (3?) timings on - * the primary (EIDE). You may probably have to enable the 32-bit support to - * get the full speed. You better get the disk interrupts disabled ( hdparm -u0 - * /dev/hd.. ) for the drives connected to the EIDE interface. (I get my - * filesystem corrupted with -u1, but under heavy disk load only :-) - * - * This card is now forced to use the "serialize" feature, - * and irq-unmasking is disallowed. If io_32bit is enabled, - * it must be done for BOTH drives on each interface. - * - * This code was written for the DTC2278E, but might work with any of these: - * - * DTC2278S has only a single IDE interface. - * DTC2278D has two IDE interfaces and is otherwise identical to the S version. - * DTC2278E also has serial ports and a printer port - * DTC2278EB: has onboard BIOS, and "works like a charm" -- Kent Bradford <kent@theory.caltech.edu> - * - * There may be a fourth controller type. The S and D versions use the - * Winbond chip, and I think the E version does also. - * - */ - -static void sub22 (char b, char c) -{ - int i; - - for(i = 0; i < 3; ++i) { - inb(0x3f6); - outb_p(b,0xb0); - inb(0x3f6); - outb_p(c,0xb4); - inb(0x3f6); - if(inb(0xb4) == c) { - outb_p(7,0xb0); - inb(0x3f6); - return; /* success */ - } - } -} - -static void tune_dtc2278 (ide_drive_t *drive, byte pio) -{ - unsigned long flags; - - pio = ide_get_best_pio_mode(drive, pio, 4, NULL); - - if (pio >= 3) { - save_flags(flags); /* all CPUs */ - cli(); /* all CPUs */ - /* - * This enables PIO mode4 (3?) on the first interface - */ - sub22(1,0xc3); - sub22(0,0xa0); - restore_flags(flags); /* all CPUs */ - } else { - /* we don't know how to set it back again.. */ - } - - /* - * 32bit I/O has to be enabled for *both* drives at the same time. - */ - drive->io_32bit = 1; - HWIF(drive)->drives[!drive->select.b.unit].io_32bit = 1; -} - -void __init init_dtc2278 (void) -{ - unsigned long flags; - - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ - /* - * This enables the second interface - */ - outb_p(4,0xb0); - inb(0x3f6); - outb_p(0x20,0xb4); - inb(0x3f6); -#ifdef ALWAYS_SET_DTC2278_PIO_MODE - /* - * This enables PIO mode4 (3?) on the first interface - * and may solve start-up problems for some people. - */ - sub22(1,0xc3); - sub22(0,0xa0); -#endif - __restore_flags(flags); /* local CPU only */ - - ide_hwifs[0].serialized = 1; - ide_hwifs[1].serialized = 1; - ide_hwifs[0].chipset = ide_dtc2278; - ide_hwifs[1].chipset = ide_dtc2278; - ide_hwifs[0].tuneproc = &tune_dtc2278; - ide_hwifs[0].drives[0].no_unmask = 1; - ide_hwifs[0].drives[1].no_unmask = 1; - ide_hwifs[1].drives[0].no_unmask = 1; - ide_hwifs[1].drives[1].no_unmask = 1; - ide_hwifs[0].mate = &ide_hwifs[1]; - ide_hwifs[1].mate = &ide_hwifs[0]; - ide_hwifs[1].channel = 1; -} diff --git a/drivers/block/elevator.c b/drivers/block/elevator.c new file mode 100644 index 000000000..11532f8fd --- /dev/null +++ b/drivers/block/elevator.c @@ -0,0 +1,150 @@ +/* + * linux/drivers/block/elevator.c + * + * Block device elevator/IO-scheduler. + * + * Copyright (C) 2000 Andrea Arcangeli <andrea@suse.de> SuSE + */ + +#include <linux/fs.h> +#include <linux/blkdev.h> +#include <linux/elevator.h> +#include <linux/blk.h> +#include <asm/uaccess.h> + +static void elevator_default(struct request * req, elevator_t * elevator, + struct list_head * real_head, + struct list_head * head, int orig_latency) +{ + struct list_head * entry = real_head, * point = NULL; + struct request * tmp; + int sequence = elevator->sequence; + int latency = orig_latency -= elevator->nr_segments, pass = 0; + int point_latency = 0xbeefbeef; + + while ((entry = entry->prev) != head) { + if (!point && latency >= 0) { + point = entry; + point_latency = latency; + } + tmp = blkdev_entry_to_request(entry); + if (elevator_sequence_before(tmp->elevator_sequence, sequence) || !tmp->q) + break; + if (latency >= 0) { + if (IN_ORDER(tmp, req) || + (pass && !IN_ORDER(tmp, blkdev_next_request(tmp)))) + goto link; + } + latency += tmp->nr_segments; + pass = 1; + } + + if (point) { + entry = point; + latency = point_latency; + } + + link: + list_add(&req->queue, entry); + req->elevator_sequence = elevator_sequence(elevator, latency); +} + +#ifdef ELEVATOR_DEBUG +void elevator_debug(request_queue_t * q, kdev_t dev) +{ + int read_pendings = 0, nr_segments = 0; + elevator_t * elevator = &q->elevator; + struct list_head * entry = &q->queue_head; + static int counter; + + if (counter++ % 100) + return; + + while ((entry = entry->prev) != &q->queue_head) + { + struct request * req; + + req = blkdev_entry_to_request(entry); + if (req->cmd != READ && req->cmd != WRITE && (req->q || req->nr_segments)) + printk(KERN_WARNING + "%s: elevator req->cmd %d req->nr_segments %u req->q %p\n", + kdevname(dev), req->cmd, req->nr_segments, req->q); + if (!req->q) { + if (req->nr_segments) + printk(KERN_WARNING + "%s: elevator req->q NULL req->nr_segments %u\n", + kdevname(dev), req->nr_segments); + continue; + } + if (req->cmd == READ) + read_pendings++; + nr_segments += req->nr_segments; + } + + if (read_pendings != elevator->read_pendings) + { + printk(KERN_WARNING + "%s: elevator read_pendings %d should be %d\n", + kdevname(dev), elevator->read_pendings, + read_pendings); + elevator->read_pendings = read_pendings; + } + if (nr_segments != elevator->nr_segments) + { + printk(KERN_WARNING + "%s: elevator nr_segments %d should be %d\n", + kdevname(dev), elevator->nr_segments, + nr_segments); + elevator->nr_segments = nr_segments; + } +} +#endif + +int blkelvget_ioctl(elevator_t * elevator, blkelv_ioctl_arg_t * arg) +{ + int ret; + blkelv_ioctl_arg_t output; + + output.queue_ID = elevator; + output.read_latency = elevator->read_latency; + output.write_latency = elevator->write_latency; + output.max_bomb_segments = elevator->max_bomb_segments; + + ret = -EFAULT; + if (copy_to_user(arg, &output, sizeof(blkelv_ioctl_arg_t))) + goto out; + ret = 0; + out: + return ret; +} + +int blkelvset_ioctl(elevator_t * elevator, const blkelv_ioctl_arg_t * arg) +{ + blkelv_ioctl_arg_t input; + int ret; + + ret = -EFAULT; + if (copy_from_user(&input, arg, sizeof(blkelv_ioctl_arg_t))) + goto out; + + ret = -EINVAL; + if (input.read_latency < 0) + goto out; + if (input.write_latency < 0) + goto out; + if (input.max_bomb_segments <= 0) + goto out; + + elevator->read_latency = input.read_latency; + elevator->write_latency = input.write_latency; + elevator->max_bomb_segments = input.max_bomb_segments; + + ret = 0; + out: + return ret; +} + +void elevator_init(elevator_t * elevator) +{ + *elevator = ELEVATOR_DEFAULTS; +} diff --git a/drivers/block/falconide.c b/drivers/block/falconide.c deleted file mode 100644 index 7bce07517..000000000 --- a/drivers/block/falconide.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * linux/drivers/block/falconide.c -- Atari Falcon IDE Driver - * - * Created 12 Jul 1997 by Geert Uytterhoeven - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive for - * more details. - */ - -#include <linux/types.h> -#include <linux/mm.h> -#include <linux/interrupt.h> -#include <linux/blkdev.h> -#include <linux/hdreg.h> -#include <linux/ide.h> - -#include <asm/atarihw.h> -#include <asm/atariints.h> -#include <asm/atari_stdma.h> - - - /* - * Base of the IDE interface - */ - -#define ATA_HD_BASE 0xfff00000 - - /* - * Offsets from the above base - */ - -#define ATA_HD_DATA 0x00 -#define ATA_HD_ERROR 0x05 /* see err-bits */ -#define ATA_HD_NSECTOR 0x09 /* nr of sectors to read/write */ -#define ATA_HD_SECTOR 0x0d /* starting sector */ -#define ATA_HD_LCYL 0x11 /* starting cylinder */ -#define ATA_HD_HCYL 0x15 /* high byte of starting cyl */ -#define ATA_HD_SELECT 0x19 /* 101dhhhh , d=drive, hhhh=head */ -#define ATA_HD_STATUS 0x1d /* see status-bits */ -#define ATA_HD_CONTROL 0x39 - -static int __init falconide_offsets[IDE_NR_PORTS] = { - ATA_HD_DATA, ATA_HD_ERROR, ATA_HD_NSECTOR, ATA_HD_SECTOR, ATA_HD_LCYL, - ATA_HD_HCYL, ATA_HD_SELECT, ATA_HD_STATUS, ATA_HD_CONTROL, -1 -}; - - - /* - * Probe for a Falcon IDE interface - */ - -void __init falconide_init(void) -{ - if (MACH_IS_ATARI && ATARIHW_PRESENT(IDE)) { - hw_regs_t hw; - int index; - - ide_setup_ports(&hw, (ide_ioreg_t)ATA_HD_BASE, falconide_offsets, - 0, 0, NULL, IRQ_MFP_IDE); - index = ide_register_hw(&hw, NULL); - - if (index != -1) - printk("ide%d: Falcon IDE interface\n", index); - } -} diff --git a/drivers/block/gayle.c b/drivers/block/gayle.c deleted file mode 100644 index 29cceb20e..000000000 --- a/drivers/block/gayle.c +++ /dev/null @@ -1,169 +0,0 @@ -/* - * linux/drivers/block/gayle.c -- Amiga Gayle IDE Driver - * - * Created 9 Jul 1997 by Geert Uytterhoeven - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive for - * more details. - */ - -#include <linux/config.h> -#include <linux/types.h> -#include <linux/mm.h> -#include <linux/interrupt.h> -#include <linux/blkdev.h> -#include <linux/hdreg.h> -#include <linux/ide.h> - -#include <asm/amigahw.h> -#include <asm/amigaints.h> - - - /* - * Bases of the IDE interfaces - */ - -#define GAYLE_BASE_4000 0xdd2020 /* A4000/A4000T */ -#define GAYLE_BASE_1200 0xda0000 /* A1200/A600 */ - - /* - * Offsets from one of the above bases - */ - -#define GAYLE_DATA 0x00 -#define GAYLE_ERROR 0x06 /* see err-bits */ -#define GAYLE_NSECTOR 0x0a /* nr of sectors to read/write */ -#define GAYLE_SECTOR 0x0e /* starting sector */ -#define GAYLE_LCYL 0x12 /* starting cylinder */ -#define GAYLE_HCYL 0x16 /* high byte of starting cyl */ -#define GAYLE_SELECT 0x1a /* 101dhhhh , d=drive, hhhh=head */ -#define GAYLE_STATUS 0x1e /* see status-bits */ -#define GAYLE_CONTROL 0x101a - -static int __init gayle_offsets[IDE_NR_PORTS] = { - GAYLE_DATA, GAYLE_ERROR, GAYLE_NSECTOR, GAYLE_SECTOR, GAYLE_LCYL, - GAYLE_HCYL, GAYLE_SELECT, GAYLE_STATUS, -1, -1 -}; - - - /* - * These are at different offsets from the base - */ - -#define GAYLE_IRQ_4000 0xdd3020 /* MSB = 1, Harddisk is source of */ -#define GAYLE_IRQ_1200 0xda9000 /* interrupt */ - - - /* - * Offset of the secondary port for IDE doublers - * Note that GAYLE_CONTROL is NOT available then! - */ - -#define GAYLE_NEXT_PORT 0x1000 - -#ifndef CONFIG_BLK_DEV_IDEDOUBLER -#define GAYLE_NUM_HWIFS 1 -#define GAYLE_NUM_PROBE_HWIFS GAYLE_NUM_HWIFS -#define GAYLE_HAS_CONTROL_REG 1 -#else /* CONFIG_BLK_DEV_IDEDOUBLER */ -#define GAYLE_NUM_HWIFS 2 -#define GAYLE_NUM_PROBE_HWIFS (ide_doubler ? GAYLE_NUM_HWIFS : \ - GAYLE_NUM_HWIFS-1) -#define GAYLE_HAS_CONTROL_REG (!ide_doubler) -int ide_doubler = 0; /* support IDE doublers? */ -#endif /* CONFIG_BLK_DEV_IDEDOUBLER */ - - - /* - * Check and acknowledge the interrupt status - */ - -static int gayle_ack_intr_a4000(ide_hwif_t *hwif) -{ - unsigned char ch; - - ch = inb(hwif->io_ports[IDE_IRQ_OFFSET]); - if (!(ch & 0x80)) - return 0; - return 1; -} - -static int gayle_ack_intr_a1200(ide_hwif_t *hwif) -{ - unsigned char ch; - - ch = inb(hwif->io_ports[IDE_IRQ_OFFSET]); - if (!(ch & 0x80)) - return 0; - (void)inb(hwif->io_ports[IDE_STATUS_OFFSET]); - outb(0x7c | (ch & 0x03), hwif->io_ports[IDE_IRQ_OFFSET]); - return 1; -} - - /* - * Probe for a Gayle IDE interface (and optionally for an IDE doubler) - */ - -void __init gayle_init(void) -{ - int a4000, i; - - if (!MACH_IS_AMIGA) - return; - - if (!(a4000 = AMIGAHW_PRESENT(A4000_IDE)) && !AMIGAHW_PRESENT(A1200_IDE)) - return; - - for (i = 0; i < GAYLE_NUM_PROBE_HWIFS; i++) { - ide_ioreg_t base, ctrlport, irqport; - ide_ack_intr_t *ack_intr; - hw_regs_t hw; - int index; - - if (a4000) { - base = (ide_ioreg_t)ZTWO_VADDR(GAYLE_BASE_4000); - irqport = (ide_ioreg_t)ZTWO_VADDR(GAYLE_IRQ_4000); - ack_intr = gayle_ack_intr_a4000; - } else { - base = (ide_ioreg_t)ZTWO_VADDR(GAYLE_BASE_1200); - irqport = (ide_ioreg_t)ZTWO_VADDR(GAYLE_IRQ_1200); - ack_intr = gayle_ack_intr_a1200; - } - - if (GAYLE_HAS_CONTROL_REG) - ctrlport = base + GAYLE_CONTROL; - else - ctrlport = 0; - - base += i*GAYLE_NEXT_PORT; - - ide_setup_ports(&hw, base, gayle_offsets, - ctrlport, irqport, ack_intr, IRQ_AMIGA_PORTS); - - index = ide_register_hw(&hw, NULL); - if (index != -1) { - switch (i) { - case 0: - printk("ide%d: Gayle IDE interface (A%d style)\n", index, - a4000 ? 4000 : 1200); - break; -#ifdef CONFIG_BLK_DEV_IDEDOUBLER - case 1: - printk("ide%d: IDE doubler\n", index); - break; -#endif /* CONFIG_BLK_DEV_IDEDOUBLER */ - } - } -#if 1 /* TESTING */ - if (i == 1) { - volatile u_short *addr = (u_short *)base; - u_short data; - printk("+++ Probing for IDE doubler... "); - *addr = 0xffff; - data = *addr; - printk("probe returned 0x%02x (PLEASE REPORT THIS!!)\n", data); - } -#endif /* TESTING */ - } -} diff --git a/drivers/block/hd.c b/drivers/block/hd.c deleted file mode 100644 index 5520c17b0..000000000 --- a/drivers/block/hd.c +++ /dev/null @@ -1,883 +0,0 @@ -/* - * linux/drivers/block/hd.c - * - * Copyright (C) 1991, 1992 Linus Torvalds - */ - -/* - * This is the low-level hd interrupt support. It traverses the - * request-list, using interrupts to jump between functions. As - * all the functions are called within interrupts, we may not - * sleep. Special care is recommended. - * - * modified by Drew Eckhardt to check nr of hd's from the CMOS. - * - * Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug - * in the early extended-partition checks and added DM partitions - * - * IRQ-unmask, drive-id, multiple-mode, support for ">16 heads", - * and general streamlining by Mark Lord. - * - * Removed 99% of above. Use Mark's ide driver for those options. - * This is now a lightweight ST-506 driver. (Paul Gortmaker) - * - * Modified 1995 Russell King for ARM processor. - */ - -/* Uncomment the following if you want verbose error reports. */ -/* #define VERBOSE_ERRORS */ - -#include <linux/errno.h> -#include <linux/signal.h> -#include <linux/sched.h> -#include <linux/timer.h> -#include <linux/fs.h> -#include <linux/devfs_fs_kernel.h> -#include <linux/kernel.h> -#include <linux/hdreg.h> -#include <linux/genhd.h> -#include <linux/malloc.h> -#include <linux/string.h> -#include <linux/ioport.h> -#include <linux/mc146818rtc.h> /* CMOS defines */ -#include <linux/init.h> -#include <linux/blkpg.h> - -#define REALLY_SLOW_IO -#include <asm/system.h> -#include <asm/io.h> -#include <asm/uaccess.h> - -#define MAJOR_NR HD_MAJOR -#include <linux/blk.h> - -#ifdef __arm__ -#undef HD_IRQ -#endif -#include <asm/irq.h> -#ifdef __arm__ -#define HD_IRQ IRQ_HARDDISK -#endif - -static int revalidate_hddisk(kdev_t, int); - -#define HD_DELAY 0 - -#define MAX_ERRORS 16 /* Max read/write errors/sector */ -#define RESET_FREQ 8 /* Reset controller every 8th retry */ -#define RECAL_FREQ 4 /* Recalibrate every 4th retry */ -#define MAX_HD 2 - -#define STAT_OK (READY_STAT|SEEK_STAT) -#define OK_STATUS(s) (((s)&(STAT_OK|(BUSY_STAT|WRERR_STAT|ERR_STAT)))==STAT_OK) - -static void recal_intr(void); -static void bad_rw_intr(void); - -static char recalibrate[MAX_HD]; -static char special_op[MAX_HD]; -static int access_count[MAX_HD]; -static char busy[MAX_HD]; -static DECLARE_WAIT_QUEUE_HEAD(busy_wait); - -static int reset; -static int hd_error; - -#define SUBSECTOR(block) (CURRENT->current_nr_sectors > 0) - -/* - * This struct defines the HD's and their types. - */ -struct hd_i_struct { - unsigned int head,sect,cyl,wpcom,lzone,ctl; -}; - -#ifdef HD_TYPE -static struct hd_i_struct hd_info[] = { HD_TYPE }; -static int NR_HD = ((sizeof (hd_info))/(sizeof (struct hd_i_struct))); -#else -static struct hd_i_struct hd_info[MAX_HD]; -static int NR_HD; -#endif - -static struct hd_struct hd[MAX_HD<<6]; -static int hd_sizes[MAX_HD<<6]; -static int hd_blocksizes[MAX_HD<<6]; -static int hd_hardsectsizes[MAX_HD<<6]; - -#if (HD_DELAY > 0) -unsigned long last_req; - -unsigned long read_timer(void) -{ - unsigned long t, flags; - int i; - - save_flags(flags); - cli(); - t = jiffies * 11932; - outb_p(0, 0x43); - i = inb_p(0x40); - i |= inb(0x40) << 8; - restore_flags(flags); - return(t - i); -} -#endif - -void __init hd_setup(char *str, int *ints) -{ - int hdind = 0; - - if (ints[0] != 3) - return; - if (hd_info[0].head != 0) - hdind=1; - hd_info[hdind].head = ints[2]; - hd_info[hdind].sect = ints[3]; - hd_info[hdind].cyl = ints[1]; - hd_info[hdind].wpcom = 0; - hd_info[hdind].lzone = ints[1]; - hd_info[hdind].ctl = (ints[2] > 8 ? 8 : 0); - NR_HD = hdind+1; -} - -static void dump_status (const char *msg, unsigned int stat) -{ - unsigned long flags; - char devc; - - devc = !QUEUE_EMPTY ? 'a' + DEVICE_NR(CURRENT->rq_dev) : '?'; - save_flags (flags); - sti(); -#ifdef VERBOSE_ERRORS - printk("hd%c: %s: status=0x%02x { ", devc, msg, stat & 0xff); - if (stat & BUSY_STAT) printk("Busy "); - if (stat & READY_STAT) printk("DriveReady "); - if (stat & WRERR_STAT) printk("WriteFault "); - if (stat & SEEK_STAT) printk("SeekComplete "); - if (stat & DRQ_STAT) printk("DataRequest "); - if (stat & ECC_STAT) printk("CorrectedError "); - if (stat & INDEX_STAT) printk("Index "); - if (stat & ERR_STAT) printk("Error "); - printk("}\n"); - if ((stat & ERR_STAT) == 0) { - hd_error = 0; - } else { - hd_error = inb(HD_ERROR); - printk("hd%c: %s: error=0x%02x { ", devc, msg, hd_error & 0xff); - if (hd_error & BBD_ERR) printk("BadSector "); - if (hd_error & ECC_ERR) printk("UncorrectableError "); - if (hd_error & ID_ERR) printk("SectorIdNotFound "); - if (hd_error & ABRT_ERR) printk("DriveStatusError "); - if (hd_error & TRK0_ERR) printk("TrackZeroNotFound "); - if (hd_error & MARK_ERR) printk("AddrMarkNotFound "); - printk("}"); - if (hd_error & (BBD_ERR|ECC_ERR|ID_ERR|MARK_ERR)) { - printk(", CHS=%d/%d/%d", (inb(HD_HCYL)<<8) + inb(HD_LCYL), - inb(HD_CURRENT) & 0xf, inb(HD_SECTOR)); - if (!QUEUE_EMPTY) - printk(", sector=%ld", CURRENT->sector); - } - printk("\n"); - } -#else - printk("hd%c: %s: status=0x%02x.\n", devc, msg, stat & 0xff); - if ((stat & ERR_STAT) == 0) { - hd_error = 0; - } else { - hd_error = inb(HD_ERROR); - printk("hd%c: %s: error=0x%02x.\n", devc, msg, hd_error & 0xff); - } -#endif /* verbose errors */ - restore_flags (flags); -} - -void check_status(void) -{ - int i = inb_p(HD_STATUS); - - if (!OK_STATUS(i)) { - dump_status("check_status", i); - bad_rw_intr(); - } -} - -static int controller_busy(void) -{ - int retries = 100000; - unsigned char status; - - do { - status = inb_p(HD_STATUS); - } while ((status & BUSY_STAT) && --retries); - return status; -} - -static int status_ok(void) -{ - unsigned char status = inb_p(HD_STATUS); - - if (status & BUSY_STAT) - return 1; /* Ancient, but does it make sense??? */ - if (status & WRERR_STAT) - return 0; - if (!(status & READY_STAT)) - return 0; - if (!(status & SEEK_STAT)) - return 0; - return 1; -} - -static int controller_ready(unsigned int drive, unsigned int head) -{ - int retry = 100; - - do { - if (controller_busy() & BUSY_STAT) - return 0; - outb_p(0xA0 | (drive<<4) | head, HD_CURRENT); - if (status_ok()) - return 1; - } while (--retry); - return 0; -} - -static void hd_out(unsigned int drive,unsigned int nsect,unsigned int sect, - unsigned int head,unsigned int cyl,unsigned int cmd, - void (*intr_addr)(void)) -{ - unsigned short port; - -#if (HD_DELAY > 0) - while (read_timer() - last_req < HD_DELAY) - /* nothing */; -#endif - if (reset) - return; - if (!controller_ready(drive, head)) { - reset = 1; - return; - } - SET_INTR(intr_addr); - outb_p(hd_info[drive].ctl,HD_CMD); - port=HD_DATA; - outb_p(hd_info[drive].wpcom>>2,++port); - outb_p(nsect,++port); - outb_p(sect,++port); - outb_p(cyl,++port); - outb_p(cyl>>8,++port); - outb_p(0xA0|(drive<<4)|head,++port); - outb_p(cmd,++port); -} - -static void hd_request (void); - -static int drive_busy(void) -{ - unsigned int i; - unsigned char c; - - for (i = 0; i < 500000 ; i++) { - c = inb_p(HD_STATUS); - if ((c & (BUSY_STAT | READY_STAT | SEEK_STAT)) == STAT_OK) - return 0; - } - dump_status("reset timed out", c); - return 1; -} - -static void reset_controller(void) -{ - int i; - - outb_p(4,HD_CMD); - for(i = 0; i < 1000; i++) barrier(); - outb_p(hd_info[0].ctl & 0x0f,HD_CMD); - for(i = 0; i < 1000; i++) barrier(); - if (drive_busy()) - printk("hd: controller still busy\n"); - else if ((hd_error = inb(HD_ERROR)) != 1) - printk("hd: controller reset failed: %02x\n",hd_error); -} - -static void reset_hd(void) -{ - static int i; - -repeat: - if (reset) { - reset = 0; - i = -1; - reset_controller(); - } else { - check_status(); - if (reset) - goto repeat; - } - if (++i < NR_HD) { - special_op[i] = recalibrate[i] = 1; - hd_out(i,hd_info[i].sect,hd_info[i].sect,hd_info[i].head-1, - hd_info[i].cyl,WIN_SPECIFY,&reset_hd); - if (reset) - goto repeat; - } else - hd_request(); -} - -/* - * Ok, don't know what to do with the unexpected interrupts: on some machines - * doing a reset and a retry seems to result in an eternal loop. Right now I - * ignore it, and just set the timeout. - * - * On laptops (and "green" PCs), an unexpected interrupt occurs whenever the - * drive enters "idle", "standby", or "sleep" mode, so if the status looks - * "good", we just ignore the interrupt completely. - */ -void unexpected_hd_interrupt(void) -{ - unsigned int stat = inb_p(HD_STATUS); - - if (stat & (BUSY_STAT|DRQ_STAT|ECC_STAT|ERR_STAT)) { - dump_status ("unexpected interrupt", stat); - SET_TIMER; - } -} - -/* - * bad_rw_intr() now tries to be a bit smarter and does things - * according to the error returned by the controller. - * -Mika Liljeberg (liljeber@cs.Helsinki.FI) - */ -static void bad_rw_intr(void) -{ - int dev; - - if (QUEUE_EMPTY) - return; - dev = DEVICE_NR(CURRENT->rq_dev); - if (++CURRENT->errors >= MAX_ERRORS || (hd_error & BBD_ERR)) { - end_request(0); - special_op[dev] = recalibrate[dev] = 1; - } else if (CURRENT->errors % RESET_FREQ == 0) - reset = 1; - else if ((hd_error & TRK0_ERR) || CURRENT->errors % RECAL_FREQ == 0) - special_op[dev] = recalibrate[dev] = 1; - /* Otherwise just retry */ -} - -static inline int wait_DRQ(void) -{ - int retries = 100000, stat; - - while (--retries > 0) - if ((stat = inb_p(HD_STATUS)) & DRQ_STAT) - return 0; - dump_status("wait_DRQ", stat); - return -1; -} - -static void read_intr(void) -{ - int i, retries = 100000; - - do { - i = (unsigned) inb_p(HD_STATUS); - if (i & BUSY_STAT) - continue; - if (!OK_STATUS(i)) - break; - if (i & DRQ_STAT) - goto ok_to_read; - } while (--retries > 0); - dump_status("read_intr", i); - bad_rw_intr(); - hd_request(); - return; -ok_to_read: - insw(HD_DATA,CURRENT->buffer,256); - CURRENT->sector++; - CURRENT->buffer += 512; - CURRENT->errors = 0; - i = --CURRENT->nr_sectors; - --CURRENT->current_nr_sectors; -#ifdef DEBUG - printk("hd%c: read: sector %ld, remaining = %ld, buffer=0x%08lx\n", - dev+'a', CURRENT->sector, CURRENT->nr_sectors, - (unsigned long) CURRENT->buffer+512)); -#endif - if (CURRENT->current_nr_sectors <= 0) - end_request(1); - if (i > 0) { - SET_INTR(&read_intr); - return; - } - (void) inb_p(HD_STATUS); -#if (HD_DELAY > 0) - last_req = read_timer(); -#endif - if (!QUEUE_EMPTY) - hd_request(); - return; -} - -static void write_intr(void) -{ - int i; - int retries = 100000; - - do { - i = (unsigned) inb_p(HD_STATUS); - if (i & BUSY_STAT) - continue; - if (!OK_STATUS(i)) - break; - if ((CURRENT->nr_sectors <= 1) || (i & DRQ_STAT)) - goto ok_to_write; - } while (--retries > 0); - dump_status("write_intr", i); - bad_rw_intr(); - hd_request(); - return; -ok_to_write: - CURRENT->sector++; - i = --CURRENT->nr_sectors; - --CURRENT->current_nr_sectors; - CURRENT->buffer += 512; - if (!i || (CURRENT->bh && !SUBSECTOR(i))) - end_request(1); - if (i > 0) { - SET_INTR(&write_intr); - outsw(HD_DATA,CURRENT->buffer,256); - sti(); - } else { -#if (HD_DELAY > 0) - last_req = read_timer(); -#endif - hd_request(); - } - return; -} - -static void recal_intr(void) -{ - check_status(); -#if (HD_DELAY > 0) - last_req = read_timer(); -#endif - hd_request(); -} - -/* - * This is another of the error-routines I don't know what to do with. The - * best idea seems to just set reset, and start all over again. - */ -static void hd_times_out(void) -{ - unsigned int dev; - - DEVICE_INTR = NULL; - if (QUEUE_EMPTY) - return; - disable_irq(HD_IRQ); - sti(); - reset = 1; - dev = DEVICE_NR(CURRENT->rq_dev); - printk("hd%c: timeout\n", dev+'a'); - if (++CURRENT->errors >= MAX_ERRORS) { -#ifdef DEBUG - printk("hd%c: too many errors\n", dev+'a'); -#endif - end_request(0); - } - cli(); - hd_request(); - enable_irq(HD_IRQ); -} - -int do_special_op (unsigned int dev) -{ - if (recalibrate[dev]) { - recalibrate[dev] = 0; - hd_out(dev,hd_info[dev].sect,0,0,0,WIN_RESTORE,&recal_intr); - return reset; - } - if (hd_info[dev].head > 16) { - printk ("hd%c: cannot handle device with more than 16 heads - giving up\n", dev+'a'); - end_request(0); - } - special_op[dev] = 0; - return 1; -} - -/* - * The driver enables interrupts as much as possible. In order to do this, - * (a) the device-interrupt is disabled before entering hd_request(), - * and (b) the timeout-interrupt is disabled before the sti(). - * - * Interrupts are still masked (by default) whenever we are exchanging - * data/cmds with a drive, because some drives seem to have very poor - * tolerance for latency during I/O. The IDE driver has support to unmask - * interrupts for non-broken hardware, so use that driver if required. - */ -static void hd_request(void) -{ - unsigned int dev, block, nsect, sec, track, head, cyl; - - if (!QUEUE_EMPTY && CURRENT->rq_status == RQ_INACTIVE) return; - if (DEVICE_INTR) - return; -repeat: - timer_active &= ~(1<<HD_TIMER); - sti(); - INIT_REQUEST; - if (reset) { - cli(); - reset_hd(); - return; - } - dev = MINOR(CURRENT->rq_dev); - block = CURRENT->sector; - nsect = CURRENT->nr_sectors; - if (dev >= (NR_HD<<6) || block >= hd[dev].nr_sects || ((block+nsect) > hd[dev].nr_sects)) { -#ifdef DEBUG - if (dev >= (NR_HD<<6)) - printk("hd: bad minor number: device=%s\n", - kdevname(CURRENT->rq_dev)); - else - printk("hd%c: bad access: block=%d, count=%d\n", - (MINOR(CURRENT->rq_dev)>>6)+'a', block, nsect); -#endif - end_request(0); - goto repeat; - } - block += hd[dev].start_sect; - dev >>= 6; - if (special_op[dev]) { - if (do_special_op(dev)) - goto repeat; - return; - } - sec = block % hd_info[dev].sect + 1; - track = block / hd_info[dev].sect; - head = track % hd_info[dev].head; - cyl = track / hd_info[dev].head; -#ifdef DEBUG - printk("hd%c: %sing: CHS=%d/%d/%d, sectors=%d, buffer=0x%08lx\n", - dev+'a', (CURRENT->cmd == READ)?"read":"writ", - cyl, head, sec, nsect, (unsigned long) CURRENT->buffer); -#endif - if (CURRENT->cmd == READ) { - hd_out(dev,nsect,sec,head,cyl,WIN_READ,&read_intr); - if (reset) - goto repeat; - return; - } - if (CURRENT->cmd == WRITE) { - hd_out(dev,nsect,sec,head,cyl,WIN_WRITE,&write_intr); - if (reset) - goto repeat; - if (wait_DRQ()) { - bad_rw_intr(); - goto repeat; - } - outsw(HD_DATA,CURRENT->buffer,256); - return; - } - panic("unknown hd-command"); -} - -static void do_hd_request (request_queue_t * q) -{ - disable_irq(HD_IRQ); - hd_request(); - enable_irq(HD_IRQ); -} - -static int hd_ioctl(struct inode * inode, struct file * file, - unsigned int cmd, unsigned long arg) -{ - struct hd_geometry *loc = (struct hd_geometry *) arg; - int dev; - - if ((!inode) || !(inode->i_rdev)) - return -EINVAL; - dev = DEVICE_NR(inode->i_rdev); - if (dev >= NR_HD) - return -EINVAL; - switch (cmd) { - case HDIO_GETGEO: - { - struct hd_geometry g; - if (!loc) return -EINVAL; - g.heads = hd_info[dev].head; - g.sectors = hd_info[dev].sect; - g.cylinders = hd_info[dev].cyl; - g.start = hd[MINOR(inode->i_rdev)].start_sect; - return copy_to_user(loc, &g, sizeof g) ? -EFAULT : 0; - } - - case BLKGETSIZE: /* Return device size */ - if (!arg) return -EINVAL; - return put_user(hd[MINOR(inode->i_rdev)].nr_sects, - (long *) arg); - - case BLKRRPART: /* Re-read partition tables */ - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - return revalidate_hddisk(inode->i_rdev, 1); - - case BLKROSET: - case BLKROGET: - case BLKRASET: - case BLKRAGET: - case BLKFLSBUF: - case BLKPG: - return blk_ioctl(inode->i_rdev, cmd, arg); - - default: - return -EINVAL; - } -} - -static int hd_open(struct inode * inode, struct file * filp) -{ - int target; - target = DEVICE_NR(inode->i_rdev); - - if (target >= NR_HD) - return -ENODEV; - while (busy[target]) - sleep_on(&busy_wait); - access_count[target]++; - return 0; -} - -/* - * Releasing a block device means we sync() it, so that it can safely - * be forgotten about... - */ -static int hd_release(struct inode * inode, struct file * file) -{ - int target = DEVICE_NR(inode->i_rdev); - access_count[target]--; - return 0; -} - -extern struct block_device_operations hd_fops; - -static struct gendisk hd_gendisk = { - MAJOR_NR, /* Major number */ - "hd", /* Major name */ - 6, /* Bits to shift to get real from partition */ - 1 << 6, /* Number of partitions per real */ - hd, /* hd struct */ - hd_sizes, /* block sizes */ - 0, /* number */ - NULL, /* internal use, not presently used */ - NULL, /* next */ - &hd_fops, /* file operations */ -}; - -static void hd_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - void (*handler)(void) = DEVICE_INTR; - - DEVICE_INTR = NULL; - timer_active &= ~(1<<HD_TIMER); - if (!handler) - handler = unexpected_hd_interrupt; - handler(); - sti(); -} - -static struct block_device_operations hd_fops = { - open: hd_open, - release: hd_release, - ioctl: hd_ioctl, -}; - -/* - * This is the hard disk IRQ description. The SA_INTERRUPT in sa_flags - * means we run the IRQ-handler with interrupts disabled: this is bad for - * interrupt latency, but anything else has led to problems on some - * machines. - * - * We enable interrupts in some of the routines after making sure it's - * safe. - */ -static void hd_geninit(void) -{ - int drive; - - for(drive=0; drive < (MAX_HD << 6); drive++) { - hd_blocksizes[drive] = 1024; - hd_hardsectsizes[drive] = 512; - } - blksize_size[MAJOR_NR] = hd_blocksizes; - hardsect_size[MAJOR_NR] = hd_hardsectsizes; - -#ifdef __i386__ - if (!NR_HD) { - extern struct drive_info drive_info; - unsigned char *BIOS = (unsigned char *) &drive_info; - int cmos_disks; - - for (drive=0 ; drive<2 ; drive++) { - hd_info[drive].cyl = *(unsigned short *) BIOS; - hd_info[drive].head = *(2+BIOS); - hd_info[drive].wpcom = *(unsigned short *) (5+BIOS); - hd_info[drive].ctl = *(8+BIOS); - hd_info[drive].lzone = *(unsigned short *) (12+BIOS); - hd_info[drive].sect = *(14+BIOS); -#ifdef does_not_work_for_everybody_with_scsi_but_helps_ibm_vp - if (hd_info[drive].cyl && NR_HD == drive) - NR_HD++; -#endif - BIOS += 16; - } - - /* - We query CMOS about hard disks : it could be that - we have a SCSI/ESDI/etc controller that is BIOS - compatible with ST-506, and thus showing up in our - BIOS table, but not register compatible, and therefore - not present in CMOS. - - Furthermore, we will assume that our ST-506 drives - <if any> are the primary drives in the system, and - the ones reflected as drive 1 or 2. - - The first drive is stored in the high nibble of CMOS - byte 0x12, the second in the low nibble. This will be - either a 4 bit drive type or 0xf indicating use byte 0x19 - for an 8 bit type, drive 1, 0x1a for drive 2 in CMOS. - - Needless to say, a non-zero value means we have - an AT controller hard disk for that drive. - - - */ - - if ((cmos_disks = CMOS_READ(0x12)) & 0xf0) { - if (cmos_disks & 0x0f) - NR_HD = 2; - else - NR_HD = 1; - } - } -#endif /* __i386__ */ -#ifdef __arm__ - if (!NR_HD) { - /* We don't know anything about the drive. This means - * that you *MUST* specify the drive parameters to the - * kernel yourself. - */ - printk("hd: no drives specified - use hd=cyl,head,sectors" - " on kernel command line\n"); - } -#endif - - for (drive=0 ; drive < NR_HD ; drive++) { - printk ("hd%c: %ldMB, CHS=%d/%d/%d\n", drive+'a', - hd[drive<<6].nr_sects / 2048, hd_info[drive].cyl, - hd_info[drive].head, hd_info[drive].sect); - } - if (!NR_HD) - return; - - if (request_irq(HD_IRQ, hd_interrupt, SA_INTERRUPT, "hd", NULL)) { - printk("hd: unable to get IRQ%d for the hard disk driver\n", - HD_IRQ); - NR_HD = 0; - return; - } - request_region(HD_DATA, 8, "hd"); - request_region(HD_CMD, 1, "hd(cmd)"); - - hd_gendisk.nr_real = NR_HD; - - for(drive=0; drive < NR_HD; drive++) - register_disk(&hd_gendisk, MKDEV(MAJOR_NR,drive<<6), 1<<6, - &hd_fops, hd_info[drive].head * hd_info[drive].sect * - hd_info[drive].cyl); -} - -int __init hd_init(void) -{ - if (devfs_register_blkdev(MAJOR_NR,"hd",&hd_fops)) { - printk("hd: unable to get major %d for hard disk\n",MAJOR_NR); - return -1; - } - blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST); - read_ahead[MAJOR_NR] = 8; /* 8 sector (4kB) read-ahead */ - hd_gendisk.next = gendisk_head; - gendisk_head = &hd_gendisk; - timer_table[HD_TIMER].fn = hd_times_out; - hd_geninit(); - return 0; -} - -#define DEVICE_BUSY busy[target] -#define USAGE access_count[target] -#define CAPACITY (hd_info[target].head*hd_info[target].sect*hd_info[target].cyl) -/* We assume that the BIOS parameters do not change, so the disk capacity - will not change */ -#undef MAYBE_REINIT -#define GENDISK_STRUCT hd_gendisk - -/* - * This routine is called to flush all partitions and partition tables - * for a changed disk, and then re-read the new partition table. - * If we are revalidating a disk because of a media change, then we - * enter with usage == 0. If we are using an ioctl, we automatically have - * usage == 1 (we need an open channel to use an ioctl :-), so this - * is our limit. - */ -static int revalidate_hddisk(kdev_t dev, int maxusage) -{ - int target; - struct gendisk * gdev; - int max_p; - int start; - int i; - long flags; - - target = DEVICE_NR(dev); - gdev = &GENDISK_STRUCT; - - save_flags(flags); - cli(); - if (DEVICE_BUSY || USAGE > maxusage) { - restore_flags(flags); - return -EBUSY; - } - DEVICE_BUSY = 1; - restore_flags(flags); - - max_p = gdev->max_p; - start = target << gdev->minor_shift; - - for (i=max_p - 1; i >=0 ; i--) { - int minor = start + i; - kdev_t devi = MKDEV(MAJOR_NR, minor); - struct super_block *sb = get_super(devi); - - sync_dev(devi); - if (sb) - invalidate_inodes(sb); - invalidate_buffers(devi); - gdev->part[minor].start_sect = 0; - gdev->part[minor].nr_sects = 0; - } - -#ifdef MAYBE_REINIT - MAYBE_REINIT; -#endif - - grok_partitions(gdev, target, 1<<6, CAPACITY); - - DEVICE_BUSY = 0; - wake_up(&busy_wait); - return 0; -} - diff --git a/drivers/block/hpt34x.c b/drivers/block/hpt34x.c deleted file mode 100644 index 425ce35a4..000000000 --- a/drivers/block/hpt34x.c +++ /dev/null @@ -1,419 +0,0 @@ -/* - * linux/drivers/block/hpt34x.c Version 0.29 Feb. 10, 2000 - * - * Copyright (C) 1998-2000 Andre Hedrick (andre@suse.com) - * May be copied or modified under the terms of the GNU General Public License - * - * - * 00:12.0 Unknown mass storage controller: - * Triones Technologies, Inc. - * Unknown device 0003 (rev 01) - * - * hde: UDMA 2 (0x0000 0x0002) (0x0000 0x0010) - * hdf: UDMA 2 (0x0002 0x0012) (0x0010 0x0030) - * hde: DMA 2 (0x0000 0x0002) (0x0000 0x0010) - * hdf: DMA 2 (0x0002 0x0012) (0x0010 0x0030) - * hdg: DMA 1 (0x0012 0x0052) (0x0030 0x0070) - * hdh: DMA 1 (0x0052 0x0252) (0x0070 0x00f0) - * - * ide-pci.c reference - * - * Since there are two cards that report almost identically, - * the only discernable difference is the values reported in pcicmd. - * Booting-BIOS card or HPT363 :: pcicmd == 0x07 - * Non-bootable card or HPT343 :: pcicmd == 0x05 - */ - -#include <linux/config.h> -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/delay.h> -#include <linux/timer.h> -#include <linux/mm.h> -#include <linux/ioport.h> -#include <linux/blkdev.h> -#include <linux/hdreg.h> -#include <linux/interrupt.h> -#include <linux/pci.h> -#include <linux/init.h> -#include <linux/ide.h> - -#include <asm/io.h> -#include <asm/irq.h> -#include "ide_modes.h" - -#ifndef SPLIT_BYTE -#define SPLIT_BYTE(B,H,L) ((H)=(B>>4), (L)=(B-((B>>4)<<4))) -#endif - -#define HPT343_DEBUG_DRIVE_INFO 0 - -#undef DISPLAY_HPT34X_TIMINGS - -#if defined(DISPLAY_HPT34X_TIMINGS) && defined(CONFIG_PROC_FS) -#include <linux/stat.h> -#include <linux/proc_fs.h> - -static int hpt34x_get_info(char *, char **, off_t, int); -extern int (*hpt34x_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -extern char *ide_media_verbose(ide_drive_t *); -static struct pci_dev *bmide_dev; - -static int hpt34x_get_info (char *buffer, char **addr, off_t offset, int count) -{ - char *p = buffer; - u32 bibma = bmide_dev->resource[4].start; - u8 c0 = 0, c1 = 0; - - /* - * at that point bibma+0x2 et bibma+0xa are byte registers - * to investigate: - */ - c0 = inb_p((unsigned short)bibma + 0x02); - c1 = inb_p((unsigned short)bibma + 0x0a); - - p += sprintf(p, "\n HPT34X Chipset.\n"); - p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n"); - p += sprintf(p, " %sabled %sabled\n", - (c0&0x80) ? "dis" : " en", - (c1&0x80) ? "dis" : " en"); - p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n"); - p += sprintf(p, "DMA enabled: %s %s %s %s\n", - (c0&0x20) ? "yes" : "no ", (c0&0x40) ? "yes" : "no ", - (c1&0x20) ? "yes" : "no ", (c1&0x40) ? "yes" : "no " ); - - p += sprintf(p, "UDMA\n"); - p += sprintf(p, "DMA\n"); - p += sprintf(p, "PIO\n"); - - return p-buffer; /* => must be less than 4k! */ -} -#endif /* defined(DISPLAY_HPT34X_TIMINGS) && defined(CONFIG_PROC_FS) */ - -byte hpt34x_proc = 0; - -extern char *ide_xfer_verbose (byte xfer_rate); - -static void hpt34x_clear_chipset (ide_drive_t *drive) -{ - int drive_number = ((HWIF(drive)->channel ? 2 : 0) + (drive->select.b.unit & 0x01)); - unsigned int reg1 = 0, tmp1 = 0; - unsigned int reg2 = 0, tmp2 = 0; - - pci_read_config_dword(HWIF(drive)->pci_dev, 0x44, ®1); - pci_read_config_dword(HWIF(drive)->pci_dev, 0x48, ®2); - tmp1 = ((0x00 << (3*drive_number)) | (reg1 & ~(7 << (3*drive_number)))); - tmp2 = (reg2 & ~(0x11 << drive_number)); - pci_write_config_dword(HWIF(drive)->pci_dev, 0x44, tmp1); - pci_write_config_dword(HWIF(drive)->pci_dev, 0x48, tmp2); -} - -static int hpt34x_tune_chipset (ide_drive_t *drive, byte speed) -{ - int err; - byte hi_speed, lo_speed; - int drive_number = ((HWIF(drive)->channel ? 2 : 0) + (drive->select.b.unit & 0x01)); - unsigned int reg1 = 0, tmp1 = 0; - unsigned int reg2 = 0, tmp2 = 0; - - SPLIT_BYTE(speed, hi_speed, lo_speed); - - if (hi_speed & 7) { - hi_speed = (hi_speed & 4) ? 0x01 : 0x10; - } else { - lo_speed <<= 5; - lo_speed >>= 5; - } - - pci_read_config_dword(HWIF(drive)->pci_dev, 0x44, ®1); - pci_read_config_dword(HWIF(drive)->pci_dev, 0x48, ®2); - tmp1 = ((lo_speed << (3*drive_number)) | (reg1 & ~(7 << (3*drive_number)))); - tmp2 = ((hi_speed << drive_number) | reg2); - err = ide_config_drive_speed(drive, speed); - pci_write_config_dword(HWIF(drive)->pci_dev, 0x44, tmp1); - pci_write_config_dword(HWIF(drive)->pci_dev, 0x48, tmp2); - -#if HPT343_DEBUG_DRIVE_INFO - printk("%s: %s drive%d (0x%04x 0x%04x) (0x%04x 0x%04x)" \ - " (0x%02x 0x%02x) 0x%04x\n", - drive->name, ide_xfer_verbose(speed), - drive_number, reg1, tmp1, reg2, tmp2, - hi_speed, lo_speed, err); -#endif /* HPT343_DEBUG_DRIVE_INFO */ - - return(err); -} - -/* - * This allows the configuration of ide_pci chipset registers - * for cards that learn about the drive's UDMA, DMA, PIO capabilities - * after the drive is reported by the OS. Initally for designed for - * HPT343 UDMA chipset by HighPoint|Triones Technologies, Inc. - */ -static int config_chipset_for_dma (ide_drive_t *drive, byte ultra) -{ - struct hd_driveid *id = drive->id; - byte speed = 0x00; - - if (drive->media != ide_disk) - return ((int) ide_dma_off_quietly); - - hpt34x_clear_chipset(drive); - - if ((id->dma_ultra & 0x0010) && ultra) { - speed = XFER_UDMA_2; - } else if ((id->dma_ultra & 0x0008) && ultra) { - speed = XFER_UDMA_2; - } else if ((id->dma_ultra & 0x0004) && ultra) { - speed = XFER_UDMA_2; - } else if ((id->dma_ultra & 0x0002) && ultra) { - speed = XFER_UDMA_1; - } else if ((id->dma_ultra & 0x0001) && ultra) { - speed = XFER_UDMA_0; - } else if (id->dma_mword & 0x0004) { - speed = XFER_MW_DMA_2; - } else if (id->dma_mword & 0x0002) { - speed = XFER_MW_DMA_1; - } else if (id->dma_mword & 0x0001) { - speed = XFER_MW_DMA_0; - } else if (id->dma_1word & 0x0004) { - speed = XFER_SW_DMA_2; - } else if (id->dma_1word & 0x0002) { - speed = XFER_SW_DMA_1; - } else if (id->dma_1word & 0x0001) { - speed = XFER_SW_DMA_0; - } else { - return ((int) ide_dma_off_quietly); - } - - (void) hpt34x_tune_chipset(drive, speed); - - return ((int) ((id->dma_ultra >> 11) & 3) ? ide_dma_off : - ((id->dma_ultra >> 8) & 7) ? ide_dma_on : - ((id->dma_mword >> 8) & 7) ? ide_dma_on : - ((id->dma_1word >> 8) & 7) ? ide_dma_on : - ide_dma_off_quietly); -} - -static void config_chipset_for_pio (ide_drive_t *drive) -{ - unsigned short eide_pio_timing[6] = {960, 480, 240, 180, 120, 90}; - unsigned short xfer_pio = drive->id->eide_pio_modes; - - byte timing, speed, pio; - - pio = ide_get_best_pio_mode(drive, 255, 5, NULL); - - if (xfer_pio> 4) - xfer_pio = 0; - - if (drive->id->eide_pio_iordy > 0) { - for (xfer_pio = 5; - xfer_pio>0 && - drive->id->eide_pio_iordy>eide_pio_timing[xfer_pio]; - xfer_pio--); - } else { - xfer_pio = (drive->id->eide_pio_modes & 4) ? 0x05 : - (drive->id->eide_pio_modes & 2) ? 0x04 : - (drive->id->eide_pio_modes & 1) ? 0x03 : xfer_pio; - } - - timing = (xfer_pio >= pio) ? xfer_pio : pio; - - switch(timing) { - case 4: speed = XFER_PIO_4;break; - case 3: speed = XFER_PIO_3;break; - case 2: speed = XFER_PIO_2;break; - case 1: speed = XFER_PIO_1;break; - default: - speed = (!drive->id->tPIO) ? XFER_PIO_0 : XFER_PIO_SLOW; - break; - } - (void) hpt34x_tune_chipset(drive, speed); -} - -static void hpt34x_tune_drive (ide_drive_t *drive, byte pio) -{ - byte speed; - - switch(pio) { - case 4: speed = XFER_PIO_4;break; - case 3: speed = XFER_PIO_3;break; - case 2: speed = XFER_PIO_2;break; - case 1: speed = XFER_PIO_1;break; - default: speed = XFER_PIO_0;break; - } - hpt34x_clear_chipset(drive); - (void) hpt34x_tune_chipset(drive, speed); -} - -static int config_drive_xfer_rate (ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - ide_dma_action_t dma_func = ide_dma_on; - - if (id && (id->capability & 1) && HWIF(drive)->autodma) { - /* Consult the list of known "bad" drives */ - if (ide_dmaproc(ide_dma_bad_drive, drive)) { - dma_func = ide_dma_off; - goto fast_ata_pio; - } - dma_func = ide_dma_off_quietly; - if (id->field_valid & 4) { - if (id->dma_ultra & 0x0007) { - /* Force if Capable UltraDMA */ - dma_func = config_chipset_for_dma(drive, 1); - if ((id->field_valid & 2) && - (dma_func != ide_dma_on)) - goto try_dma_modes; - } - } else if (id->field_valid & 2) { -try_dma_modes: - if ((id->dma_mword & 0x0007) || - (id->dma_1word & 0x0007)) { - /* Force if Capable regular DMA modes */ - dma_func = config_chipset_for_dma(drive, 0); - if (dma_func != ide_dma_on) - goto no_dma_set; - } - } else if (ide_dmaproc(ide_dma_good_drive, drive)) { - if (id->eide_dma_time > 150) { - goto no_dma_set; - } - /* Consult the list of known "good" drives */ - dma_func = config_chipset_for_dma(drive, 0); - if (dma_func != ide_dma_on) - goto no_dma_set; - } else { - goto fast_ata_pio; - } - } else if ((id->capability & 8) || (id->field_valid & 2)) { -fast_ata_pio: - dma_func = ide_dma_off_quietly; -no_dma_set: - config_chipset_for_pio(drive); - } - -#ifndef CONFIG_HPT34X_AUTODMA - if (dma_func == ide_dma_on) - dma_func = ide_dma_off; -#endif /* CONFIG_HPT34X_AUTODMA */ - - return HWIF(drive)->dmaproc(dma_func, drive); -} - -/* - * hpt34x_dmaproc() initiates/aborts (U)DMA read/write operations on a drive. - * - * This is specific to the HPT343 UDMA bios-less chipset - * and HPT345 UDMA bios chipset (stamped HPT363) - * by HighPoint|Triones Technologies, Inc. - */ - -int hpt34x_dmaproc (ide_dma_action_t func, ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - unsigned long dma_base = hwif->dma_base; - unsigned int count, reading = 0; - byte dma_stat; - - switch (func) { - case ide_dma_check: - return config_drive_xfer_rate(drive); - case ide_dma_read: - reading = 1 << 3; - case ide_dma_write: - if (!(count = ide_build_dmatable(drive, func))) - return 1; /* try PIO instead of DMA */ - outl(hwif->dmatable_dma, dma_base + 4); /* PRD table */ - reading |= 0x01; - outb(reading, dma_base); /* specify r/w */ - outb(inb(dma_base+2)|6, dma_base+2); /* clear INTR & ERROR flags */ - drive->waiting_for_dma = 1; - if (drive->media != ide_disk) - return 0; - ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL); /* issue cmd to drive */ - OUT_BYTE((reading == 9) ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); - return 0; - case ide_dma_end: /* returns 1 on error, 0 otherwise */ - drive->waiting_for_dma = 0; - outb(inb(dma_base)&~1, dma_base); /* stop DMA */ - dma_stat = inb(dma_base+2); /* get DMA status */ - outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */ - ide_destroy_dmatable(drive); /* purge DMA mappings */ - return (dma_stat & 7) != 4; /* verify good DMA status */ - default: - break; - } - return ide_dmaproc(func, drive); /* use standard DMA stuff */ -} - -/* - * If the BIOS does not set the IO base addaress to XX00, 343 will fail. - */ -#define HPT34X_PCI_INIT_REG 0x80 - -unsigned int __init pci_init_hpt34x (struct pci_dev *dev, const char *name) -{ - int i = 0; - unsigned long hpt34xIoBase = dev->resource[4].start; - unsigned short cmd; - unsigned long flags; - - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ - - pci_write_config_byte(dev, HPT34X_PCI_INIT_REG, 0x00); - pci_read_config_word(dev, PCI_COMMAND, &cmd); - - if (cmd & PCI_COMMAND_MEMORY) { - if (dev->resource[PCI_ROM_RESOURCE].start) { - pci_write_config_byte(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); - printk(KERN_INFO "HPT345: ROM enabled at 0x%08lx\n", dev->resource[PCI_ROM_RESOURCE].start); - } - pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0xF0); - } else { - pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20); - } - - pci_write_config_word(dev, PCI_COMMAND, cmd & ~PCI_COMMAND_IO); - dev->resource[0].start = (hpt34xIoBase + 0x20); - dev->resource[1].start = (hpt34xIoBase + 0x34); - dev->resource[2].start = (hpt34xIoBase + 0x28); - dev->resource[3].start = (hpt34xIoBase + 0x3c); - for(i=0; i<4; i++) - dev->resource[i].flags |= PCI_BASE_ADDRESS_SPACE_IO; - /* - * Since 20-23 can be assigned and are R/W, we correct them. - */ - pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, dev->resource[0].start); - pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, dev->resource[1].start); - pci_write_config_dword(dev, PCI_BASE_ADDRESS_2, dev->resource[2].start); - pci_write_config_dword(dev, PCI_BASE_ADDRESS_3, dev->resource[3].start); - pci_write_config_word(dev, PCI_COMMAND, cmd); - - __restore_flags(flags); /* local CPU only */ - -#if defined(DISPLAY_HPT34X_TIMINGS) && defined(CONFIG_PROC_FS) - hpt34x_proc = 1; - bmide_dev = dev; - hpt34x_display_info = &hpt34x_get_info; -#endif /* DISPLAY_HPT34X_TIMINGS && CONFIG_PROC_FS */ - - return dev->irq; -} - -void __init ide_init_hpt34x (ide_hwif_t *hwif) -{ - hwif->tuneproc = &hpt34x_tune_drive; - if (hwif->dma_base) { - unsigned short pcicmd = 0; - - pci_read_config_word(hwif->pci_dev, PCI_COMMAND, &pcicmd); - hwif->autodma = (pcicmd & PCI_COMMAND_MEMORY) ? 1 : 0; - hwif->dmaproc = &hpt34x_dmaproc; - } else { - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - } -} diff --git a/drivers/block/hpt366.c b/drivers/block/hpt366.c deleted file mode 100644 index d2f2fb433..000000000 --- a/drivers/block/hpt366.c +++ /dev/null @@ -1,564 +0,0 @@ -/* - * linux/drivers/block/hpt366.c Version 0.16 Feb. 10, 2000 - * - * Copyright (C) 1999-2000 Andre Hedrick <andre@suse.com> - * May be copied or modified under the terms of the GNU General Public License - * - * Thanks to HighPoint Technologies for their assistance, and hardware. - * Special Thanks to Jon Burchmore in SanDiego for the deep pockets, his - * donation of an ABit BP6 mainboard, processor, and memory acellerated - * development and support. - */ - -#include <linux/config.h> -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/delay.h> -#include <linux/timer.h> -#include <linux/mm.h> -#include <linux/ioport.h> -#include <linux/blkdev.h> -#include <linux/hdreg.h> - -#include <linux/interrupt.h> -#include <linux/pci.h> -#include <linux/init.h> -#include <linux/ide.h> - -#include <asm/io.h> -#include <asm/irq.h> - -#include "ide_modes.h" - -#undef DISPLAY_HPT366_TIMINGS - -#if defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) -#include <linux/stat.h> -#include <linux/proc_fs.h> -#endif /* defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) */ - -const char *bad_ata66_4[] = { - "WDC AC310200R", - NULL -}; - -const char *bad_ata66_3[] = { - "WDC AC310200R", - NULL -}; - -const char *bad_ata33[] = { - "Maxtor 92720U8", "Maxtor 92040U6", "Maxtor 91360U4", "Maxtor 91020U3", "Maxtor 90845U3", "Maxtor 90650U2", - "Maxtor 91360D8", "Maxtor 91190D7", "Maxtor 91020D6", "Maxtor 90845D5", "Maxtor 90680D4", "Maxtor 90510D3", "Maxtor 90340D2", - "Maxtor 91152D8", "Maxtor 91008D7", "Maxtor 90845D6", "Maxtor 90840D6", "Maxtor 90720D5", "Maxtor 90648D5", "Maxtor 90576D4", - "Maxtor 90510D4", - "Maxtor 90432D3", "Maxtor 90288D2", "Maxtor 90256D2", - "Maxtor 91000D8", "Maxtor 90910D8", "Maxtor 90875D7", "Maxtor 90840D7", "Maxtor 90750D6", "Maxtor 90625D5", "Maxtor 90500D4", - "Maxtor 91728D8", "Maxtor 91512D7", "Maxtor 91303D6", "Maxtor 91080D5", "Maxtor 90845D4", "Maxtor 90680D4", "Maxtor 90648D3", "Maxtor 90432D2", - NULL -}; - -struct chipset_bus_clock_list_entry { - byte xfer_speed; - unsigned int chipset_settings; -}; - -struct chipset_bus_clock_list_entry forty_base [] = { - - { XFER_UDMA_4 , 0x900fd943 }, - { XFER_UDMA_3 , 0x900ad943 }, - { XFER_UDMA_2 , 0x900bd943 }, - { XFER_UDMA_1 , 0x9008d943 }, - { XFER_UDMA_0 , 0x9008d943 }, - - { XFER_MW_DMA_2 , 0xa008d943 }, - { XFER_MW_DMA_1 , 0xa010d955 }, - { XFER_MW_DMA_0 , 0xa010d9fc }, - - { XFER_PIO_4 , 0xc008d963 }, - { XFER_PIO_3 , 0xc010d974 }, - { XFER_PIO_2 , 0xc010d997 }, - { XFER_PIO_1 , 0xc010d9c7 }, - { XFER_PIO_0 , 0xc018d9d9 }, - { 0 , 0x0120d9d9 } -}; - -struct chipset_bus_clock_list_entry thirty_three_base [] = { - - { XFER_UDMA_4 , 0x90c9a731 }, - { XFER_UDMA_3 , 0x90cfa731 }, - { XFER_UDMA_2 , 0x90caa731 }, - { XFER_UDMA_1 , 0x90cba731 }, - { XFER_UDMA_0 , 0x90c8a731 }, - - { XFER_MW_DMA_2 , 0xa0c8a731 }, - { XFER_MW_DMA_1 , 0xa0c8a732 }, /* 0xa0c8a733 */ - { XFER_MW_DMA_0 , 0xa0c8a797 }, - - { XFER_PIO_4 , 0xc0c8a731 }, - { XFER_PIO_3 , 0xc0c8a742 }, - { XFER_PIO_2 , 0xc0d0a753 }, - { XFER_PIO_1 , 0xc0d0a7a3 }, /* 0xc0d0a793 */ - { XFER_PIO_0 , 0xc0d0a7aa }, /* 0xc0d0a7a7 */ - { 0 , 0x0120a7a7 } -}; - -struct chipset_bus_clock_list_entry twenty_five_base [] = { - - { XFER_UDMA_4 , 0x90c98521 }, - { XFER_UDMA_3 , 0x90cf8521 }, - { XFER_UDMA_2 , 0x90cf8521 }, - { XFER_UDMA_1 , 0x90cb8521 }, - { XFER_UDMA_0 , 0x90cb8521 }, - - { XFER_MW_DMA_2 , 0xa0ca8521 }, - { XFER_MW_DMA_1 , 0xa0ca8532 }, - { XFER_MW_DMA_0 , 0xa0ca8575 }, - - { XFER_PIO_4 , 0xc0ca8521 }, - { XFER_PIO_3 , 0xc0ca8532 }, - { XFER_PIO_2 , 0xc0ca8542 }, - { XFER_PIO_1 , 0xc0d08572 }, - { XFER_PIO_0 , 0xc0d08585 }, - { 0 , 0x01208585 } -}; - -#define HPT366_DEBUG_DRIVE_INFO 0 -#define HPT366_ALLOW_ATA66_4 1 -#define HPT366_ALLOW_ATA66_3 1 - -#if defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) -static int hpt366_get_info(char *, char **, off_t, int); -extern int (*hpt366_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -extern char *ide_media_verbose(ide_drive_t *); -static struct pci_dev *bmide_dev; -static struct pci_dev *bmide2_dev; - -static int hpt366_get_info (char *buffer, char **addr, off_t offset, int count) -{ - char *p = buffer; - u32 bibma = bmide_dev->resource[4].start; - u32 bibma2 = bmide2_dev->resource[4].start; - u8 c0 = 0, c1 = 0; - - /* - * at that point bibma+0x2 et bibma+0xa are byte registers - * to investigate: - */ - c0 = inb_p((unsigned short)bibma + 0x02); - if (bmide2_dev) - c1 = inb_p((unsigned short)bibma2 + 0x02); - - p += sprintf(p, "\n HPT366 Chipset.\n"); - p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n"); - p += sprintf(p, " %sabled %sabled\n", - (c0&0x80) ? "dis" : " en", - (c1&0x80) ? "dis" : " en"); - p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n"); - p += sprintf(p, "DMA enabled: %s %s %s %s\n", - (c0&0x20) ? "yes" : "no ", (c0&0x40) ? "yes" : "no ", - (c1&0x20) ? "yes" : "no ", (c1&0x40) ? "yes" : "no " ); - - p += sprintf(p, "UDMA\n"); - p += sprintf(p, "DMA\n"); - p += sprintf(p, "PIO\n"); - - return p-buffer;/* => must be less than 4k! */ -} -#endif /* defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) */ - -byte hpt366_proc = 0; - -extern char *ide_xfer_verbose (byte xfer_rate); -byte hpt363_shared_irq = 0; -byte hpt363_shared_pin = 0; - -static int check_in_drive_lists (ide_drive_t *drive, const char **list) -{ - struct hd_driveid *id = drive->id; -#if HPT366_DEBUG_DRIVE_INFO - printk("check_in_drive_lists(%s, %p)\n", drive->name, list); -#endif /* HPT366_DEBUG_DRIVE_INFO */ - - while (*list) { - if (!strcmp(*list++,id->model)) { -#ifdef DEBUG - printk("%s: Broken ASIC, BackSpeeding (U)DMA for %s\n", drive->name, id->model); -#endif /* DEBUG */ - return 1; - } - } - return 0; -} - -static unsigned int pci_bus_clock_list (byte speed, struct chipset_bus_clock_list_entry * chipset_table) -{ -#if HPT366_DEBUG_DRIVE_INFO - printk("pci_bus_clock_list(speed=0x%02x, table=%p)\n", speed, chipset_table); -#endif /* HPT366_DEBUG_DRIVE_INFO */ - for ( ; chipset_table->xfer_speed ; chipset_table++) - if (chipset_table->xfer_speed == speed) { -#if HPT366_DEBUG_DRIVE_INFO - printk("pci_bus_clock_list: found match: 0x%08x\n", chipset_table->chipset_settings); -#endif /* HPT366_DEBUG_DRIVE_INFO */ - return chipset_table->chipset_settings; - } -#if HPT366_DEBUG_DRIVE_INFO - printk("pci_bus_clock_list: using default: 0x%08x\n", 0x01208585); -#endif /* HPT366_DEBUG_DRIVE_INFO */ - return 0x01208585; -} - -static int hpt366_tune_chipset (ide_drive_t *drive, byte speed) -{ - int err; -#if HPT366_DEBUG_DRIVE_INFO - int drive_number = ((HWIF(drive)->channel ? 2 : 0) + (drive->select.b.unit & 0x01)); -#endif /* HPT366_DEBUG_DRIVE_INFO */ - byte regtime = (drive->select.b.unit & 0x01) ? 0x44 : 0x40; - unsigned int reg1 = 0; - unsigned int reg2 = 0; - -#if HPT366_DEBUG_DRIVE_INFO - printk("hpt366_tune_chipset(%s, speed=0x%02x)\n", drive->name, speed); -#endif /* HPT366_DEBUG_DRIVE_INFO */ - - pci_read_config_dword(HWIF(drive)->pci_dev, regtime, ®1); - /* detect bus speed by looking at control reg timing: */ - switch((reg1 >> 8) & 7) { - case 5: - reg2 = pci_bus_clock_list(speed, forty_base); - break; - case 9: - reg2 = pci_bus_clock_list(speed, twenty_five_base); - break; - default: - printk("hpt366: assuming 33Mhz PCI bus\n"); - case 7: - reg2 = pci_bus_clock_list(speed, thirty_three_base); - break; - } - /* - * Disable on-chip PIO FIFO/buffer (to avoid problems handling I/O errors later) - */ - if (speed >= XFER_MW_DMA_0) { - reg2 = (reg2 & ~0xc0000000) | (reg1 & 0xc0000000); - } else { - reg2 = (reg2 & ~0x30070000) | (reg1 & 0x30070000); - } - reg2 &= ~0x80000000; - - pci_write_config_dword(HWIF(drive)->pci_dev, regtime, reg2); - err = ide_config_drive_speed(drive, speed); - -#if HPT366_DEBUG_DRIVE_INFO - printk("%s: speed=0x%02x(%s), drive%d, old=0x%08x, new=0x%08x, err=0x%04x\n", - drive->name, speed, ide_xfer_verbose(speed), - drive_number, reg1, reg2, err); -#endif /* HPT366_DEBUG_DRIVE_INFO */ - return(err); -} - -/* - * This allows the configuration of ide_pci chipset registers - * for cards that learn about the drive's UDMA, DMA, PIO capabilities - * after the drive is reported by the OS. Initally for designed for - * HPT366 UDMA chipset by HighPoint|Triones Technologies, Inc. - * - * check_in_drive_lists(drive, bad_ata66_4) - * check_in_drive_lists(drive, bad_ata66_3) - * check_in_drive_lists(drive, bad_ata33) - * - */ -static int config_chipset_for_dma (ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - byte speed = 0x00; - byte reg51h = 0; - int rval; - - if ((id->dma_ultra & 0x0010) && - (!check_in_drive_lists(drive, bad_ata66_4)) && - (HPT366_ALLOW_ATA66_4) && - (HWIF(drive)->udma_four)) { - speed = XFER_UDMA_4; - } else if ((id->dma_ultra & 0x0008) && - (!check_in_drive_lists(drive, bad_ata66_3)) && - (HPT366_ALLOW_ATA66_3) && - (HWIF(drive)->udma_four)) { - speed = XFER_UDMA_3; - } else if (id->dma_ultra && (!check_in_drive_lists(drive, bad_ata33))) { - if (id->dma_ultra & 0x0004) { - speed = XFER_UDMA_2; - } else if (id->dma_ultra & 0x0002) { - speed = XFER_UDMA_1; - } else if (id->dma_ultra & 0x0001) { - speed = XFER_UDMA_0; - } - } else if (id->dma_mword & 0x0004) { - speed = XFER_MW_DMA_2; - } else if (id->dma_mword & 0x0002) { - speed = XFER_MW_DMA_1; - } else if (id->dma_mword & 0x0001) { - speed = XFER_MW_DMA_0; - } else if (id->dma_1word & 0x0004) { - speed = XFER_SW_DMA_2; - } else if (id->dma_1word & 0x0002) { - speed = XFER_SW_DMA_1; - } else if (id->dma_1word & 0x0001) { - speed = XFER_SW_DMA_0; - } else { -#if HPT366_DEBUG_DRIVE_INFO - printk("%s: config_chipset_for_dma: returning 'ide_dma_off_quietly'\n", drive->name); -#endif /* HPT366_DEBUG_DRIVE_INFO */ - return ((int) ide_dma_off_quietly); - } - - pci_read_config_byte(HWIF(drive)->pci_dev, 0x51, ®51h); - -#ifdef CONFIG_HPT366_FIP - /* - * Some drives prefer/allow for the method of handling interrupts. - */ - if (!(reg51h & 0x80)) - pci_write_config_byte(HWIF(drive)->pci_dev, 0x51, reg51h|0x80); -#else /* ! CONFIG_HPT366_FIP */ - /* - * Disable the "fast interrupt" prediction. - * Instead, always wait for the real interrupt from the drive! - */ - if (reg51h & 0x80) - pci_write_config_byte(HWIF(drive)->pci_dev, 0x51, reg51h & ~0x80); -#endif /* CONFIG_HPT366_FIP */ -#if HPT366_DEBUG_DRIVE_INFO - printk("%s: config_chipset_for_dma: speed=0x%04x\n", drive->name, speed); -#endif /* HPT366_DEBUG_DRIVE_INFO */ - (void) hpt366_tune_chipset(drive, speed); - - rval = (int)( ((id->dma_ultra >> 11) & 3) ? ide_dma_on : - ((id->dma_ultra >> 8) & 7) ? ide_dma_on : - ((id->dma_mword >> 8) & 7) ? ide_dma_on : - ((id->dma_1word >> 8) & 7) ? ide_dma_on : - ide_dma_off_quietly); - -#if HPT366_DEBUG_DRIVE_INFO - printk("%s: config_chipset_for_dma: returning %d (%s)\n", drive->name, rval, rval == ide_dma_on ? "dma_on" : "dma_off"); -#endif /* HPT366_DEBUG_DRIVE_INFO */ - return rval; -} - -static void config_chipset_for_pio (ide_drive_t *drive) -{ - unsigned short eide_pio_timing[6] = {960, 480, 240, 180, 120, 90}; - unsigned short xfer_pio = drive->id->eide_pio_modes; - byte timing, speed, pio; - -#if HPT366_DEBUG_DRIVE_INFO - printk("%s: config_chipset_for_pio\n", drive->name); -#endif /* HPT366_DEBUG_DRIVE_INFO */ - pio = ide_get_best_pio_mode(drive, 255, 5, NULL); - - if (xfer_pio> 4) - xfer_pio = 0; - - if (drive->id->eide_pio_iordy > 0) { - for (xfer_pio = 5; - xfer_pio>0 && - drive->id->eide_pio_iordy>eide_pio_timing[xfer_pio]; - xfer_pio--); - } else { - xfer_pio = (drive->id->eide_pio_modes & 4) ? 0x05 : - (drive->id->eide_pio_modes & 2) ? 0x04 : - (drive->id->eide_pio_modes & 1) ? 0x03 : - (drive->id->tPIO & 2) ? 0x02 : - (drive->id->tPIO & 1) ? 0x01 : xfer_pio; - } - - timing = (xfer_pio >= pio) ? xfer_pio : pio; - - switch(timing) { - case 4: speed = XFER_PIO_4;break; - case 3: speed = XFER_PIO_3;break; - case 2: speed = XFER_PIO_2;break; - case 1: speed = XFER_PIO_1;break; - default: - speed = (!drive->id->tPIO) ? XFER_PIO_0 : XFER_PIO_SLOW; - break; - } -#if HPT366_DEBUG_DRIVE_INFO - printk("%s: config_chipset_for_pio: speed=0x%04x\n", drive->name, speed); -#endif /* HPT366_DEBUG_DRIVE_INFO */ - (void) hpt366_tune_chipset(drive, speed); -} - -static void hpt366_tune_drive (ide_drive_t *drive, byte pio) -{ - byte speed; - switch(pio) { - case 4: speed = XFER_PIO_4;break; - case 3: speed = XFER_PIO_3;break; - case 2: speed = XFER_PIO_2;break; - case 1: speed = XFER_PIO_1;break; - default: speed = XFER_PIO_0;break; - } - (void) hpt366_tune_chipset(drive, speed); -} - -static int config_drive_xfer_rate (ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - ide_dma_action_t dma_func = ide_dma_on; - - if (id && (id->capability & 1) && HWIF(drive)->autodma) { - /* Consult the list of known "bad" drives */ - if (ide_dmaproc(ide_dma_bad_drive, drive)) { - dma_func = ide_dma_off; - goto fast_ata_pio; - } - dma_func = ide_dma_off_quietly; - if (id->field_valid & 4) { - if (id->dma_ultra & 0x001F) { - /* Force if Capable UltraDMA */ - dma_func = config_chipset_for_dma(drive); - if ((id->field_valid & 2) && - (dma_func != ide_dma_on)) - goto try_dma_modes; - } - } else if (id->field_valid & 2) { -try_dma_modes: - if ((id->dma_mword & 0x0007) || - (id->dma_1word & 0x0007)) { - /* Force if Capable regular DMA modes */ - dma_func = config_chipset_for_dma(drive); - if (dma_func != ide_dma_on) - goto no_dma_set; - } - } else if (ide_dmaproc(ide_dma_good_drive, drive)) { - if (id->eide_dma_time > 150) { - goto no_dma_set; - } - /* Consult the list of known "good" drives */ - dma_func = config_chipset_for_dma(drive); - if (dma_func != ide_dma_on) - goto no_dma_set; - } else { - goto fast_ata_pio; - } - } else if ((id->capability & 8) || (id->field_valid & 2)) { -fast_ata_pio: - dma_func = ide_dma_off_quietly; -no_dma_set: - - config_chipset_for_pio(drive); - } - return HWIF(drive)->dmaproc(dma_func, drive); -} - -/* - * hpt366_dmaproc() initiates/aborts (U)DMA read/write operations on a drive. - * - * This is specific to the HPT366 UDMA bios chipset - * by HighPoint|Triones Technologies, Inc. - */ -int hpt366_dmaproc (ide_dma_action_t func, ide_drive_t *drive) -{ - byte reg50h = 0; - - switch (func) { - case ide_dma_check: - return config_drive_xfer_rate(drive); - case ide_dma_lostirq: - pci_read_config_byte(HWIF(drive)->pci_dev, 0x50, ®50h); - pci_write_config_byte(HWIF(drive)->pci_dev, 0x50, reg50h|0x03); - pci_read_config_byte(HWIF(drive)->pci_dev, 0x50, ®50h); - /* ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL); */ - case ide_dma_timeout: - default: - break; - } - return ide_dmaproc(func, drive); /* use standard DMA stuff */ -} - -unsigned int __init pci_init_hpt366 (struct pci_dev *dev, const char *name) -{ - byte test = 0; - - if (dev->resource[PCI_ROM_RESOURCE].start) - pci_write_config_byte(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); - - pci_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &test); - if (test != 0x08) - pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 0x08); - - pci_read_config_byte(dev, PCI_LATENCY_TIMER, &test); - if (test != 0x78) - pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78); - - pci_read_config_byte(dev, PCI_MIN_GNT, &test); - if (test != 0x08) - pci_write_config_byte(dev, PCI_MIN_GNT, 0x08); - - pci_read_config_byte(dev, PCI_MAX_LAT, &test); - if (test != 0x08) - pci_write_config_byte(dev, PCI_MAX_LAT, 0x08); - -#if defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) - if (!hpt366_proc) { - hpt366_proc = 1; - bmide_dev = dev; - hpt366_display_info = &hpt366_get_info; - } - if ((hpt366_proc) && ((dev->devfn - bmide_dev->devfn) == 1)) { - bmide2_dev = dev; - } -#endif /* DISPLAY_HPT366_TIMINGS && CONFIG_PROC_FS */ - - return dev->irq; -} - -unsigned int __init ata66_hpt366 (ide_hwif_t *hwif) -{ - byte ata66 = 0; - - pci_read_config_byte(hwif->pci_dev, 0x5a, &ata66); -#ifdef DEBUG - printk("HPT366: reg5ah=0x%02x ATA-%s Cable Port%d\n", - ata66, (ata66 & 0x02) ? "33" : "66", - PCI_FUNC(hwif->pci_dev->devfn)); -#endif /* DEBUG */ - return ((ata66 & 0x02) ? 0 : 1); -} - -void __init ide_init_hpt366 (ide_hwif_t *hwif) -{ - hwif->tuneproc = &hpt366_tune_drive; - if (hwif->dma_base) { - hwif->dmaproc = &hpt366_dmaproc; - } else { - hwif->autodma = 0; - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - } -} - -void ide_dmacapable_hpt366 (ide_hwif_t *hwif, unsigned long dmabase) -{ - byte masterdma = 0, slavedma = 0; - byte dma_new = 0, dma_old = inb(dmabase+2); - unsigned long flags; - - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ - - dma_new = dma_old; - pci_read_config_byte(hwif->pci_dev, 0x43, &masterdma); - pci_read_config_byte(hwif->pci_dev, 0x47, &slavedma); - - if (masterdma & 0x30) dma_new |= 0x20; - if (slavedma & 0x30) dma_new |= 0x40; - if (dma_new != dma_old) outb(dma_new, dmabase+2); - - __restore_flags(flags); /* local CPU only */ - - ide_setup_dma(hwif, dmabase, 8); -} diff --git a/drivers/block/ht6560b.c b/drivers/block/ht6560b.c deleted file mode 100644 index 6b7d5af72..000000000 --- a/drivers/block/ht6560b.c +++ /dev/null @@ -1,342 +0,0 @@ -/* - * linux/drivers/block/ht6560b.c Version 0.07 Feb 1, 2000 - * - * Copyright (C) 1995-2000 Linus Torvalds & author (see below) - */ - -/* - * - * Version 0.01 Initial version hacked out of ide.c - * - * Version 0.02 Added support for PIO modes, auto-tune - * - * Version 0.03 Some cleanups - * - * Version 0.05 PIO mode cycle timings auto-tune using bus-speed - * - * Version 0.06 Prefetch mode now defaults no OFF. To set - * prefetch mode OFF/ON use "hdparm -p8/-p9". - * Unmask irq is disabled when prefetch mode - * is enabled. - * - * Version 0.07 Trying to fix CD-ROM detection problem. - * "Prefetch" mode bit OFF for ide disks and - * ON for anything else. - * - * - * HT-6560B EIDE-controller support - * To activate controller support use kernel parameter "ide0=ht6560b". - * Use hdparm utility to enable PIO mode support. - * - * Author: Mikko Ala-Fossi <maf@iki.fi> - * Jan Evert van Grootheest <janevert@iae.nl> - * - * Try: http://www.maf.iki.fi/~maf/ht6560b/ - */ - -#define HT6560B_VERSION "v0.07" - -#undef REALLY_SLOW_IO /* most systems can safely undef this */ - -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/delay.h> -#include <linux/timer.h> -#include <linux/mm.h> -#include <linux/ioport.h> -#include <linux/blkdev.h> -#include <linux/hdreg.h> -#include <linux/ide.h> - -#include <asm/io.h> - -#include "ide_modes.h" - -/* #define DEBUG */ /* remove comments for DEBUG messages */ - -/* - * The special i/o-port that HT-6560B uses to configuration: - * bit0 (0x01): "1" selects secondary interface - * bit2 (0x04): "1" enables FIFO function - * bit5 (0x20): "1" enables prefetched data read function (???) - * - * The special i/o-port that HT-6560A uses to configuration: - * bit0 (0x01): "1" selects secondary interface - * bit1 (0x02): "1" enables prefetched data read function - * bit2 (0x04): "0" enables multi-master system (?) - * bit3 (0x08): "1" 3 cycle time, "0" 2 cycle time (?) - */ -#define HT_CONFIG_PORT 0x3e6 -#define HT_CONFIG(drivea) (byte)(((drivea)->drive_data & 0xff00) >> 8) -/* - * FIFO + PREFETCH (both a/b-model) - */ -#define HT_CONFIG_DEFAULT 0x1c /* no prefetch */ -/* #define HT_CONFIG_DEFAULT 0x3c */ /* with prefetch */ -#define HT_SECONDARY_IF 0x01 -#define HT_PREFETCH_MODE 0x20 - -/* - * ht6560b Timing values: - * - * I reviewed some assembler source listings of htide drivers and found - * out how they setup those cycle time interfacing values, as they at Holtek - * call them. IDESETUP.COM that is supplied with the drivers figures out - * optimal values and fetches those values to drivers. I found out that - * they use IDE_SELECT_REG to fetch timings to the ide board right after - * interface switching. After that it was quite easy to add code to - * ht6560b.c. - * - * IDESETUP.COM gave me values 0x24, 0x45, 0xaa, 0xff that worked fine - * for hda and hdc. But hdb needed higher values to work, so I guess - * that sometimes it is necessary to give higher value than IDESETUP - * gives. [see cmd640.c for an extreme example of this. -ml] - * - * Perhaps I should explain something about these timing values: - * The higher nibble of value is the Recovery Time (rt) and the lower nibble - * of the value is the Active Time (at). Minimum value 2 is the fastest and - * the maximum value 15 is the slowest. Default values should be 15 for both. - * So 0x24 means 2 for rt and 4 for at. Each of the drives should have - * both values, and IDESETUP gives automatically rt=15 st=15 for CDROMs or - * similar. If value is too small there will be all sorts of failures. - * - * Timing byte consists of - * High nibble: Recovery Cycle Time (rt) - * The valid values range from 2 to 15. The default is 15. - * - * Low nibble: Active Cycle Time (at) - * The valid values range from 2 to 15. The default is 15. - * - * You can obtain optimized timing values by running Holtek IDESETUP.COM - * for DOS. DOS drivers get their timing values from command line, where - * the first value is the Recovery Time and the second value is the - * Active Time for each drive. Smaller value gives higher speed. - * In case of failures you should probably fall back to a higher value. - */ -#define HT_TIMING(drivea) (byte)((drivea)->drive_data & 0x00ff) -#define HT_TIMING_DEFAULT 0xff - -/* - * This routine handles interface switching for the peculiar hardware design - * on the F.G.I./Holtek HT-6560B VLB IDE interface. - * The HT-6560B can only enable one IDE port at a time, and requires a - * silly sequence (below) whenever we switch between primary and secondary. - */ - -/* - * This routine is invoked from ide.c to prepare for access to a given drive. - */ -static void ht6560b_selectproc (ide_drive_t *drive) -{ - unsigned long flags; - static byte current_select = 0; - static byte current_timing = 0; - byte select, timing; - - __save_flags (flags); /* local CPU only */ - __cli(); /* local CPU only */ - - select = HT_CONFIG(drive); - timing = HT_TIMING(drive); - - if (select != current_select || timing != current_timing) { - current_select = select; - current_timing = timing; - if (drive->media != ide_disk || !drive->present) - select |= HT_PREFETCH_MODE; - (void) inb(HT_CONFIG_PORT); - (void) inb(HT_CONFIG_PORT); - (void) inb(HT_CONFIG_PORT); - (void) inb(HT_CONFIG_PORT); - outb(select, HT_CONFIG_PORT); - /* - * Set timing for this drive: - */ - outb(timing, IDE_SELECT_REG); - (void) inb(IDE_STATUS_REG); -#ifdef DEBUG - printk("ht6560b: %s: select=%#x timing=%#x\n", drive->name, select, timing); -#endif - } - __restore_flags (flags); /* local CPU only */ -} - -/* - * Autodetection and initialization of ht6560b - */ -static int __init try_to_init_ht6560b(void) -{ - byte orig_value; - int i; - - /* Autodetect ht6560b */ - if ((orig_value=inb(HT_CONFIG_PORT)) == 0xff) - return 0; - - for (i=3;i>0;i--) { - outb(0x00, HT_CONFIG_PORT); - if (!( (~inb(HT_CONFIG_PORT)) & 0x3f )) { - outb(orig_value, HT_CONFIG_PORT); - return 0; - } - } - outb(0x00, HT_CONFIG_PORT); - if ((~inb(HT_CONFIG_PORT))& 0x3f) { - outb(orig_value, HT_CONFIG_PORT); - return 0; - } - /* - * Ht6560b autodetected - */ - outb(HT_CONFIG_DEFAULT, HT_CONFIG_PORT); - outb(HT_TIMING_DEFAULT, 0x1f6); /* IDE_SELECT_REG */ - (void) inb(0x1f7); /* IDE_STATUS_REG */ - - printk("\nht6560b " HT6560B_VERSION - ": chipset detected and initialized" -#ifdef DEBUG - " with debug enabled" -#endif - ); - return 1; -} - -static byte ht_pio2timings(ide_drive_t *drive, byte pio) -{ - int bus_speed, active_time, recovery_time; - int active_cycles, recovery_cycles; - ide_pio_data_t d; - - if (pio) { - pio = ide_get_best_pio_mode(drive, pio, 5, &d); - - /* - * Just like opti621.c we try to calculate the - * actual cycle time for recovery and activity - * according system bus speed. - */ - bus_speed = ide_system_bus_speed(); - active_time = ide_pio_timings[pio].active_time; - recovery_time = d.cycle_time - - active_time - - ide_pio_timings[pio].setup_time; - /* - * Cycle times should be Vesa bus cycles - */ - active_cycles = (active_time * bus_speed + 999) / 1000; - recovery_cycles = (recovery_time * bus_speed + 999) / 1000; - /* - * Upper and lower limits - */ - if (active_cycles < 2) active_cycles = 2; - if (recovery_cycles < 2) recovery_cycles = 2; - if (active_cycles > 15) active_cycles = 15; - if (recovery_cycles > 15) recovery_cycles = 0; /* 0==16 */ - -#ifdef DEBUG - printk("ht6560b: drive %s setting pio=%d recovery=%d (%dns) active=%d (%dns)\n", drive->name, pio, recovery_cycles, recovery_time, active_cycles, active_time); -#endif - - return (byte)((recovery_cycles << 4) | active_cycles); - } else { - -#ifdef DEBUG - printk("ht6560b: drive %s setting pio=0\n", drive->name); -#endif - - return HT_TIMING_DEFAULT; /* default setting */ - } -} - -/* - * Enable/Disable so called prefetch mode - */ -static void ht_set_prefetch(ide_drive_t *drive, byte state) -{ - unsigned long flags; - int t = HT_PREFETCH_MODE << 8; - - save_flags (flags); /* all CPUs */ - cli(); /* all CPUs */ - - /* - * Prefetch mode and unmask irq seems to conflict - */ - if (state) { - drive->drive_data |= t; /* enable prefetch mode */ - drive->no_unmask = 1; - drive->unmask = 0; - } else { - drive->drive_data &= ~t; /* disable prefetch mode */ - drive->no_unmask = 0; - } - - restore_flags (flags); /* all CPUs */ - -#ifdef DEBUG - printk("ht6560b: drive %s prefetch mode %sabled\n", drive->name, (state ? "en" : "dis")); -#endif -} - -static void tune_ht6560b (ide_drive_t *drive, byte pio) -{ - unsigned long flags; - byte timing; - - switch (pio) { - case 8: /* set prefetch off */ - case 9: /* set prefetch on */ - ht_set_prefetch(drive, pio & 1); - return; - } - - timing = ht_pio2timings(drive, pio); - - save_flags (flags); /* all CPUs */ - cli(); /* all CPUs */ - - drive->drive_data &= 0xff00; - drive->drive_data |= timing; - - restore_flags (flags); /* all CPUs */ - -#ifdef DEBUG - printk("ht6560b: drive %s tuned to pio mode %#x timing=%#x\n", drive->name, pio, timing); -#endif -} - -void __init init_ht6560b (void) -{ - int t; - - if (check_region(HT_CONFIG_PORT,1)) { - printk(KERN_ERR "ht6560b: PORT %#x ALREADY IN USE\n", HT_CONFIG_PORT); - } else { - if (try_to_init_ht6560b()) { - request_region(HT_CONFIG_PORT, 1, ide_hwifs[0].name); - ide_hwifs[0].chipset = ide_ht6560b; - ide_hwifs[1].chipset = ide_ht6560b; - ide_hwifs[0].selectproc = &ht6560b_selectproc; - ide_hwifs[1].selectproc = &ht6560b_selectproc; - ide_hwifs[0].tuneproc = &tune_ht6560b; - ide_hwifs[1].tuneproc = &tune_ht6560b; - ide_hwifs[0].serialized = 1; /* is this needed? */ - ide_hwifs[1].serialized = 1; /* is this needed? */ - ide_hwifs[0].mate = &ide_hwifs[1]; - ide_hwifs[1].mate = &ide_hwifs[0]; - ide_hwifs[1].channel = 1; - - /* - * Setting default configurations for drives - */ - t = (HT_CONFIG_DEFAULT << 8); - t |= HT_TIMING_DEFAULT; - ide_hwifs[0].drives[0].drive_data = t; - ide_hwifs[0].drives[1].drive_data = t; - t |= (HT_SECONDARY_IF << 8); - ide_hwifs[1].drives[0].drive_data = t; - ide_hwifs[1].drives[1].drive_data = t; - } else - printk(KERN_ERR "ht6560b: not found\n"); - } -} diff --git a/drivers/block/icside.c b/drivers/block/icside.c deleted file mode 100644 index d0e8f8328..000000000 --- a/drivers/block/icside.c +++ /dev/null @@ -1,643 +0,0 @@ -/* - * linux/drivers/block/icside.c - * - * Copyright (c) 1996,1997 Russell King. - * - * Changelog: - * 08-Jun-1996 RMK Created - * 12-Sep-1997 RMK Added interrupt enable/disable - * 17-Apr-1999 RMK Added support for V6 EASI - * 22-May-1999 RMK Added support for V6 DMA - */ - -#include <linux/config.h> -#include <linux/string.h> -#include <linux/module.h> -#include <linux/ioport.h> -#include <linux/malloc.h> -#include <linux/blkdev.h> -#include <linux/errno.h> -#include <linux/hdreg.h> -#include <linux/ide.h> - -#include <asm/dma.h> -#include <asm/ecard.h> -#include <asm/io.h> - -extern char *ide_xfer_verbose (byte xfer_rate); - -/* - * Maximum number of interfaces per card - */ -#define MAX_IFS 2 - -#define ICS_IDENT_OFFSET 0x8a0 - -#define ICS_ARCIN_V5_INTRSTAT 0x000 -#define ICS_ARCIN_V5_INTROFFSET 0x001 -#define ICS_ARCIN_V5_IDEOFFSET 0xa00 -#define ICS_ARCIN_V5_IDEALTOFFSET 0xae0 -#define ICS_ARCIN_V5_IDESTEPPING 4 - -#define ICS_ARCIN_V6_IDEOFFSET_1 0x800 -#define ICS_ARCIN_V6_INTROFFSET_1 0x880 -#define ICS_ARCIN_V6_INTRSTAT_1 0x8a4 -#define ICS_ARCIN_V6_IDEALTOFFSET_1 0x8e0 -#define ICS_ARCIN_V6_IDEOFFSET_2 0xc00 -#define ICS_ARCIN_V6_INTROFFSET_2 0xc80 -#define ICS_ARCIN_V6_INTRSTAT_2 0xca4 -#define ICS_ARCIN_V6_IDEALTOFFSET_2 0xce0 -#define ICS_ARCIN_V6_IDESTEPPING 4 - -struct cardinfo { - unsigned int dataoffset; - unsigned int ctrloffset; - unsigned int stepping; -}; - -static struct cardinfo icside_cardinfo_v5 = { - ICS_ARCIN_V5_IDEOFFSET, - ICS_ARCIN_V5_IDEALTOFFSET, - ICS_ARCIN_V5_IDESTEPPING -}; - -static struct cardinfo icside_cardinfo_v6_1 = { - ICS_ARCIN_V6_IDEOFFSET_1, - ICS_ARCIN_V6_IDEALTOFFSET_1, - ICS_ARCIN_V6_IDESTEPPING -}; - -static struct cardinfo icside_cardinfo_v6_2 = { - ICS_ARCIN_V6_IDEOFFSET_2, - ICS_ARCIN_V6_IDEALTOFFSET_2, - ICS_ARCIN_V6_IDESTEPPING -}; - -static const card_ids icside_cids[] = { - { MANU_ICS, PROD_ICS_IDE }, - { MANU_ICS2, PROD_ICS2_IDE }, - { 0xffff, 0xffff } -}; - -typedef enum { - ics_if_unknown, - ics_if_arcin_v5, - ics_if_arcin_v6 -} iftype_t; - -/* ---------------- Version 5 PCB Support Functions --------------------- */ -/* Prototype: icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr) - * Purpose : enable interrupts from card - */ -static void icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr) -{ - unsigned int memc_port = (unsigned int)ec->irq_data; - outb (0, memc_port + ICS_ARCIN_V5_INTROFFSET); -} - -/* Prototype: icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr) - * Purpose : disable interrupts from card - */ -static void icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr) -{ - unsigned int memc_port = (unsigned int)ec->irq_data; - inb (memc_port + ICS_ARCIN_V5_INTROFFSET); -} - -static const expansioncard_ops_t icside_ops_arcin_v5 = { - icside_irqenable_arcin_v5, - icside_irqdisable_arcin_v5, - NULL, - NULL, - NULL, - NULL -}; - - -/* ---------------- Version 6 PCB Support Functions --------------------- */ -/* Prototype: icside_irqenable_arcin_v6 (struct expansion_card *ec, int irqnr) - * Purpose : enable interrupts from card - */ -static void icside_irqenable_arcin_v6 (struct expansion_card *ec, int irqnr) -{ - unsigned int ide_base_port = (unsigned int)ec->irq_data; - - outb (0, ide_base_port + ICS_ARCIN_V6_INTROFFSET_1); - outb (0, ide_base_port + ICS_ARCIN_V6_INTROFFSET_2); -} - -/* Prototype: icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr) - * Purpose : disable interrupts from card - */ -static void icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr) -{ - unsigned int ide_base_port = (unsigned int)ec->irq_data; - - inb (ide_base_port + ICS_ARCIN_V6_INTROFFSET_1); - inb (ide_base_port + ICS_ARCIN_V6_INTROFFSET_2); -} - -/* Prototype: icside_irqprobe(struct expansion_card *ec) - * Purpose : detect an active interrupt from card - */ -static int icside_irqpending_arcin_v6(struct expansion_card *ec) -{ - unsigned int ide_base_port = (unsigned int)ec->irq_data; - - return inb(ide_base_port + ICS_ARCIN_V6_INTRSTAT_1) & 1 || - inb(ide_base_port + ICS_ARCIN_V6_INTRSTAT_2) & 1; -} - -static const expansioncard_ops_t icside_ops_arcin_v6 = { - icside_irqenable_arcin_v6, - icside_irqdisable_arcin_v6, - icside_irqpending_arcin_v6, - NULL, - NULL, - NULL -}; - -/* Prototype: icside_identifyif (struct expansion_card *ec) - * Purpose : identify IDE interface type - * Notes : checks the description string - */ -static iftype_t icside_identifyif (struct expansion_card *ec) -{ - unsigned int addr; - iftype_t iftype; - int id = 0; - - iftype = ics_if_unknown; - - addr = ecard_address (ec, ECARD_IOC, ECARD_FAST) + ICS_IDENT_OFFSET; - - id = inb (addr) & 1; - id |= (inb (addr + 1) & 1) << 1; - id |= (inb (addr + 2) & 1) << 2; - id |= (inb (addr + 3) & 1) << 3; - - switch (id) { - case 0: /* A3IN */ - printk("icside: A3IN unsupported\n"); - break; - - case 1: /* A3USER */ - printk("icside: A3USER unsupported\n"); - break; - - case 3: /* ARCIN V6 */ - printk(KERN_DEBUG "icside: detected ARCIN V6 in slot %d\n", ec->slot_no); - iftype = ics_if_arcin_v6; - break; - - case 15:/* ARCIN V5 (no id) */ - printk(KERN_DEBUG "icside: detected ARCIN V5 in slot %d\n", ec->slot_no); - iftype = ics_if_arcin_v5; - break; - - default:/* we don't know - complain very loudly */ - printk("icside: ***********************************\n"); - printk("icside: *** UNKNOWN ICS INTERFACE id=%d ***\n", id); - printk("icside: ***********************************\n"); - printk("icside: please report this to linux@arm.linux.org.uk\n"); - printk("icside: defaulting to ARCIN V5\n"); - iftype = ics_if_arcin_v5; - break; - } - - return iftype; -} - -#ifdef CONFIG_BLK_DEV_IDEDMA_ICS -/* - * SG-DMA support. - * - * Similar to the BM-DMA, but we use the RiscPCs IOMD DMA controllers. - * There is only one DMA controller per card, which means that only - * one drive can be accessed at one time. NOTE! We do not enforce that - * here, but we rely on the main IDE driver spotting that both - * interfaces use the same IRQ, which should guarantee this. - */ -#define TABLE_SIZE 2048 - -static int -icside_build_dmatable(ide_drive_t *drive, int reading) -{ - struct request *rq = HWGROUP(drive)->rq; - struct buffer_head *bh = rq->bh; - unsigned long addr, size; - unsigned char *virt_addr; - unsigned int count = 0; - dmasg_t *sg = (dmasg_t *)HWIF(drive)->dmatable_cpu; - - do { - if (bh == NULL) { - /* paging requests have (rq->bh == NULL) */ - virt_addr = rq->buffer; - addr = virt_to_bus (virt_addr); - size = rq->nr_sectors << 9; - } else { - /* group sequential buffers into one large buffer */ - virt_addr = bh->b_data; - addr = virt_to_bus (virt_addr); - size = bh->b_size; - while ((bh = bh->b_reqnext) != NULL) { - if ((addr + size) != virt_to_bus (bh->b_data)) - break; - size += bh->b_size; - } - } - - if (addr & 3) { - printk("%s: misaligned DMA buffer\n", drive->name); - return 0; - } - - if (size) { - if (reading) - dma_cache_inv((unsigned int)virt_addr, size); - else - dma_cache_wback((unsigned int)virt_addr, size); - } - - sg[count].address = addr; - sg[count].length = size; - if (++count >= (TABLE_SIZE / sizeof(dmasg_t))) { - printk("%s: DMA table too small\n", drive->name); - return 0; - } - } while (bh != NULL); - - if (!count) - printk("%s: empty DMA table?\n", drive->name); - - return count; -} - -static int -icside_config_if(ide_drive_t *drive, int xfer_mode) -{ - int func = ide_dma_off; - - switch (xfer_mode) { - case XFER_MW_DMA_2: - /* - * The cycle time is limited to 250ns by the r/w - * pulse width (90ns), however we should still - * have a maximum burst transfer rate of 8MB/s. - */ - drive->drive_data = 250; - break; - - case XFER_MW_DMA_1: - drive->drive_data = 250; - break; - - case XFER_MW_DMA_0: - drive->drive_data = 480; - break; - - default: - drive->drive_data = 0; - break; - } - - if (drive->drive_data && - ide_config_drive_speed(drive, (byte) xfer_mode) == 0) - func = ide_dma_on; - else - drive->drive_data = 480; - - printk("%s: %s selected (peak %dMB/s)\n", drive->name, - ide_xfer_verbose(xfer_mode), 2000 / drive->drive_data); - - return func; -} - -static int -icside_dma_check(ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - ide_hwif_t *hwif = HWIF(drive); - int autodma = hwif->autodma; - int xfer_mode = XFER_PIO_2; - int func = ide_dma_off_quietly; - - if (!id || !(id->capability & 1) || !autodma) - goto out; - - /* - * Consult the list of known "bad" drives - */ - if (ide_dmaproc(ide_dma_bad_drive, drive)) { - func = ide_dma_off; - goto out; - } - - /* - * Enable DMA on any drive that has multiword DMA - */ - if (id->field_valid & 2) { - if (id->dma_mword & 4) { - xfer_mode = XFER_MW_DMA_2; - func = ide_dma_on; - } else if (id->dma_mword & 2) { - xfer_mode = XFER_MW_DMA_1; - func = ide_dma_on; - } else if (id->dma_mword & 1) { - xfer_mode = XFER_MW_DMA_0; - func = ide_dma_on; - } - goto out; - } - - /* - * Consult the list of known "good" drives - */ - if (ide_dmaproc(ide_dma_good_drive, drive)) { - if (id->eide_dma_time > 150) - goto out; - xfer_mode = XFER_MW_DMA_1; - func = ide_dma_on; - } - -out: - func = icside_config_if(drive, xfer_mode); - - return hwif->dmaproc(func, drive); -} - -static int -icside_dmaproc(ide_dma_action_t func, ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - int count, reading = 0; - - switch (func) { - case ide_dma_check: - return icside_dma_check(drive); - - case ide_dma_read: - reading = 1; - case ide_dma_write: - count = icside_build_dmatable(drive, reading); - if (!count) - return 1; - disable_dma(hwif->hw.dma); - - /* Route the DMA signals to - * to the correct interface. - */ - outb(hwif->select_data, hwif->config_data); - - /* Select the correct timing - * for this drive - */ - set_dma_speed(hwif->hw.dma, drive->drive_data); - - set_dma_sg(hwif->hw.dma, (dmasg_t *)hwif->dmatable_cpu, count); - set_dma_mode(hwif->hw.dma, reading ? DMA_MODE_READ - : DMA_MODE_WRITE); - - drive->waiting_for_dma = 1; - if (drive->media != ide_disk) - return 0; - - ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL); - OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, - IDE_COMMAND_REG); - - case ide_dma_begin: - enable_dma(hwif->hw.dma); - return 0; - - case ide_dma_end: - drive->waiting_for_dma = 0; - disable_dma(hwif->hw.dma); - return get_dma_residue(hwif->hw.dma) != 0; - - case ide_dma_test_irq: - return inb((unsigned long)hwif->hw.priv) & 1; - - default: - return ide_dmaproc(func, drive); - } -} - -static unsigned long -icside_alloc_dmatable(void) -{ - static unsigned long dmatable; - static unsigned int leftover; - unsigned long table; - - if (leftover < TABLE_SIZE) { -#if PAGE_SIZE == TABLE_SIZE * 2 - dmatable = __get_free_pages(GFP_KERNEL, 1); - leftover = PAGE_SIZE; -#else - dmatable = kmalloc(TABLE_SIZE, GFP_KERNEL); - leftover = TABLE_SIZE; -#endif - } - - table = dmatable; - if (table) { - dmatable += TABLE_SIZE; - leftover -= TABLE_SIZE; - } - - return table; -} - -static int -icside_setup_dma(ide_hwif_t *hwif, int autodma) -{ - unsigned long table = icside_alloc_dmatable(); - - printk(" %s: SG-DMA", hwif->name); - - if (!table) - printk(" -- ERROR, unable to allocate DMA table\n"); - else { - hwif->dmatable_cpu = (void *)table; - hwif->dmaproc = icside_dmaproc; - hwif->autodma = autodma; - - printk(" capable%s\n", autodma ? - ", auto-enable" : ""); - } - - return hwif->dmatable_cpu != NULL; -} -#endif - -static ide_hwif_t * -icside_find_hwif(unsigned long dataport) -{ - ide_hwif_t *hwif; - int index; - - for (index = 0; index < MAX_HWIFS; ++index) { - hwif = &ide_hwifs[index]; - if (hwif->hw.io_ports[IDE_DATA_OFFSET] == (ide_ioreg_t)dataport) - goto found; - } - - for (index = 0; index < MAX_HWIFS; ++index) { - hwif = &ide_hwifs[index]; - if (!hwif->hw.io_ports[IDE_DATA_OFFSET]) - goto found; - } - - return NULL; -found: - return hwif; -} - -static ide_hwif_t * -icside_setup(unsigned long base, struct cardinfo *info, int irq) -{ - unsigned long port = base + info->dataoffset; - ide_hwif_t *hwif; - - hwif = icside_find_hwif(base); - if (hwif) { - int i; - - memset(&hwif->hw, 0, sizeof(hw_regs_t)); - - for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { - hwif->hw.io_ports[i] = (ide_ioreg_t)port; - port += 1 << info->stepping; - } - hwif->hw.io_ports[IDE_CONTROL_OFFSET] = base + info->ctrloffset; - hwif->hw.irq = irq; - hwif->hw.dma = NO_DMA; - hwif->noprobe = 0; - hwif->chipset = ide_acorn; - } - - return hwif; -} - -static int icside_register_v5(struct expansion_card *ec, int autodma) -{ - unsigned long slot_port; - ide_hwif_t *hwif; - - slot_port = ecard_address(ec, ECARD_MEMC, 0); - - ec->irqaddr = (unsigned char *)ioaddr(slot_port + ICS_ARCIN_V5_INTRSTAT); - ec->irqmask = 1; - ec->irq_data = (void *)slot_port; - ec->ops = (expansioncard_ops_t *)&icside_ops_arcin_v5; - - /* - * Be on the safe side - disable interrupts - */ - inb(slot_port + ICS_ARCIN_V5_INTROFFSET); - - hwif = icside_setup(slot_port, &icside_cardinfo_v5, ec->irq); - - return hwif ? 0 : -1; -} - -static int icside_register_v6(struct expansion_card *ec, int autodma) -{ - unsigned long slot_port, port; - ide_hwif_t *hwif, *mate; - int sel = 0; - - slot_port = ecard_address(ec, ECARD_IOC, ECARD_FAST); - port = ecard_address(ec, ECARD_EASI, ECARD_FAST); - - if (port == 0) - port = slot_port; - else - sel = 1 << 5; - - outb(sel, slot_port); - - ec->irq_data = (void *)port; - ec->ops = (expansioncard_ops_t *)&icside_ops_arcin_v6; - - /* - * Be on the safe side - disable interrupts - */ - inb(port + ICS_ARCIN_V6_INTROFFSET_1); - inb(port + ICS_ARCIN_V6_INTROFFSET_2); - - hwif = icside_setup(port, &icside_cardinfo_v6_1, ec->irq); - mate = icside_setup(port, &icside_cardinfo_v6_2, ec->irq); - -#ifdef CONFIG_BLK_DEV_IDEDMA_ICS - if (ec->dma != NO_DMA) { - if (request_dma(ec->dma, hwif->name)) - goto no_dma; - - if (hwif) { - hwif->config_data = slot_port; - hwif->select_data = sel; - hwif->hw.dma = ec->dma; - hwif->hw.priv = (void *) - (port + ICS_ARCIN_V6_INTRSTAT_1); - hwif->channel = 0; - icside_setup_dma(hwif, autodma); - } - if (mate) { - mate->config_data = slot_port; - mate->select_data = sel | 1; - mate->hw.dma = ec->dma; - mate->hw.priv = (void *) - (port + ICS_ARCIN_V6_INTRSTAT_2); - mate->channel = 1; - icside_setup_dma(mate, autodma); - } - } -#endif - -no_dma: - return hwif || mate ? 0 : -1; -} - -int icside_init(void) -{ - int autodma = 0; - -#ifdef CONFIG_IDEDMA_ICS_AUTO - autodma = 1; -#endif - - ecard_startfind (); - - do { - struct expansion_card *ec; - int result; - - ec = ecard_find(0, icside_cids); - if (ec == NULL) - break; - - ecard_claim(ec); - - switch (icside_identifyif(ec)) { - case ics_if_arcin_v5: - result = icside_register_v5(ec, autodma); - break; - - case ics_if_arcin_v6: - result = icside_register_v6(ec, autodma); - break; - - default: - result = -1; - break; - } - - if (result) - ecard_release(ec); - } while (1); - - return 0; -} diff --git a/drivers/block/ide-cd.c b/drivers/block/ide-cd.c deleted file mode 100644 index 641783e9c..000000000 --- a/drivers/block/ide-cd.c +++ /dev/null @@ -1,2729 +0,0 @@ -/* - * linux/drivers/block/ide-cd.c - * Copyright (C) 1994, 1995, 1996 scott snyder <snyder@fnald0.fnal.gov> - * Copyright (C) 1996-1998 Erik Andersen <andersee@debian.org> - * Copyright (C) 1998, 1999 Jens Axboe <axboe@image.dk> - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * ATAPI CD-ROM driver. To be used with ide.c. - * See Documentation/cdrom/ide-cd for usage information. - * - * Suggestions are welcome. Patches that work are more welcome though. ;-) - * For those wishing to work on this driver, please be sure you download - * and comply with the latest Mt. Fuji (SFF8090 version 4) and ATAPI - * (SFF-8020i rev 2.6) standards. These documents can be obtained by - * anonymous ftp from: - * ftp://fission.dt.wdc.com/pub/standards/SFF/specs/INF-8020.PDF - * ftp://ftp.avc-pioneer.com/Mtfuji4/Spec/Fuji4r01.pdf - * - * Drives that deviate from these standards will be accomodated as much - * as possible via compile time or command-line options. Since I only have - * a few drives, you generally need to send me patches... - * - * ---------------------------------- - * TO DO LIST: - * -Make it so that Pioneer CD DR-A24X and friends don't get screwed up on - * boot - * - * ---------------------------------- - * 1.00 Oct 31, 1994 -- Initial version. - * 1.01 Nov 2, 1994 -- Fixed problem with starting request in - * cdrom_check_status. - * 1.03 Nov 25, 1994 -- leaving unmask_intr[] as a user-setting (as for disks) - * (from mlord) -- minor changes to cdrom_setup() - * -- renamed ide_dev_s to ide_drive_t, enable irq on command - * 2.00 Nov 27, 1994 -- Generalize packet command interface; - * add audio ioctls. - * 2.01 Dec 3, 1994 -- Rework packet command interface to handle devices - * which send an interrupt when ready for a command. - * 2.02 Dec 11, 1994 -- Cache the TOC in the driver. - * Don't use SCMD_PLAYAUDIO_TI; it's not included - * in the current version of ATAPI. - * Try to use LBA instead of track or MSF addressing - * when possible. - * Don't wait for READY_STAT. - * 2.03 Jan 10, 1995 -- Rewrite block read routines to handle block sizes - * other than 2k and to move multiple sectors in a - * single transaction. - * 2.04 Apr 21, 1995 -- Add work-around for Creative Labs CD220E drives. - * Thanks to Nick Saw <cwsaw@pts7.pts.mot.com> for - * help in figuring this out. Ditto for Acer and - * Aztech drives, which seem to have the same problem. - * 2.04b May 30, 1995 -- Fix to match changes in ide.c version 3.16 -ml - * 2.05 Jun 8, 1995 -- Don't attempt to retry after an illegal request - * or data protect error. - * Use HWIF and DEV_HWIF macros as in ide.c. - * Always try to do a request_sense after - * a failed command. - * Include an option to give textual descriptions - * of ATAPI errors. - * Fix a bug in handling the sector cache which - * showed up if the drive returned data in 512 byte - * blocks (like Pioneer drives). Thanks to - * Richard Hirst <srh@gpt.co.uk> for diagnosing this. - * Properly supply the page number field in the - * MODE_SELECT command. - * PLAYAUDIO12 is broken on the Aztech; work around it. - * 2.05x Aug 11, 1995 -- lots of data structure renaming/restructuring in ide.c - * (my apologies to Scott, but now ide-cd.c is independent) - * 3.00 Aug 22, 1995 -- Implement CDROMMULTISESSION ioctl. - * Implement CDROMREADAUDIO ioctl (UNTESTED). - * Use input_ide_data() and output_ide_data(). - * Add door locking. - * Fix usage count leak in cdrom_open, which happened - * when a read-write mount was attempted. - * Try to load the disk on open. - * Implement CDROMEJECT_SW ioctl (off by default). - * Read total cdrom capacity during open. - * Rearrange logic in cdrom_decode_status. Issue - * request sense commands for failed packet commands - * from here instead of from cdrom_queue_packet_command. - * Fix a race condition in retrieving error information. - * Suppress printing normal unit attention errors and - * some drive not ready errors. - * Implement CDROMVOLREAD ioctl. - * Implement CDROMREADMODE1/2 ioctls. - * Fix race condition in setting up interrupt handlers - * when the `serialize' option is used. - * 3.01 Sep 2, 1995 -- Fix ordering of reenabling interrupts in - * cdrom_queue_request. - * Another try at using ide_[input,output]_data. - * 3.02 Sep 16, 1995 -- Stick total disk capacity in partition table as well. - * Make VERBOSE_IDE_CD_ERRORS dump failed command again. - * Dump out more information for ILLEGAL REQUEST errs. - * Fix handling of errors occurring before the - * packet command is transferred. - * Fix transfers with odd bytelengths. - * 3.03 Oct 27, 1995 -- Some Creative drives have an id of just `CD'. - * `DCI-2S10' drives are broken too. - * 3.04 Nov 20, 1995 -- So are Vertos drives. - * 3.05 Dec 1, 1995 -- Changes to go with overhaul of ide.c and ide-tape.c - * 3.06 Dec 16, 1995 -- Add support needed for partitions. - * More workarounds for Vertos bugs (based on patches - * from Holger Dietze <dietze@aix520.informatik.uni-leipzig.de>). - * Try to eliminate byteorder assumptions. - * Use atapi_cdrom_subchnl struct definition. - * Add STANDARD_ATAPI compilation option. - * 3.07 Jan 29, 1996 -- More twiddling for broken drives: Sony 55D, - * Vertos 300. - * Add NO_DOOR_LOCKING configuration option. - * Handle drive_cmd requests w/NULL args (for hdparm -t). - * Work around sporadic Sony55e audio play problem. - * 3.07a Feb 11, 1996 -- check drive->id for NULL before dereferencing, to fix - * problem with "hde=cdrom" with no drive present. -ml - * 3.08 Mar 6, 1996 -- More Vertos workarounds. - * 3.09 Apr 5, 1996 -- Add CDROMCLOSETRAY ioctl. - * Switch to using MSF addressing for audio commands. - * Reformat to match kernel tabbing style. - * Add CDROM_GET_UPC ioctl. - * 3.10 Apr 10, 1996 -- Fix compilation error with STANDARD_ATAPI. - * 3.11 Apr 29, 1996 -- Patch from Heiko Eissfeldt <heiko@colossus.escape.de> - * to remove redundant verify_area calls. - * 3.12 May 7, 1996 -- Rudimentary changer support. Based on patches - * from Gerhard Zuber <zuber@berlin.snafu.de>. - * Let open succeed even if there's no loaded disc. - * 3.13 May 19, 1996 -- Fixes for changer code. - * 3.14 May 29, 1996 -- Add work-around for Vertos 600. - * (From Hennus Bergman <hennus@sky.ow.nl>.) - * 3.15 July 2, 1996 -- Added support for Sanyo 3 CD changers - * from Ben Galliart <bgallia@luc.edu> with - * special help from Jeff Lightfoot - * <jeffml@pobox.com> - * 3.15a July 9, 1996 -- Improved Sanyo 3 CD changer identification - * 3.16 Jul 28, 1996 -- Fix from Gadi to reduce kernel stack usage for ioctl. - * 3.17 Sep 17, 1996 -- Tweak audio reads for some drives. - * Start changing CDROMLOADFROMSLOT to CDROM_SELECT_DISC. - * 3.18 Oct 31, 1996 -- Added module and DMA support. - * - * - * 4.00 Nov 5, 1996 -- New ide-cd maintainer, - * Erik B. Andersen <andersee@debian.org> - * -- Newer Creative drives don't always set the error - * register correctly. Make sure we see media changes - * regardless. - * -- Integrate with generic cdrom driver. - * -- CDROMGETSPINDOWN and CDROMSETSPINDOWN ioctls, based on - * a patch from Ciro Cattuto <>. - * -- Call set_device_ro. - * -- Implement CDROMMECHANISMSTATUS and CDROMSLOTTABLE - * ioctls, based on patch by Erik Andersen - * -- Add some probes of drive capability during setup. - * - * 4.01 Nov 11, 1996 -- Split into ide-cd.c and ide-cd.h - * -- Removed CDROMMECHANISMSTATUS and CDROMSLOTTABLE - * ioctls in favor of a generalized approach - * using the generic cdrom driver. - * -- Fully integrated with the 2.1.X kernel. - * -- Other stuff that I forgot (lots of changes) - * - * 4.02 Dec 01, 1996 -- Applied patch from Gadi Oxman <gadio@netvision.net.il> - * to fix the drive door locking problems. - * - * 4.03 Dec 04, 1996 -- Added DSC overlap support. - * 4.04 Dec 29, 1996 -- Added CDROMREADRAW ioclt based on patch - * by Ales Makarov (xmakarov@sun.felk.cvut.cz) - * - * 4.05 Nov 20, 1997 -- Modified to print more drive info on init - * Minor other changes - * Fix errors on CDROMSTOP (If you have a "Dolphin", - * you must define IHAVEADOLPHIN) - * Added identifier so new Sanyo CD-changer works - * Better detection if door locking isn't supported - * - * 4.06 Dec 17, 1997 -- fixed endless "tray open" messages -ml - * 4.07 Dec 17, 1997 -- fallback to set pc->stat on "tray open" - * 4.08 Dec 18, 1997 -- spew less noise when tray is empty - * -- fix speed display for ACER 24X, 18X - * 4.09 Jan 04, 1998 -- fix handling of the last block so we return - * an end of file instead of an I/O error (Gadi) - * 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. - * -- Fixed a memory leak where info->changer_info was - * malloc'ed but never free'd when closing the device. - * -- Cleaned up the global namespace a bit by making more - * functions static that should already have been. - * 4.11 Mar 12, 1998 -- Added support for the CDROM_SELECT_SPEED ioctl - * based on a patch for 2.0.33 by Jelle Foks - * <jelle@scintilla.utwente.nl>, a patch for 2.0.33 - * by Toni Giorgino <toni@pcape2.pi.infn.it>, the SCSI - * version, and my own efforts. -erik - * -- Fixed a stupid bug which egcs was kind enough to - * inform me of where "Illegal mode for this track" - * was never returned due to a comparison on data - * types of limited range. - * 4.12 Mar 29, 1998 -- Fixed bug in CDROM_SELECT_SPEED so write speed is - * now set ionly for CD-R and CD-RW drives. I had - * removed this support because it produced errors. - * It produced errors _only_ for non-writers. duh. - * 4.13 May 05, 1998 -- Suppress useless "in progress of becoming ready" - * messages, since this is not an error. - * -- Change error messages to be const - * -- Remove a "\t" which looks ugly in the syslogs - * 4.14 July 17, 1998 -- Change to pointing to .ps version of ATAPI spec - * since the .pdf version doesn't seem to work... - * -- Updated the TODO list to something more current. - * - * 4.15 Aug 25, 1998 -- Updated ide-cd.h to respect mechine endianess, - * patch thanks to "Eddie C. Dost" <ecd@skynet.be> - * - * 4.50 Oct 19, 1998 -- New maintainers! - * Jens Axboe <axboe@image.dk> - * Chris Zwilling <chris@cloudnet.com> - * - * 4.51 Dec 23, 1998 -- Jens Axboe <axboe@image.dk> - * - ide_cdrom_reset enabled since the ide subsystem - * handles resets fine now. <axboe@image.dk> - * - Transfer size fix for Samsung CD-ROMs, thanks to - * "Ville Hallik" <ville.hallik@mail.ee>. - * - other minor stuff. - * - * 4.52 Jan 19, 1999 -- Jens Axboe <axboe@image.dk> - * - Detect DVD-ROM/RAM drives - * - * 4.53 Feb 22, 1999 - Include other model Samsung and one Goldstar - * drive in transfer size limit. - * - Fix the I/O error when doing eject without a medium - * loaded on some drives. - * - CDROMREADMODE2 is now implemented through - * CDROMREADRAW, since many drives don't support - * MODE2 (even though ATAPI 2.6 says they must). - * - Added ignore parameter to ide-cd (as a module), eg - * insmod ide-cd ignore='hda hdb' - * Useful when using ide-cd in conjunction with - * ide-scsi. TODO: non-modular way of doing the - * same. - * - * 4.54 Aug 5, 1999 - Support for MMC2 class commands through the generic - * packet interface to cdrom.c. - * - Unified audio ioctl support, most of it. - * - cleaned up various deprecated verify_area(). - * - Added ide_cdrom_packet() as the interface for - * the Uniform generic_packet(). - * - bunch of other stuff, will fill in logs later. - * - report 1 slot for non-changers, like the other - * cd-rom drivers. don't report select disc for - * non-changers as well. - * - mask out audio playing, if the device can't do it. - * - * 4.55 Sep 1, 1999 - Eliminated the rest of the audio ioctls, except - * for CDROMREADTOC[ENTRY|HEADER]. Some of the drivers - * use this independently of the actual audio handling. - * They will disappear later when I get the time to - * do it cleanly. - * - Minimize the TOC reading - only do it when we - * know a media change has occured. - * - Moved all the CDROMREADx ioctls to the Uniform layer. - * - Heiko Eissfeldt <heiko@colossus.escape.de> supplied - * some fixes for CDI. - * - CD-ROM leaving door locked fix from Andries - * Brouwer <Andries.Brouwer@cwi.nl> - * - Erik Andersen <andersen@xmission.com> unified - * commands across the various drivers and how - * sense errors are handled. - * - * 4.56 Sep 12, 1999 - Removed changer support - it is now in the - * Uniform layer. - * - Added partition based multisession handling. - * - Mode sense and mode select moved to the - * Uniform layer. - * - Fixed a problem with WPI CDS-32X drive - it - * failed the capabilities - * - * - *************************************************************************/ - -#define IDECD_VERSION "4.56" - -#include <linux/module.h> -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/delay.h> -#include <linux/timer.h> -#include <linux/malloc.h> -#include <linux/interrupt.h> -#include <linux/errno.h> -#include <linux/cdrom.h> -#include <linux/ide.h> - -#include <asm/irq.h> -#include <asm/io.h> -#include <asm/byteorder.h> -#include <asm/uaccess.h> -#include <asm/unaligned.h> - -#include "ide-cd.h" - -/**************************************************************************** - * Generic packet command support and error handling routines. - */ - -/* Mark that we've seen a media change, and invalidate our internal - buffers. */ -static void cdrom_saw_media_change (ide_drive_t *drive) -{ - struct cdrom_info *info = drive->driver_data; - - CDROM_STATE_FLAGS (drive)->media_changed = 1; - CDROM_STATE_FLAGS (drive)->toc_valid = 0; - info->nsectors_buffered = 0; -} - - -static -void cdrom_analyze_sense_data (ide_drive_t *drive, struct request_sense *reqbuf, - struct packet_command *failed_command) -{ - if (reqbuf->sense_key == NOT_READY || - reqbuf->sense_key == UNIT_ATTENTION) { - /* Make good and sure we've seen this potential media change. - Some drives (i.e. Creative) fail to present the correct - sense key in the error register. */ - cdrom_saw_media_change (drive); - - - /* Don't print not ready or unit attention errors for - READ_SUBCHANNEL. Workman (and probably other programs) - uses this command to poll the drive, and we don't want - to fill the syslog with useless errors. */ - if (failed_command && - failed_command->c[0] == GPCMD_READ_SUBCHANNEL) - return; - } - - if (reqbuf->error_code == 0x70 && reqbuf->sense_key == 0x02 - && ((reqbuf->asc == 0x3a && reqbuf->ascq == 0x00) || - (reqbuf->asc == 0x04 && reqbuf->ascq == 0x01))) - { - /* - * Suppress the following errors: - * "Medium not present", "in progress of becoming ready", - * and "writing" to keep the noise level down to a dull roar. - */ - return; - } - -#if VERBOSE_IDE_CD_ERRORS - { - int i; - const char *s; - char buf[80]; - - printk ("ATAPI device %s:\n", drive->name); - if (reqbuf->error_code==0x70) - printk(" Error: "); - else if (reqbuf->error_code==0x71) - printk(" Deferred Error: "); - else - printk(" Unknown Error Type: "); - - if ( reqbuf->sense_key < ARY_LEN (sense_key_texts)) - s = sense_key_texts[reqbuf->sense_key]; - else - s = "bad sense key!"; - - printk ("%s -- (Sense key=0x%02x)\n", s, reqbuf->sense_key); - - if (reqbuf->asc == 0x40) { - sprintf (buf, "Diagnostic failure on component 0x%02x", - reqbuf->ascq); - s = buf; - } else { - int lo=0, mid, hi=ARY_LEN (sense_data_texts); - unsigned long key = (reqbuf->sense_key << 16); - key |= (reqbuf->asc << 8); - if ( ! (reqbuf->ascq >= 0x80 && reqbuf->ascq <= 0xdd) ) - key |= reqbuf->ascq; - s = NULL; - - while (hi > lo) { - mid = (lo + hi) / 2; - if (sense_data_texts[mid].asc_ascq == key || - sense_data_texts[mid].asc_ascq == (0xff0000|key)) { - s = sense_data_texts[mid].text; - break; - } - else if (sense_data_texts[mid].asc_ascq > key) - hi = mid; - else - lo = mid+1; - } - } - - if (s == NULL) { - if (reqbuf->asc > 0x80) - s = "(vendor-specific error)"; - else - s = "(reserved error code)"; - } - - printk (" %s -- (asc=0x%02x, ascq=0x%02x)\n", - s, reqbuf->asc, reqbuf->ascq); - - if (failed_command != NULL) { - - int lo=0, mid, hi= ARY_LEN (packet_command_texts); - s = NULL; - - while (hi > lo) { - mid = (lo + hi) / 2; - if (packet_command_texts[mid].packet_command == failed_command->c[0]) { - s = packet_command_texts[mid].text; - break; - } - else if (packet_command_texts[mid].packet_command > failed_command->c[0]) - hi = mid; - else - lo = mid+1; - } - - printk (" The failed \"%s\" packet command was: \n \"", s); - for (i=0; i<sizeof (failed_command->c); i++) - printk ("%02x ", failed_command->c[i]); - printk ("\"\n"); - } - - /* The SKSV bit specifies validity of the sense_key_specific - * in the next two commands. It is bit 7 of the first byte. - * In the case of NOT_READY, if SKSV is set the drive can - * give us nice ETA readings. - */ - if (reqbuf->sense_key == NOT_READY && (reqbuf->sks[0] & 0x80)) { - int progress = (reqbuf->sks[1] << 8 | reqbuf->sks[2]) * 100; - printk(" Command is %02d%% complete\n", progress / 0xffff); - - } - - if (reqbuf->sense_key == ILLEGAL_REQUEST && - (reqbuf->sks[0] & 0x80) != 0) { - printk (" Error in %s byte %d", - (reqbuf->sks[0] & 0x40) != 0 ? - "command packet" : "command data", - (reqbuf->sks[1] << 8) + reqbuf->sks[2]); - - if ((reqbuf->sks[0] & 0x40) != 0) - printk (" bit %d", reqbuf->sks[0] & 0x07); - - printk ("\n"); - } - } - -#else /* not VERBOSE_IDE_CD_ERRORS */ - - /* Suppress printing unit attention and `in progress of becoming ready' - errors when we're not being verbose. */ - - if (reqbuf->sense_key == UNIT_ATTENTION || - (reqbuf->sense_key == NOT_READY && (reqbuf->asc == 4 || - reqbuf->asc == 0x3a))) - return; - - printk ("%s: error code: 0x%02x sense_key: 0x%02x asc: 0x%02x ascq: 0x%02x\n", - drive->name, - reqbuf->error_code, reqbuf->sense_key, - reqbuf->asc, reqbuf->ascq); -#endif /* not VERBOSE_IDE_CD_ERRORS */ -} - -static void cdrom_queue_request_sense (ide_drive_t *drive, - struct semaphore *sem, - struct packet_command *failed_command) -{ - struct cdrom_info *info = drive->driver_data; - struct request *rq; - struct packet_command *pc; - - /* Make up a new request to retrieve sense information. */ - pc = &info->request_sense_pc; - memset(pc, 0, sizeof (*pc)); - - pc->c[0] = GPCMD_REQUEST_SENSE; - - /* just get the first 18 bytes of the sense info, there might not - * be more available */ - pc->c[4] = pc->buflen = 18; - pc->buffer = (char *)&info->sense_data; - pc->sense_data = (struct request_sense *)failed_command; - - /* stuff the sense request in front of our current request */ - rq = &info->request_sense_request; - ide_init_drive_cmd (rq); - rq->cmd = REQUEST_SENSE_COMMAND; - rq->buffer = (char *)pc; - rq->sem = sem; - (void) ide_do_drive_cmd (drive, rq, ide_preempt); -} - - -static void cdrom_end_request (int uptodate, ide_drive_t *drive) -{ - struct request *rq = HWGROUP(drive)->rq; - - if (rq->cmd == REQUEST_SENSE_COMMAND && uptodate) { - struct packet_command *pc = (struct packet_command *) - rq->buffer; - cdrom_analyze_sense_data (drive, - (struct request_sense *) (pc->buffer - pc->c[4]), - (struct packet_command *) pc->sense_data); - } - if (rq->cmd == READ && !rq->current_nr_sectors) - uptodate = 1; - - ide_end_request (uptodate, HWGROUP(drive)); -} - - -/* Returns 0 if the request should be continued. - Returns 1 if the request was ended. */ -static int cdrom_decode_status (ide_startstop_t *startstop, ide_drive_t *drive, int good_stat, - int *stat_ret) -{ - struct request *rq = HWGROUP(drive)->rq; - int stat, cmd, err, sense_key; - struct packet_command *pc = (struct packet_command *) rq->buffer; - - /* Check for errors. */ - stat = GET_STAT(); - *stat_ret = stat; - - if (OK_STAT (stat, good_stat, BAD_R_STAT)) - return 0; - - /* Get the IDE error register. */ - err = GET_ERR(); - sense_key = err >> 4; - - if (rq == NULL) - printk ("%s: missing request in cdrom_decode_status\n", - drive->name); - else { - cmd = rq->cmd; - - if (cmd == REQUEST_SENSE_COMMAND) { - /* We got an error trying to get sense info - from the drive (probably while trying - to recover from a former error). Just give up. */ - - pc->stat = 1; - cdrom_end_request (1, drive); - *startstop = ide_error (drive, "request sense failure", stat); - return 1; - - } else if (cmd == PACKET_COMMAND) { - /* All other functions, except for READ. */ - - struct semaphore *sem = NULL; - - /* Check for tray open. */ - if (sense_key == NOT_READY) { - cdrom_saw_media_change (drive); - } else if (sense_key == UNIT_ATTENTION) { - /* Check for media change. */ - cdrom_saw_media_change (drive); - /*printk("%s: media changed\n",drive->name);*/ - return 0; - } else { - /* Otherwise, print an error. */ - ide_dump_status (drive, "packet command error", - stat); - } - - /* Set the error flag and complete the request. - Then, if we have a CHECK CONDITION status, - queue a request sense command. We must be careful, - though: we don't want the thread in - cdrom_queue_packet_command to wake up until - the request sense has completed. We do this - by transferring the semaphore from the packet - command request to the request sense request. */ - - if ((stat & ERR_STAT) != 0) { - sem = rq->sem; - rq->sem = NULL; - } - - pc->stat = 1; - cdrom_end_request (1, drive); - - if ((stat & ERR_STAT) != 0) - cdrom_queue_request_sense(drive, sem, pc); - } else { - /* Handle errors from READ requests. */ - - if (sense_key == NOT_READY) { - /* Tray open. */ - cdrom_saw_media_change (drive); - - /* Fail the request. */ - printk ("%s: tray open\n", drive->name); - cdrom_end_request (0, drive); - } else if (sense_key == UNIT_ATTENTION) { - /* Media change. */ - cdrom_saw_media_change (drive); - - /* Arrange to retry the request. - But be sure to give up if we've retried - too many times. */ - if (++rq->errors > ERROR_MAX) - cdrom_end_request (0, drive); - } else if (sense_key == ILLEGAL_REQUEST || - sense_key == DATA_PROTECT) { - /* No point in retrying after an illegal - request or data protect error.*/ - ide_dump_status (drive, "command error", stat); - cdrom_end_request (0, drive); - } else if ((err & ~ABRT_ERR) != 0) { - /* Go to the default handler - for other errors. */ - *startstop = ide_error (drive, "cdrom_decode_status", stat); - return 1; - } else if ((++rq->errors > ERROR_MAX)) { - /* We've racked up too many retries. Abort. */ - cdrom_end_request (0, drive); - } - - /* If we got a CHECK_CONDITION status, - queue a request sense command. */ - if ((stat & ERR_STAT) != 0) - cdrom_queue_request_sense(drive, NULL, NULL); - } - } - - /* Retry, or handle the next request. */ - *startstop = ide_stopped; - return 1; -} - -static int cdrom_timer_expiry(ide_drive_t *drive) -{ - struct request *rq = HWGROUP(drive)->rq; - struct packet_command *pc = (struct packet_command *) rq->buffer; - unsigned long wait = 0; - - /* blank and format can take an extremly long time to - * complete, if the IMMED bit was not set. - */ - if (pc->c[0] == GPCMD_BLANK || pc->c[0] == GPCMD_FORMAT_UNIT) - wait = 60*60*HZ; - - return wait; -} - -/* Set up the device registers for transferring a packet command on DEV, - expecting to later transfer XFERLEN bytes. HANDLER is the routine - which actually transfers the command to the drive. If this is a - drq_interrupt device, this routine will arrange for HANDLER to be - called when the interrupt from the drive arrives. Otherwise, HANDLER - will be called immediately after the drive is prepared for the transfer. */ - -static ide_startstop_t cdrom_start_packet_command (ide_drive_t *drive, int xferlen, - ide_handler_t *handler) -{ - ide_startstop_t startstop; - struct cdrom_info *info = drive->driver_data; - - /* Wait for the controller to be idle. */ - if (ide_wait_stat(&startstop, drive, 0, BUSY_STAT, WAIT_READY)) - return startstop; - - if (info->dma) - info->dma = !HWIF(drive)->dmaproc(ide_dma_read, drive); - - /* Set up the controller registers. */ - OUT_BYTE (info->dma, IDE_FEATURE_REG); - OUT_BYTE (0, IDE_NSECTOR_REG); - OUT_BYTE (0, IDE_SECTOR_REG); - - OUT_BYTE (xferlen & 0xff, IDE_LCYL_REG); - OUT_BYTE (xferlen >> 8 , IDE_HCYL_REG); - if (IDE_CONTROL_REG) - OUT_BYTE (drive->ctl, IDE_CONTROL_REG); - - if (info->dma) - (void) (HWIF(drive)->dmaproc(ide_dma_begin, drive)); - - if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) { - ide_set_handler (drive, handler, WAIT_CMD, cdrom_timer_expiry); - OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* packet command */ - return ide_started; - } else { - OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* packet command */ - return (*handler) (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. */ -static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive, - unsigned char *cmd_buf, int cmd_len, - ide_handler_t *handler) -{ - if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) { - /* Here we should have been called after receiving an interrupt - from the device. DRQ should how be set. */ - int stat_dum; - ide_startstop_t startstop; - - /* Check for errors. */ - if (cdrom_decode_status (&startstop, drive, DRQ_STAT, &stat_dum)) - return startstop; - } else { - ide_startstop_t startstop; - /* Otherwise, we must wait for DRQ to get set. */ - if (ide_wait_stat (&startstop, drive, DRQ_STAT, BUSY_STAT, WAIT_READY)) - return startstop; - } - - /* Arm the interrupt handler. */ - ide_set_handler (drive, handler, WAIT_CMD, cdrom_timer_expiry); - - /* Send the command to the device. */ - atapi_output_bytes (drive, cmd_buf, cmd_len); - - return ide_started; -} - - - -/**************************************************************************** - * Block read functions. - */ - -/* - * Buffer up to SECTORS_TO_TRANSFER sectors from the drive in our sector - * buffer. Once the first sector is added, any subsequent sectors are - * assumed to be continuous (until the buffer is cleared). For the first - * sector added, SECTOR is its sector number. (SECTOR is then ignored until - * the buffer is cleared.) - */ -static void cdrom_buffer_sectors (ide_drive_t *drive, unsigned long sector, - int sectors_to_transfer) -{ - struct cdrom_info *info = drive->driver_data; - - /* Number of sectors to read into the buffer. */ - int sectors_to_buffer = MIN (sectors_to_transfer, - (SECTOR_BUFFER_SIZE >> SECTOR_BITS) - - info->nsectors_buffered); - - char *dest; - - /* If we couldn't get a buffer, don't try to buffer anything... */ - if (info->buffer == NULL) - sectors_to_buffer = 0; - - /* If this is the first sector in the buffer, remember its number. */ - if (info->nsectors_buffered == 0) - info->sector_buffered = sector; - - /* Read the data into the buffer. */ - dest = info->buffer + info->nsectors_buffered * SECTOR_SIZE; - while (sectors_to_buffer > 0) { - atapi_input_bytes (drive, dest, SECTOR_SIZE); - --sectors_to_buffer; - --sectors_to_transfer; - ++info->nsectors_buffered; - dest += SECTOR_SIZE; - } - - /* Throw away any remaining data. */ - while (sectors_to_transfer > 0) { - char dum[SECTOR_SIZE]; - atapi_input_bytes (drive, dum, sizeof (dum)); - --sectors_to_transfer; - } -} - -/* - * Check the contents of the interrupt reason register from the cdrom - * and attempt to recover if there are problems. Returns 0 if everything's - * ok; nonzero if the request has been terminated. - */ -static inline -int cdrom_read_check_ireason (ide_drive_t *drive, int len, int ireason) -{ - ireason &= 3; - if (ireason == 2) return 0; - - if (ireason == 0) { - /* Whoops... The drive is expecting to receive data from us! */ - printk ("%s: cdrom_read_intr: " - "Drive wants to transfer data the wrong way!\n", - drive->name); - - /* Throw some data at the drive so it doesn't hang - and quit this request. */ - while (len > 0) { - int dum = 0; - atapi_output_bytes (drive, &dum, sizeof (dum)); - len -= sizeof (dum); - } - } else if (ireason == 1) { - /* Some drives (ASUS) seem to tell us that status - * info is available. just get it and ignore. - */ - GET_STAT(); - return 0; - } else { - /* Drive wants a command packet, or invalid ireason... */ - printk ("%s: cdrom_read_intr: bad interrupt reason %d\n", - drive->name, ireason); - } - - cdrom_end_request (0, drive); - return -1; -} - -/* - * Interrupt routine. Called when a read request has completed. - */ -static ide_startstop_t cdrom_read_intr (ide_drive_t *drive) -{ - int stat; - int ireason, len, sectors_to_transfer, nskip; - struct cdrom_info *info = drive->driver_data; - int i, dma = info->dma, dma_error = 0; - ide_startstop_t startstop; - - struct request *rq = HWGROUP(drive)->rq; - - /* Check for errors. */ - if (dma) { - info->dma = 0; - if ((dma_error = HWIF(drive)->dmaproc(ide_dma_end, drive))) - HWIF(drive)->dmaproc(ide_dma_off, drive); - } - - if (cdrom_decode_status (&startstop, drive, 0, &stat)) - return startstop; - - if (dma) { - if (!dma_error) { - for (i = rq->nr_sectors; i > 0;) { - i -= rq->current_nr_sectors; - ide_end_request(1, HWGROUP(drive)); - } - return ide_stopped; - } else - return ide_error (drive, "dma error", stat); - } - - /* Read the interrupt reason and the transfer length. */ - ireason = IN_BYTE (IDE_NSECTOR_REG); - len = IN_BYTE (IDE_LCYL_REG) + 256 * IN_BYTE (IDE_HCYL_REG); - - /* If DRQ is clear, the command has completed. */ - if ((stat & DRQ_STAT) == 0) { - /* If we're not done filling the current buffer, complain. - Otherwise, complete the command normally. */ - if (rq->current_nr_sectors > 0) { - printk ("%s: cdrom_read_intr: data underrun (%ld blocks)\n", - drive->name, rq->current_nr_sectors); - cdrom_end_request (0, drive); - } else - cdrom_end_request (1, drive); - return ide_stopped; - } - - /* Check that the drive is expecting to do the same thing we are. */ - if (cdrom_read_check_ireason (drive, len, ireason)) - return ide_stopped; - - /* Assume that the drive will always provide data in multiples - of at least SECTOR_SIZE, as it gets hairy to keep track - of the transfers otherwise. */ - if ((len % SECTOR_SIZE) != 0) { - printk ("%s: cdrom_read_intr: Bad transfer size %d\n", - drive->name, len); - if (CDROM_CONFIG_FLAGS (drive)->limit_nframes) - printk (" This drive is not supported by this version of the driver\n"); - else { - printk (" Trying to limit transfer sizes\n"); - CDROM_CONFIG_FLAGS (drive)->limit_nframes = 1; - } - cdrom_end_request (0, drive); - return ide_stopped; - } - - /* The number of sectors we need to read from the drive. */ - sectors_to_transfer = len / SECTOR_SIZE; - - /* First, figure out if we need to bit-bucket - any of the leading sectors. */ - nskip = MIN ((int)(rq->current_nr_sectors - (rq->bh->b_size >> SECTOR_BITS)), - sectors_to_transfer); - - while (nskip > 0) { - /* We need to throw away a sector. */ - char dum[SECTOR_SIZE]; - atapi_input_bytes (drive, dum, sizeof (dum)); - - --rq->current_nr_sectors; - --nskip; - --sectors_to_transfer; - } - - /* Now loop while we still have data to read from the drive. */ - while (sectors_to_transfer > 0) { - int this_transfer; - - /* If we've filled the present buffer but there's another - chained buffer after it, move on. */ - if (rq->current_nr_sectors == 0 && - rq->nr_sectors > 0) - cdrom_end_request (1, drive); - - /* If the buffers are full, cache the rest of the data in our - internal buffer. */ - if (rq->current_nr_sectors == 0) { - cdrom_buffer_sectors(drive, rq->sector, sectors_to_transfer); - sectors_to_transfer = 0; - } else { - /* Transfer data to the buffers. - Figure out how many sectors we can transfer - to the current buffer. */ - this_transfer = MIN (sectors_to_transfer, - rq->current_nr_sectors); - - /* Read this_transfer sectors - into the current buffer. */ - while (this_transfer > 0) { - atapi_input_bytes(drive, rq->buffer, SECTOR_SIZE); - rq->buffer += SECTOR_SIZE; - --rq->nr_sectors; - --rq->current_nr_sectors; - ++rq->sector; - --this_transfer; - --sectors_to_transfer; - } - } - } - - /* Done moving data! - Wait for another interrupt. */ - ide_set_handler(drive, &cdrom_read_intr, WAIT_CMD, NULL); - return ide_started; -} - -/* - * Try to satisfy some of the current read request from our cached data. - * Returns nonzero if the request has been completed, zero otherwise. - */ -static int cdrom_read_from_buffer (ide_drive_t *drive) -{ - struct cdrom_info *info = drive->driver_data; - struct request *rq = HWGROUP(drive)->rq; - - /* Can't do anything if there's no buffer. */ - if (info->buffer == NULL) return 0; - - /* Loop while this request needs data and the next block is present - in our cache. */ - while (rq->nr_sectors > 0 && - rq->sector >= info->sector_buffered && - rq->sector < info->sector_buffered + info->nsectors_buffered) { - if (rq->current_nr_sectors == 0) - cdrom_end_request (1, drive); - - memcpy (rq->buffer, - info->buffer + - (rq->sector - info->sector_buffered) * SECTOR_SIZE, - SECTOR_SIZE); - rq->buffer += SECTOR_SIZE; - --rq->current_nr_sectors; - --rq->nr_sectors; - ++rq->sector; - } - - /* If we've satisfied the current request, - terminate it successfully. */ - if (rq->nr_sectors == 0) { - cdrom_end_request (1, drive); - return -1; - } - - /* Move on to the next buffer if needed. */ - if (rq->current_nr_sectors == 0) - cdrom_end_request (1, drive); - - /* If this condition does not hold, then the kluge i use to - represent the number of sectors to skip at the start of a transfer - will fail. I think that this will never happen, but let's be - paranoid and check. */ - if (rq->current_nr_sectors < (rq->bh->b_size >> SECTOR_BITS) && - (rq->sector % SECTORS_PER_FRAME) != 0) { - printk ("%s: cdrom_read_from_buffer: buffer botch (%ld)\n", - drive->name, rq->sector); - cdrom_end_request (0, drive); - return -1; - } - - return 0; -} - -/* - * Routine to send a read packet command to the drive. - * This is usually called directly from cdrom_start_read. - * However, for drq_interrupt devices, it is called from an interrupt - * when the drive is ready to accept the command. - */ -static ide_startstop_t cdrom_start_read_continuation (ide_drive_t *drive) -{ - struct packet_command pc; - struct request *rq = HWGROUP(drive)->rq; - int nsect, sector, nframes, frame, nskip; - - /* Number of sectors to transfer. */ - nsect = rq->nr_sectors; - - /* Starting sector. */ - sector = rq->sector; - - /* If the requested sector doesn't start on a cdrom block boundary, - we must adjust the start of the transfer so that it does, - and remember to skip the first few sectors. - If the CURRENT_NR_SECTORS field is larger than the size - of the buffer, it will mean that we're to skip a number - of sectors equal to the amount by which CURRENT_NR_SECTORS - is larger than the buffer size. */ - nskip = (sector % SECTORS_PER_FRAME); - if (nskip > 0) { - /* Sanity check... */ - if (rq->current_nr_sectors != (rq->bh->b_size >> SECTOR_BITS) && - (rq->sector % CD_FRAMESIZE != 0)) { - printk ("%s: cdrom_start_read_continuation: buffer botch (%lu)\n", - drive->name, rq->current_nr_sectors); - cdrom_end_request (0, drive); - return ide_stopped; - } - sector -= nskip; - nsect += nskip; - rq->current_nr_sectors += nskip; - } - - /* Convert from sectors to cdrom blocks, rounding up the transfer - length if needed. */ - nframes = (nsect + SECTORS_PER_FRAME-1) / SECTORS_PER_FRAME; - frame = sector / SECTORS_PER_FRAME; - - /* Largest number of frames was can transfer at once is 64k-1. For - some drives we need to limit this even more. */ - nframes = MIN (nframes, (CDROM_CONFIG_FLAGS (drive)->limit_nframes) ? - (65534 / CD_FRAMESIZE) : 65535); - - /* Set up the command */ - memset (&pc.c, 0, sizeof (pc.c)); - pc.c[0] = GPCMD_READ_10; - pc.c[7] = (nframes >> 8); - pc.c[8] = (nframes & 0xff); - put_unaligned(htonl (frame), (unsigned int *) &pc.c[2]); - - /* Send the command to the drive and return. */ - return cdrom_transfer_packet_command (drive, pc.c, sizeof (pc.c), - &cdrom_read_intr); -} - - -#define IDECD_SEEK_THRESHOLD (1000) /* 1000 blocks */ -#define IDECD_SEEK_TIMER (5 * WAIT_MIN_SLEEP) /* 100 ms */ -#define IDECD_SEEK_TIMEOUT WAIT_CMD /* 10 sec */ - -static ide_startstop_t cdrom_seek_intr (ide_drive_t *drive) -{ - struct cdrom_info *info = drive->driver_data; - int stat; - static int retry = 10; - ide_startstop_t startstop; - - if (cdrom_decode_status (&startstop, drive, 0, &stat)) - return startstop; - CDROM_CONFIG_FLAGS(drive)->seeking = 1; - - if (retry && jiffies - info->start_seek > IDECD_SEEK_TIMER) { - if (--retry == 0) { - printk("%s: disabled DSC seek overlap\n", drive->name); - drive->dsc_overlap = 0; - } - } - return ide_stopped; -} - -static ide_startstop_t cdrom_start_seek_continuation (ide_drive_t *drive) -{ - struct packet_command pc; - struct request *rq = HWGROUP(drive)->rq; - int sector, frame, nskip; - - sector = rq->sector; - nskip = (sector % SECTORS_PER_FRAME); - if (nskip > 0) - sector -= nskip; - frame = sector / SECTORS_PER_FRAME; - - memset (&pc.c, 0, sizeof (pc.c)); - pc.c[0] = GPCMD_SEEK; - put_unaligned(cpu_to_be32(frame), (unsigned int *) &pc.c[2]); - return cdrom_transfer_packet_command (drive, pc.c, sizeof (pc.c), &cdrom_seek_intr); -} - -static ide_startstop_t cdrom_start_seek (ide_drive_t *drive, unsigned int block) -{ - struct cdrom_info *info = drive->driver_data; - - info->dma = 0; - info->start_seek = jiffies; - return cdrom_start_packet_command (drive, 0, cdrom_start_seek_continuation); -} - -/* Fix up a possibly partially-processed request so that we can - start it over entirely, or even put it back on the request queue. */ -static void restore_request (struct request *rq) -{ - if (rq->buffer != rq->bh->b_data) { - int n = (rq->buffer - rq->bh->b_data) / SECTOR_SIZE; - rq->buffer = rq->bh->b_data; - rq->nr_sectors += n; - rq->sector -= n; - } - rq->current_nr_sectors = rq->bh->b_size >> SECTOR_BITS; -} - -/* - * Start a read request from the CD-ROM. - */ -static ide_startstop_t cdrom_start_read (ide_drive_t *drive, unsigned int block) -{ - struct cdrom_info *info = drive->driver_data; - struct request *rq = HWGROUP(drive)->rq; - int minor = MINOR (rq->rq_dev); - - /* If the request is relative to a partition, fix it up to refer to the - absolute address. */ - if ((minor & PARTN_MASK) != 0) { - rq->sector = block; - minor &= ~PARTN_MASK; - rq->rq_dev = MKDEV (MAJOR(rq->rq_dev), minor); - } - - /* We may be retrying this request after an error. Fix up - any weirdness which might be present in the request packet. */ - restore_request (rq); - - /* Satisfy whatever we can of this request from our cached sector. */ - if (cdrom_read_from_buffer(drive)) - return ide_stopped; - - /* Clear the local sector buffer. */ - info->nsectors_buffered = 0; - - /* use dma, if possible. */ - if (drive->using_dma && (rq->sector % SECTORS_PER_FRAME == 0) && - (rq->nr_sectors % SECTORS_PER_FRAME == 0)) - info->dma = 1; - else - info->dma = 0; - - /* Start sending the read request to the drive. */ - return cdrom_start_packet_command(drive, 32768, cdrom_start_read_continuation); -} - -/**************************************************************************** - * Execute all other packet commands. - */ - -/* Forward declarations. */ -static int cdrom_lockdoor(ide_drive_t *drive, int lockflag); - -/* Interrupt routine for packet command completion. */ -static ide_startstop_t cdrom_pc_intr (ide_drive_t *drive) -{ - int ireason, len, stat, thislen; - struct request *rq = HWGROUP(drive)->rq; - struct packet_command *pc = (struct packet_command *)rq->buffer; - struct cdrom_info *info = drive->driver_data; - ide_startstop_t startstop; - - pc->sense_data = &info->sense_data; - - /* Check for errors. */ - if (cdrom_decode_status (&startstop, drive, 0, &stat)) - return startstop; - - /* Read the interrupt reason and the transfer length. */ - ireason = IN_BYTE (IDE_NSECTOR_REG); - len = IN_BYTE (IDE_LCYL_REG) + 256 * IN_BYTE (IDE_HCYL_REG); - - /* If DRQ is clear, the command has completed. - Complain if we still have data left to transfer. */ - if ((stat & DRQ_STAT) == 0) { - /* Some of the trailing request sense fields are optional, and - some drives don't send them. Sigh. */ - if (pc->c[0] == GPCMD_REQUEST_SENSE && - pc->buflen > 0 && - pc->buflen <= 5) { - while (pc->buflen > 0) { - *pc->buffer++ = 0; - --pc->buflen; - } - } - - if (pc->buflen == 0) - cdrom_end_request (1, drive); - else { - /* Comment this out, because this always happens - right after a reset occurs, and it is annoying to - always print expected stuff. */ - /* - printk ("%s: cdrom_pc_intr: data underrun %d\n", - drive->name, pc->buflen); - */ - pc->stat = 1; - cdrom_end_request (1, drive); - } - return ide_stopped; - } - - /* Figure out how much data to transfer. */ - thislen = pc->buflen; - if (thislen > len) thislen = len; - - /* The drive wants to be written to. */ - if ((ireason & 3) == 0) { - /* Transfer the data. */ - atapi_output_bytes (drive, pc->buffer, thislen); - - /* If we haven't moved enough data to satisfy the drive, - add some padding. */ - while (len > thislen) { - int dum = 0; - atapi_output_bytes (drive, &dum, sizeof (dum)); - len -= sizeof (dum); - } - - /* Keep count of how much data we've moved. */ - pc->buffer += thislen; - pc->buflen -= thislen; - } - - /* Same drill for reading. */ - else if ((ireason & 3) == 2) { - - /* Transfer the data. */ - atapi_input_bytes (drive, pc->buffer, thislen); - - /* If we haven't moved enough data to satisfy the drive, - add some padding. */ - while (len > thislen) { - int dum = 0; - atapi_input_bytes (drive, &dum, sizeof (dum)); - len -= sizeof (dum); - } - - /* Keep count of how much data we've moved. */ - pc->buffer += thislen; - pc->buflen -= thislen; - } else { - printk ("%s: cdrom_pc_intr: The drive " - "appears confused (ireason = 0x%2x)\n", - drive->name, ireason); - pc->stat = 1; - } - - /* Now we wait for another interrupt. */ - ide_set_handler (drive, &cdrom_pc_intr, WAIT_CMD, cdrom_timer_expiry); - return ide_started; -} - - -static ide_startstop_t cdrom_do_pc_continuation (ide_drive_t *drive) -{ - struct request *rq = HWGROUP(drive)->rq; - struct packet_command *pc = (struct packet_command *)rq->buffer; - - /* Send the command to the drive and return. */ - return cdrom_transfer_packet_command (drive, pc->c, - sizeof (pc->c), &cdrom_pc_intr); -} - - -static ide_startstop_t cdrom_do_packet_command (ide_drive_t *drive) -{ - int len; - struct request *rq = HWGROUP(drive)->rq; - struct packet_command *pc = (struct packet_command *)rq->buffer; - struct cdrom_info *info = drive->driver_data; - - info->dma = 0; - pc->stat = 0; - len = pc->buflen; - - /* Start sending the command to the drive. */ - return cdrom_start_packet_command (drive, len, cdrom_do_pc_continuation); -} - - -/* Sleep for TIME jiffies. - Not to be called from an interrupt handler. */ -static -void cdrom_sleep (int time) -{ - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(time); -} - -static -int cdrom_queue_packet_command(ide_drive_t *drive, struct packet_command *pc) -{ - int retries = 10; - struct request req; - - /* Start of retry loop. */ - do { - ide_init_drive_cmd (&req); - req.cmd = PACKET_COMMAND; - req.buffer = (char *)pc; - if (ide_do_drive_cmd (drive, &req, ide_wait)) { - printk("%s: do_drive_cmd returned stat=%02x,err=%02x\n", - drive->name, req.buffer[0], req.buffer[1]); - /* FIXME: we should probably abort/retry or something */ - } - if (pc->stat != 0) { - /* The request failed. Retry if it was due to a unit - attention status - (usually means media was changed). */ - struct request_sense *reqbuf = pc->sense_data; - - if (reqbuf->sense_key == UNIT_ATTENTION) - cdrom_saw_media_change (drive); - else if (reqbuf->sense_key == NOT_READY && - reqbuf->asc == 4 && reqbuf->ascq != 4) { - /* The drive is in the process of loading - a disk. Retry, but wait a little to give - the drive time to complete the load. */ - cdrom_sleep (HZ); - } else { - /* Otherwise, don't retry. */ - retries = 0; - } - --retries; - } - - /* End of retry loop. */ - } while (pc->stat != 0 && retries >= 0); - - /* Return an error if the command failed. */ - if (pc->stat) - return -EIO; - - /* The command succeeded. If it was anything other than - a request sense, eject, or door lock command, - and we think that the door is presently unlocked, lock it - again. (The door was probably unlocked via an explicit - CDROMEJECT ioctl.) */ - if (CDROM_STATE_FLAGS (drive)->door_locked == 0 && - (pc->c[0] != GPCMD_TEST_UNIT_READY && - pc->c[0] != GPCMD_REQUEST_SENSE && - pc->c[0] != GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL && - pc->c[0] != GPCMD_START_STOP_UNIT && - pc->c[0] != GPCMD_MODE_SENSE_10 && - pc->c[0] != GPCMD_MODE_SELECT_10)) { - (void) cdrom_lockdoor (drive, 1); - } - return 0; -} - -/**************************************************************************** - * cdrom driver request routine. - */ -static ide_startstop_t -ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, unsigned long block) -{ - ide_startstop_t action; - struct cdrom_info *info = drive->driver_data; - - switch (rq->cmd) { - case READ: { - if (CDROM_CONFIG_FLAGS(drive)->seeking) { - unsigned long elpased = jiffies - info->start_seek; - int stat = GET_STAT(); - - if ((stat & SEEK_STAT) != SEEK_STAT) { - if (elpased < IDECD_SEEK_TIMEOUT) { - ide_stall_queue(drive, IDECD_SEEK_TIMER); - return ide_stopped; - } - printk ("%s: DSC timeout\n", drive->name); - } - CDROM_CONFIG_FLAGS(drive)->seeking = 0; - } - if (IDE_LARGE_SEEK(info->last_block, block, IDECD_SEEK_THRESHOLD) && drive->dsc_overlap) - action = cdrom_start_seek (drive, block); - else - action = cdrom_start_read (drive, block); - info->last_block = block; - return action; - } - - case PACKET_COMMAND: - case REQUEST_SENSE_COMMAND: { - return cdrom_do_packet_command(drive); - } - - case RESET_DRIVE_COMMAND: { - cdrom_end_request(1, drive); - return ide_do_reset(drive); - } - - default: { - printk("ide-cd: bad cmd %d\n", rq -> cmd); - cdrom_end_request(0, drive); - return ide_stopped; - } - } -} - - - -/**************************************************************************** - * Ioctl handling. - * - * Routines which queue packet commands take as a final argument a pointer - * to a request_sense struct. If execution of the command results - * in an error with a CHECK CONDITION status, this structure will be filled - * with the results of the subsequent request sense command. The pointer - * can also be NULL, in which case no sense information is returned. - */ - -#if ! STANDARD_ATAPI -static inline -int bin2bcd (int x) -{ - return (x%10) | ((x/10) << 4); -} - - -static inline -int bcd2bin (int x) -{ - return (x >> 4) * 10 + (x & 0x0f); -} - -static -void msf_from_bcd (struct atapi_msf *msf) -{ - msf->minute = bcd2bin (msf->minute); - msf->second = bcd2bin (msf->second); - msf->frame = bcd2bin (msf->frame); -} - -#endif /* not STANDARD_ATAPI */ - - -static inline -void lba_to_msf (int lba, byte *m, byte *s, byte *f) -{ - lba += CD_MSF_OFFSET; - lba &= 0xffffff; /* negative lbas use only 24 bits */ - *m = lba / (CD_SECS * CD_FRAMES); - lba %= (CD_SECS * CD_FRAMES); - *s = lba / CD_FRAMES; - *f = lba % CD_FRAMES; -} - - -static inline -int msf_to_lba (byte m, byte s, byte f) -{ - return (((m * CD_SECS) + s) * CD_FRAMES + f) - CD_MSF_OFFSET; -} - -static int cdrom_check_status (ide_drive_t *drive) -{ - struct packet_command pc; - struct cdrom_info *info = drive->driver_data; - struct cdrom_device_info *cdi = &info->devinfo; - - memset(&pc, 0, sizeof(pc)); - - pc.c[0] = GPCMD_TEST_UNIT_READY; - -#if ! STANDARD_ATAPI - /* the Sanyo 3 CD changer uses byte 7 of TEST_UNIT_READY to - switch CDs instead of supporting the LOAD_UNLOAD opcode */ - - pc.c[7] = cdi->sanyo_slot % 3; -#endif /* not STANDARD_ATAPI */ - - return cdrom_queue_packet_command(drive, &pc); -} - - -/* Lock the door if LOCKFLAG is nonzero; unlock it otherwise. */ -static int -cdrom_lockdoor(ide_drive_t *drive, int lockflag) -{ - struct request_sense *sense; - struct packet_command pc; - int stat; - - /* If the drive cannot lock the door, just pretend. */ - if (CDROM_CONFIG_FLAGS (drive)->no_doorlock) - stat = 0; - else { - memset(&pc, 0, sizeof(pc)); - pc.c[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL; - pc.c[4] = (lockflag != 0); - stat = cdrom_queue_packet_command (drive, &pc); - } - - sense = pc.sense_data; - - /* If we got an illegal field error, the drive - probably cannot lock the door. */ - if (stat != 0 && - sense->sense_key == ILLEGAL_REQUEST && - (sense->asc == 0x24 || sense->asc == 0x20)) { - printk ("%s: door locking not supported\n", - drive->name); - CDROM_CONFIG_FLAGS (drive)->no_doorlock = 1; - stat = 0; - } - - /* no medium, that's alright. */ - if (stat != 0 && sense->sense_key == NOT_READY && sense->asc == 0x3a) - stat = 0; - - if (stat == 0) - CDROM_STATE_FLAGS (drive)->door_locked = lockflag; - - return stat; -} - - -/* Eject the disk if EJECTFLAG is 0. - If EJECTFLAG is 1, try to reload the disk. */ -static int cdrom_eject(ide_drive_t *drive, int ejectflag) -{ - struct packet_command pc; - - if (CDROM_CONFIG_FLAGS(drive)->no_eject && !ejectflag) - return -EDRIVE_CANT_DO_THIS; - - /* reload fails on some drives, if the tray is locked */ - if (CDROM_STATE_FLAGS(drive)->door_locked && ejectflag) - return 0; - - memset(&pc, 0, sizeof (pc)); - - pc.c[0] = GPCMD_START_STOP_UNIT; - pc.c[4] = 0x02 + (ejectflag != 0); - return cdrom_queue_packet_command (drive, &pc); -} - -static int cdrom_read_capacity(ide_drive_t *drive, unsigned *capacity) -{ - struct { - __u32 lba; - __u32 blocklen; - } capbuf; - - int stat; - struct packet_command pc; - - memset(&pc, 0, sizeof (pc)); - - pc.c[0] = GPCMD_READ_CDVD_CAPACITY; - pc.buffer = (char *)&capbuf; - pc.buflen = sizeof(capbuf); - - stat = cdrom_queue_packet_command(drive, &pc); - if (stat == 0) - *capacity = be32_to_cpu(capbuf.lba); - - return stat; -} - -static int cdrom_read_tocentry(ide_drive_t *drive, int trackno, int msf_flag, - int format, char *buf, int buflen) -{ - struct packet_command pc; - - memset(&pc, 0, sizeof(pc)); - - pc.buffer = buf; - pc.buflen = buflen; - 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); - - if (msf_flag) - pc.c[1] = 2; - - return cdrom_queue_packet_command (drive, &pc); -} - - -/* Try to read the entire TOC for the disk into our internal buffer. */ -static int cdrom_read_toc (ide_drive_t *drive) -{ - int stat, ntracks, i; - struct cdrom_info *info = drive->driver_data; - struct atapi_toc *toc = info->toc; - int minor = drive->select.b.unit << PARTN_BITS; - struct { - struct atapi_toc_header hdr; - struct atapi_toc_entry ent; - } ms_tmp; - - if (toc == NULL) { - /* Try to allocate space. */ - toc = (struct atapi_toc *) kmalloc (sizeof (struct atapi_toc), - GFP_KERNEL); - info->toc = toc; - if (toc == NULL) { - printk ("%s: No cdrom TOC buffer!\n", drive->name); - return -ENOMEM; - } - } - - /* Check to see if the existing data is still valid. - If it is, just return. */ - if (CDROM_STATE_FLAGS (drive)->toc_valid) - (void) cdrom_check_status(drive); - - if (CDROM_STATE_FLAGS (drive)->toc_valid) return 0; - - /* First read just the header, so we know how long the TOC is. */ - stat = cdrom_read_tocentry (drive, 0, 1, 0, (char *)&toc->hdr, - sizeof (struct atapi_toc_header)); - if (stat) return stat; - -#if ! STANDARD_ATAPI - if (CDROM_CONFIG_FLAGS (drive)->toctracks_as_bcd) { - toc->hdr.first_track = bcd2bin (toc->hdr.first_track); - toc->hdr.last_track = bcd2bin (toc->hdr.last_track); - } -#endif /* not STANDARD_ATAPI */ - - ntracks = toc->hdr.last_track - toc->hdr.first_track + 1; - if (ntracks <= 0) return -EIO; - if (ntracks > MAX_TRACKS) ntracks = MAX_TRACKS; - - /* Now read the whole schmeer. */ - stat = cdrom_read_tocentry (drive, toc->hdr.first_track, 1, 0, (char *)&toc->hdr, - sizeof (struct atapi_toc_header) + - (ntracks + 1) * - sizeof (struct atapi_toc_entry)); - - if (stat && toc->hdr.first_track > 1) { - /* Cds with CDI tracks only don't have any TOC entries, - despite of this the returned values are - first_track == last_track = number of CDI tracks + 1, - so that this case is indistinguishable from the same - layout plus an additional audio track. - If we get an error for the regular case, we assume - a CDI without additional audio tracks. In this case - the readable TOC is empty (CDI tracks are not included) - and only holds the Leadout entry. Heiko Eißfeldt */ - ntracks = 0; - stat = cdrom_read_tocentry (drive, CDROM_LEADOUT, 1, - 0, (char *)&toc->hdr, - sizeof (struct atapi_toc_header) + - (ntracks+1) * - sizeof (struct atapi_toc_entry)); - if (stat) { - return stat; - } -#if ! STANDARD_ATAPI - if (CDROM_CONFIG_FLAGS (drive)->toctracks_as_bcd) { - toc->hdr.first_track = bin2bcd(CDROM_LEADOUT); - toc->hdr.last_track = bin2bcd(CDROM_LEADOUT); - } else -#endif /* not STANDARD_ATAPI */ - { - toc->hdr.first_track = CDROM_LEADOUT; - toc->hdr.last_track = CDROM_LEADOUT; - } - } else if (stat) { - return stat; - } - if (stat) return stat; - - toc->hdr.toc_length = ntohs (toc->hdr.toc_length); - -#if ! STANDARD_ATAPI - if (CDROM_CONFIG_FLAGS (drive)->toctracks_as_bcd) { - toc->hdr.first_track = bcd2bin (toc->hdr.first_track); - toc->hdr.last_track = bcd2bin (toc->hdr.last_track); - } -#endif /* not STANDARD_ATAPI */ - - for (i=0; i<=ntracks; i++) { -#if ! STANDARD_ATAPI - if (CDROM_CONFIG_FLAGS (drive)->tocaddr_as_bcd) { - if (CDROM_CONFIG_FLAGS (drive)->toctracks_as_bcd) - toc->ent[i].track = bcd2bin (toc->ent[i].track); - msf_from_bcd (&toc->ent[i].addr.msf); - } -#endif /* not STANDARD_ATAPI */ - toc->ent[i].addr.lba = msf_to_lba (toc->ent[i].addr.msf.minute, - toc->ent[i].addr.msf.second, - toc->ent[i].addr.msf.frame); - } - - /* Read the multisession information. */ - if (toc->hdr.first_track != CDROM_LEADOUT) { - /* Read the multisession information. */ - stat = cdrom_read_tocentry (drive, 0, 1, 1, - (char *)&ms_tmp, sizeof (ms_tmp)); - if (stat) return stat; - } else { - ms_tmp.ent.addr.msf.minute = 0; - ms_tmp.ent.addr.msf.second = 2; - ms_tmp.ent.addr.msf.frame = 0; - ms_tmp.hdr.first_track = ms_tmp.hdr.last_track = CDROM_LEADOUT; - } - -#if ! STANDARD_ATAPI - if (CDROM_CONFIG_FLAGS (drive)->tocaddr_as_bcd) - msf_from_bcd (&ms_tmp.ent.addr.msf); -#endif /* not STANDARD_ATAPI */ - - toc->last_session_lba = msf_to_lba (ms_tmp.ent.addr.msf.minute, - ms_tmp.ent.addr.msf.second, - ms_tmp.ent.addr.msf.frame); - - toc->xa_flag = (ms_tmp.hdr.first_track != ms_tmp.hdr.last_track); - - /* Now try to get the total cdrom capacity. */ -#if 0 - stat = cdrom_get_last_written(MKDEV(HWIF(drive)->major, minor), - (long *)&toc->capacity); - if (stat) -#endif - stat = cdrom_read_capacity (drive, &toc->capacity); - if (stat) toc->capacity = 0x1fffff; - - /* for general /dev/cdrom like mounting, one big disc */ - drive->part[0].nr_sects = toc->capacity * SECTORS_PER_FRAME; - HWIF(drive)->gd->sizes[minor] = (toc->capacity * SECTORS_PER_FRAME) >> - (BLOCK_SIZE_BITS - 9); - - /* Remember that we've read this stuff. */ - CDROM_STATE_FLAGS (drive)->toc_valid = 1; - - /* should be "if multisession", but it does no harm. */ - if (ntracks == 1) - return 0; - - /* setup each minor to respond to a session */ - minor++; - i = toc->hdr.first_track; - while ((i <= ntracks) && ((minor & CD_PART_MASK) < CD_PART_MAX)) { - drive->part[minor & PARTN_MASK].start_sect = 0; - drive->part[minor & PARTN_MASK].nr_sects = - (toc->ent[i].addr.lba * - SECTORS_PER_FRAME) << (BLOCK_SIZE_BITS - 9); - HWIF(drive)->gd->sizes[minor] = (toc->ent[i].addr.lba * - SECTORS_PER_FRAME) >> (BLOCK_SIZE_BITS - 9); - i++; - minor++; - } - - return 0; -} - - -static int cdrom_read_subchannel(ide_drive_t *drive, int format, char *buf, - int buflen) -{ - struct packet_command pc; - - memset(&pc, 0, sizeof(pc)); - - pc.buffer = buf; - pc.buflen = buflen; - pc.c[0] = GPCMD_READ_SUBCHANNEL; - pc.c[1] = 2; /* MSF addressing */ - pc.c[2] = 0x40; /* request subQ data */ - pc.c[3] = format; - pc.c[7] = (buflen >> 8); - pc.c[8] = (buflen & 0xff); - return cdrom_queue_packet_command(drive, &pc); -} - -/* ATAPI cdrom drives are free to select the speed you request or any slower - rate :-( Requesting too fast a speed will _not_ produce an error. */ -static int cdrom_select_speed (ide_drive_t *drive, int speed) -{ - struct packet_command pc; - memset(&pc, 0, sizeof(pc)); - - if (speed == 0) - speed = 0xffff; /* set to max */ - else - speed *= 177; /* Nx to kbytes/s */ - - pc.c[0] = GPCMD_SET_SPEED; - /* Read Drive speed in kbytes/second MSB */ - pc.c[2] = (speed >> 8) & 0xff; - /* Read Drive speed in kbytes/second LSB */ - pc.c[3] = speed & 0xff; - if ( CDROM_CONFIG_FLAGS(drive)->cd_r || - CDROM_CONFIG_FLAGS(drive)->cd_rw ) { - /* Write Drive speed in kbytes/second MSB */ - pc.c[4] = (speed >> 8) & 0xff; - /* Write Drive speed in kbytes/second LSB */ - pc.c[5] = speed & 0xff; - } - - return cdrom_queue_packet_command (drive, &pc); -} - - -static int cdrom_get_toc_entry(ide_drive_t *drive, int track, - struct atapi_toc_entry **ent) -{ - struct cdrom_info *info = drive->driver_data; - struct atapi_toc *toc = info->toc; - int ntracks; - - /* Check validity of requested track number. */ - ntracks = toc->hdr.last_track - toc->hdr.first_track + 1; - if (toc->hdr.first_track == CDROM_LEADOUT) ntracks = 0; - if (track == CDROM_LEADOUT) - *ent = &toc->ent[ntracks]; - else if (track < toc->hdr.first_track || - track > toc->hdr.last_track) - return -EINVAL; - else - *ent = &toc->ent[track - toc->hdr.first_track]; - - return 0; -} - - - - - -/* the generic packet interface to cdrom.c */ -static int ide_cdrom_packet(struct cdrom_device_info *cdi, - struct cdrom_generic_command *cgc) -{ - struct packet_command pc; - ide_drive_t *drive = (ide_drive_t*) cdi->handle; - - /* here we queue the commands from the uniform CD-ROM - layer. the packet must be complete, as we do not - touch it at all. */ - memset(&pc, 0, sizeof(pc)); - memcpy(pc.c, cgc->cmd, CDROM_PACKET_SIZE); - pc.buffer = cgc->buffer; - pc.buflen = cgc->buflen; - cgc->stat = cdrom_queue_packet_command(drive, &pc); - - /* There was an error, assign sense. */ - if (cgc->stat) - cgc->sense = pc.sense_data; - - return cgc->stat; -} - -static -int ide_cdrom_dev_ioctl (struct cdrom_device_info *cdi, - unsigned int cmd, unsigned long arg) -{ - struct cdrom_generic_command cgc; - char buffer[16]; - int stat; - - init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_UNKNOWN); - - /* These will be moved into the Uniform layer shortly... */ - switch (cmd) { - case CDROMSETSPINDOWN: { - char spindown; - - if (copy_from_user(&spindown, (void *) arg, sizeof(char))) - return -EFAULT; - - if ((stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CDROM_PAGE, 0))) - return stat; - - buffer[11] = (buffer[11] & 0xf0) | (spindown & 0x0f); - - return cdrom_mode_select(cdi, &cgc); - } - - case CDROMGETSPINDOWN: { - char spindown; - - if ((stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CDROM_PAGE, 0))) - return stat; - - spindown = buffer[11] & 0x0f; - - if (copy_to_user((void *) arg, &spindown, sizeof (char))) - return -EFAULT; - - return 0; - } - - default: - return -EINVAL; - } - -} - -static -int ide_cdrom_audio_ioctl (struct cdrom_device_info *cdi, - unsigned int cmd, void *arg) - -{ - ide_drive_t *drive = (ide_drive_t*) cdi->handle; - struct cdrom_info *info = drive->driver_data; - - switch (cmd) { - case CDROMREADTOCHDR: { - int stat; - struct cdrom_tochdr *tochdr = (struct cdrom_tochdr *) arg; - struct atapi_toc *toc; - - /* Make sure our saved TOC is valid. */ - stat = cdrom_read_toc(drive); - if (stat) return stat; - - toc = info->toc; - tochdr->cdth_trk0 = toc->hdr.first_track; - tochdr->cdth_trk1 = toc->hdr.last_track; - - return 0; - } - - case CDROMREADTOCENTRY: { - int stat; - struct cdrom_tocentry *tocentry = (struct cdrom_tocentry*) arg; - struct atapi_toc_entry *toce; - - stat = cdrom_get_toc_entry (drive, tocentry->cdte_track, &toce); - if (stat) return stat; - - tocentry->cdte_ctrl = toce->control; - tocentry->cdte_adr = toce->adr; - if (tocentry->cdte_format == CDROM_MSF) { - lba_to_msf (toce->addr.lba, - &tocentry->cdte_addr.msf.minute, - &tocentry->cdte_addr.msf.second, - &tocentry->cdte_addr.msf.frame); - } else - tocentry->cdte_addr.lba = toce->addr.lba; - - return 0; - } - - default: - return -EINVAL; - } -} - -static -int ide_cdrom_reset (struct cdrom_device_info *cdi) -{ - ide_drive_t *drive = (ide_drive_t*) cdi->handle; - struct request req; - - ide_init_drive_cmd (&req); - req.cmd = RESET_DRIVE_COMMAND; - return ide_do_drive_cmd (drive, &req, ide_wait); -} - - -static -int ide_cdrom_tray_move (struct cdrom_device_info *cdi, int position) -{ - ide_drive_t *drive = (ide_drive_t*) cdi->handle; - - if (position) { - int stat = cdrom_lockdoor (drive, 0); - if (stat) return stat; - } - - return cdrom_eject(drive, !position); -} - -static -int ide_cdrom_lock_door (struct cdrom_device_info *cdi, int lock) -{ - ide_drive_t *drive = (ide_drive_t*) cdi->handle; - return cdrom_lockdoor (drive, lock); -} - -#undef __ACER50__ - -#ifdef __ACER50__ -/* - * the buffer struct used by ide_cdrom_get_capabilities() - */ -struct get_capabilities_buf { - char pad[8]; - struct atapi_capabilities_page cap; /* this is 4 bytes short of ATAPI standard */ - char extra_cap[4]; /* Acer 50X needs the regulation size buffer */ -}; - -static -int ide_cdrom_get_capabilities (struct cdrom_device_info *cdi, struct get_capabilities_buf *buf) -{ - int stat, attempts = 3, buflen = sizeof(*buf); - ide_drive_t *drive = (ide_drive_t*) cdi->handle; - struct cdrom_generic_command cgc; - - /* - * Most drives don't care about the buffer size; - * they return as much info as there's room for. - * But some older drives (?) had trouble with the - * standard size, preferring 4 bytes less. - * And the modern Acer 50X rejects anything smaller - * than the standard size. - */ - if (!(drive->id && !strcmp(drive->id->model,"ATAPI CD ROM DRIVE 50X MAX"))) - buflen -= sizeof(buf->extra_cap); /* for all drives except Acer 50X */ - - do { /* we seem to get stat=0x01,err=0x00 the first time (??) */ - stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CAPABILITIES_PAGE, 0); - if (stat == 0) { - /* - * The ACER/AOpen 24X cdrom has the speed - * fields byte-swapped from the standard. - */ - if (!(drive->id && !drive->id->model[0] && !strncmp(drive->id->fw_rev, "241N", 4))) { - buf->cap.curspeed = ntohs(buf->cap.curspeed); - buf->cap.maxspeed = ntohs(buf->cap.maxspeed); - } - CDROM_STATE_FLAGS (drive)->current_speed = (((unsigned int)buf->cap.curspeed) + (176/2)) / 176; - CDROM_CONFIG_FLAGS(drive)->max_speed = (((unsigned int)buf->cap.maxspeed) + (176/2)) / 176; - return 0; - } - } while (--attempts); - return stat; -} -#endif /* __ACER50__ */ - -static -int ide_cdrom_select_speed (struct cdrom_device_info *cdi, int speed) -{ -#ifndef __ACER50__ - int stat, attempts = 3; - ide_drive_t *drive = (ide_drive_t*) cdi->handle; - struct cdrom_generic_command cgc; - struct { - char pad[8]; - struct atapi_capabilities_page cap; - } buf; -#else - int stat; - ide_drive_t *drive = (ide_drive_t*) cdi->handle; - struct cdrom_generic_command cgc; - struct get_capabilities_buf buf; -#endif /* __ACER50__ */ - - if ((stat = cdrom_select_speed (drive, speed)) < 0) - return stat; - - init_cdrom_command(&cgc, &buf, sizeof(buf), CGC_DATA_UNKNOWN); - -#ifndef __ACER50__ - /* Now with that done, update the speed fields */ - do { /* we seem to get stat=0x01,err=0x00 the first time (??) */ - if (attempts-- <= 0) - return 0; - stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CAPABILITIES_PAGE, 0); - } while (stat); - - /* The ACER/AOpen 24X cdrom has the speed fields byte-swapped */ - if (drive->id && !drive->id->model[0] && !strncmp(drive->id->fw_rev, "241N", 4)) { - CDROM_STATE_FLAGS (drive)->current_speed = - (((unsigned int)buf.cap.curspeed) + (176/2)) / 176; - CDROM_CONFIG_FLAGS (drive)->max_speed = - (((unsigned int)buf.cap.maxspeed) + (176/2)) / 176; - } else { - CDROM_STATE_FLAGS (drive)->current_speed = - (ntohs(buf.cap.curspeed) + (176/2)) / 176; - CDROM_CONFIG_FLAGS (drive)->max_speed = - (ntohs(buf.cap.maxspeed) + (176/2)) / 176; - } -#else - if (ide_cdrom_get_capabilities(cdi,&buf)) - return 0; -#endif /* __ACER50__ */ - - cdi->speed = CDROM_STATE_FLAGS (drive)->current_speed; - return 0; -} - -static -int ide_cdrom_drive_status (struct cdrom_device_info *cdi, int slot_nr) -{ - ide_drive_t *drive = (ide_drive_t*) cdi->handle; - struct cdrom_info *info = drive->driver_data; - - if (slot_nr == CDSL_CURRENT) { - struct request_sense *sense = &info->sense_data; - int stat = cdrom_check_status(drive); - if (stat == 0 || sense->sense_key == UNIT_ATTENTION) - return CDS_DISC_OK; - - if (sense->sense_key == NOT_READY && sense->asc == 0x04 && - sense->ascq == 0x04) - return CDS_DISC_OK; - - if (sense->sense_key == NOT_READY) { - /* ATAPI doesn't have anything that can help - us decide whether the drive is really - emtpy or the tray is just open. irk. */ - return CDS_TRAY_OPEN; - } - - return CDS_DRIVE_NOT_READY; - } else { - return -EINVAL; - } -} - -static -int ide_cdrom_get_last_session (struct cdrom_device_info *cdi, - struct cdrom_multisession *ms_info) -{ - struct atapi_toc *toc; - ide_drive_t *drive = (ide_drive_t*) cdi->handle; - struct cdrom_info *info = drive->driver_data; - - toc = info->toc; - ms_info->addr.lba = toc->last_session_lba; - ms_info->xa_flag = toc->xa_flag; - - return 0; -} - -static -int ide_cdrom_get_mcn (struct cdrom_device_info *cdi, - struct cdrom_mcn *mcn_info) -{ - int stat; - char mcnbuf[24]; - ide_drive_t *drive = (ide_drive_t*) cdi->handle; - -/* get MCN */ - if ((stat = cdrom_read_subchannel(drive, 2, mcnbuf, sizeof (mcnbuf)))) - return stat; - - memcpy (mcn_info->medium_catalog_number, mcnbuf+9, - sizeof (mcn_info->medium_catalog_number)-1); - mcn_info->medium_catalog_number[sizeof (mcn_info->medium_catalog_number)-1] - = '\0'; - - return 0; -} - - - -/**************************************************************************** - * Other driver requests (open, close, check media change). - */ - -static -int ide_cdrom_check_media_change_real (struct cdrom_device_info *cdi, - int slot_nr) -{ - ide_drive_t *drive = (ide_drive_t*) cdi->handle; - - if (slot_nr == CDSL_CURRENT) { - (void) cdrom_check_status(drive); - CDROM_STATE_FLAGS (drive)->media_changed = 0; - return CDROM_STATE_FLAGS (drive)->media_changed; - } else { - return -EINVAL; - } -} - - -static -int ide_cdrom_open_real (struct cdrom_device_info *cdi, int purpose) -{ - return 0; -} - - -/* - * Close down the device. Invalidate all cached blocks. - */ - -static -void ide_cdrom_release_real (struct cdrom_device_info *cdi) -{ -} - - - -/**************************************************************************** - * Device initialization. - */ - -static -struct cdrom_device_ops ide_cdrom_dops = { - ide_cdrom_open_real, /* open */ - ide_cdrom_release_real, /* release */ - ide_cdrom_drive_status, /* drive_status */ - ide_cdrom_check_media_change_real, /* media_changed */ - ide_cdrom_tray_move, /* tray_move */ - ide_cdrom_lock_door, /* lock_door */ - ide_cdrom_select_speed, /* select_speed */ - NULL, /* select_disc */ - ide_cdrom_get_last_session, /* get_last_session */ - ide_cdrom_get_mcn, /* get_mcn */ - ide_cdrom_reset, /* reset */ - ide_cdrom_audio_ioctl, /* audio_ioctl */ - ide_cdrom_dev_ioctl, /* dev_ioctl */ - CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | CDC_SELECT_SPEED - | CDC_SELECT_DISC | CDC_MULTI_SESSION | CDC_MCN - | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | CDC_RESET | CDC_IOCTLS - | CDC_DRIVE_STATUS | CDC_CD_R | CDC_CD_RW | CDC_DVD - | CDC_DVD_R| CDC_DVD_RAM | CDC_GENERIC_PACKET, /* capability */ - 0, /* n_minors */ - ide_cdrom_packet -}; - -static int ide_cdrom_register (ide_drive_t *drive, int nslots) -{ - struct cdrom_info *info = drive->driver_data; - struct cdrom_device_info *devinfo = &info->devinfo; - int minor = (drive->select.b.unit)<<PARTN_BITS; - - devinfo->dev = MKDEV (HWIF(drive)->major, minor | CD_PART_MASK); - devinfo->ops = &ide_cdrom_dops; - devinfo->mask = 0; - *(int *)&devinfo->speed = CDROM_STATE_FLAGS (drive)->current_speed; - *(int *)&devinfo->capacity = nslots; - devinfo->handle = (void *) drive; - strcpy(devinfo->name, drive->name); - - /* set capability mask to match the probe. */ - if (!CDROM_CONFIG_FLAGS (drive)->cd_r) - devinfo->mask |= CDC_CD_R; - if (!CDROM_CONFIG_FLAGS (drive)->cd_rw) - devinfo->mask |= CDC_CD_RW; - if (!CDROM_CONFIG_FLAGS (drive)->dvd) - devinfo->mask |= CDC_DVD; - if (!CDROM_CONFIG_FLAGS (drive)->dvd_r) - devinfo->mask |= CDC_DVD_R; - if (!CDROM_CONFIG_FLAGS (drive)->dvd_ram) - devinfo->mask |= CDC_DVD_RAM; - if (!CDROM_CONFIG_FLAGS (drive)->is_changer) - devinfo->mask |= CDC_SELECT_DISC; - if (!CDROM_CONFIG_FLAGS (drive)->audio_play) - devinfo->mask |= CDC_PLAY_AUDIO; - if (!CDROM_CONFIG_FLAGS (drive)->close_tray) - devinfo->mask |= CDC_CLOSE_TRAY; - - devinfo->de = devfs_register (drive->de, "cd", 2, DEVFS_FL_DEFAULT, - HWIF(drive)->major, minor, - S_IFBLK | S_IRUGO | S_IWUGO, 0, 0, - ide_fops, NULL); - - return register_cdrom (devinfo); -} - - -static -int ide_cdrom_probe_capabilities (ide_drive_t *drive) -{ - struct cdrom_info *info = drive->driver_data; - struct cdrom_device_info *cdi = &info->devinfo; -#ifndef __ACER50__ - int stat, nslots = 1, attempts = 3; - struct cdrom_generic_command cgc; - struct { - char pad[8]; - struct atapi_capabilities_page cap; - } buf; -#else - int nslots = 1; - struct cdrom_generic_command cgc; - struct get_capabilities_buf buf; -#endif /* __ACER50__ */ - - if (CDROM_CONFIG_FLAGS (drive)->nec260) { - CDROM_CONFIG_FLAGS (drive)->no_eject = 0; - CDROM_CONFIG_FLAGS (drive)->audio_play = 1; - return nslots; - } - - init_cdrom_command(&cgc, &buf, sizeof(buf), CGC_DATA_UNKNOWN); - /* we have to cheat a little here. the packet will eventually - * be queued with ide_cdrom_packet(), which extracts the - * drive from cdi->handle. Since this device hasn't been - * registered with the Uniform layer yet, it can't do this. - * Same goes for cdi->ops. - */ - cdi->handle = (ide_drive_t *) drive; - cdi->ops = &ide_cdrom_dops; -#ifndef __ACER50__ - /* we seem to get stat=0x01,err=0x00 the first time (??) */ - do { - if (attempts-- <= 0) - return 0; - stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CAPABILITIES_PAGE, 0); - } while (stat); -#else - if (ide_cdrom_get_capabilities(cdi,&buf)) - return 0; -#endif /* __ACER50__ */ - - if (buf.cap.lock == 0) - CDROM_CONFIG_FLAGS (drive)->no_doorlock = 1; - if (buf.cap.eject) - CDROM_CONFIG_FLAGS (drive)->no_eject = 0; - if (buf.cap.cd_r_write) - CDROM_CONFIG_FLAGS (drive)->cd_r = 1; - if (buf.cap.cd_rw_write) - CDROM_CONFIG_FLAGS (drive)->cd_rw = 1; - if (buf.cap.test_write) - CDROM_CONFIG_FLAGS (drive)->test_write = 1; - if (buf.cap.dvd_ram_read || buf.cap.dvd_r_read || buf.cap.dvd_rom) - CDROM_CONFIG_FLAGS (drive)->dvd = 1; - if (buf.cap.dvd_ram_write) - CDROM_CONFIG_FLAGS (drive)->dvd_r = 1; - if (buf.cap.dvd_r_write) - CDROM_CONFIG_FLAGS (drive)->dvd_ram = 1; - if (buf.cap.audio_play) - CDROM_CONFIG_FLAGS (drive)->audio_play = 1; - if (buf.cap.mechtype == 0) - CDROM_CONFIG_FLAGS (drive)->close_tray = 0; - -#if ! STANDARD_ATAPI - if (cdi->sanyo_slot > 0) { - CDROM_CONFIG_FLAGS (drive)->is_changer = 1; - nslots = 3; - } - - else -#endif /* not STANDARD_ATAPI */ - if (buf.cap.mechtype == mechtype_individual_changer || - buf.cap.mechtype == mechtype_cartridge_changer) { - if ((nslots = cdrom_number_of_slots(cdi)) > 1) { - CDROM_CONFIG_FLAGS (drive)->is_changer = 1; - CDROM_CONFIG_FLAGS (drive)->supp_disc_present = 1; - } - } - -#ifndef __ACER50__ - /* The ACER/AOpen 24X cdrom has the speed fields byte-swapped */ - if (drive->id && !drive->id->model[0] && !strncmp(drive->id->fw_rev, "241N", 4)) { - CDROM_STATE_FLAGS (drive)->current_speed = - (((unsigned int)buf.cap.curspeed) + (176/2)) / 176; - CDROM_CONFIG_FLAGS (drive)->max_speed = - (((unsigned int)buf.cap.maxspeed) + (176/2)) / 176; - } else { - CDROM_STATE_FLAGS (drive)->current_speed = - (ntohs(buf.cap.curspeed) + (176/2)) / 176; - CDROM_CONFIG_FLAGS (drive)->max_speed = - (ntohs(buf.cap.maxspeed) + (176/2)) / 176; - } -#endif /* __ACER50__ */ - - /* don't print speed if the drive reported 0. - */ - printk("%s: ATAPI", drive->name); - if (CDROM_CONFIG_FLAGS(drive)->max_speed) - printk(" %dX", CDROM_CONFIG_FLAGS(drive)->max_speed); - printk(" %s", CDROM_CONFIG_FLAGS(drive)->dvd ? "DVD-ROM" : "CD-ROM"); - - if (CDROM_CONFIG_FLAGS (drive)->dvd_r|CDROM_CONFIG_FLAGS (drive)->dvd_ram) - printk (" DVD%s%s", - (CDROM_CONFIG_FLAGS (drive)->dvd_r)? "-R" : "", - (CDROM_CONFIG_FLAGS (drive)->dvd_ram)? "AM" : ""); - - if (CDROM_CONFIG_FLAGS (drive)->cd_r|CDROM_CONFIG_FLAGS (drive)->cd_rw) - printk (" CD%s%s", - (CDROM_CONFIG_FLAGS (drive)->cd_r)? "-R" : "", - (CDROM_CONFIG_FLAGS (drive)->cd_rw)? "/RW" : ""); - - if (CDROM_CONFIG_FLAGS (drive)->is_changer) - printk (" changer w/%d slots", nslots); - else - printk (" drive"); - - printk (", %dkB Cache", be16_to_cpu(buf.cap.buffer_size)); - - if (drive->using_dma) { - if ((drive->id->field_valid & 4) && - (drive->id->hw_config & 0x2000) && - (HWIF(drive)->udma_four) && - (drive->id->dma_ultra & (drive->id->dma_ultra >> 11) & 3)) { - printk(", UDMA(66)"); /* UDMA BIOS-enabled! */ - } else if ((drive->id->field_valid & 4) && - (drive->id->dma_ultra & (drive->id->dma_ultra >> 8) & 7)) { - printk(", UDMA(33)"); /* UDMA BIOS-enabled! */ - } else if (drive->id->field_valid & 4) { - printk(", (U)DMA"); /* Can be BIOS-enabled! */ - } else { - printk(", DMA"); - } - } - printk("\n"); - - return nslots; -} - -static void ide_cdrom_add_settings(ide_drive_t *drive) -{ - int major = HWIF(drive)->major; - int minor = drive->select.b.unit << PARTN_BITS; - - ide_add_setting(drive, "breada_readahead", SETTING_RW, BLKRAGET, BLKRASET, TYPE_INT, 0, 255, 1, 2, &read_ahead[major], NULL); - ide_add_setting(drive, "file_readahead", SETTING_RW, BLKFRAGET, BLKFRASET, TYPE_INTA, 0, INT_MAX, 1, 1024, &max_readahead[major][minor], NULL); - ide_add_setting(drive, "max_kb_per_request", SETTING_RW, BLKSECTGET, BLKSECTSET, TYPE_INTA, 1, 255, 1, 2, &max_sectors[major][minor], NULL); - ide_add_setting(drive, "dsc_overlap", SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->dsc_overlap, NULL); -} - -static -int ide_cdrom_setup (ide_drive_t *drive) -{ - struct cdrom_info *info = drive->driver_data; - struct cdrom_device_info *cdi = &info->devinfo; - int minor = drive->select.b.unit << PARTN_BITS; - int nslots; - - set_device_ro(MKDEV(HWIF(drive)->major, minor), 1); - set_blocksize(MKDEV(HWIF(drive)->major, minor), CD_FRAMESIZE); - - drive->special.all = 0; - drive->ready_stat = 0; - - CDROM_STATE_FLAGS (drive)->media_changed = 1; - CDROM_STATE_FLAGS (drive)->toc_valid = 0; - CDROM_STATE_FLAGS (drive)->door_locked = 0; - -#if NO_DOOR_LOCKING - CDROM_CONFIG_FLAGS (drive)->no_doorlock = 1; -#else - CDROM_CONFIG_FLAGS (drive)->no_doorlock = 0; -#endif - - if (drive->id != NULL) - CDROM_CONFIG_FLAGS (drive)->drq_interrupt = - ((drive->id->config & 0x0060) == 0x20); - else - CDROM_CONFIG_FLAGS (drive)->drq_interrupt = 0; - - CDROM_CONFIG_FLAGS (drive)->is_changer = 0; - CDROM_CONFIG_FLAGS (drive)->cd_r = 0; - CDROM_CONFIG_FLAGS (drive)->cd_rw = 0; - CDROM_CONFIG_FLAGS (drive)->test_write = 0; - CDROM_CONFIG_FLAGS (drive)->dvd = 0; - CDROM_CONFIG_FLAGS (drive)->dvd_r = 0; - CDROM_CONFIG_FLAGS (drive)->dvd_ram = 0; - CDROM_CONFIG_FLAGS (drive)->no_eject = 1; - CDROM_CONFIG_FLAGS (drive)->supp_disc_present = 0; - CDROM_CONFIG_FLAGS (drive)->audio_play = 0; - CDROM_CONFIG_FLAGS (drive)->close_tray = 1; - - /* limit transfer size per interrupt. */ - CDROM_CONFIG_FLAGS (drive)->limit_nframes = 0; - if (drive->id != NULL) { - /* a testament to the nice quality of Samsung drives... */ - if (!strcmp(drive->id->model, "SAMSUNG CD-ROM SCR-2430")) - CDROM_CONFIG_FLAGS (drive)->limit_nframes = 1; - else if (!strcmp(drive->id->model, "SAMSUNG CD-ROM SCR-2432")) - CDROM_CONFIG_FLAGS (drive)->limit_nframes = 1; - /* the 3231 model does not support the SET_CD_SPEED command */ - else if (!strcmp(drive->id->model, "SAMSUNG CD-ROM SCR-3231")) - cdi->mask |= CDC_SELECT_SPEED; - } - -#if ! STANDARD_ATAPI - /* by default Sanyo 3 CD changer support is turned off and - ATAPI Rev 2.2+ standard support for CD changers is used */ - cdi->sanyo_slot = 0; - - CDROM_CONFIG_FLAGS (drive)->nec260 = 0; - CDROM_CONFIG_FLAGS (drive)->toctracks_as_bcd = 0; - CDROM_CONFIG_FLAGS (drive)->tocaddr_as_bcd = 0; - CDROM_CONFIG_FLAGS (drive)->playmsf_as_bcd = 0; - CDROM_CONFIG_FLAGS (drive)->subchan_as_bcd = 0; - - if (drive->id != NULL) { - if (strcmp (drive->id->model, "V003S0DS") == 0 && - drive->id->fw_rev[4] == '1' && - drive->id->fw_rev[6] <= '2') { - /* Vertos 300. - Some versions of this drive like to talk BCD. */ - CDROM_CONFIG_FLAGS (drive)->toctracks_as_bcd = 1; - CDROM_CONFIG_FLAGS (drive)->tocaddr_as_bcd = 1; - CDROM_CONFIG_FLAGS (drive)->playmsf_as_bcd = 1; - CDROM_CONFIG_FLAGS (drive)->subchan_as_bcd = 1; - } - - else if (strcmp (drive->id->model, "V006E0DS") == 0 && - drive->id->fw_rev[4] == '1' && - drive->id->fw_rev[6] <= '2') { - /* Vertos 600 ESD. */ - CDROM_CONFIG_FLAGS (drive)->toctracks_as_bcd = 1; - } - - else if (strcmp (drive->id->model, - "NEC CD-ROM DRIVE:260") == 0 && - strncmp (drive->id->fw_rev, "1.01", 4) == 0) { /* FIXME */ - /* Old NEC260 (not R). - This drive was released before the 1.2 version - of the spec. */ - CDROM_CONFIG_FLAGS (drive)->tocaddr_as_bcd = 1; - CDROM_CONFIG_FLAGS (drive)->playmsf_as_bcd = 1; - CDROM_CONFIG_FLAGS (drive)->subchan_as_bcd = 1; - CDROM_CONFIG_FLAGS (drive)->nec260 = 1; - } - - else if (strcmp (drive->id->model, "WEARNES CDD-120") == 0 && - strncmp (drive->id->fw_rev, "A1.1", 4) == 0) { /* FIXME */ - /* Wearnes */ - CDROM_CONFIG_FLAGS (drive)->playmsf_as_bcd = 1; - CDROM_CONFIG_FLAGS (drive)->subchan_as_bcd = 1; - } - - /* Sanyo 3 CD changer uses a non-standard command - for CD changing */ - else if ((strcmp(drive->id->model, "CD-ROM CDR-C3 G") == 0) || - (strcmp(drive->id->model, "CD-ROM CDR-C3G") == 0) || - (strcmp(drive->id->model, "CD-ROM CDR_C36") == 0)) { - /* uses CD in slot 0 when value is set to 3 */ - cdi->sanyo_slot = 3; - } - - - } -#endif /* not STANDARD_ATAPI */ - - info->toc = NULL; - info->buffer = NULL; - info->sector_buffered = 0; - info->nsectors_buffered = 0; - info->changer_info = NULL; - info->last_block = 0; - info->start_seek = 0; - - nslots = ide_cdrom_probe_capabilities (drive); - - if (ide_cdrom_register (drive, nslots)) { - printk ("%s: ide_cdrom_setup failed to register device with the cdrom driver.\n", drive->name); - info->devinfo.handle = NULL; - return 1; - } - ide_cdrom_add_settings(drive); - return 0; -} - -/* Forwarding functions to generic routines. */ -static -int ide_cdrom_ioctl (ide_drive_t *drive, - struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - return cdrom_fops.ioctl (inode, file, cmd, arg); -} - -static -int ide_cdrom_open (struct inode *ip, struct file *fp, ide_drive_t *drive) -{ - struct cdrom_info *info = drive->driver_data; - int rc; - - MOD_INC_USE_COUNT; - if (info->buffer == NULL) - info->buffer = (char *) kmalloc(SECTOR_BUFFER_SIZE, GFP_KERNEL); - rc = cdrom_fops.open (ip, fp); - if (rc) { - drive->usage--; - MOD_DEC_USE_COUNT; - } - return rc; -} - -static -void ide_cdrom_release (struct inode *inode, struct file *file, - ide_drive_t *drive) -{ - cdrom_fops.release (inode, file); - MOD_DEC_USE_COUNT; -} - -static -int ide_cdrom_check_media_change (ide_drive_t *drive) -{ - return cdrom_fops.check_media_change - (MKDEV (HWIF (drive)->major, - (drive->select.b.unit)<<PARTN_BITS)); -} - -static -int ide_cdrom_cleanup(ide_drive_t *drive) -{ - struct cdrom_info *info = drive->driver_data; - struct cdrom_device_info *devinfo = &info->devinfo; - - if (ide_unregister_subdriver (drive)) - return 1; - if (info->buffer != NULL) - kfree(info->buffer); - if (info->toc != NULL) - kfree(info->toc); - if (info->changer_info != NULL) - kfree(info->changer_info); - if (devinfo->handle == drive && unregister_cdrom (devinfo)) - printk ("%s: ide_cdrom_cleanup failed to unregister device from the cdrom driver.\n", drive->name); - kfree(info); - drive->driver_data = NULL; - return 0; -} - -static ide_driver_t ide_cdrom_driver = { - "ide-cdrom", /* name */ - IDECD_VERSION, /* version */ - ide_cdrom, /* media */ - 0, /* busy */ - 1, /* supports_dma */ - 1, /* supports_dsc_overlap */ - ide_cdrom_cleanup, /* cleanup */ - ide_do_rw_cdrom, /* do_request */ - NULL, /* ??? or perhaps cdrom_end_request? */ - ide_cdrom_ioctl, /* ioctl */ - ide_cdrom_open, /* open */ - ide_cdrom_release, /* release */ - ide_cdrom_check_media_change, /* media_change */ - NULL, /* pre_reset */ - NULL, /* capacity */ - NULL, /* special */ - NULL /* proc */ -}; - -int ide_cdrom_init (void); -static ide_module_t ide_cdrom_module = { - IDE_DRIVER_MODULE, - ide_cdrom_init, - &ide_cdrom_driver, - NULL -}; - -/* options */ -char *ignore = NULL; - -#ifdef MODULE -MODULE_PARM(ignore, "s"); -MODULE_DESCRIPTION("ATAPI CD-ROM Driver"); - -void __exit ide_cdrom_exit(void) -{ - ide_drive_t *drive; - int failed = 0; - - while ((drive = ide_scan_devices (ide_cdrom, ide_cdrom_driver.name, &ide_cdrom_driver, failed)) != NULL) - if (ide_cdrom_cleanup (drive)) { - printk ("%s: cleanup_module() called while still busy\n", drive->name); - failed++; - } - ide_unregister_module (&ide_cdrom_module); -} -#endif /* MODULE */ - -int ide_cdrom_init (void) -{ - ide_drive_t *drive; - struct cdrom_info *info; - int failed = 0; - - MOD_INC_USE_COUNT; - while ((drive = ide_scan_devices (ide_cdrom, ide_cdrom_driver.name, NULL, failed++)) != NULL) { - /* skip drives that we were told to ignore */ - if (ignore != NULL) { - if (strstr(ignore, drive->name)) { - printk("ide-cd: ignoring drive %s\n", drive->name); - continue; - } - } - if (drive->scsi) { - printk("ide-cd: passing drive %s to ide-scsi emulation.\n", drive->name); - continue; - } - info = (struct cdrom_info *) kmalloc (sizeof (struct cdrom_info), GFP_KERNEL); - if (info == NULL) { - printk ("%s: Can't allocate a cdrom structure\n", drive->name); - continue; - } - if (ide_register_subdriver (drive, &ide_cdrom_driver, IDE_SUBDRIVER_VERSION)) { - printk ("%s: Failed to register the driver with ide.c\n", drive->name); - kfree (info); - continue; - } - memset (info, 0, sizeof (struct cdrom_info)); - drive->driver_data = info; - DRIVER(drive)->busy++; - if (ide_cdrom_setup (drive)) { - DRIVER(drive)->busy--; - if (ide_cdrom_cleanup (drive)) - printk ("%s: ide_cdrom_cleanup failed in ide_cdrom_init\n", drive->name); - continue; - } - DRIVER(drive)->busy--; - failed--; - } - ide_register_module(&ide_cdrom_module); - MOD_DEC_USE_COUNT; - return 0; -} - -module_init(ide_cdrom_init); -module_exit(ide_cdrom_exit); diff --git a/drivers/block/ide-cd.h b/drivers/block/ide-cd.h deleted file mode 100644 index 1eb48ef6c..000000000 --- a/drivers/block/ide-cd.h +++ /dev/null @@ -1,736 +0,0 @@ -/* - * linux/drivers/block/ide_cd.h - * - * Copyright (C) 1996-98 Erik Andersen - * Copyright (C) 1998-2000 Jens Axboe - */ -#ifndef _IDE_CD_H -#define _IDE_CD_H - -#include <linux/cdrom.h> -#include <asm/byteorder.h> - -/* Turn this on to have the driver print out the meanings of the - ATAPI error codes. This will use up additional kernel-space - memory, though. */ - -#ifndef VERBOSE_IDE_CD_ERRORS -#define VERBOSE_IDE_CD_ERRORS 1 -#endif - - -/* Turning this on will remove code to work around various nonstandard - ATAPI implementations. If you know your drive follows the standard, - this will give you a slightly smaller kernel. */ - -#ifndef STANDARD_ATAPI -#define STANDARD_ATAPI 0 -#endif - - -/* Turning this on will disable the door-locking functionality. - This is apparently needed for supermount. */ - -#ifndef NO_DOOR_LOCKING -#define NO_DOOR_LOCKING 0 -#endif - -/************************************************************************/ - -#define SECTOR_SIZE 512 -#define SECTOR_BITS 9 -#define SECTORS_PER_FRAME (CD_FRAMESIZE / SECTOR_SIZE) -#define SECTOR_BUFFER_SIZE (CD_FRAMESIZE * 32) -#define SECTORS_BUFFER (SECTOR_BUFFER_SIZE / SECTOR_SIZE) - -#define MIN(a,b) ((a) < (b) ? (a) : (b)) - -/* special command codes for strategy routine. */ -#define PACKET_COMMAND 4315 -#define REQUEST_SENSE_COMMAND 4316 -#define RESET_DRIVE_COMMAND 4317 - - -/* Configuration flags. These describe the capabilities of the drive. - They generally do not change after initialization, unless we learn - more about the drive from stuff failing. */ -struct ide_cd_config_flags { - __u8 drq_interrupt : 1; /* Device sends an interrupt when ready - for a packet command. */ - __u8 no_doorlock : 1; /* Drive cannot lock the door. */ - __u8 no_eject : 1; /* Drive cannot eject the disc. */ - __u8 nec260 : 1; /* Drive is a pre-1.2 NEC 260 drive. */ - __u8 playmsf_as_bcd : 1; /* PLAYMSF command takes BCD args. */ - __u8 tocaddr_as_bcd : 1; /* TOC addresses are in BCD. */ - __u8 toctracks_as_bcd : 1; /* TOC track numbers are in BCD. */ - __u8 subchan_as_bcd : 1; /* Subchannel info is in BCD. */ - __u8 is_changer : 1; /* Drive is a changer. */ - __u8 cd_r : 1; /* Drive can write to CD-R media . */ - __u8 cd_rw : 1; /* Drive can write to CD-R/W media . */ - __u8 dvd : 1; /* Drive is a DVD-ROM */ - __u8 dvd_r : 1; /* Drive can write DVD-R */ - __u8 dvd_ram : 1; /* Drive can write DVD-RAM */ - __u8 test_write : 1; /* Drive can fake writes */ - __u8 supp_disc_present : 1; /* Changer can report exact contents - of slots. */ - __u8 limit_nframes : 1; /* Drive does not provide data in - multiples of SECTOR_SIZE when more - than one interrupt is needed. */ - __u8 seeking : 1; /* Seeking in progress */ - __u8 audio_play : 1; /* can do audio related commands */ - __u8 close_tray : 1; /* can close the tray */ - __u8 writing : 1; /* pseudo write in progress */ - __u8 reserved : 3; - byte max_speed; /* Max speed of the drive */ -}; -#define CDROM_CONFIG_FLAGS(drive) (&(((struct cdrom_info *)(drive->driver_data))->config_flags)) - - -/* State flags. These give information about the current state of the - drive, and will change during normal operation. */ -struct ide_cd_state_flags { - __u8 media_changed : 1; /* Driver has noticed a media change. */ - __u8 toc_valid : 1; /* Saved TOC information is current. */ - __u8 door_locked : 1; /* We think that the drive door is locked. */ - __u8 writing : 1; /* the drive is currently writing */ - __u8 reserved : 4; - byte current_speed; /* Current speed of the drive */ -}; - -#define CDROM_STATE_FLAGS(drive) (&(((struct cdrom_info *)(drive->driver_data))->state_flags)) - -struct packet_command { - char *buffer; - int buflen; - int stat; - struct request_sense *sense_data; - unsigned char c[12]; -}; - -/* Structure of a MSF cdrom address. */ -struct atapi_msf { - byte reserved; - byte minute; - byte second; - byte frame; -}; - -/* Space to hold the disk TOC. */ -#define MAX_TRACKS 99 -struct atapi_toc_header { - unsigned short toc_length; - byte first_track; - byte last_track; -}; - -struct atapi_toc_entry { - byte reserved1; -#if defined(__BIG_ENDIAN_BITFIELD) - __u8 adr : 4; - __u8 control : 4; -#elif defined(__LITTLE_ENDIAN_BITFIELD) - __u8 control : 4; - __u8 adr : 4; -#else -#error "Please fix <asm/byteorder.h>" -#endif - byte track; - byte reserved2; - union { - unsigned lba; - struct atapi_msf msf; - } addr; -}; - -struct atapi_toc { - int last_session_lba; - int xa_flag; - unsigned capacity; - struct atapi_toc_header hdr; - struct atapi_toc_entry ent[MAX_TRACKS+1]; - /* One extra for the leadout. */ -}; - - -/* This structure is annoyingly close to, but not identical with, - the cdrom_subchnl structure from cdrom.h. */ -struct atapi_cdrom_subchnl { - u_char acdsc_reserved; - u_char acdsc_audiostatus; - u_short acdsc_length; - u_char acdsc_format; - -#if defined(__BIG_ENDIAN_BITFIELD) - u_char acdsc_ctrl: 4; - u_char acdsc_adr: 4; -#elif defined(__LITTLE_ENDIAN_BITFIELD) - u_char acdsc_adr: 4; - u_char acdsc_ctrl: 4; -#else -#error "Please fix <asm/byteorder.h>" -#endif - u_char acdsc_trk; - u_char acdsc_ind; - union { - struct atapi_msf msf; - int lba; - } acdsc_absaddr; - union { - struct atapi_msf msf; - int lba; - } acdsc_reladdr; -}; - - - -/* This should probably go into cdrom.h along with the other - * generic stuff now in the Mt. Fuji spec. - */ -struct atapi_capabilities_page { -#if defined(__BIG_ENDIAN_BITFIELD) - __u8 parameters_saveable : 1; - __u8 reserved1 : 1; - __u8 page_code : 6; -#elif defined(__LITTLE_ENDIAN_BITFIELD) - __u8 page_code : 6; - __u8 reserved1 : 1; - __u8 parameters_saveable : 1; -#else -#error "Please fix <asm/byteorder.h>" -#endif - - byte page_length; - -#if defined(__BIG_ENDIAN_BITFIELD) - __u8 reserved2 : 2; - /* Drive supports reading of DVD-RAM discs */ - __u8 dvd_ram_read : 1; - /* Drive supports reading of DVD-R discs */ - __u8 dvd_r_read : 1; - /* Drive supports reading of DVD-ROM discs */ - __u8 dvd_rom : 1; - /* Drive supports reading CD-R discs with addressing method 2 */ - __u8 method2 : 1; /* reserved in 1.2 */ - /* Drive can read from CD-R/W (CD-E) discs (orange book, part III) */ - __u8 cd_rw_read : 1; /* reserved in 1.2 */ - /* Drive supports read from CD-R discs (orange book, part II) */ - __u8 cd_r_read : 1; /* reserved in 1.2 */ -#elif defined(__LITTLE_ENDIAN_BITFIELD) - /* Drive supports read from CD-R discs (orange book, part II) */ - __u8 cd_r_read : 1; /* reserved in 1.2 */ - /* Drive can read from CD-R/W (CD-E) discs (orange book, part III) */ - __u8 cd_rw_read : 1; /* reserved in 1.2 */ - /* Drive supports reading CD-R discs with addressing method 2 */ - __u8 method2 : 1; - /* Drive supports reading of DVD-ROM discs */ - __u8 dvd_rom : 1; - /* Drive supports reading of DVD-R discs */ - __u8 dvd_r_read : 1; - /* Drive supports reading of DVD-RAM discs */ - __u8 dvd_ram_read : 1; - __u8 reserved2 : 2; -#else -#error "Please fix <asm/byteorder.h>" -#endif - -#if defined(__BIG_ENDIAN_BITFIELD) - __u8 reserved3 : 2; - /* Drive can write DVD-RAM discs */ - __u8 dvd_ram_write : 1; - /* Drive can write DVD-R discs */ - __u8 dvd_r_write : 1; - __u8 reserved3a : 1; - /* Drive can fake writes */ - __u8 test_write : 1; - /* Drive can write to CD-R/W (CD-E) discs (orange book, part III) */ - __u8 cd_rw_write : 1; /* reserved in 1.2 */ - /* Drive supports write to CD-R discs (orange book, part II) */ - __u8 cd_r_write : 1; /* reserved in 1.2 */ -#elif defined(__LITTLE_ENDIAN_BITFIELD) - /* Drive can write to CD-R discs (orange book, part II) */ - __u8 cd_r_write : 1; /* reserved in 1.2 */ - /* Drive can write to CD-R/W (CD-E) discs (orange book, part III) */ - __u8 cd_rw_write : 1; /* reserved in 1.2 */ - /* Drive can fake writes */ - __u8 test_write : 1; - __u8 reserved3a : 1; - /* Drive can write DVD-R discs */ - __u8 dvd_r_write : 1; - /* Drive can write DVD-RAM discs */ - __u8 dvd_ram_write : 1; - __u8 reserved3 : 2; -#else -#error "Please fix <asm/byteorder.h>" -#endif - -#if defined(__BIG_ENDIAN_BITFIELD) - __u8 reserved4 : 1; - /* Drive can read multisession discs. */ - __u8 multisession : 1; - /* Drive can read mode 2, form 2 data. */ - __u8 mode2_form2 : 1; - /* Drive can read mode 2, form 1 (XA) data. */ - __u8 mode2_form1 : 1; - /* Drive supports digital output on port 2. */ - __u8 digport2 : 1; - /* Drive supports digital output on port 1. */ - __u8 digport1 : 1; - /* Drive can deliver a composite audio/video data stream. */ - __u8 composite : 1; - /* Drive supports audio play operations. */ - __u8 audio_play : 1; -#elif defined(__LITTLE_ENDIAN_BITFIELD) - /* Drive supports audio play operations. */ - __u8 audio_play : 1; - /* Drive can deliver a composite audio/video data stream. */ - __u8 composite : 1; - /* Drive supports digital output on port 1. */ - __u8 digport1 : 1; - /* Drive supports digital output on port 2. */ - __u8 digport2 : 1; - /* Drive can read mode 2, form 1 (XA) data. */ - __u8 mode2_form1 : 1; - /* Drive can read mode 2, form 2 data. */ - __u8 mode2_form2 : 1; - /* Drive can read multisession discs. */ - __u8 multisession : 1; - __u8 reserved4 : 1; -#else -#error "Please fix <asm/byteorder.h>" -#endif - -#if defined(__BIG_ENDIAN_BITFIELD) - __u8 reserved5 : 1; - /* Drive can return Media Catalog Number (UPC) info. */ - __u8 upc : 1; - /* Drive can return International Standard Recording Code info. */ - __u8 isrc : 1; - /* Drive supports C2 error pointers. */ - __u8 c2_pointers : 1; - /* R-W data will be returned deinterleaved and error corrected. */ - __u8 rw_corr : 1; - /* Subchannel reads can return combined R-W information. */ - __u8 rw_supported : 1; - /* Drive can continue a read cdda operation from a loss of streaming.*/ - __u8 cdda_accurate : 1; - /* Drive can read Red Book audio data. */ - __u8 cdda : 1; -#elif defined(__LITTLE_ENDIAN_BITFIELD) - /* Drive can read Red Book audio data. */ - __u8 cdda : 1; - /* Drive can continue a read cdda operation from a loss of streaming.*/ - __u8 cdda_accurate : 1; - /* Subchannel reads can return combined R-W information. */ - __u8 rw_supported : 1; - /* R-W data will be returned deinterleaved and error corrected. */ - __u8 rw_corr : 1; - /* Drive supports C2 error pointers. */ - __u8 c2_pointers : 1; - /* Drive can return International Standard Recording Code info. */ - __u8 isrc : 1; - /* Drive can return Media Catalog Number (UPC) info. */ - __u8 upc : 1; - __u8 reserved5 : 1; -#else -#error "Please fix <asm/byteorder.h>" -#endif - -#if defined(__BIG_ENDIAN_BITFIELD) - /* Drive mechanism types. */ - mechtype_t mechtype : 3; - __u8 reserved6 : 1; - /* Drive can eject a disc or changer cartridge. */ - __u8 eject : 1; - /* State of prevent/allow jumper. */ - __u8 prevent_jumper : 1; - /* Present state of door lock. */ - __u8 lock_state : 1; - /* Drive can lock the door. */ - __u8 lock : 1; -#elif defined(__LITTLE_ENDIAN_BITFIELD) - - /* Drive can lock the door. */ - __u8 lock : 1; - /* Present state of door lock. */ - __u8 lock_state : 1; - /* State of prevent/allow jumper. */ - __u8 prevent_jumper : 1; - /* Drive can eject a disc or changer cartridge. */ - __u8 eject : 1; - __u8 reserved6 : 1; - /* Drive mechanism types. */ - mechtype_t mechtype : 3; -#else -#error "Please fix <asm/byteorder.h>" -#endif - -#if defined(__BIG_ENDIAN_BITFIELD) - __u8 reserved7 : 4; - /* Drive supports software slot selection. */ - __u8 sss : 1; /* reserved in 1.2 */ - /* Changer can report exact contents of slots. */ - __u8 disc_present : 1; /* reserved in 1.2 */ - /* Audio for each channel can be muted independently. */ - __u8 separate_mute : 1; - /* Audio level for each channel can be controlled independently. */ - __u8 separate_volume : 1; -#elif defined(__LITTLE_ENDIAN_BITFIELD) - - /* Audio level for each channel can be controlled independently. */ - __u8 separate_volume : 1; - /* Audio for each channel can be muted independently. */ - __u8 separate_mute : 1; - /* Changer can report exact contents of slots. */ - __u8 disc_present : 1; /* reserved in 1.2 */ - /* Drive supports software slot selection. */ - __u8 sss : 1; /* reserved in 1.2 */ - __u8 reserved7 : 4; -#else -#error "Please fix <asm/byteorder.h>" -#endif - - /* Note: the following four fields are returned in big-endian form. */ - /* Maximum speed (in kB/s). */ - unsigned short maxspeed; - /* Number of discrete volume levels. */ - unsigned short n_vol_levels; - /* Size of cache in drive, in kB. */ - unsigned short buffer_size; - /* Current speed (in kB/s). */ - unsigned short curspeed; - - /* Truncate the structure here, so we don't have headaches reading - from older drives. */ -}; - - -struct atapi_mechstat_header { -#if defined(__BIG_ENDIAN_BITFIELD) - __u8 fault : 1; - __u8 changer_state : 2; - __u8 curslot : 5; -#elif defined(__LITTLE_ENDIAN_BITFIELD) - __u8 curslot : 5; - __u8 changer_state : 2; - __u8 fault : 1; -#else -#error "Please fix <asm/byteorder.h>" -#endif - -#if defined(__BIG_ENDIAN_BITFIELD) - __u8 mech_state : 3; - __u8 door_open : 1; - __u8 reserved1 : 4; -#elif defined(__LITTLE_ENDIAN_BITFIELD) - __u8 reserved1 : 4; - __u8 door_open : 1; - __u8 mech_state : 3; -#else -#error "Please fix <asm/byteorder.h>" -#endif - - byte curlba[3]; - byte nslots; - __u8 short slot_tablelen; -}; - - -struct atapi_slot { -#if defined(__BIG_ENDIAN_BITFIELD) - __u8 disc_present : 1; - __u8 reserved1 : 6; - __u8 change : 1; -#elif defined(__LITTLE_ENDIAN_BITFIELD) - __u8 change : 1; - __u8 reserved1 : 6; - __u8 disc_present : 1; -#else -#error "Please fix <asm/byteorder.h>" -#endif - - byte reserved2[3]; -}; - -struct atapi_changer_info { - struct atapi_mechstat_header hdr; - struct atapi_slot slots[0]; -}; - -/* Extra per-device info for cdrom drives. */ -struct cdrom_info { - - /* Buffer for table of contents. NULL if we haven't allocated - a TOC buffer for this device yet. */ - - struct atapi_toc *toc; - - unsigned long sector_buffered; - unsigned long nsectors_buffered; - unsigned char *buffer; - - /* The result of the last successful request sense command - on this device. */ - struct request_sense sense_data; - - struct request request_sense_request; - struct packet_command request_sense_pc; - int dma; - unsigned long last_block; - unsigned long start_seek; - /* Buffer to hold mechanism status and changer slot table. */ - struct atapi_changer_info *changer_info; - - struct ide_cd_config_flags config_flags; - struct ide_cd_state_flags state_flags; - - /* Per-device info needed by cdrom.c generic driver. */ - struct cdrom_device_info devinfo; -}; - -/**************************************************************************** - * Descriptions of ATAPI error codes. - */ - -#define ARY_LEN(a) ((sizeof(a) / sizeof(a[0]))) - -/* This stuff should be in cdrom.h, since it is now generic... */ - -/* ATAPI sense keys (from table 140 of ATAPI 2.6) */ -#define NO_SENSE 0x00 -#define RECOVERED_ERROR 0x01 -#define NOT_READY 0x02 -#define MEDIUM_ERROR 0x03 -#define HARDWARE_ERROR 0x04 -#define ILLEGAL_REQUEST 0x05 -#define UNIT_ATTENTION 0x06 -#define DATA_PROTECT 0x07 -#define ABORTED_COMMAND 0x0b -#define MISCOMPARE 0x0e - - - -/* This stuff should be in cdrom.h, since it is now generic... */ -#if VERBOSE_IDE_CD_ERRORS - - /* The generic packet command opcodes for CD/DVD Logical Units, - * From Table 57 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */ -const struct { - unsigned short packet_command; - const char * const text; -} packet_command_texts[] = { - { GPCMD_TEST_UNIT_READY, "Test Unit Ready" }, - { GPCMD_REQUEST_SENSE, "Request Sense" }, - { GPCMD_FORMAT_UNIT, "Format Unit" }, - { GPCMD_INQUIRY, "Inquiry" }, - { GPCMD_START_STOP_UNIT, "Start/Stop Unit" }, - { GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL, "Prevent/Allow Medium Removal" }, - { GPCMD_READ_FORMAT_CAPACITIES, "Read Format Capacities" }, - { GPCMD_READ_CDVD_CAPACITY, "Read Cd/Dvd Capacity" }, - { GPCMD_READ_10, "Read 10" }, - { GPCMD_WRITE_10, "Write 10" }, - { GPCMD_SEEK, "Seek" }, - { GPCMD_WRITE_AND_VERIFY_10, "Write and Verify 10" }, - { GPCMD_VERIFY_10, "Verify 10" }, - { GPCMD_FLUSH_CACHE, "Flush Cache" }, - { GPCMD_READ_SUBCHANNEL, "Read Subchannel" }, - { GPCMD_READ_TOC_PMA_ATIP, "Read Table of Contents" }, - { GPCMD_READ_HEADER, "Read Header" }, - { GPCMD_PLAY_AUDIO_10, "Play Audio 10" }, - { GPCMD_GET_CONFIGURATION, "Get Configuration" }, - { GPCMD_PLAY_AUDIO_MSF, "Play Audio MSF" }, - { GPCMD_PLAYAUDIO_TI, "Play Audio TrackIndex" }, - { GPCMD_GET_EVENT_STATUS_NOTIFICATION, "Get Event Status Notification" }, - { GPCMD_PAUSE_RESUME, "Pause/Resume" }, - { GPCMD_STOP_PLAY_SCAN, "Stop Play/Scan" }, - { GPCMD_READ_DISC_INFO, "Read Disc Info" }, - { GPCMD_READ_TRACK_RZONE_INFO, "Read Track Rzone Info" }, - { GPCMD_RESERVE_RZONE_TRACK, "Reserve Rzone Track" }, - { GPCMD_SEND_OPC, "Send OPC" }, - { GPCMD_MODE_SELECT_10, "Mode Select 10" }, - { GPCMD_REPAIR_RZONE_TRACK, "Repair Rzone Track" }, - { GPCMD_MODE_SENSE_10, "Mode Sense 10" }, - { GPCMD_CLOSE_TRACK, "Close Track" }, - { GPCMD_BLANK, "Blank" }, - { GPCMD_SEND_EVENT, "Send Event" }, - { GPCMD_SEND_KEY, "Send Key" }, - { GPCMD_REPORT_KEY, "Report Key" }, - { GPCMD_LOAD_UNLOAD, "Load/Unload" }, - { GPCMD_SET_READ_AHEAD, "Set Read-ahead" }, - { GPCMD_READ_12, "Read 12" }, - { GPCMD_GET_PERFORMANCE, "Get Performance" }, - { GPCMD_SEND_DVD_STRUCTURE, "Send DVD Structure" }, - { GPCMD_READ_DVD_STRUCTURE, "Read DVD Structure" }, - { GPCMD_SET_STREAMING, "Set Streaming" }, - { GPCMD_READ_CD_MSF, "Read CD MSF" }, - { GPCMD_SCAN, "Scan" }, - { GPCMD_SET_SPEED, "Set Speed" }, - { GPCMD_PLAY_CD, "Play CD" }, - { GPCMD_MECHANISM_STATUS, "Mechanism Status" }, - { GPCMD_READ_CD, "Read CD" }, -}; - - - -/* From Table 303 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */ -const char * const sense_key_texts[16] = { - "No sense data", - "Recovered error", - "Not ready", - "Medium error", - "Hardware error", - "Illegal request", - "Unit attention", - "Data protect", - "(reserved)", - "(reserved)", - "(reserved)", - "Aborted command", - "(reserved)", - "(reserved)", - "Miscompare", - "(reserved)", -}; - -/* From Table 304 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */ -const struct { - unsigned long asc_ascq; - const char * const text; -} sense_data_texts[] = { - { 0x000000, "No additional sense information" }, - { 0x000011, "Play operation in progress" }, - { 0x000012, "Play operation paused" }, - { 0x000013, "Play operation successfully completed" }, - { 0x000014, "Play operation stopped due to error" }, - { 0x000015, "No current audio status to return" }, - { 0x010c0a, "Write error - padding blocks added" }, - { 0x011700, "Recovered data with no error correction applied" }, - { 0x011701, "Recovered data with retries" }, - { 0x011702, "Recovered data with positive head offset" }, - { 0x011703, "Recovered data with negative head offset" }, - { 0x011704, "Recovered data with retries and/or CIRC applied" }, - { 0x011705, "Recovered data using previous sector ID" }, - { 0x011800, "Recovered data with error correction applied" }, - { 0x011801, "Recovered data with error correction and retries applied"}, - { 0x011802, "Recovered data - the data was auto-reallocated" }, - { 0x011803, "Recovered data with CIRC" }, - { 0x011804, "Recovered data with L-EC" }, - { 0x015d00, - "Failure prediction threshold exceeded - Predicted logical unit failure" }, - { 0x015d01, - "Failure prediction threshold exceeded - Predicted media failure" }, - { 0x015dff, "Failure prediction threshold exceeded - False" }, - { 0x017301, "Power calibration area almost full" }, - { 0x020400, "Logical unit not ready - cause not reportable" }, - /* Following is misspelled in ATAPI 2.6, _and_ in Mt. Fuji */ - { 0x020401, - "Logical unit not ready - in progress [sic] of becoming ready" }, - { 0x020402, "Logical unit not ready - initializing command required" }, - { 0x020403, "Logical unit not ready - manual intervention required" }, - { 0x020404, "In process of becoming ready - writing" }, - { 0x020600, "No reference position found (media may be upside down)" }, - { 0x023000, "Incompatible medium installed" }, - { 0x023a00, "Medium not present" }, - { 0x025300, "Media load or eject failed" }, - { 0x025700, "Unable to recover table of contents" }, - { 0x030300, "Peripheral device write fault" }, - { 0x030301, "No write current" }, - { 0x030302, "Excessive write errors" }, - { 0x030c00, "Write error" }, - { 0x030c01, "Write error - Recovered with auto reallocation" }, - { 0x030c02, "Write error - auto reallocation failed" }, - { 0x030c03, "Write error - recommend reassignment" }, - { 0x030c04, "Compression check miscompare error" }, - { 0x030c05, "Data expansion occurred during compress" }, - { 0x030c06, "Block not compressible" }, - { 0x030c07, "Write error - recovery needed" }, - { 0x030c08, "Write error - recovery failed" }, - { 0x030c09, "Write error - loss of streaming" }, - { 0x031100, "Unrecovered read error" }, - { 0x031106, "CIRC unrecovered error" }, - { 0x033101, "Format command failed" }, - { 0x033200, "No defect spare location available" }, - { 0x033201, "Defect list update failure" }, - { 0x035100, "Erase failure" }, - { 0x037200, "Session fixation error" }, - { 0x037201, "Session fixation error writin lead-in" }, - { 0x037202, "Session fixation error writin lead-out" }, - { 0x037300, "CD control error" }, - { 0x037302, "Power calibration area is full" }, - { 0x037303, "Power calibration area error" }, - { 0x037304, "Program memory area / RMA update failure" }, - { 0x037305, "Program memory area / RMA is full" }, - { 0x037306, "Program memory area / RMA is (almost) full" }, - - { 0x040200, "No seek complete" }, - { 0x040300, "Write fault" }, - { 0x040900, "Track following error" }, - { 0x040901, "Tracking servo failure" }, - { 0x040902, "Focus servo failure" }, - { 0x040903, "Spindle servo failure" }, - { 0x041500, "Random positioning error" }, - { 0x041501, "Mechanical positioning or changer error" }, - { 0x041502, "Positioning error detected by read of medium" }, - { 0x043c00, "Mechanical positioning or changer error" }, - { 0x044000, "Diagnostic failure on component (ASCQ)" }, - { 0x044400, "Internal CD/DVD logical unit failure" }, - { 0x04b600, "Media load mechanism failed" }, - { 0x051a00, "Parameter list length error" }, - { 0x052000, "Invalid command operation code" }, - { 0x052c00, "Command sequence error" }, - { 0x052100, "Logical block address out of range" }, - { 0x052102, "Invalid address for write" }, - { 0x052400, "Invalid field in command packet" }, - { 0x052600, "Invalid field in parameter list" }, - { 0x052601, "Parameter not supported" }, - { 0x052602, "Parameter value invalid" }, - { 0x052700, "Write protected media" }, - { 0x052c00, "Command sequence error" }, - { 0x052c03, "Current program area is not empty" }, - { 0x052c04, "Current program area is empty" }, - { 0x053001, "Cannot read medium - unknown format" }, - { 0x053002, "Cannot read medium - incompatible format" }, - { 0x053900, "Saving parameters not supported" }, - { 0x054e00, "Overlapped commands attempted" }, - { 0x055302, "Medium removal prevented" }, - { 0x055500, "System resource failure" }, - { 0x056300, "End of user area encountered on this track" }, - { 0x056400, "Illegal mode for this track or incompatible medium" }, - { 0x056f00, "Copy protection key exchange failure - Authentication failure" }, - { 0x056f01, "Copy protection key exchange failure - Key not present" }, - { 0x056f02, "Copy protection key exchange failure - Key not established" }, - { 0x056f03, "Read of scrambled sector without authentication" }, - { 0x056f04, "Media region code is mismatched to logical unit" }, - { 0x056f05, "Drive region must be permanent / region reset count error" }, - { 0x057203, "Session fixation error - incomplete track in session" }, - { 0x057204, "Empty or partially written reserved track" }, - { 0x057205, "No more RZONE reservations are allowed" }, - { 0x05bf00, "Loss of streaming" }, - { 0x062800, "Not ready to ready transition, medium may have changed" }, - { 0x062900, "Power on, reset or hardware reset occurred" }, - { 0x062a00, "Parameters changed" }, - { 0x062a01, "Mode parameters changed" }, - { 0x062e00, "Insufficient time for operation" }, - { 0x063f00, "Logical unit operating conditions have changed" }, - { 0x063f01, "Microcode has been changed" }, - { 0x065a00, "Operator request or state change input (unspecified)" }, - { 0x065a01, "Operator medium removal request" }, - { 0x0bb900, "Play operation aborted" }, - - /* Here we use 0xff for the key (not a valid key) to signify - * that these can have _any_ key value associated with them... */ - { 0xff0401, "Logical unit is in process of becoming ready" }, - { 0xff0400, "Logical unit not ready, cause not reportable" }, - { 0xff0402, "Logical unit not ready, initializing command required" }, - { 0xff0403, "Logical unit not ready, manual intervention required" }, - { 0xff0500, "Logical unit does not respond to selection" }, - { 0xff0800, "Logical unit communication failure" }, - { 0xff0802, "Logical unit communication parity error" }, - { 0xff0801, "Logical unit communication time-out" }, - { 0xff2500, "Logical unit not supported" }, - { 0xff4c00, "Logical unit failed self-configuration" }, - { 0xff3e00, "Logical unit has not self-configured yet" }, -}; -#endif - - -#endif /* _IDE_CD_H */ diff --git a/drivers/block/ide-cs.c b/drivers/block/ide-cs.c deleted file mode 100644 index 73d285cb1..000000000 --- a/drivers/block/ide-cs.c +++ /dev/null @@ -1,481 +0,0 @@ -/*====================================================================== - - A driver for PCMCIA IDE/ATA disk cards - - ide_cs.c 1.26 1999/11/16 02:10:49 - - The contents of this file are subject to the Mozilla Public - License Version 1.1 (the "License"); you may not use this file - except in compliance with the License. You may obtain a copy of - the License at http://www.mozilla.org/MPL/ - - Software distributed under the License is distributed on an "AS - IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - implied. See the License for the specific language governing - rights and limitations under the License. - - The initial developer of the original code is David A. Hinds - <dhinds@pcmcia.sourceforge.org>. Portions created by David A. Hinds - are Copyright (C) 1999 David A. Hinds. All Rights Reserved. - - Alternatively, the contents of this file may be used under the - terms of the GNU Public License version 2 (the "GPL"), in which - case the provisions of the GPL are applicable instead of the - above. If you wish to allow the use of your version of this file - only under the terms of the GPL and not to allow others to use - your version of this file under the MPL, indicate your decision - by deleting the provisions above and replace them with the notice - and other provisions required by the GPL. If you do not delete - the provisions above, a recipient may use your version of this - file under either the MPL or the GPL. - -======================================================================*/ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/sched.h> -#include <linux/ptrace.h> -#include <linux/malloc.h> -#include <linux/string.h> -#include <linux/timer.h> -#include <linux/ioport.h> -#include <linux/hdreg.h> -#include <linux/major.h> - -#include <asm/io.h> -#include <asm/system.h> - -#include <pcmcia/version.h> -#include <pcmcia/cs_types.h> -#include <pcmcia/cs.h> -#include <pcmcia/cistpl.h> -#include <pcmcia/ds.h> -#include <pcmcia/cisreg.h> - -#ifdef PCMCIA_DEBUG -static int pc_debug = PCMCIA_DEBUG; -MODULE_PARM(pc_debug, "i"); -#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) -static char *version = -"ide_cs.c 1.26 1999/11/16 02:10:49 (David Hinds)"; -#else -#define DEBUG(n, args...) -#endif - -/*====================================================================*/ - -/* Parameters that can be set with 'insmod' */ - -/* Bit map of interrupts to choose from */ -static u_int irq_mask = 0xdeb8; -static int irq_list[4] = { -1 }; - -MODULE_PARM(irq_mask, "i"); -MODULE_PARM(irq_list, "1-4i"); - -/*====================================================================*/ - -static const char ide_major[] = { - IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR, -#ifdef IDE4_MAJOR - IDE4_MAJOR, IDE5_MAJOR -#endif -}; - -typedef struct ide_info_t { - dev_link_t link; - int ndev; - dev_node_t node; - int hd; -} ide_info_t; - -static void ide_config(dev_link_t *link); -static void ide_release(u_long arg); -static int ide_event(event_t event, int priority, - event_callback_args_t *args); - -static dev_info_t dev_info = "ide_cs"; - -static dev_link_t *ide_attach(void); -static void ide_detach(dev_link_t *); - -static dev_link_t *dev_list = NULL; - -/*====================================================================*/ - -static void cs_error(client_handle_t handle, int func, int ret) -{ - error_info_t err = { func, ret }; - CardServices(ReportError, handle, &err); -} - -/*====================================================================== - - ide_attach() creates an "instance" of the driver, allocating - local data structures for one device. The device is registered - with Card Services. - -======================================================================*/ - -static dev_link_t *ide_attach(void) -{ - ide_info_t *info; - dev_link_t *link; - client_reg_t client_reg; - int i, ret; - - DEBUG(0, "ide_attach()\n"); - - /* Create new ide device */ - info = kmalloc(sizeof(*info), GFP_KERNEL); - if (!info) return NULL; - memset(info, 0, sizeof(*info)); - link = &info->link; link->priv = info; - - link->release.function = &ide_release; - link->release.data = (u_long)link; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - link->io.Attributes2 = IO_DATA_PATH_WIDTH_8; - link->io.IOAddrLines = 3; - link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; - link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID; - if (irq_list[0] == -1) - link->irq.IRQInfo2 = irq_mask; - else - for (i = 0; i < 4; i++) - link->irq.IRQInfo2 |= 1 << irq_list[i]; - link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.Vcc = 50; - link->conf.IntType = INT_MEMORY_AND_IO; - - /* Register with Card Services */ - link->next = dev_list; - dev_list = link; - client_reg.dev_info = &dev_info; - client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &ide_event; - client_reg.Version = 0x0210; - client_reg.event_callback_args.client_data = link; - ret = CardServices(RegisterClient, &link->handle, &client_reg); - if (ret != CS_SUCCESS) { - cs_error(link->handle, RegisterClient, ret); - ide_detach(link); - return NULL; - } - - return link; -} /* ide_attach */ - -/*====================================================================== - - This deletes a driver "instance". The device is de-registered - with Card Services. If it has been released, all local data - structures are freed. Otherwise, the structures will be freed - when the device is released. - -======================================================================*/ - -static void ide_detach(dev_link_t *link) -{ - dev_link_t **linkp; - long flags; - int ret; - - DEBUG(0, "ide_detach(0x%p)\n", link); - - /* Locate device structure */ - for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) - if (*linkp == link) break; - if (*linkp == NULL) - return; - - save_flags(flags); - cli(); - if (link->state & DEV_RELEASE_PENDING) { - del_timer(&link->release); - link->state &= ~DEV_RELEASE_PENDING; - } - restore_flags(flags); - - if (link->state & DEV_CONFIG) - ide_release((u_long)link); - - if (link->handle) { - ret = CardServices(DeregisterClient, link->handle); - if (ret != CS_SUCCESS) - cs_error(link->handle, DeregisterClient, ret); - } - - /* Unlink, free device structure */ - *linkp = link->next; - kfree(link->priv); - -} /* ide_detach */ - -/*====================================================================== - - ide_config() is scheduled to run after a CARD_INSERTION event - is received, to configure the PCMCIA socket, and to make the - ide device available to the system. - -======================================================================*/ - -#define CS_CHECK(fn, args...) \ -while ((last_ret=CardServices(last_fn=(fn), args))!=0) goto cs_failed - -#define CFG_CHECK(fn, args...) \ -if (CardServices(fn, args) != 0) goto next_entry - -void ide_config(dev_link_t *link) -{ - client_handle_t handle = link->handle; - ide_info_t *info = link->priv; - tuple_t tuple; - u_short buf[128]; - cisparse_t parse; - config_info_t conf; - cistpl_cftable_entry_t *cfg = &parse.cftable_entry; - cistpl_cftable_entry_t dflt = { 0 }; - int i, pass, last_ret, last_fn, hd, io_base, ctl_base; - - DEBUG(0, "ide_config(0x%p)\n", link); - - tuple.TupleData = (cisdata_t *)buf; - tuple.TupleOffset = 0; tuple.TupleDataMax = 255; - tuple.Attributes = 0; - tuple.DesiredTuple = CISTPL_CONFIG; - CS_CHECK(GetFirstTuple, handle, &tuple); - CS_CHECK(GetTupleData, handle, &tuple); - CS_CHECK(ParseTuple, handle, &tuple, &parse); - link->conf.ConfigBase = parse.config.base; - link->conf.Present = parse.config.rmask[0]; - - /* Configure card */ - link->state |= DEV_CONFIG; - - /* Not sure if this is right... look up the current Vcc */ - CS_CHECK(GetConfigurationInfo, handle, &conf); - link->conf.Vcc = conf.Vcc; - - pass = io_base = ctl_base = 0; - tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - tuple.Attributes = 0; - CS_CHECK(GetFirstTuple, handle, &tuple); - while (1) { - CFG_CHECK(GetTupleData, handle, &tuple); - CFG_CHECK(ParseTuple, handle, &tuple, &parse); - - /* Check for matching Vcc, unless we're desperate */ - if (!pass) { - if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) { - if (conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM]/10000) - goto next_entry; - } else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM)) { - if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM]/10000) - goto next_entry; - } - } - - if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM)) - link->conf.Vpp1 = link->conf.Vpp2 = - cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; - else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM)) - link->conf.Vpp1 = link->conf.Vpp2 = - dflt.vpp1.param[CISTPL_POWER_VNOM]/10000; - - if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { - cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; - link->conf.ConfigIndex = cfg->index; - link->io.BasePort1 = io->win[0].base; - link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; - if (!(io->flags & CISTPL_IO_16BIT)) - link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - if (io->nwin == 2) { - link->io.NumPorts1 = 8; - link->io.BasePort2 = io->win[1].base; - link->io.NumPorts2 = 1; - CFG_CHECK(RequestIO, link->handle, &link->io); - io_base = link->io.BasePort1; - ctl_base = link->io.BasePort2; - } else if ((io->nwin == 1) && (io->win[0].len >= 16)) { - link->io.NumPorts1 = io->win[0].len; - link->io.NumPorts2 = 0; - CFG_CHECK(RequestIO, link->handle, &link->io); - io_base = link->io.BasePort1; - ctl_base = link->io.BasePort1+0x0e; - } else goto next_entry; - /* If we've got this far, we're done */ - break; - } - - next_entry: - if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg; - if (pass) { - CS_CHECK(GetNextTuple, handle, &tuple); - } else if (CardServices(GetNextTuple, handle, &tuple) != 0) { - CS_CHECK(GetFirstTuple, handle, &tuple); - memset(&dflt, 0, sizeof(dflt)); - pass++; - } - } - - CS_CHECK(RequestIRQ, handle, &link->irq); - CS_CHECK(RequestConfiguration, handle, &link->conf); - - /* deal with brain dead IDE resource management */ - release_region(link->io.BasePort1, link->io.NumPorts1); - if (link->io.NumPorts2) - release_region(link->io.BasePort2, link->io.NumPorts2); - - /* retry registration in case device is still spinning up */ - for (i = 0; i < 10; i++) { - hd = ide_register(io_base, ctl_base, link->irq.AssignedIRQ); - if (hd >= 0) break; - if (link->io.NumPorts1 == 0x20) { - hd = ide_register(io_base+0x10, ctl_base+0x10, - link->irq.AssignedIRQ); - if (hd >= 0) { - io_base += 0x10; ctl_base += 0x10; - break; - } - } - __set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ/10); - } - - if (hd < 0) { - printk(KERN_NOTICE "ide_cs: ide_register() at 0x%3x & 0x%3x" - ", irq %u failed\n", io_base, ctl_base, - link->irq.AssignedIRQ); - goto failed; - } - - MOD_INC_USE_COUNT; - info->ndev = 1; - sprintf(info->node.dev_name, "hd%c", 'a'+(hd*2)); - info->node.major = ide_major[hd]; - info->node.minor = 0; - info->hd = hd; - link->dev = &info->node; - printk(KERN_INFO "ide_cs: %s: Vcc = %d.%d, Vpp = %d.%d\n", - info->node.dev_name, link->conf.Vcc/10, link->conf.Vcc%10, - link->conf.Vpp1/10, link->conf.Vpp1%10); - - link->state &= ~DEV_CONFIG_PENDING; - return; - -cs_failed: - cs_error(link->handle, last_fn, last_ret); -failed: - ide_release((u_long)link); - -} /* ide_config */ - -/*====================================================================== - - After a card is removed, ide_release() will unregister the net - device, and release the PCMCIA configuration. If the device is - still open, this will be postponed until it is closed. - -======================================================================*/ - -void ide_release(u_long arg) -{ - dev_link_t *link = (dev_link_t *)arg; - ide_info_t *info = link->priv; - - DEBUG(0, "ide_release(0x%p)\n", link); - - if (info->ndev) { - ide_unregister(info->hd); - MOD_DEC_USE_COUNT; - } - info->ndev = 0; - link->dev = NULL; - - CardServices(ReleaseConfiguration, link->handle); - CardServices(ReleaseIO, link->handle, &link->io); - CardServices(ReleaseIRQ, link->handle, &link->irq); - - link->state &= ~DEV_CONFIG; - -} /* ide_release */ - -/*====================================================================== - - The card status event handler. Mostly, this schedules other - stuff to run after an event is received. A CARD_REMOVAL event - also sets some flags to discourage the ide drivers from - talking to the ports. - -======================================================================*/ - -int ide_event(event_t event, int priority, - event_callback_args_t *args) -{ - dev_link_t *link = args->client_data; - - DEBUG(1, "ide_event(0x%06x)\n", event); - - switch (event) { - case CS_EVENT_CARD_REMOVAL: - link->state &= ~DEV_PRESENT; - if (link->state & DEV_CONFIG) { - link->release.expires = jiffies + HZ/20; - link->state |= DEV_RELEASE_PENDING; - add_timer(&link->release); - } - break; - case CS_EVENT_CARD_INSERTION: - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - ide_config(link); - break; - case CS_EVENT_PM_SUSPEND: - link->state |= DEV_SUSPEND; - /* Fall through... */ - case CS_EVENT_RESET_PHYSICAL: - if (link->state & DEV_CONFIG) - CardServices(ReleaseConfiguration, link->handle); - break; - case CS_EVENT_PM_RESUME: - link->state &= ~DEV_SUSPEND; - /* Fall through... */ - case CS_EVENT_CARD_RESET: - if (DEV_OK(link)) - CardServices(RequestConfiguration, link->handle, &link->conf); - break; - } - return 0; -} /* ide_event */ - -/*====================================================================*/ - -static int __init init_ide_cs(void) -{ - servinfo_t serv; - DEBUG(0, "%s\n", version); - CardServices(GetCardServicesInfo, &serv); - if (serv.Revision != CS_RELEASE_CODE) { - printk(KERN_NOTICE "ide_cs: Card Services release " - "does not match!\n"); - return -1; - } - register_pccard_driver(&dev_info, &ide_attach, &ide_detach); - return 0; -} - -static void __exit exit_ide_cs(void) -{ - DEBUG(0, "ide_cs: unloading\n"); - unregister_pccard_driver(&dev_info); - while (dev_list != NULL) - ide_detach(dev_list); -} - -module_init(init_ide_cs); -module_exit(exit_ide_cs); diff --git a/drivers/block/ide-disk.c b/drivers/block/ide-disk.c deleted file mode 100644 index 2ef50f285..000000000 --- a/drivers/block/ide-disk.c +++ /dev/null @@ -1,906 +0,0 @@ -/* - * linux/drivers/block/ide-disk.c Version 1.09 April 23, 1999 - * - * Copyright (C) 1994-1998 Linus Torvalds & authors (see below) - */ - -/* - * Mostly written by Mark Lord <mlord@pobox.com> - * and Gadi Oxman <gadio@netvision.net.il> - * - * See linux/MAINTAINERS for address of current maintainer. - * - * This is the IDE/ATA disk driver, as evolved from hd.c and ide.c. - * - * Version 1.00 move disk only code from ide.c to ide-disk.c - * support optional byte-swapping of all data - * Version 1.01 fix previous byte-swapping code - * Version 1.02 remove ", LBA" from drive identification msgs - * Version 1.03 fix display of id->buf_size for big-endian - * Version 1.04 add /proc configurable settings and S.M.A.R.T support - * Version 1.05 add capacity support for ATA3 >= 8GB - * Version 1.06 get boot-up messages to show full cyl count - * Version 1.07 disable door-locking if it fails - * Version 1.08 fixed CHS/LBA translations for ATA4 > 8GB, - * process of adding new ATA4 compliance. - * fixed problems in allowing fdisk to see - * the entire disk. - * Version 1.09 added increment of rq->sector in ide_multwrite - * added UDMA 3/4 reporting - */ - -#define IDEDISK_VERSION "1.09" - -#undef REALLY_SLOW_IO /* most systems can safely undef this */ - -#define _IDE_DISK_C /* Tell linux/hdsmart.h it's really us */ - -#include <linux/config.h> -#include <linux/module.h> -#include <linux/types.h> -#include <linux/string.h> -#include <linux/kernel.h> -#include <linux/timer.h> -#include <linux/mm.h> -#include <linux/interrupt.h> -#include <linux/major.h> -#include <linux/errno.h> -#include <linux/genhd.h> -#include <linux/malloc.h> -#include <linux/delay.h> -#include <linux/ide.h> - -#include <asm/byteorder.h> -#include <asm/irq.h> -#include <asm/uaccess.h> -#include <asm/io.h> - -#ifdef CONFIG_BLK_DEV_PDC4030 -#define IS_PDC4030_DRIVE (HWIF(drive)->chipset == ide_pdc4030) -#else -#define IS_PDC4030_DRIVE (0) /* auto-NULLs out pdc4030 code */ -#endif - -static void idedisk_bswap_data (void *buffer, int wcount) -{ - u16 *p = buffer; - - while (wcount--) { - *p++ = *p << 8 | *p >> 8; - *p++ = *p << 8 | *p >> 8; - } -} - -static inline void idedisk_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount) -{ - ide_input_data(drive, buffer, wcount); - if (drive->bswap) - idedisk_bswap_data(buffer, wcount); -} - -static inline void idedisk_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount) -{ - if (drive->bswap) { - idedisk_bswap_data(buffer, wcount); - ide_output_data(drive, buffer, wcount); - idedisk_bswap_data(buffer, wcount); - } else - ide_output_data(drive, buffer, wcount); -} - -/* - * lba_capacity_is_ok() performs a sanity check on the claimed "lba_capacity" - * value for this drive (from its reported identification information). - * - * Returns: 1 if lba_capacity looks sensible - * 0 otherwise - * - * It is called only once for each drive. - */ -static int lba_capacity_is_ok (struct hd_driveid *id) -{ - unsigned long lba_sects, chs_sects, head, tail; - - /* - * The ATA spec tells large drives to return - * C/H/S = 16383/16/63 independent of their size. - * Some drives can be jumpered to use 15 heads instead of 16. - * Some drives can be jumpered to use 4092 cyls instead of 16383. - */ - if ((id->cyls == 16383 - || (id->cyls == 4092 && id->cur_cyls == 16383)) && - id->sectors == 63 && - (id->heads == 15 || id->heads == 16) && - id->lba_capacity >= 16383*63*id->heads) - return 1; - - lba_sects = id->lba_capacity; - chs_sects = id->cyls * id->heads * id->sectors; - - /* perform a rough sanity check on lba_sects: within 10% is OK */ - if ((lba_sects - chs_sects) < chs_sects/10) - return 1; - - /* some drives have the word order reversed */ - head = ((lba_sects >> 16) & 0xffff); - tail = (lba_sects & 0xffff); - lba_sects = (head | (tail << 16)); - if ((lba_sects - chs_sects) < chs_sects/10) { - id->lba_capacity = lba_sects; - return 1; /* lba_capacity is (now) good */ - } - - return 0; /* lba_capacity value may be bad */ -} - -/* - * read_intr() is the handler for disk read/multread interrupts - */ -static ide_startstop_t read_intr (ide_drive_t *drive) -{ - byte stat; - int i; - unsigned int msect, nsect; - struct request *rq; -#if 0 - if (!OK_STAT(stat=GET_STAT(),DATA_READY,BAD_R_STAT)) { - return ide_error(drive, "read_intr", stat); - } -#else /* new way for dealing with premature shared PCI interrupts */ - if (!OK_STAT(stat=GET_STAT(),DATA_READY,BAD_R_STAT)) { - if (stat & (ERR_STAT|DRQ_STAT)) { - return ide_error(drive, "read_intr", stat); - } - /* no data yet, so wait for another interrupt */ - ide_set_handler(drive, &read_intr, WAIT_CMD, NULL); - return ide_started; - } -#endif - msect = drive->mult_count; - -read_next: - rq = HWGROUP(drive)->rq; - if (msect) { - if ((nsect = rq->current_nr_sectors) > msect) - nsect = msect; - msect -= nsect; - } else - nsect = 1; - idedisk_input_data(drive, rq->buffer, nsect * SECTOR_WORDS); -#ifdef DEBUG - printk("%s: read: sectors(%ld-%ld), buffer=0x%08lx, remaining=%ld\n", - drive->name, rq->sector, rq->sector+nsect-1, - (unsigned long) rq->buffer+(nsect<<9), rq->nr_sectors-nsect); -#endif - rq->sector += nsect; - rq->buffer += nsect<<9; - rq->errors = 0; - i = (rq->nr_sectors -= nsect); - if (((long)(rq->current_nr_sectors -= nsect)) <= 0) - ide_end_request(1, HWGROUP(drive)); - if (i > 0) { - if (msect) - goto read_next; - ide_set_handler (drive, &read_intr, WAIT_CMD, NULL); - return ide_started; - } - return ide_stopped; -} - -/* - * write_intr() is the handler for disk write interrupts - */ -static ide_startstop_t write_intr (ide_drive_t *drive) -{ - byte stat; - int i; - ide_hwgroup_t *hwgroup = HWGROUP(drive); - struct request *rq = hwgroup->rq; - - if (!OK_STAT(stat=GET_STAT(),DRIVE_READY,drive->bad_wstat)) { - printk("%s: write_intr error1: nr_sectors=%ld, stat=0x%02x\n", drive->name, rq->nr_sectors, stat); - } else { -#ifdef DEBUG - printk("%s: write: sector %ld, buffer=0x%08lx, remaining=%ld\n", - drive->name, rq->sector, (unsigned long) rq->buffer, - rq->nr_sectors-1); -#endif - if ((rq->nr_sectors == 1) ^ ((stat & DRQ_STAT) != 0)) { - rq->sector++; - rq->buffer += 512; - rq->errors = 0; - i = --rq->nr_sectors; - --rq->current_nr_sectors; - if (((long)rq->current_nr_sectors) <= 0) - ide_end_request(1, hwgroup); - if (i > 0) { - idedisk_output_data (drive, rq->buffer, SECTOR_WORDS); - ide_set_handler (drive, &write_intr, WAIT_CMD, NULL); - return ide_started; - } - return ide_stopped; - } - return ide_stopped; /* the original code did this here (?) */ - } - return ide_error(drive, "write_intr", stat); -} - -/* - * ide_multwrite() transfers a block of up to mcount sectors of data - * to a drive as part of a disk multiple-sector write operation. - * - * Returns 0 if successful; returns 1 if request had to be aborted due to corrupted buffer list. - */ -int ide_multwrite (ide_drive_t *drive, unsigned int mcount) -{ - ide_hwgroup_t *hwgroup= HWGROUP(drive); - - /* - * This may look a bit odd, but remember wrq is a copy of the - * request not the original. The pointers are real however so the - * bh's are not copies. Remember that or bad stuff will happen - * - * At the point we are called the drive has asked us for the - * data, and its our job to feed it, walking across bh boundaries - * if need be. - */ - - struct request *rq = &hwgroup->wrq; - - do { - unsigned long flags; - unsigned int nsect = rq->current_nr_sectors; - if (nsect > mcount) - nsect = mcount; - mcount -= nsect; - - idedisk_output_data(drive, rq->buffer, nsect<<7); -#ifdef DEBUG - printk("%s: multwrite: sector %ld, buffer=0x%08lx, count=%d, remaining=%ld\n", - drive->name, rq->sector, (unsigned long) rq->buffer, - nsect, rq->nr_sectors - nsect); -#endif - spin_lock_irqsave(&io_request_lock, flags); /* Is this really necessary? */ -#ifdef CONFIG_BLK_DEV_PDC4030 - rq->sector += nsect; -#endif - if (((long)(rq->nr_sectors -= nsect)) <= 0) { -#ifdef DEBUG - printk("%s: multwrite: count=%d, current=%ld\n", - drive->name, nsect, rq->nr_sectors); -#endif - spin_unlock_irqrestore(&io_request_lock, flags); - break; - } - if ((rq->current_nr_sectors -= nsect) == 0) { - if ((rq->bh = rq->bh->b_reqnext) != NULL) { - rq->current_nr_sectors = rq->bh->b_size>>9; - rq->buffer = rq->bh->b_data; - } else { - spin_unlock_irqrestore(&io_request_lock, flags); - printk("%s: buffer list corrupted (%ld, %ld, %d)\n", - drive->name, rq->current_nr_sectors, - rq->nr_sectors, nsect); - ide_end_request(0, hwgroup); - return 1; - } - } else { - /* Fix the pointer.. we ate data */ - rq->buffer += nsect << 9; - } - spin_unlock_irqrestore(&io_request_lock, flags); - } while (mcount); - return 0; -} - -/* - * multwrite_intr() is the handler for disk multwrite interrupts - */ -static ide_startstop_t multwrite_intr (ide_drive_t *drive) -{ - byte stat; - int i; - ide_hwgroup_t *hwgroup = HWGROUP(drive); - struct request *rq = &hwgroup->wrq; - - if (OK_STAT(stat=GET_STAT(),DRIVE_READY,drive->bad_wstat)) { - if (stat & DRQ_STAT) { - /* - * The drive wants data. Remember rq is the copy - * of the request - */ - if (rq->nr_sectors) { - if (ide_multwrite(drive, drive->mult_count)) - return ide_stopped; - ide_set_handler (drive, &multwrite_intr, WAIT_CMD, NULL); - return ide_started; - } - } else { - /* - * If the copy has all the blocks completed then - * we can end the original request. - */ - if (!rq->nr_sectors) { /* all done? */ - rq = hwgroup->rq; - for (i = rq->nr_sectors; i > 0;){ - i -= rq->current_nr_sectors; - ide_end_request(1, hwgroup); - } - return ide_stopped; - } - } - return ide_stopped; /* the original code did this here (?) */ - } - return ide_error(drive, "multwrite_intr", stat); -} - -/* - * set_multmode_intr() is invoked on completion of a WIN_SETMULT cmd. - */ -static ide_startstop_t set_multmode_intr (ide_drive_t *drive) -{ - byte stat; - - if (OK_STAT(stat=GET_STAT(),READY_STAT,BAD_STAT)) { - drive->mult_count = drive->mult_req; - } else { - drive->mult_req = drive->mult_count = 0; - drive->special.b.recalibrate = 1; - (void) ide_dump_status(drive, "set_multmode", stat); - } - return ide_stopped; -} - -/* - * set_geometry_intr() is invoked on completion of a WIN_SPECIFY cmd. - */ -static ide_startstop_t set_geometry_intr (ide_drive_t *drive) -{ - byte stat; - - if (OK_STAT(stat=GET_STAT(),READY_STAT,BAD_STAT)) - return ide_stopped; - - if (stat & (ERR_STAT|DRQ_STAT)) - return ide_error(drive, "set_geometry_intr", stat); - - ide_set_handler(drive, &set_geometry_intr, WAIT_CMD, NULL); - return ide_started; -} - -/* - * recal_intr() is invoked on completion of a WIN_RESTORE (recalibrate) cmd. - */ -static ide_startstop_t recal_intr (ide_drive_t *drive) -{ - byte stat = GET_STAT(); - - if (!OK_STAT(stat,READY_STAT,BAD_STAT)) - return ide_error(drive, "recal_intr", stat); - return ide_stopped; -} - -/* - * do_rw_disk() issues READ and WRITE commands to a disk, - * using LBA if supported, or CHS otherwise, to address sectors. - * It also takes care of issuing special DRIVE_CMDs. - */ -static ide_startstop_t do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block) -{ - if (IDE_CONTROL_REG) - OUT_BYTE(drive->ctl,IDE_CONTROL_REG); - OUT_BYTE(rq->nr_sectors,IDE_NSECTOR_REG); -#ifdef CONFIG_BLK_DEV_PDC4030 - if (drive->select.b.lba || IS_PDC4030_DRIVE) { -#else /* !CONFIG_BLK_DEV_PDC4030 */ - if (drive->select.b.lba) { -#endif /* CONFIG_BLK_DEV_PDC4030 */ -#ifdef DEBUG - printk("%s: %sing: LBAsect=%ld, sectors=%ld, buffer=0x%08lx\n", - drive->name, (rq->cmd==READ)?"read":"writ", - block, rq->nr_sectors, (unsigned long) rq->buffer); -#endif - OUT_BYTE(block,IDE_SECTOR_REG); - OUT_BYTE(block>>=8,IDE_LCYL_REG); - OUT_BYTE(block>>=8,IDE_HCYL_REG); - OUT_BYTE(((block>>8)&0x0f)|drive->select.all,IDE_SELECT_REG); - } else { - unsigned int sect,head,cyl,track; - track = block / drive->sect; - sect = block % drive->sect + 1; - OUT_BYTE(sect,IDE_SECTOR_REG); - head = track % drive->head; - cyl = track / drive->head; - OUT_BYTE(cyl,IDE_LCYL_REG); - OUT_BYTE(cyl>>8,IDE_HCYL_REG); - OUT_BYTE(head|drive->select.all,IDE_SELECT_REG); -#ifdef DEBUG - printk("%s: %sing: CHS=%d/%d/%d, sectors=%ld, buffer=0x%08lx\n", - drive->name, (rq->cmd==READ)?"read":"writ", cyl, - head, sect, rq->nr_sectors, (unsigned long) rq->buffer); -#endif - } -#ifdef CONFIG_BLK_DEV_PDC4030 - if (IS_PDC4030_DRIVE) { - extern ide_startstop_t do_pdc4030_io(ide_drive_t *, struct request *); - return do_pdc4030_io (drive, rq); - } -#endif /* CONFIG_BLK_DEV_PDC4030 */ - if (rq->cmd == READ) { -#ifdef CONFIG_BLK_DEV_IDEDMA - if (drive->using_dma && !(HWIF(drive)->dmaproc(ide_dma_read, drive))) - return ide_started; -#endif /* CONFIG_BLK_DEV_IDEDMA */ - ide_set_handler(drive, &read_intr, WAIT_CMD, NULL); - OUT_BYTE(drive->mult_count ? WIN_MULTREAD : WIN_READ, IDE_COMMAND_REG); - return ide_started; - } - if (rq->cmd == WRITE) { - ide_startstop_t startstop; -#ifdef CONFIG_BLK_DEV_IDEDMA - if (drive->using_dma && !(HWIF(drive)->dmaproc(ide_dma_write, drive))) - return ide_started; -#endif /* CONFIG_BLK_DEV_IDEDMA */ - OUT_BYTE(drive->mult_count ? WIN_MULTWRITE : WIN_WRITE, IDE_COMMAND_REG); - if (ide_wait_stat(&startstop, drive, DATA_READY, drive->bad_wstat, WAIT_DRQ)) { - printk(KERN_ERR "%s: no DRQ after issuing %s\n", drive->name, - drive->mult_count ? "MULTWRITE" : "WRITE"); - return startstop; - } - if (!drive->unmask) - __cli(); /* local CPU only */ - if (drive->mult_count) { - ide_hwgroup_t *hwgroup = HWGROUP(drive); - /* - * Ugh.. this part looks ugly because we MUST set up - * the interrupt handler before outputting the first block - * of data to be written. If we hit an error (corrupted buffer list) - * in ide_multwrite(), then we need to remove the handler/timer - * before returning. Fortunately, this NEVER happens (right?). - * - * Except when you get an error it seems... - */ - hwgroup->wrq = *rq; /* scratchpad */ - ide_set_handler (drive, &multwrite_intr, WAIT_CMD, NULL); - if (ide_multwrite(drive, drive->mult_count)) { - unsigned long flags; - spin_lock_irqsave(&io_request_lock, flags); - hwgroup->handler = NULL; - del_timer(&hwgroup->timer); - spin_unlock_irqrestore(&io_request_lock, flags); - return ide_stopped; - } - } else { - ide_set_handler (drive, &write_intr, WAIT_CMD, NULL); - idedisk_output_data(drive, rq->buffer, SECTOR_WORDS); - } - return ide_started; - } - printk(KERN_ERR "%s: bad command: %d\n", drive->name, rq->cmd); - ide_end_request(0, HWGROUP(drive)); - return ide_stopped; -} - -static int idedisk_open (struct inode *inode, struct file *filp, ide_drive_t *drive) -{ - MOD_INC_USE_COUNT; - if (drive->removable && drive->usage == 1) { - check_disk_change(inode->i_rdev); - /* - * Ignore the return code from door_lock, - * since the open() has already succeeded, - * and the door_lock is irrelevant at this point. - */ - if (drive->doorlocking && ide_wait_cmd(drive, WIN_DOORLOCK, 0, 0, 0, NULL)) - drive->doorlocking = 0; - } - return 0; -} - -static void idedisk_release (struct inode *inode, struct file *filp, ide_drive_t *drive) -{ - if (drive->removable && !drive->usage) { - invalidate_buffers(inode->i_rdev); - if (drive->doorlocking && ide_wait_cmd(drive, WIN_DOORUNLOCK, 0, 0, 0, NULL)) - drive->doorlocking = 0; - } - MOD_DEC_USE_COUNT; -} - -static int idedisk_media_change (ide_drive_t *drive) -{ - return drive->removable; /* if removable, always assume it was changed */ -} - -/* - * Compute drive->capacity, the full capacity of the drive - * Called with drive->id != NULL. - */ -static void init_idedisk_capacity (ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - unsigned long capacity = drive->cyl * drive->head * drive->sect; - - drive->select.b.lba = 0; - - /* Determine capacity, and use LBA if the drive properly supports it */ - if ((id->capability & 2) && lba_capacity_is_ok(id)) { - capacity = id->lba_capacity; - drive->cyl = capacity / (drive->head * drive->sect); - drive->select.b.lba = 1; - } - drive->capacity = capacity; -} - -static unsigned long idedisk_capacity (ide_drive_t *drive) -{ - return (drive->capacity - drive->sect0); -} - -static ide_startstop_t idedisk_special (ide_drive_t *drive) -{ - special_t *s = &drive->special; - - if (s->b.set_geometry) { - s->b.set_geometry = 0; - OUT_BYTE(drive->sect,IDE_SECTOR_REG); - OUT_BYTE(drive->cyl,IDE_LCYL_REG); - OUT_BYTE(drive->cyl>>8,IDE_HCYL_REG); - OUT_BYTE(((drive->head-1)|drive->select.all)&0xBF,IDE_SELECT_REG); - if (!IS_PDC4030_DRIVE) - ide_cmd(drive, WIN_SPECIFY, drive->sect, &set_geometry_intr); - } else if (s->b.recalibrate) { - s->b.recalibrate = 0; - if (!IS_PDC4030_DRIVE) - ide_cmd(drive, WIN_RESTORE, drive->sect, &recal_intr); - } else if (s->b.set_multmode) { - s->b.set_multmode = 0; - if (drive->id && drive->mult_req > drive->id->max_multsect) - drive->mult_req = drive->id->max_multsect; - if (!IS_PDC4030_DRIVE) - ide_cmd(drive, WIN_SETMULT, drive->mult_req, &set_multmode_intr); - } else if (s->all) { - int special = s->all; - s->all = 0; - printk(KERN_ERR "%s: bad special flag: 0x%02x\n", drive->name, special); - return ide_stopped; - } - return IS_PDC4030_DRIVE ? ide_stopped : ide_started; -} - -static void idedisk_pre_reset (ide_drive_t *drive) -{ - drive->special.all = 0; - drive->special.b.set_geometry = 1; - drive->special.b.recalibrate = 1; - if (OK_TO_RESET_CONTROLLER) - drive->mult_count = 0; - if (!drive->keep_settings && !drive->using_dma) - drive->mult_req = 0; - if (drive->mult_req != drive->mult_count) - drive->special.b.set_multmode = 1; -} - -#ifdef CONFIG_PROC_FS - -static int smart_enable(ide_drive_t *drive) -{ - return ide_wait_cmd(drive, WIN_SMART, 0, SMART_ENABLE, 0, NULL); -} - -static int get_smart_values(ide_drive_t *drive, byte *buf) -{ - (void) smart_enable(drive); - return ide_wait_cmd(drive, WIN_SMART, 0, SMART_READ_VALUES, 1, buf); -} - -static int get_smart_thresholds(ide_drive_t *drive, byte *buf) -{ - (void) smart_enable(drive); - return ide_wait_cmd(drive, WIN_SMART, 0, SMART_READ_THRESHOLDS, 1, buf); -} - -static int proc_idedisk_read_cache - (char *page, char **start, off_t off, int count, int *eof, void *data) -{ - ide_drive_t *drive = (ide_drive_t *) data; - char *out = page; - int len; - - if (drive->id) - len = sprintf(out,"%i\n", drive->id->buf_size / 2); - else - len = sprintf(out,"(none)\n"); - PROC_IDE_READ_RETURN(page,start,off,count,eof,len); -} - -static int proc_idedisk_read_smart_thresholds - (char *page, char **start, off_t off, int count, int *eof, void *data) -{ - ide_drive_t *drive = (ide_drive_t *)data; - int len = 0, i = 0; - - if (!get_smart_thresholds(drive, page)) { - unsigned short *val = ((unsigned short *)page) + 2; - char *out = ((char *)val) + (SECTOR_WORDS * 4); - page = out; - do { - out += sprintf(out, "%04x%c", le16_to_cpu(*val), (++i & 7) ? ' ' : '\n'); - val += 1; - } while (i < (SECTOR_WORDS * 2)); - len = out - page; - } - PROC_IDE_READ_RETURN(page,start,off,count,eof,len); -} - -static int proc_idedisk_read_smart_values - (char *page, char **start, off_t off, int count, int *eof, void *data) -{ - ide_drive_t *drive = (ide_drive_t *)data; - int len = 0, i = 0; - - if (!get_smart_values(drive, page)) { - unsigned short *val = ((unsigned short *)page) + 2; - char *out = ((char *)val) + (SECTOR_WORDS * 4); - page = out; - do { - out += sprintf(out, "%04x%c", le16_to_cpu(*val), (++i & 7) ? ' ' : '\n'); - val += 1; - } while (i < (SECTOR_WORDS * 2)); - len = out - page; - } - PROC_IDE_READ_RETURN(page,start,off,count,eof,len); -} - -static ide_proc_entry_t idedisk_proc[] = { - { "cache", S_IFREG|S_IRUGO, proc_idedisk_read_cache, NULL }, - { "geometry", S_IFREG|S_IRUGO, proc_ide_read_geometry, NULL }, - { "smart_values", S_IFREG|S_IRUSR, proc_idedisk_read_smart_values, NULL }, - { "smart_thresholds", S_IFREG|S_IRUSR, proc_idedisk_read_smart_thresholds, NULL }, - { NULL, 0, NULL, NULL } -}; - -#else - -#define idedisk_proc NULL - -#endif /* CONFIG_PROC_FS */ - -static int set_multcount(ide_drive_t *drive, int arg) -{ - struct request rq; - - if (drive->special.b.set_multmode) - return -EBUSY; - ide_init_drive_cmd (&rq); - drive->mult_req = arg; - drive->special.b.set_multmode = 1; - (void) ide_do_drive_cmd (drive, &rq, ide_wait); - return (drive->mult_count == arg) ? 0 : -EIO; -} - -static int set_nowerr(ide_drive_t *drive, int arg) -{ - unsigned long flags; - - if (ide_spin_wait_hwgroup(drive, &flags)) - return -EBUSY; - drive->nowerr = arg; - drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT; - spin_unlock_irqrestore(&io_request_lock, flags); - return 0; -} - -static void idedisk_add_settings(ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - int major = HWIF(drive)->major; - int minor = drive->select.b.unit << PARTN_BITS; - - ide_add_setting(drive, "bios_cyl", SETTING_RW, -1, -1, TYPE_INT, 0, 65535, 1, 1, &drive->bios_cyl, NULL); - ide_add_setting(drive, "bios_head", SETTING_RW, -1, -1, TYPE_BYTE, 0, 255, 1, 1, &drive->bios_head, NULL); - ide_add_setting(drive, "bios_sect", SETTING_RW, -1, -1, TYPE_BYTE, 0, 63, 1, 1, &drive->bios_sect, NULL); - ide_add_setting(drive, "bswap", SETTING_READ, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->bswap, NULL); - ide_add_setting(drive, "multcount", id ? SETTING_RW : SETTING_READ, HDIO_GET_MULTCOUNT, HDIO_SET_MULTCOUNT, TYPE_BYTE, 0, id ? id->max_multsect : 0, 1, 2, &drive->mult_count, set_multcount); - ide_add_setting(drive, "nowerr", SETTING_RW, HDIO_GET_NOWERR, HDIO_SET_NOWERR, TYPE_BYTE, 0, 1, 1, 1, &drive->nowerr, set_nowerr); - ide_add_setting(drive, "breada_readahead", SETTING_RW, BLKRAGET, BLKRASET, TYPE_INT, 0, 255, 1, 2, &read_ahead[major], NULL); - ide_add_setting(drive, "file_readahead", SETTING_RW, BLKFRAGET, BLKFRASET, TYPE_INTA, 0, INT_MAX, 1, 1024, &max_readahead[major][minor], NULL); - ide_add_setting(drive, "max_kb_per_request", SETTING_RW, BLKSECTGET, BLKSECTSET, TYPE_INTA, 1, 255, 1, 2, &max_sectors[major][minor], NULL); - -} - -/* - * IDE subdriver functions, registered with ide.c - */ -static ide_driver_t idedisk_driver = { - "ide-disk", /* name */ - IDEDISK_VERSION, /* version */ - ide_disk, /* media */ - 0, /* busy */ - 1, /* supports_dma */ - 0, /* supports_dsc_overlap */ - NULL, /* cleanup */ - do_rw_disk, /* do_request */ - NULL, /* end_request */ - NULL, /* ioctl */ - idedisk_open, /* open */ - idedisk_release, /* release */ - idedisk_media_change, /* media_change */ - idedisk_pre_reset, /* pre_reset */ - idedisk_capacity, /* capacity */ - idedisk_special, /* special */ - idedisk_proc /* proc */ -}; - -int idedisk_init (void); -static ide_module_t idedisk_module = { - IDE_DRIVER_MODULE, - idedisk_init, - &idedisk_driver, - NULL -}; - -static int idedisk_cleanup (ide_drive_t *drive) -{ - return ide_unregister_subdriver(drive); -} - -static void idedisk_setup (ide_drive_t *drive) -{ - int i; - - struct hd_driveid *id = drive->id; - unsigned long capacity; - - idedisk_add_settings(drive); - - if (id == NULL) - return; - - /* - * CompactFlash cards and their brethern look just like hard drives - * to us, but they are removable and don't have a doorlock mechanism. - */ - if (drive->removable && !drive_is_flashcard(drive)) { - /* - * Removable disks (eg. SYQUEST); ignore 'WD' drives - */ - if (id->model[0] != 'W' || id->model[1] != 'D') { - drive->doorlocking = 1; - } - } - for (i = 0; i < MAX_DRIVES; ++i) { - ide_hwif_t *hwif = HWIF(drive); - - if (drive != &hwif->drives[i]) continue; - hwif->gd->de_arr[i] = drive->de; - if (drive->removable) - hwif->gd->flags[i] |= GENHD_FL_REMOVABLE; - break; - } - - /* Extract geometry if we did not already have one for the drive */ - if (!drive->cyl || !drive->head || !drive->sect) { - drive->cyl = drive->bios_cyl = id->cyls; - drive->head = drive->bios_head = id->heads; - drive->sect = drive->bios_sect = id->sectors; - } - - /* Handle logical geometry translation by the drive */ - if ((id->field_valid & 1) && id->cur_cyls && - id->cur_heads && (id->cur_heads <= 16) && id->cur_sectors) { - drive->cyl = id->cur_cyls; - drive->head = id->cur_heads; - drive->sect = id->cur_sectors; - } - - /* Use physical geometry if what we have still makes no sense */ - if (drive->head > 16 && id->heads && id->heads <= 16) { - drive->cyl = id->cyls; - drive->head = id->heads; - drive->sect = id->sectors; - } - - /* calculate drive capacity, and select LBA if possible */ - init_idedisk_capacity (drive); - - /* - * if possible, give fdisk access to more of the drive, - * by correcting bios_cyls: - */ - capacity = idedisk_capacity (drive); - if ((capacity >= (drive->bios_cyl * drive->bios_sect * drive->bios_head)) && - (!drive->forced_geom) && drive->bios_sect && drive->bios_head) - drive->bios_cyl = (capacity / drive->bios_sect) / drive->bios_head; - -#if 0 /* done instead for entire identify block in arch/ide.h stuff */ - /* fix byte-ordering of buffer size field */ - id->buf_size = le16_to_cpu(id->buf_size); -#endif - printk (KERN_INFO "%s: %.40s, %ldMB w/%dkB Cache, CHS=%d/%d/%d", - drive->name, id->model, - capacity/2048L, id->buf_size/2, - drive->bios_cyl, drive->bios_head, drive->bios_sect); - - if (drive->using_dma) { - if ((id->field_valid & 4) && (id->hw_config & 0x2000) && - (HWIF(drive)->udma_four) && - (id->dma_ultra & (id->dma_ultra >> 11) & 3)) { - printk(", UDMA(66)"); /* UDMA BIOS-enabled! */ - } else if ((id->field_valid & 4) && - (id->dma_ultra & (id->dma_ultra >> 8) & 7)) { - printk(", UDMA(33)"); /* UDMA BIOS-enabled! */ - } else if (id->field_valid & 4) { - printk(", (U)DMA"); /* Can be BIOS-enabled! */ - } else { - printk(", DMA"); - } - } - printk("\n"); - - drive->mult_count = 0; - if (id->max_multsect) { -#ifdef CONFIG_IDEDISK_MULTI_MODE - id->multsect = ((id->max_multsect/2) > 1) ? id->max_multsect : 0; - id->multsect_valid = id->multsect ? 1 : 0; - drive->mult_req = id->multsect_valid ? id->max_multsect : INITIAL_MULT_COUNT; - drive->special.b.set_multmode = drive->mult_req ? 1 : 0; -#else /* original, pre IDE-NFG, per request of AC */ - drive->mult_req = INITIAL_MULT_COUNT; - if (drive->mult_req > id->max_multsect) - drive->mult_req = id->max_multsect; - if (drive->mult_req || ((id->multsect_valid & 1) && id->multsect)) - drive->special.b.set_multmode = 1; -#endif - } - drive->no_io_32bit = id->dword_io ? 1 : 0; -} - -int idedisk_init (void) -{ - ide_drive_t *drive; - int failed = 0; - - MOD_INC_USE_COUNT; - while ((drive = ide_scan_devices (ide_disk, idedisk_driver.name, NULL, failed++)) != NULL) { - if (ide_register_subdriver (drive, &idedisk_driver, IDE_SUBDRIVER_VERSION)) { - printk (KERN_ERR "ide-disk: %s: Failed to register the driver with ide.c\n", drive->name); - continue; - } - idedisk_setup(drive); - if ((!drive->head || drive->head > 16) && !drive->select.b.lba) { - printk(KERN_ERR "%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n", drive->name, drive->head); - (void) idedisk_cleanup(drive); - continue; - } - failed--; - } - ide_register_module(&idedisk_module); - MOD_DEC_USE_COUNT; - return 0; -} - -#ifdef MODULE -int init_module (void) -{ - return idedisk_init(); -} - -void cleanup_module (void) -{ - ide_drive_t *drive; - int failed = 0; - - while ((drive = ide_scan_devices (ide_disk, idedisk_driver.name, &idedisk_driver, failed)) != NULL) { - if (idedisk_cleanup (drive)) { - printk (KERN_ERR "%s: cleanup_module() called while still busy\n", drive->name); - failed++; - } - /* We must remove proc entries defined in this module. - Otherwise we oops while accessing these entries */ - if (drive->proc) - ide_remove_proc_entries(drive->proc, idedisk_proc); - } - ide_unregister_module(&idedisk_module); -} -#endif /* MODULE */ diff --git a/drivers/block/ide-dma.c b/drivers/block/ide-dma.c deleted file mode 100644 index 751424831..000000000 --- a/drivers/block/ide-dma.c +++ /dev/null @@ -1,580 +0,0 @@ -/* - * linux/drivers/block/ide-dma.c Version 4.09 April 23, 1999 - * - * Copyright (c) 1999 Andre Hedrick - * May be copied or modified under the terms of the GNU General Public License - */ - -/* - * Special Thanks to Mark for his Six years of work. - * - * Copyright (c) 1995-1998 Mark Lord - * May be copied or modified under the terms of the GNU General Public License - */ - -/* - * This module provides support for the bus-master IDE DMA functions - * of various PCI chipsets, including the Intel PIIX (i82371FB for - * the 430 FX chipset), the PIIX3 (i82371SB for the 430 HX/VX and - * 440 chipsets), and the PIIX4 (i82371AB for the 430 TX chipset) - * ("PIIX" stands for "PCI ISA IDE Xcellerator"). - * - * Pretty much the same code works for other IDE PCI bus-mastering chipsets. - * - * DMA is supported for all IDE devices (disk drives, cdroms, tapes, floppies). - * - * By default, DMA support is prepared for use, but is currently enabled only - * for drives which already have DMA enabled (UltraDMA or mode 2 multi/single), - * or which are recognized as "good" (see table below). Drives with only mode0 - * or mode1 (multi/single) DMA should also work with this chipset/driver - * (eg. MC2112A) but are not enabled by default. - * - * Use "hdparm -i" to view modes supported by a given drive. - * - * The hdparm-3.5 (or later) utility can be used for manually enabling/disabling - * DMA support, but must be (re-)compiled against this kernel version or later. - * - * To enable DMA, use "hdparm -d1 /dev/hd?" on a per-drive basis after booting. - * If problems arise, ide.c will disable DMA operation after a few retries. - * This error recovery mechanism works and has been extremely well exercised. - * - * IDE drives, depending on their vintage, may support several different modes - * of DMA operation. The boot-time modes are indicated with a "*" in - * the "hdparm -i" listing, and can be changed with *knowledgeable* use of - * the "hdparm -X" feature. There is seldom a need to do this, as drives - * normally power-up with their "best" PIO/DMA modes enabled. - * - * Testing has been done with a rather extensive number of drives, - * with Quantum & Western Digital models generally outperforming the pack, - * and Fujitsu & Conner (and some Seagate which are really Conner) drives - * showing more lackluster throughput. - * - * Keep an eye on /var/adm/messages for "DMA disabled" messages. - * - * Some people have reported trouble with Intel Zappa motherboards. - * This can be fixed by upgrading the AMI BIOS to version 1.00.04.BS0, - * available from ftp://ftp.intel.com/pub/bios/10004bs0.exe - * (thanks to Glen Morrell <glen@spin.Stanford.edu> for researching this). - * - * Thanks to "Christopher J. Reimer" <reimer@doe.carleton.ca> for - * fixing the problem with the BIOS on some Acer motherboards. - * - * Thanks to "Benoit Poulot-Cazajous" <poulot@chorus.fr> for testing - * "TX" chipset compatibility and for providing patches for the "TX" chipset. - * - * Thanks to Christian Brunner <chb@muc.de> for taking a good first crack - * at generic DMA -- his patches were referred to when preparing this code. - * - * Most importantly, thanks to Robert Bringman <rob@mars.trion.com> - * for supplying a Promise UDMA board & WD UDMA drive for this work! - * - * And, yes, Intel Zappa boards really *do* use both PIIX IDE ports. - * - * ACARD ATP850UF Chipset "Modified SCSI Class" with other names - * AEC6210 U/UF - * SIIG's UltraIDE Pro CN-2449 - * TTI HPT343 Chipset "Modified SCSI Class" but reports as an - * unknown storage device. - * NEW check_drive_lists(ide_drive_t *drive, int good_bad) - */ - -#include <linux/config.h> -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/timer.h> -#include <linux/mm.h> -#include <linux/interrupt.h> -#include <linux/pci.h> -#include <linux/init.h> -#include <linux/ide.h> - -#include <asm/io.h> -#include <asm/irq.h> - -extern char *ide_dmafunc_verbose(ide_dma_action_t dmafunc); - -#ifdef CONFIG_IDEDMA_NEW_DRIVE_LISTINGS - -struct drive_list_entry { - char * id_model; - char * id_firmware; -}; - -struct drive_list_entry drive_whitelist [] = { - - { "Micropolis 2112A" , "ALL" }, - { "CONNER CTMA 4000" , "ALL" }, - { "CONNER CTT8000-A" , "ALL" }, - { "ST34342A" , "ALL" }, - { 0 , 0 } -}; - -struct drive_list_entry drive_blacklist [] = { - - { "WDC AC11000H" , "ALL" }, - { "WDC AC22100H" , "ALL" }, - { "WDC AC32500H" , "ALL" }, - { "WDC AC33100H" , "ALL" }, - { "WDC AC31600H" , "ALL" }, - { "WDC AC32100H" , "24.09P07" }, - { "WDC AC23200L" , "21.10N21" }, - { 0 , 0 } - -}; - -int in_drive_list(struct hd_driveid *id, struct drive_list_entry * drive_table) -{ - for ( ; drive_table->id_model ; drive_table++) - if ((!strcmp(drive_table->id_model, id->model)) && - ((!strstr(drive_table->id_firmware, id->fw_rev)) || - (!strcmp(drive_table->id_firmware, "ALL")))) - return 1; - return 0; -} - -#else /* !CONFIG_IDEDMA_NEW_DRIVE_LISTINGS */ - -/* - * good_dma_drives() lists the model names (from "hdparm -i") - * of drives which do not support mode2 DMA but which are - * known to work fine with this interface under Linux. - */ -const char *good_dma_drives[] = {"Micropolis 2112A", - "CONNER CTMA 4000", - "CONNER CTT8000-A", - "ST34342A", /* for Sun Ultra */ - NULL}; - -/* - * bad_dma_drives() lists the model names (from "hdparm -i") - * of drives which supposedly support (U)DMA but which are - * known to corrupt data with this interface under Linux. - * - * This is an empirical list. Its generated from bug reports. That means - * while it reflects actual problem distributions it doesn't answer whether - * the drive or the controller, or cabling, or software, or some combination - * thereof is the fault. If you don't happen to agree with the kernel's - * opinion of your drive - use hdparm to turn DMA on. - */ -const char *bad_dma_drives[] = {"WDC AC11000H", - "WDC AC22100H", - "WDC AC32100H", - "WDC AC32500H", - "WDC AC33100H", - "WDC AC31600H", - NULL}; - -#endif /* CONFIG_IDEDMA_NEW_DRIVE_LISTINGS */ - -/* - * Our Physical Region Descriptor (PRD) table should be large enough - * to handle the biggest I/O request we are likely to see. Since requests - * can have no more than 256 sectors, and since the typical blocksize is - * two or more sectors, we could get by with a limit of 128 entries here for - * the usual worst case. Most requests seem to include some contiguous blocks, - * further reducing the number of table entries required. - * - * The driver reverts to PIO mode for individual requests that exceed - * this limit (possible with 512 byte blocksizes, eg. MSDOS f/s), so handling - * 100% of all crazy scenarios here is not necessary. - * - * As it turns out though, we must allocate a full 4KB page for this, - * so the two PRD tables (ide0 & ide1) will each get half of that, - * allowing each to have about 256 entries (8 bytes each) from this. - */ -#define PRD_BYTES 8 -#define PRD_ENTRIES (PAGE_SIZE / (2 * PRD_BYTES)) - -/* - * dma_intr() is the handler for disk read/write DMA interrupts - */ -ide_startstop_t ide_dma_intr (ide_drive_t *drive) -{ - int i; - byte stat, dma_stat; - - dma_stat = HWIF(drive)->dmaproc(ide_dma_end, drive); - stat = GET_STAT(); /* get drive status */ - if (OK_STAT(stat,DRIVE_READY,drive->bad_wstat|DRQ_STAT)) { - if (!dma_stat) { - struct request *rq = HWGROUP(drive)->rq; - rq = HWGROUP(drive)->rq; - for (i = rq->nr_sectors; i > 0;) { - i -= rq->current_nr_sectors; - ide_end_request(1, HWGROUP(drive)); - } - return ide_stopped; - } - printk("%s: dma_intr: bad DMA status\n", drive->name); - } - return ide_error(drive, "dma_intr", stat); -} - -static int ide_build_sglist (ide_hwif_t *hwif, struct request *rq) -{ - struct buffer_head *bh; - struct scatterlist *sg = hwif->sg_table; - int nents = 0; - - if (rq->cmd == READ) - hwif->sg_dma_direction = PCI_DMA_FROMDEVICE; - else - hwif->sg_dma_direction = PCI_DMA_TODEVICE; - bh = rq->bh; - do { - unsigned char *virt_addr = bh->b_data; - unsigned int size = bh->b_size; - - while ((bh = bh->b_reqnext) != NULL) { - if ((virt_addr + size) != (unsigned char *) bh->b_data) - break; - size += bh->b_size; - } - memset(&sg[nents], 0, sizeof(*sg)); - sg[nents].address = virt_addr; - sg[nents].length = size; - nents++; - } while (bh != NULL); - - return pci_map_sg(hwif->pci_dev, sg, nents, hwif->sg_dma_direction); -} - -/* - * ide_build_dmatable() prepares a dma request. - * Returns 0 if all went okay, returns 1 otherwise. - * May also be invoked from trm290.c - */ -int ide_build_dmatable (ide_drive_t *drive, ide_dma_action_t func) -{ - unsigned int *table = HWIF(drive)->dmatable_cpu; -#ifdef CONFIG_BLK_DEV_TRM290 - unsigned int is_trm290_chipset = (HWIF(drive)->chipset == ide_trm290); -#else - const int is_trm290_chipset = 0; -#endif - unsigned int count = 0; - int i; - struct scatterlist *sg; - - HWIF(drive)->sg_nents = i = ide_build_sglist(HWIF(drive), HWGROUP(drive)->rq); - - sg = HWIF(drive)->sg_table; - while (i && sg_dma_len(sg)) { - u32 cur_addr; - u32 cur_len; - - cur_addr = sg_dma_address(sg); - cur_len = sg_dma_len(sg); - - while (cur_len) { - if (++count >= PRD_ENTRIES) { - printk("%s: DMA table too small\n", drive->name); - pci_unmap_sg(HWIF(drive)->pci_dev, - HWIF(drive)->sg_table, - HWIF(drive)->sg_nents, - HWIF(drive)->sg_dma_direction); - return 0; /* revert to PIO for this request */ - } else { - u32 xcount, bcount = 0x10000 - (cur_addr & 0xffff); - - if (bcount > cur_len) - bcount = cur_len; - *table++ = cpu_to_le32(cur_addr); - xcount = bcount & 0xffff; - if (is_trm290_chipset) - xcount = ((xcount >> 2) - 1) << 16; - *table++ = cpu_to_le32(xcount); - cur_addr += bcount; - cur_len -= bcount; - } - } - - sg++; - i--; - } - - if (!count) - printk("%s: empty DMA table?\n", drive->name); - else if (!is_trm290_chipset) - *--table |= cpu_to_le32(0x80000000); - - return count; -} - -/* Teardown mappings after DMA has completed. */ -void ide_destroy_dmatable (ide_drive_t *drive) -{ - struct pci_dev *dev = HWIF(drive)->pci_dev; - struct scatterlist *sg = HWIF(drive)->sg_table; - int nents = HWIF(drive)->sg_nents; - - pci_unmap_sg(dev, sg, nents, HWIF(drive)->sg_dma_direction); -} - -/* - * For both Blacklisted and Whitelisted drives. - * This is setup to be called as an extern for future support - * to other special driver code. - */ -int check_drive_lists (ide_drive_t *drive, int good_bad) -{ - struct hd_driveid *id = drive->id; - -#ifdef CONFIG_IDEDMA_NEW_DRIVE_LISTINGS - if (good_bad) { - return in_drive_list(id, drive_whitelist); - } else { - int blacklist = in_drive_list(id, drive_blacklist); - if (blacklist) - printk("%s: Disabling (U)DMA for %s\n", drive->name, id->model); - return(blacklist); - } -#else /* !CONFIG_IDEDMA_NEW_DRIVE_LISTINGS */ - const char **list; - - if (good_bad) { - /* Consult the list of known "good" drives */ - list = good_dma_drives; - while (*list) { - if (!strcmp(*list++,id->model)) - return 1; - } - } else { - /* Consult the list of known "bad" drives */ - list = bad_dma_drives; - while (*list) { - if (!strcmp(*list++,id->model)) { - printk("%s: Disabling (U)DMA for %s\n", - drive->name, id->model); - return 1; - } - } - } -#endif /* CONFIG_IDEDMA_NEW_DRIVE_LISTINGS */ - return 0; -} - -static int config_drive_for_dma (ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - ide_hwif_t *hwif = HWIF(drive); - - if (id && (id->capability & 1) && hwif->autodma) { - /* Consult the list of known "bad" drives */ - if (ide_dmaproc(ide_dma_bad_drive, drive)) - return hwif->dmaproc(ide_dma_off, drive); - - /* Enable DMA on any drive that has UltraDMA (mode 3/4) enabled */ - if ((id->field_valid & 4) && (hwif->udma_four) && (id->hw_config & 0x2000)) - if ((id->dma_ultra & (id->dma_ultra >> 11) & 3)) - return hwif->dmaproc(ide_dma_on, drive); - /* Enable DMA on any drive that has UltraDMA (mode 0/1/2) enabled */ - if (id->field_valid & 4) /* UltraDMA */ - if ((id->dma_ultra & (id->dma_ultra >> 8) & 7)) - return hwif->dmaproc(ide_dma_on, drive); - /* Enable DMA on any drive that has mode2 DMA (multi or single) enabled */ - if (id->field_valid & 2) /* regular DMA */ - if ((id->dma_mword & 0x404) == 0x404 || (id->dma_1word & 0x404) == 0x404) - return hwif->dmaproc(ide_dma_on, drive); - /* Consult the list of known "good" drives */ - if (ide_dmaproc(ide_dma_good_drive, drive)) - return hwif->dmaproc(ide_dma_on, drive); - } - return hwif->dmaproc(ide_dma_off_quietly, drive); -} - -/* - * ide_dmaproc() initiates/aborts DMA read/write operations on a drive. - * - * The caller is assumed to have selected the drive and programmed the drive's - * sector address using CHS or LBA. All that remains is to prepare for DMA - * and then issue the actual read/write DMA/PIO command to the drive. - * - * For ATAPI devices, we just prepare for DMA and return. The caller should - * then issue the packet command to the drive and call us again with - * ide_dma_begin afterwards. - * - * Returns 0 if all went well. - * Returns 1 if DMA read/write could not be started, in which case - * the caller should revert to PIO for the current request. - * May also be invoked from trm290.c - */ -int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - unsigned long dma_base = hwif->dma_base; - byte unit = (drive->select.b.unit & 0x01); - unsigned int count, reading = 0; - byte dma_stat; - - switch (func) { - case ide_dma_off: - printk("%s: DMA disabled\n", drive->name); - case ide_dma_off_quietly: - outb(inb(dma_base+2) & ~(1<<(5+unit)), dma_base+2); - case ide_dma_on: - drive->using_dma = (func == ide_dma_on); - if (drive->using_dma) - outb(inb(dma_base+2)|(1<<(5+unit)), dma_base+2); - return 0; - case ide_dma_check: - return config_drive_for_dma (drive); - case ide_dma_read: - reading = 1 << 3; - case ide_dma_write: - if (!(count = ide_build_dmatable(drive, func))) - return 1; /* try PIO instead of DMA */ - outl(hwif->dmatable_dma, dma_base + 4); /* PRD table */ - outb(reading, dma_base); /* specify r/w */ - outb(inb(dma_base+2)|6, dma_base+2); /* clear INTR & ERROR flags */ - drive->waiting_for_dma = 1; - if (drive->media != ide_disk) - return 0; - ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL); /* issue cmd to drive */ - OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); - case ide_dma_begin: - /* Note that this is done *after* the cmd has - * been issued to the drive, as per the BM-IDE spec. - * The Promise Ultra33 doesn't work correctly when - * we do this part before issuing the drive cmd. - */ - outb(inb(dma_base)|1, dma_base); /* start DMA */ - return 0; - case ide_dma_end: /* returns 1 on error, 0 otherwise */ - drive->waiting_for_dma = 0; - outb(inb(dma_base)&~1, dma_base); /* stop DMA */ - dma_stat = inb(dma_base+2); /* get DMA status */ - outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */ - ide_destroy_dmatable(drive); /* purge DMA mappings */ - return (dma_stat & 7) != 4; /* verify good DMA status */ - case ide_dma_test_irq: /* returns 1 if dma irq issued, 0 otherwise */ - dma_stat = inb(dma_base+2); - return (dma_stat & 4) == 4; /* return 1 if INTR asserted */ - case ide_dma_bad_drive: - case ide_dma_good_drive: - return check_drive_lists(drive, (func == ide_dma_good_drive)); - case ide_dma_lostirq: - case ide_dma_timeout: - printk("ide_dmaproc: chipset supported %s func only: %d\n", ide_dmafunc_verbose(func), func); - return 1; - default: - printk("ide_dmaproc: unsupported %s func: %d\n", ide_dmafunc_verbose(func), func); - return 1; - } -} - -/* - * Needed for allowing full modular support of ide-driver - */ -int ide_release_dma (ide_hwif_t *hwif) -{ - if (hwif->dmatable_cpu) { - pci_free_consistent(hwif->pci_dev, - PRD_ENTRIES * PRD_BYTES, - hwif->dmatable_cpu, - hwif->dmatable_dma); - hwif->dmatable_cpu = NULL; - } - if (hwif->sg_table) { - kfree(hwif->sg_table); - hwif->sg_table = NULL; - } - if ((hwif->dma_extra) && (hwif->channel == 0)) - release_region((hwif->dma_base + 16), hwif->dma_extra); - release_region(hwif->dma_base, 8); - return 1; -} - -/* - * This can be called for a dynamically installed interface. Don't __init it - */ - -void ide_setup_dma (ide_hwif_t *hwif, unsigned long dma_base, unsigned int num_ports) -{ - printk(" %s: BM-DMA at 0x%04lx-0x%04lx", hwif->name, dma_base, dma_base + num_ports - 1); - if (check_region(dma_base, num_ports)) { - printk(" -- ERROR, PORT ADDRESSES ALREADY IN USE\n"); - return; - } - request_region(dma_base, num_ports, hwif->name); - hwif->dma_base = dma_base; - hwif->dmatable_cpu = pci_alloc_consistent(hwif->pci_dev, - PRD_ENTRIES * PRD_BYTES, - &hwif->dmatable_dma); - if (hwif->dmatable_cpu == NULL) - goto dma_alloc_failure; - - hwif->sg_table = kmalloc(sizeof(struct scatterlist) * PRD_ENTRIES, - GFP_KERNEL); - if (hwif->sg_table == NULL) { - pci_free_consistent(hwif->pci_dev, PRD_ENTRIES * PRD_BYTES, - hwif->dmatable_cpu, hwif->dmatable_dma); - goto dma_alloc_failure; - } - - hwif->dmaproc = &ide_dmaproc; - - if (hwif->chipset != ide_trm290) { - byte dma_stat = inb(dma_base+2); - printk(", BIOS settings: %s:%s, %s:%s", - hwif->drives[0].name, (dma_stat & 0x20) ? "DMA" : "pio", - hwif->drives[1].name, (dma_stat & 0x40) ? "DMA" : "pio"); - } - printk("\n"); - return; - -dma_alloc_failure: - printk(" -- ERROR, UNABLE TO ALLOCATE DMA TABLES\n"); -} - -/* - * Fetch the DMA Bus-Master-I/O-Base-Address (BMIBA) from PCI space: - */ -unsigned long __init ide_get_or_set_dma_base (ide_hwif_t *hwif, int extra, const char *name) -{ - unsigned long dma_base = 0; - struct pci_dev *dev = hwif->pci_dev; - - if (hwif->mate && hwif->mate->dma_base) { - dma_base = hwif->mate->dma_base - (hwif->channel ? 0 : 8); - } else { - dma_base = dev->resource[4].start; - if (!dma_base || dma_base == PCI_BASE_ADDRESS_IO_MASK) { - printk("%s: dma_base is invalid (0x%04lx)\n", name, dma_base); - dma_base = 0; - } - } - if (dma_base) { - if (extra) /* PDC20246, PDC20262, HPT343, & HPT366 */ - request_region(dma_base+16, extra, name); - dma_base += hwif->channel ? 8 : 0; - hwif->dma_extra = extra; - - switch(dev->device) { - case PCI_DEVICE_ID_AL_M5219: - case PCI_DEVICE_ID_AMD_VIPER_7409: - case PCI_DEVICE_ID_CMD_643: - outb(inb(dma_base+2) & 0x60, dma_base+2); - if (inb(dma_base+2) & 0x80) { - printk("%s: simplex device: DMA forced\n", name); - } - break; - default: - /* - * If the device claims "simplex" DMA, - * this means only one of the two interfaces - * can be trusted with DMA at any point in time. - * So we should enable DMA only on one of the - * two interfaces. - */ - if ((inb(dma_base+2) & 0x80)) { /* simplex device? */ - if ((!hwif->drives[0].present && !hwif->drives[1].present) || - (hwif->mate && hwif->mate->dma_base)) { - printk("%s: simplex device: DMA disabled\n", name); - dma_base = 0; - } - } - } - } - return dma_base; -} diff --git a/drivers/block/ide-features.c b/drivers/block/ide-features.c deleted file mode 100644 index 3f29ed591..000000000 --- a/drivers/block/ide-features.c +++ /dev/null @@ -1,312 +0,0 @@ -/* - * linux/drivers/block/ide-features.c Version 0.03 Feb. 10, 2000 - * - * Copyright (C) 1999-2000 Linus Torvalds & authors (see below) - * - * Copyright (C) 1999-2000 Andre Hedrick <andre@suse.com> - * - * Extracts if ide.c to address the evolving transfer rate code for - * the SETFEATURES_XFER callouts. Various parts of any given function - * are credited to previous ATA-IDE maintainers. - * - * May be copied or modified under the terms of the GNU General Public License - */ - -#define __NO_VERSION__ -#include <linux/module.h> -#include <linux/types.h> -#include <linux/string.h> -#include <linux/kernel.h> -#include <linux/timer.h> -#include <linux/mm.h> -#include <linux/interrupt.h> -#include <linux/major.h> -#include <linux/errno.h> -#include <linux/genhd.h> -#include <linux/blkpg.h> -#include <linux/malloc.h> -#include <linux/pci.h> -#include <linux/delay.h> -#include <linux/ide.h> - -#include <asm/byteorder.h> -#include <asm/irq.h> -#include <asm/uaccess.h> -#include <asm/io.h> -#include <asm/bitops.h> - -#define SETFEATURES_CONTROL_REG (0) /* some arch's may need */ - -/* - * A Verbose noise maker for debugging on the attempted transfer rates. - */ -char *ide_xfer_verbose (byte xfer_rate) -{ - switch(xfer_rate) { - case XFER_UDMA_7: return("UDMA 7"); - case XFER_UDMA_6: return("UDMA 6"); - case XFER_UDMA_5: return("UDMA 5"); - case XFER_UDMA_4: return("UDMA 4"); - case XFER_UDMA_3: return("UDMA 3"); - case XFER_UDMA_2: return("UDMA 2"); - case XFER_UDMA_1: return("UDMA 1"); - case XFER_UDMA_0: return("UDMA 0"); - case XFER_MW_DMA_2: return("MW DMA 2"); - case XFER_MW_DMA_1: return("MW DMA 1"); - case XFER_MW_DMA_0: return("MW DMA 0"); - case XFER_SW_DMA_2: return("SW DMA 2"); - case XFER_SW_DMA_1: return("SW DMA 1"); - case XFER_SW_DMA_0: return("SW DMA 0"); - case XFER_PIO_4: return("PIO 4"); - case XFER_PIO_3: return("PIO 3"); - case XFER_PIO_2: return("PIO 2"); - case XFER_PIO_1: return("PIO 1"); - case XFER_PIO_0: return("PIO 0"); - case XFER_PIO_SLOW: return("PIO SLOW"); - default: return("XFER ERROR"); - } -} - -/* - * - */ -char *ide_media_verbose (ide_drive_t *drive) -{ - switch (drive->media) { - case ide_scsi: return("scsi "); - case ide_disk: return("disk "); - case ide_optical: return("optical"); - case ide_cdrom: return("cdrom "); - case ide_tape: return("tape "); - case ide_floppy: return("floppy "); - default: return("???????"); - } -} - -/* - * A Verbose noise maker for debugging on the attempted dmaing calls. - */ -char *ide_dmafunc_verbose (ide_dma_action_t dmafunc) -{ - switch (dmafunc) { - case ide_dma_read: return("ide_dma_read"); - case ide_dma_write: return("ide_dma_write"); - case ide_dma_begin: return("ide_dma_begin"); - case ide_dma_end: return("ide_dma_end:"); - case ide_dma_check: return("ide_dma_check"); - case ide_dma_on: return("ide_dma_on"); - case ide_dma_off: return("ide_dma_off"); - case ide_dma_off_quietly: return("ide_dma_off_quietly"); - case ide_dma_test_irq: return("ide_dma_test_irq"); - case ide_dma_bad_drive: return("ide_dma_bad_drive"); - case ide_dma_good_drive: return("ide_dma_good_drive"); - case ide_dma_lostirq: return("ide_dma_lostirq"); - case ide_dma_timeout: return("ide_dma_timeout"); - default: return("unknown"); - } -} - -/* - * Update the - */ -int ide_driveid_update (ide_drive_t *drive) -{ - /* - * Re-read drive->id for possible DMA mode - * change (copied from ide-probe.c) - */ - struct hd_driveid *id; - unsigned long timeout, irqs, flags; - - probe_irq_off(probe_irq_on()); - irqs = probe_irq_on(); - if (IDE_CONTROL_REG) - OUT_BYTE(drive->ctl,IDE_CONTROL_REG); - ide_delay_50ms(); - OUT_BYTE(WIN_IDENTIFY, IDE_COMMAND_REG); - timeout = jiffies + WAIT_WORSTCASE; - do { - if (0 < (signed long)(jiffies - timeout)) { - if (irqs) - (void) probe_irq_off(irqs); - return 0; /* drive timed-out */ - } - ide_delay_50ms(); /* give drive a breather */ - } while (IN_BYTE(IDE_ALTSTATUS_REG) & BUSY_STAT); - ide_delay_50ms(); /* wait for IRQ and DRQ_STAT */ - if (!OK_STAT(GET_STAT(),DRQ_STAT,BAD_R_STAT)) - return 0; - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only; some systems need this */ - id = kmalloc(SECTOR_WORDS*4, GFP_ATOMIC); - ide_input_data(drive, id, SECTOR_WORDS); - (void) GET_STAT(); /* clear drive IRQ */ - ide__sti(); /* local CPU only */ - __restore_flags(flags); /* local CPU only */ - ide_fix_driveid(id); - if (id && id->cyls) { - drive->id->dma_ultra = id->dma_ultra; - drive->id->dma_mword = id->dma_mword; - drive->id->dma_1word = id->dma_1word; - /* anything more ? */ -#ifdef DEBUG - printk("%s: dma_ultra=%04X, dma_mword=%04X, dma_1word=%04X\n", - drive->name, id->dma_ultra, id->dma_mword, id->dma_1word); -#endif - kfree(id); - } - return 1; -} - -/* - * Verify that we are doing an approved SETFEATURES_XFER with respect - * to the hardware being able to support request. Since some hardware - * can improperly report capabilties, we check to see if the host adapter - * in combination with the device (usually a disk) properly detect - * and acknowledge each end of the ribbon. - */ -int ide_ata66_check (ide_drive_t *drive, int cmd, int nsect, int feature) -{ - if ((cmd == WIN_SETFEATURES) && - (nsect > XFER_UDMA_2) && - (feature == SETFEATURES_XFER)) { - if (!HWIF(drive)->udma_four) { - printk("%s: Speed warnings UDMA 3/4 is not functional.\n", HWIF(drive)->name); - return 1; - } - if ((drive->id->hw_config & 0x2000) == 0) { - printk("%s: Speed warnings UDMA 3/4 is not functional.\n", drive->name); - return 1; - } - } - return 0; -} - -/* - * Backside of HDIO_DRIVE_CMD call of SETFEATURES_XFER. - * 1 : Safe to update drive->id DMA registers. - * 0 : OOPs not allowed. - */ -int set_transfer (ide_drive_t *drive, int cmd, int nsect, int feature) -{ - struct hd_driveid *id = drive->id; - - if ((cmd == WIN_SETFEATURES) && - (nsect >= XFER_SW_DMA_0) && - (feature == SETFEATURES_XFER) && - (id->dma_ultra || id->dma_mword || id->dma_1word)) - return 1; - return 0; -} - -/* - * Similar to ide_wait_stat(), except it never calls ide_error internally. - * This is a kludge to handle the new ide_config_drive_speed() function, - * and should not otherwise be used anywhere. Eventually, the tuneproc's - * should be updated to return ide_startstop_t, in which case we can get - * rid of this abomination again. :) -ml - * - * It is gone.......... - * - * const char *msg == consider adding for verbose errors. - */ -int ide_config_drive_speed (ide_drive_t *drive, byte speed) -{ - ide_hwif_t *hwif = HWIF(drive); - int i, error = 1; - byte unit = (drive->select.b.unit & 0x01); - byte stat; - - /* - * Don't use ide_wait_cmd here - it will - * attempt to set_geometry and recalibrate, - * but for some reason these don't work at - * this point (lost interrupt). - */ - /* - * Select the drive, and issue the SETFEATURES command - */ - disable_irq(hwif->irq); /* disable_irq_nosync ?? */ - udelay(1); - SELECT_DRIVE(HWIF(drive), drive); - udelay(1); - if (IDE_CONTROL_REG) - OUT_BYTE(drive->ctl | 2, IDE_CONTROL_REG); - OUT_BYTE(speed, IDE_NSECTOR_REG); - OUT_BYTE(SETFEATURES_XFER, IDE_FEATURE_REG); - OUT_BYTE(WIN_SETFEATURES, IDE_COMMAND_REG); - if ((IDE_CONTROL_REG) && (SETFEATURES_CONTROL_REG)) - OUT_BYTE(drive->ctl, IDE_CONTROL_REG); - udelay(1); - /* - * Wait for drive to become non-BUSY - */ - if ((stat = GET_STAT()) & BUSY_STAT) { - unsigned long flags, timeout; - __save_flags(flags); /* local CPU only */ - ide__sti(); /* local CPU only -- for jiffies */ - timeout = jiffies + WAIT_CMD; - while ((stat = GET_STAT()) & BUSY_STAT) { - if (0 < (signed long)(jiffies - timeout)) - break; - } - __restore_flags(flags); /* local CPU only */ - } - - /* - * Allow status to settle, then read it again. - * A few rare drives vastly violate the 400ns spec here, - * so we'll wait up to 10usec for a "good" status - * rather than expensively fail things immediately. - * This fix courtesy of Matthew Faupel & Niccolo Rigacci. - */ - for (i = 0; i < 10; i++) { - udelay(1); - if (OK_STAT((stat = GET_STAT()), DRIVE_READY, BUSY_STAT|DRQ_STAT|ERR_STAT)) { - error = 0; - break; - } - } - - enable_irq(hwif->irq); - - if (error) { - (void) ide_dump_status(drive, "set_drive_speed_status", stat); - return error; - } - - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - - if (speed > XFER_PIO_4) { - outb(inb(hwif->dma_base+2)|(1<<(5+unit)), hwif->dma_base+2); - } else { - outb(inb(hwif->dma_base+2) & ~(1<<(5+unit)), hwif->dma_base+2); - } - - switch(speed) { - case XFER_UDMA_7: drive->id->dma_ultra |= 0x8080; break; - case XFER_UDMA_6: drive->id->dma_ultra |= 0x4040; break; - case XFER_UDMA_5: drive->id->dma_ultra |= 0x2020; break; - case XFER_UDMA_4: drive->id->dma_ultra |= 0x1010; break; - case XFER_UDMA_3: drive->id->dma_ultra |= 0x0808; break; - case XFER_UDMA_2: drive->id->dma_ultra |= 0x0404; break; - case XFER_UDMA_1: drive->id->dma_ultra |= 0x0202; break; - case XFER_UDMA_0: drive->id->dma_ultra |= 0x0101; break; - case XFER_MW_DMA_2: drive->id->dma_mword |= 0x0404; break; - case XFER_MW_DMA_1: drive->id->dma_mword |= 0x0202; break; - case XFER_MW_DMA_0: drive->id->dma_mword |= 0x0101; break; - case XFER_SW_DMA_2: drive->id->dma_1word |= 0x0404; break; - case XFER_SW_DMA_1: drive->id->dma_1word |= 0x0202; break; - case XFER_SW_DMA_0: drive->id->dma_1word |= 0x0101; break; - default: break; - } - return error; -} - -EXPORT_SYMBOL(ide_driveid_update); -EXPORT_SYMBOL(ide_ata66_check); -EXPORT_SYMBOL(set_transfer); -EXPORT_SYMBOL(ide_config_drive_speed); - diff --git a/drivers/block/ide-floppy.c b/drivers/block/ide-floppy.c deleted file mode 100644 index bee6a4c6c..000000000 --- a/drivers/block/ide-floppy.c +++ /dev/null @@ -1,1680 +0,0 @@ -/* - * linux/drivers/block/ide-floppy.c Version 0.9 Jul 4, 1999 - * - * Copyright (C) 1996 - 1999 Gadi Oxman <gadio@netvision.net.il> - */ - -/* - * IDE ATAPI floppy driver. - * - * The driver currently doesn't have any fancy features, just the bare - * minimum read/write support. - * - * Many thanks to Lode Leroy <Lode.Leroy@www.ibase.be>, who tested so many - * ALPHA patches to this driver on an EASYSTOR LS-120 ATAPI floppy drive. - * - * Ver 0.1 Oct 17 96 Initial test version, mostly based on ide-tape.c. - * Ver 0.2 Oct 31 96 Minor changes. - * Ver 0.3 Dec 2 96 Fixed error recovery bug. - * Ver 0.4 Jan 26 97 Add support for the HDIO_GETGEO ioctl. - * Ver 0.5 Feb 21 97 Add partitions support. - * Use the minimum of the LBA and CHS capacities. - * Avoid hwgroup->rq == NULL on the last irq. - * Fix potential null dereferencing with DEBUG_LOG. - * Ver 0.8 Dec 7 97 Increase irq timeout from 10 to 50 seconds. - * Add media write-protect detection. - * Issue START command only if TEST UNIT READY fails. - * Add work-around for IOMEGA ZIP revision 21.D. - * Remove idefloppy_get_capabilities(). - * Ver 0.9 Jul 4 99 Fix a bug which might have caused the number of - * bytes requested on each interrupt to be zero. - * Thanks to <shanos@es.co.nz> for pointing this out. - */ - -#define IDEFLOPPY_VERSION "0.9" - -#include <linux/config.h> -#include <linux/module.h> -#include <linux/types.h> -#include <linux/string.h> -#include <linux/kernel.h> -#include <linux/delay.h> -#include <linux/timer.h> -#include <linux/mm.h> -#include <linux/interrupt.h> -#include <linux/major.h> -#include <linux/errno.h> -#include <linux/genhd.h> -#include <linux/malloc.h> -#include <linux/cdrom.h> -#include <linux/ide.h> - -#include <asm/byteorder.h> -#include <asm/irq.h> -#include <asm/uaccess.h> -#include <asm/io.h> -#include <asm/unaligned.h> -#include <asm/bitops.h> - -/* - * The following are used to debug the driver. - */ -#define IDEFLOPPY_DEBUG_LOG 0 -#define IDEFLOPPY_DEBUG_INFO 0 -#define IDEFLOPPY_DEBUG_BUGS 1 - -/* - * Some drives require a longer irq timeout. - */ -#define IDEFLOPPY_WAIT_CMD (5 * WAIT_CMD) - -/* - * After each failed packet command we issue a request sense command - * and retry the packet command IDEFLOPPY_MAX_PC_RETRIES times. - */ -#define IDEFLOPPY_MAX_PC_RETRIES 3 - -/* - * With each packet command, we allocate a buffer of - * IDEFLOPPY_PC_BUFFER_SIZE bytes. - */ -#define IDEFLOPPY_PC_BUFFER_SIZE 256 - -/* - * In various places in the driver, we need to allocate storage - * for packet commands and requests, which will remain valid while - * we leave the driver to wait for an interrupt or a timeout event. - */ -#define IDEFLOPPY_PC_STACK (10 + IDEFLOPPY_MAX_PC_RETRIES) - -/* - * Our view of a packet command. - */ -typedef struct idefloppy_packet_command_s { - u8 c[12]; /* Actual packet bytes */ - int retries; /* On each retry, we increment retries */ - int error; /* Error code */ - int request_transfer; /* Bytes to transfer */ - int actually_transferred; /* Bytes actually transferred */ - int buffer_size; /* Size of our data buffer */ - char *b_data; /* Pointer which runs on the buffers */ - int b_count; /* Missing/Available data on the current buffer */ - struct request *rq; /* The corresponding request */ - byte *buffer; /* Data buffer */ - byte *current_position; /* Pointer into the above buffer */ - void (*callback) (ide_drive_t *); /* Called when this packet command is completed */ - byte pc_buffer[IDEFLOPPY_PC_BUFFER_SIZE]; /* Temporary buffer */ - unsigned int flags; /* Status/Action bit flags */ -} idefloppy_pc_t; - -/* - * Packet command flag bits. - */ -#define PC_ABORT 0 /* Set when an error is considered normal - We won't retry */ -#define PC_DMA_RECOMMENDED 2 /* 1 when we prefer to use DMA if possible */ -#define PC_DMA_IN_PROGRESS 3 /* 1 while DMA in progress */ -#define PC_DMA_ERROR 4 /* 1 when encountered problem during DMA */ -#define PC_WRITING 5 /* Data direction */ - -/* - * Removable Block Access Capabilities Page - */ -typedef struct { -#if defined(__LITTLE_ENDIAN_BITFIELD) - unsigned page_code :6; /* Page code - Should be 0x1b */ - unsigned reserved1_6 :1; /* Reserved */ - unsigned ps :1; /* Should be 0 */ -#elif defined(__BIG_ENDIAN_BITFIELD) - unsigned ps :1; /* Should be 0 */ - unsigned reserved1_6 :1; /* Reserved */ - unsigned page_code :6; /* Page code - Should be 0x1b */ -#else -#error "Bitfield endianness not defined! Check your byteorder.h" -#endif - u8 page_length; /* Page Length - Should be 0xa */ -#if defined(__LITTLE_ENDIAN_BITFIELD) - unsigned reserved2 :6; - unsigned srfp :1; /* Supports reporting progress of format */ - unsigned sflp :1; /* System floppy type device */ - unsigned tlun :3; /* Total logical units supported by the device */ - unsigned reserved3 :3; - unsigned sml :1; /* Single / Multiple lun supported */ - unsigned ncd :1; /* Non cd optical device */ -#elif defined(__BIG_ENDIAN_BITFIELD) - unsigned sflp :1; /* System floppy type device */ - unsigned srfp :1; /* Supports reporting progress of format */ - unsigned reserved2 :6; - unsigned ncd :1; /* Non cd optical device */ - unsigned sml :1; /* Single / Multiple lun supported */ - unsigned reserved3 :3; - unsigned tlun :3; /* Total logical units supported by the device */ -#else -#error "Bitfield endianness not defined! Check your byteorder.h" -#endif - u8 reserved[8]; -} idefloppy_capabilities_page_t; - -/* - * Flexible disk page. - */ -typedef struct { -#if defined(__LITTLE_ENDIAN_BITFIELD) - unsigned page_code :6; /* Page code - Should be 0x5 */ - unsigned reserved1_6 :1; /* Reserved */ - unsigned ps :1; /* The device is capable of saving the page */ -#elif defined(__BIG_ENDIAN_BITFIELD) - unsigned ps :1; /* The device is capable of saving the page */ - unsigned reserved1_6 :1; /* Reserved */ - unsigned page_code :6; /* Page code - Should be 0x5 */ -#else -#error "Bitfield endianness not defined! Check your byteorder.h" -#endif - u8 page_length; /* Page Length - Should be 0x1e */ - u16 transfer_rate; /* In kilobits per second */ - u8 heads, sectors; /* Number of heads, Number of sectors per track */ - u16 sector_size; /* Byes per sector */ - u16 cyls; /* Number of cylinders */ - u8 reserved10[10]; - u8 motor_delay; /* Motor off delay */ - u8 reserved21[7]; - u16 rpm; /* Rotations per minute */ - u8 reserved30[2]; -} idefloppy_flexible_disk_page_t; - -/* - * Format capacity - */ -typedef struct { - u8 reserved[3]; - u8 length; /* Length of the following descriptors in bytes */ -} idefloppy_capacity_header_t; - -typedef struct { - u32 blocks; /* Number of blocks */ -#if defined(__LITTLE_ENDIAN_BITFIELD) - unsigned dc :2; /* Descriptor Code */ - unsigned reserved :6; -#elif defined(__BIG_ENDIAN_BITFIELD) - unsigned reserved :6; - unsigned dc :2; /* Descriptor Code */ -#else -#error "Bitfield endianness not defined! Check your byteorder.h" -#endif - u8 length_msb; /* Block Length (MSB)*/ - u16 length; /* Block Length */ -} idefloppy_capacity_descriptor_t; - -#define CAPACITY_INVALID 0x00 -#define CAPACITY_UNFORMATTED 0x01 -#define CAPACITY_CURRENT 0x02 -#define CAPACITY_NO_CARTRIDGE 0x03 - -/* - * Most of our global data which we need to save even as we leave the - * driver due to an interrupt or a timer event is stored in a variable - * of type idefloppy_floppy_t, defined below. - */ -typedef struct { - ide_drive_t *drive; - - idefloppy_pc_t *pc; /* Current packet command */ - idefloppy_pc_t *failed_pc; /* Last failed packet command */ - idefloppy_pc_t pc_stack[IDEFLOPPY_PC_STACK];/* Packet command stack */ - int pc_stack_index; /* Next free packet command storage space */ - struct request rq_stack[IDEFLOPPY_PC_STACK]; - int rq_stack_index; /* We implement a circular array */ - - /* - * Last error information - */ - byte sense_key, asc, ascq; - - /* - * Device information - */ - int blocks, block_size, bs_factor; /* Current format */ - idefloppy_capacity_descriptor_t capacity; /* Last format capacity */ - idefloppy_flexible_disk_page_t flexible_disk_page; /* Copy of the flexible disk page */ - int wp; /* Write protect */ - - unsigned int flags; /* Status/Action flags */ -} idefloppy_floppy_t; - -/* - * Floppy flag bits values. - */ -#define IDEFLOPPY_DRQ_INTERRUPT 0 /* DRQ interrupt device */ -#define IDEFLOPPY_MEDIA_CHANGED 1 /* Media may have changed */ -#define IDEFLOPPY_USE_READ12 2 /* Use READ12/WRITE12 or READ10/WRITE10 */ - -/* - * ATAPI floppy drive packet commands - */ -#define IDEFLOPPY_FORMAT_UNIT_CMD 0x04 -#define IDEFLOPPY_INQUIRY_CMD 0x12 -#define IDEFLOPPY_MODE_SELECT_CMD 0x55 -#define IDEFLOPPY_MODE_SENSE_CMD 0x5a -#define IDEFLOPPY_READ10_CMD 0x28 -#define IDEFLOPPY_READ12_CMD 0xa8 -#define IDEFLOPPY_READ_CAPACITY_CMD 0x23 -#define IDEFLOPPY_REQUEST_SENSE_CMD 0x03 -#define IDEFLOPPY_PREVENT_REMOVAL_CMD 0x1e -#define IDEFLOPPY_SEEK_CMD 0x2b -#define IDEFLOPPY_START_STOP_CMD 0x1b -#define IDEFLOPPY_TEST_UNIT_READY_CMD 0x00 -#define IDEFLOPPY_VERIFY_CMD 0x2f -#define IDEFLOPPY_WRITE10_CMD 0x2a -#define IDEFLOPPY_WRITE12_CMD 0xaa -#define IDEFLOPPY_WRITE_VERIFY_CMD 0x2e - -/* - * Defines for the mode sense command - */ -#define MODE_SENSE_CURRENT 0x00 -#define MODE_SENSE_CHANGEABLE 0x01 -#define MODE_SENSE_DEFAULT 0x02 -#define MODE_SENSE_SAVED 0x03 - -/* - * Special requests for our block device strategy routine. - */ -#define IDEFLOPPY_FIRST_RQ 90 - -/* - * IDEFLOPPY_PC_RQ is used to queue a packet command in the request queue. - */ -#define IDEFLOPPY_PC_RQ 90 - -#define IDEFLOPPY_LAST_RQ 90 - -/* - * A macro which can be used to check if a given request command - * originated in the driver or in the buffer cache layer. - */ -#define IDEFLOPPY_RQ_CMD(cmd) ((cmd >= IDEFLOPPY_FIRST_RQ) && (cmd <= IDEFLOPPY_LAST_RQ)) - -/* - * Error codes which are returned in rq->errors to the higher part - * of the driver. - */ -#define IDEFLOPPY_ERROR_GENERAL 101 - -/* - * The ATAPI Status Register. - */ -typedef union { - unsigned all :8; - struct { -#if defined(__LITTLE_ENDIAN_BITFIELD) - unsigned check :1; /* Error occurred */ - unsigned idx :1; /* Reserved */ - unsigned corr :1; /* Correctable error occurred */ - unsigned drq :1; /* Data is request by the device */ - unsigned dsc :1; /* Media access command finished */ - unsigned reserved5 :1; /* Reserved */ - unsigned drdy :1; /* Ignored for ATAPI commands (ready to accept ATA command) */ - unsigned bsy :1; /* The device has access to the command block */ -#elif defined(__BIG_ENDIAN_BITFIELD) - unsigned bsy :1; /* The device has access to the command block */ - unsigned drdy :1; /* Ignored for ATAPI commands (ready to accept ATA command) */ - unsigned reserved5 :1; /* Reserved */ - unsigned dsc :1; /* Media access command finished */ - unsigned drq :1; /* Data is request by the device */ - unsigned corr :1; /* Correctable error occurred */ - unsigned idx :1; /* Reserved */ - unsigned check :1; /* Error occurred */ -#else -#error "Bitfield endianness not defined! Check your byteorder.h" -#endif - } b; -} idefloppy_status_reg_t; - -/* - * The ATAPI error register. - */ -typedef union { - unsigned all :8; - struct { -#if defined(__LITTLE_ENDIAN_BITFIELD) - unsigned ili :1; /* Illegal Length Indication */ - unsigned eom :1; /* End Of Media Detected */ - unsigned abrt :1; /* Aborted command - As defined by ATA */ - unsigned mcr :1; /* Media Change Requested - As defined by ATA */ - unsigned sense_key :4; /* Sense key of the last failed packet command */ -#elif defined(__BIG_ENDIAN_BITFIELD) - unsigned sense_key :4; /* Sense key of the last failed packet command */ - unsigned mcr :1; /* Media Change Requested - As defined by ATA */ - unsigned abrt :1; /* Aborted command - As defined by ATA */ - unsigned eom :1; /* End Of Media Detected */ - unsigned ili :1; /* Illegal Length Indication */ -#else -#error "Bitfield endianness not defined! Check your byteorder.h" -#endif - } b; -} idefloppy_error_reg_t; - -/* - * ATAPI Feature Register - */ -typedef union { - unsigned all :8; - struct { -#if defined(__LITTLE_ENDIAN_BITFIELD) - unsigned dma :1; /* Using DMA or PIO */ - unsigned reserved321 :3; /* Reserved */ - unsigned reserved654 :3; /* Reserved (Tag Type) */ - unsigned reserved7 :1; /* Reserved */ -#elif defined(__BIG_ENDIAN_BITFIELD) - unsigned reserved7 :1; /* Reserved */ - unsigned reserved654 :3; /* Reserved (Tag Type) */ - unsigned reserved321 :3; /* Reserved */ - unsigned dma :1; /* Using DMA or PIO */ -#else -#error "Bitfield endianness not defined! Check your byteorder.h" -#endif - } b; -} idefloppy_feature_reg_t; - -/* - * ATAPI Byte Count Register. - */ -typedef union { - unsigned all :16; - struct { -#if defined(__LITTLE_ENDIAN_BITFIELD) - unsigned low :8; /* LSB */ - unsigned high :8; /* MSB */ -#elif defined(__BIG_ENDIAN_BITFIELD) - unsigned high :8; /* MSB */ - unsigned low :8; /* LSB */ -#else -#error "Bitfield endianness not defined! Check your byteorder.h" -#endif - } b; -} idefloppy_bcount_reg_t; - -/* - * ATAPI Interrupt Reason Register. - */ -typedef union { - unsigned all :8; - struct { -#if defined(__LITTLE_ENDIAN_BITFIELD) - unsigned cod :1; /* Information transferred is command (1) or data (0) */ - unsigned io :1; /* The device requests us to read (1) or write (0) */ - unsigned reserved :6; /* Reserved */ -#elif defined(__BIG_ENDIAN_BITFIELD) - unsigned reserved :6; /* Reserved */ - unsigned io :1; /* The device requests us to read (1) or write (0) */ - unsigned cod :1; /* Information transferred is command (1) or data (0) */ -#else -#error "Bitfield endianness not defined! Check your byteorder.h" -#endif - } b; -} idefloppy_ireason_reg_t; - -/* - * ATAPI floppy Drive Select Register - */ -typedef union { - unsigned all :8; - struct { -#if defined(__LITTLE_ENDIAN_BITFIELD) - unsigned sam_lun :3; /* Logical unit number */ - unsigned reserved3 :1; /* Reserved */ - unsigned drv :1; /* The responding drive will be drive 0 (0) or drive 1 (1) */ - unsigned one5 :1; /* Should be set to 1 */ - unsigned reserved6 :1; /* Reserved */ - unsigned one7 :1; /* Should be set to 1 */ -#elif defined(__BIG_ENDIAN_BITFIELD) - unsigned one7 :1; /* Should be set to 1 */ - unsigned reserved6 :1; /* Reserved */ - unsigned one5 :1; /* Should be set to 1 */ - unsigned drv :1; /* The responding drive will be drive 0 (0) or drive 1 (1) */ - unsigned reserved3 :1; /* Reserved */ - unsigned sam_lun :3; /* Logical unit number */ -#else -#error "Bitfield endianness not defined! Check your byteorder.h" -#endif - } b; -} idefloppy_drivesel_reg_t; - -/* - * ATAPI Device Control Register - */ -typedef union { - unsigned all :8; - struct { -#if defined(__LITTLE_ENDIAN_BITFIELD) - unsigned zero0 :1; /* Should be set to zero */ - unsigned nien :1; /* Device interrupt is disabled (1) or enabled (0) */ - unsigned srst :1; /* ATA software reset. ATAPI devices should use the new ATAPI srst. */ - unsigned one3 :1; /* Should be set to 1 */ - unsigned reserved4567 :4; /* Reserved */ -#elif defined(__BIG_ENDIAN_BITFIELD) - unsigned reserved4567 :4; /* Reserved */ - unsigned one3 :1; /* Should be set to 1 */ - unsigned srst :1; /* ATA software reset. ATAPI devices should use the new ATAPI srst. */ - unsigned nien :1; /* Device interrupt is disabled (1) or enabled (0) */ - unsigned zero0 :1; /* Should be set to zero */ -#else -#error "Bitfield endianness not defined! Check your byteorder.h" -#endif - } b; -} idefloppy_control_reg_t; - -/* - * The following is used to format the general configuration word of - * the ATAPI IDENTIFY DEVICE command. - */ -struct idefloppy_id_gcw { -#if defined(__LITTLE_ENDIAN_BITFIELD) - unsigned packet_size :2; /* Packet Size */ - unsigned reserved234 :3; /* Reserved */ - unsigned drq_type :2; /* Command packet DRQ type */ - unsigned removable :1; /* Removable media */ - unsigned device_type :5; /* Device type */ - unsigned reserved13 :1; /* Reserved */ - unsigned protocol :2; /* Protocol type */ -#elif defined(__BIG_ENDIAN_BITFIELD) - unsigned protocol :2; /* Protocol type */ - unsigned reserved13 :1; /* Reserved */ - unsigned device_type :5; /* Device type */ - unsigned removable :1; /* Removable media */ - unsigned drq_type :2; /* Command packet DRQ type */ - unsigned reserved234 :3; /* Reserved */ - unsigned packet_size :2; /* Packet Size */ -#else -#error "Bitfield endianness not defined! Check your byteorder.h" -#endif -}; - -/* - * INQUIRY packet command - Data Format - */ -typedef struct { -#if defined(__LITTLE_ENDIAN_BITFIELD) - unsigned device_type :5; /* Peripheral Device Type */ - unsigned reserved0_765 :3; /* Peripheral Qualifier - Reserved */ - unsigned reserved1_6t0 :7; /* Reserved */ - unsigned rmb :1; /* Removable Medium Bit */ - unsigned ansi_version :3; /* ANSI Version */ - unsigned ecma_version :3; /* ECMA Version */ - unsigned iso_version :2; /* ISO Version */ - unsigned response_format :4; /* Response Data Format */ - unsigned reserved3_45 :2; /* Reserved */ - unsigned reserved3_6 :1; /* TrmIOP - Reserved */ - unsigned reserved3_7 :1; /* AENC - Reserved */ -#elif defined(__BIG_ENDIAN_BITFIELD) - unsigned reserved0_765 :3; /* Peripheral Qualifier - Reserved */ - unsigned device_type :5; /* Peripheral Device Type */ - unsigned rmb :1; /* Removable Medium Bit */ - unsigned reserved1_6t0 :7; /* Reserved */ - unsigned iso_version :2; /* ISO Version */ - unsigned ecma_version :3; /* ECMA Version */ - unsigned ansi_version :3; /* ANSI Version */ - unsigned reserved3_7 :1; /* AENC - Reserved */ - unsigned reserved3_6 :1; /* TrmIOP - Reserved */ - unsigned reserved3_45 :2; /* Reserved */ - unsigned response_format :4; /* Response Data Format */ -#else -#error "Bitfield endianness not defined! Check your byteorder.h" -#endif - u8 additional_length; /* Additional Length (total_length-4) */ - u8 rsv5, rsv6, rsv7; /* Reserved */ - u8 vendor_id[8]; /* Vendor Identification */ - u8 product_id[16]; /* Product Identification */ - u8 revision_level[4]; /* Revision Level */ - u8 vendor_specific[20]; /* Vendor Specific - Optional */ - u8 reserved56t95[40]; /* Reserved - Optional */ - /* Additional information may be returned */ -} idefloppy_inquiry_result_t; - -/* - * REQUEST SENSE packet command result - Data Format. - */ -typedef struct { -#if defined(__LITTLE_ENDIAN_BITFIELD) - unsigned error_code :7; /* Current error (0x70) */ - unsigned valid :1; /* The information field conforms to SFF-8070i */ - u8 reserved1 :8; /* Reserved */ - unsigned sense_key :4; /* Sense Key */ - unsigned reserved2_4 :1; /* Reserved */ - unsigned ili :1; /* Incorrect Length Indicator */ - unsigned reserved2_67 :2; -#elif defined(__BIG_ENDIAN_BITFIELD) - unsigned valid :1; /* The information field conforms to SFF-8070i */ - unsigned error_code :7; /* Current error (0x70) */ - u8 reserved1 :8; /* Reserved */ - unsigned reserved2_67 :2; - unsigned ili :1; /* Incorrect Length Indicator */ - unsigned reserved2_4 :1; /* Reserved */ - unsigned sense_key :4; /* Sense Key */ -#else -#error "Bitfield endianness not defined! Check your byteorder.h" -#endif - u32 information __attribute__ ((packed)); - u8 asl; /* Additional sense length (n-7) */ - u32 command_specific; /* Additional command specific information */ - u8 asc; /* Additional Sense Code */ - u8 ascq; /* Additional Sense Code Qualifier */ - u8 replaceable_unit_code; /* Field Replaceable Unit Code */ - u8 reserved[3]; - u8 pad[2]; /* Padding to 20 bytes */ -} idefloppy_request_sense_result_t; - -/* - * Pages of the SELECT SENSE / MODE SENSE packet commands. - */ -#define IDEFLOPPY_CAPABILITIES_PAGE 0x1b -#define IDEFLOPPY_FLEXIBLE_DISK_PAGE 0x05 - -/* - * Mode Parameter Header for the MODE SENSE packet command - */ -typedef struct { - u16 mode_data_length; /* Length of the following data transfer */ - u8 medium_type; /* Medium Type */ -#if defined(__LITTLE_ENDIAN_BITFIELD) - unsigned reserved3 :7; - unsigned wp :1; /* Write protect */ -#elif defined(__BIG_ENDIAN_BITFIELD) - unsigned wp :1; /* Write protect */ - unsigned reserved3 :7; -#else -#error "Bitfield endianness not defined! Check your byteorder.h" -#endif - u8 reserved[4]; -} idefloppy_mode_parameter_header_t; - -#define IDEFLOPPY_MIN(a,b) ((a)<(b) ? (a):(b)) -#define IDEFLOPPY_MAX(a,b) ((a)>(b) ? (a):(b)) - -/* - * Too bad. The drive wants to send us data which we are not ready to accept. - * Just throw it away. - */ -static void idefloppy_discard_data (ide_drive_t *drive, unsigned int bcount) -{ - while (bcount--) - IN_BYTE (IDE_DATA_REG); -} - -#if IDEFLOPPY_DEBUG_BUGS -static void idefloppy_write_zeros (ide_drive_t *drive, unsigned int bcount) -{ - while (bcount--) - OUT_BYTE (0, IDE_DATA_REG); -} -#endif /* IDEFLOPPY_DEBUG_BUGS */ - -/* - * idefloppy_end_request is used to finish servicing a request. - * - * For read/write requests, we will call ide_end_request to pass to the - * next buffer. - */ -static void idefloppy_end_request (byte uptodate, ide_hwgroup_t *hwgroup) -{ - ide_drive_t *drive = hwgroup->drive; - idefloppy_floppy_t *floppy = drive->driver_data; - struct request *rq = hwgroup->rq; - int error; - -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "Reached idefloppy_end_request\n"); -#endif /* IDEFLOPPY_DEBUG_LOG */ - - switch (uptodate) { - case 0: error = IDEFLOPPY_ERROR_GENERAL; break; - case 1: error = 0; break; - default: error = uptodate; - } - if (error) - floppy->failed_pc = NULL; - /* Why does this happen? */ - if (!rq) - return; - if (!IDEFLOPPY_RQ_CMD (rq->cmd)) { - ide_end_request (uptodate, hwgroup); - return; - } - rq->errors = error; - ide_end_drive_cmd (drive, 0, 0); -} - -static void idefloppy_input_buffers (ide_drive_t *drive, idefloppy_pc_t *pc, unsigned int bcount) -{ - struct request *rq = pc->rq; - struct buffer_head *bh = rq->bh; - int count; - - while (bcount) { - if (pc->b_count == bh->b_size) { - rq->sector += rq->current_nr_sectors; - rq->nr_sectors -= rq->current_nr_sectors; - idefloppy_end_request (1, HWGROUP(drive)); - if ((bh = rq->bh) != NULL) - pc->b_count = 0; - } - if (bh == NULL) { - printk (KERN_ERR "%s: bh == NULL in idefloppy_input_buffers, bcount == %d\n", drive->name, bcount); - idefloppy_discard_data (drive, bcount); - return; - } - count = IDEFLOPPY_MIN (bh->b_size - pc->b_count, bcount); - atapi_input_bytes (drive, bh->b_data + pc->b_count, count); - bcount -= count; pc->b_count += count; - } -} - -static void idefloppy_output_buffers (ide_drive_t *drive, idefloppy_pc_t *pc, unsigned int bcount) -{ - struct request *rq = pc->rq; - struct buffer_head *bh = rq->bh; - int count; - - while (bcount) { - if (!pc->b_count) { - rq->sector += rq->current_nr_sectors; - rq->nr_sectors -= rq->current_nr_sectors; - idefloppy_end_request (1, HWGROUP(drive)); - if ((bh = rq->bh) != NULL) { - pc->b_data = bh->b_data; - pc->b_count = bh->b_size; - } - } - if (bh == NULL) { - printk (KERN_ERR "%s: bh == NULL in idefloppy_output_buffers, bcount == %d\n", drive->name, bcount); - idefloppy_write_zeros (drive, bcount); - return; - } - count = IDEFLOPPY_MIN (pc->b_count, bcount); - atapi_output_bytes (drive, pc->b_data, count); - bcount -= count; pc->b_data += count; pc->b_count -= count; - } -} - -#ifdef CONFIG_BLK_DEV_IDEDMA -static void idefloppy_update_buffers (ide_drive_t *drive, idefloppy_pc_t *pc) -{ - struct request *rq = pc->rq; - struct buffer_head *bh = rq->bh; - - while ((bh = rq->bh) != NULL) - idefloppy_end_request (1, HWGROUP(drive)); -} -#endif /* CONFIG_BLK_DEV_IDEDMA */ - -/* - * idefloppy_queue_pc_head generates a new packet command request in front - * of the request queue, before the current request, so that it will be - * processed immediately, on the next pass through the driver. - */ -static void idefloppy_queue_pc_head (ide_drive_t *drive,idefloppy_pc_t *pc,struct request *rq) -{ - ide_init_drive_cmd (rq); - rq->buffer = (char *) pc; - rq->cmd = IDEFLOPPY_PC_RQ; - (void) ide_do_drive_cmd (drive, rq, ide_preempt); -} - -static idefloppy_pc_t *idefloppy_next_pc_storage (ide_drive_t *drive) -{ - idefloppy_floppy_t *floppy = drive->driver_data; - - if (floppy->pc_stack_index==IDEFLOPPY_PC_STACK) - floppy->pc_stack_index=0; - return (&floppy->pc_stack[floppy->pc_stack_index++]); -} - -static struct request *idefloppy_next_rq_storage (ide_drive_t *drive) -{ - idefloppy_floppy_t *floppy = drive->driver_data; - - if (floppy->rq_stack_index==IDEFLOPPY_PC_STACK) - floppy->rq_stack_index=0; - return (&floppy->rq_stack[floppy->rq_stack_index++]); -} - -/* - * idefloppy_analyze_error is called on each failed packet command retry - * to analyze the request sense. - */ -static void idefloppy_analyze_error (ide_drive_t *drive,idefloppy_request_sense_result_t *result) -{ - idefloppy_floppy_t *floppy = drive->driver_data; - - floppy->sense_key = result->sense_key; floppy->asc = result->asc; floppy->ascq = result->ascq; -#if IDEFLOPPY_DEBUG_LOG - if (floppy->failed_pc) - printk (KERN_INFO "ide-floppy: pc = %x, sense key = %x, asc = %x, ascq = %x\n",floppy->failed_pc->c[0],result->sense_key,result->asc,result->ascq); - else - printk (KERN_INFO "ide-floppy: sense key = %x, asc = %x, ascq = %x\n",result->sense_key,result->asc,result->ascq); -#endif /* IDEFLOPPY_DEBUG_LOG */ -} - -static void idefloppy_request_sense_callback (ide_drive_t *drive) -{ - idefloppy_floppy_t *floppy = drive->driver_data; - -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "ide-floppy: Reached idefloppy_request_sense_callback\n"); -#endif /* IDEFLOPPY_DEBUG_LOG */ - if (!floppy->pc->error) { - idefloppy_analyze_error (drive,(idefloppy_request_sense_result_t *) floppy->pc->buffer); - idefloppy_end_request (1,HWGROUP (drive)); - } else { - printk (KERN_ERR "Error in REQUEST SENSE itself - Aborting request!\n"); - idefloppy_end_request (0,HWGROUP (drive)); - } -} - -/* - * General packet command callback function. - */ -static void idefloppy_pc_callback (ide_drive_t *drive) -{ - idefloppy_floppy_t *floppy = drive->driver_data; - -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "ide-floppy: Reached idefloppy_pc_callback\n"); -#endif /* IDEFLOPPY_DEBUG_LOG */ - - idefloppy_end_request (floppy->pc->error ? 0:1, HWGROUP(drive)); -} - -/* - * idefloppy_init_pc initializes a packet command. - */ -static void idefloppy_init_pc (idefloppy_pc_t *pc) -{ - memset (pc->c, 0, 12); - pc->retries = 0; - pc->flags = 0; - pc->request_transfer = 0; - pc->buffer = pc->pc_buffer; - pc->buffer_size = IDEFLOPPY_PC_BUFFER_SIZE; - pc->b_data = NULL; - pc->callback = &idefloppy_pc_callback; -} - -static void idefloppy_create_request_sense_cmd (idefloppy_pc_t *pc) -{ - idefloppy_init_pc (pc); - pc->c[0] = IDEFLOPPY_REQUEST_SENSE_CMD; - pc->c[4] = 255; - pc->request_transfer = 18; - pc->callback = &idefloppy_request_sense_callback; -} - -/* - * idefloppy_retry_pc is called when an error was detected during the - * last packet command. We queue a request sense packet command in - * the head of the request list. - */ -static void idefloppy_retry_pc (ide_drive_t *drive) -{ - idefloppy_pc_t *pc; - struct request *rq; - idefloppy_error_reg_t error; - - error.all = IN_BYTE (IDE_ERROR_REG); - pc = idefloppy_next_pc_storage (drive); - rq = idefloppy_next_rq_storage (drive); - idefloppy_create_request_sense_cmd (pc); - idefloppy_queue_pc_head (drive, pc, rq); -} - -/* - * idefloppy_pc_intr is the usual interrupt handler which will be called - * during a packet command. - */ -static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive) -{ - idefloppy_floppy_t *floppy = drive->driver_data; - idefloppy_status_reg_t status; - idefloppy_bcount_reg_t bcount; - idefloppy_ireason_reg_t ireason; - idefloppy_pc_t *pc=floppy->pc; - struct request *rq = pc->rq; - unsigned int temp; - -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "ide-floppy: Reached idefloppy_pc_intr interrupt handler\n"); -#endif /* IDEFLOPPY_DEBUG_LOG */ - -#ifdef CONFIG_BLK_DEV_IDEDMA - if (test_bit (PC_DMA_IN_PROGRESS, &pc->flags)) { - if (HWIF(drive)->dmaproc(ide_dma_end, drive)) { - set_bit (PC_DMA_ERROR, &pc->flags); - } else { - pc->actually_transferred=pc->request_transfer; - idefloppy_update_buffers (drive, pc); - } -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "ide-floppy: DMA finished\n"); -#endif /* IDEFLOPPY_DEBUG_LOG */ - } -#endif /* CONFIG_BLK_DEV_IDEDMA */ - - status.all = GET_STAT(); /* Clear the interrupt */ - - if (!status.b.drq) { /* No more interrupts */ -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "Packet command completed, %d bytes transferred\n", pc->actually_transferred); -#endif /* IDEFLOPPY_DEBUG_LOG */ - clear_bit (PC_DMA_IN_PROGRESS, &pc->flags); - - ide__sti(); /* local CPU only */ - - if (status.b.check || test_bit (PC_DMA_ERROR, &pc->flags)) { /* Error detected */ -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "ide-floppy: %s: I/O error\n",drive->name); -#endif /* IDEFLOPPY_DEBUG_LOG */ - rq->errors++; - if (pc->c[0] == IDEFLOPPY_REQUEST_SENSE_CMD) { - printk (KERN_ERR "ide-floppy: I/O error in request sense command\n"); - return ide_do_reset (drive); - } - idefloppy_retry_pc (drive); /* Retry operation */ - return ide_stopped; /* queued, but not started */ - } - pc->error = 0; - if (floppy->failed_pc == pc) - floppy->failed_pc=NULL; - pc->callback(drive); /* Command finished - Call the callback function */ - return ide_stopped; - } -#ifdef CONFIG_BLK_DEV_IDEDMA - if (test_and_clear_bit (PC_DMA_IN_PROGRESS, &pc->flags)) { - printk (KERN_ERR "ide-floppy: The floppy wants to issue more interrupts in DMA mode\n"); - (void) HWIF(drive)->dmaproc(ide_dma_off, drive); - return ide_do_reset (drive); - } -#endif /* CONFIG_BLK_DEV_IDEDMA */ - bcount.b.high=IN_BYTE (IDE_BCOUNTH_REG); /* Get the number of bytes to transfer */ - bcount.b.low=IN_BYTE (IDE_BCOUNTL_REG); /* on this interrupt */ - ireason.all=IN_BYTE (IDE_IREASON_REG); - - if (ireason.b.cod) { - printk (KERN_ERR "ide-floppy: CoD != 0 in idefloppy_pc_intr\n"); - return ide_do_reset (drive); - } - if (ireason.b.io == test_bit (PC_WRITING, &pc->flags)) { /* Hopefully, we will never get here */ - printk (KERN_ERR "ide-floppy: We wanted to %s, ", ireason.b.io ? "Write":"Read"); - printk (KERN_ERR "but the floppy wants us to %s !\n",ireason.b.io ? "Read":"Write"); - return ide_do_reset (drive); - } - if (!test_bit (PC_WRITING, &pc->flags)) { /* Reading - Check that we have enough space */ - temp = pc->actually_transferred + bcount.all; - if ( temp > pc->request_transfer) { - if (temp > pc->buffer_size) { - printk (KERN_ERR "ide-floppy: The floppy wants to send us more data than expected - discarding data\n"); - idefloppy_discard_data (drive,bcount.all); - ide_set_handler (drive,&idefloppy_pc_intr,IDEFLOPPY_WAIT_CMD, NULL); - return ide_started; - } -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_NOTICE "ide-floppy: The floppy wants to send us more data than expected - allowing transfer\n"); -#endif /* IDEFLOPPY_DEBUG_LOG */ - } - } - if (test_bit (PC_WRITING, &pc->flags)) { - if (pc->buffer != NULL) - atapi_output_bytes (drive,pc->current_position,bcount.all); /* Write the current buffer */ - else - idefloppy_output_buffers (drive, pc, bcount.all); - } else { - if (pc->buffer != NULL) - atapi_input_bytes (drive,pc->current_position,bcount.all); /* Read the current buffer */ - else - idefloppy_input_buffers (drive, pc, bcount.all); - } - pc->actually_transferred+=bcount.all; /* Update the current position */ - pc->current_position+=bcount.all; - - ide_set_handler (drive,&idefloppy_pc_intr,IDEFLOPPY_WAIT_CMD, NULL); /* And set the interrupt handler again */ - return ide_started; -} - -static ide_startstop_t idefloppy_transfer_pc (ide_drive_t *drive) -{ - ide_startstop_t startstop; - idefloppy_floppy_t *floppy = drive->driver_data; - idefloppy_ireason_reg_t ireason; - - if (ide_wait_stat (&startstop,drive,DRQ_STAT,BUSY_STAT,WAIT_READY)) { - printk (KERN_ERR "ide-floppy: Strange, packet command initiated yet DRQ isn't asserted\n"); - return startstop; - } - ireason.all=IN_BYTE (IDE_IREASON_REG); - if (!ireason.b.cod || ireason.b.io) { - printk (KERN_ERR "ide-floppy: (IO,CoD) != (0,1) while issuing a packet command\n"); - return ide_do_reset (drive); - } - ide_set_handler (drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL); /* Set the interrupt routine */ - atapi_output_bytes (drive, floppy->pc->c, 12); /* Send the actual packet */ - return ide_started; -} - -/* - * Issue a packet command - */ -static ide_startstop_t idefloppy_issue_pc (ide_drive_t *drive, idefloppy_pc_t *pc) -{ - idefloppy_floppy_t *floppy = drive->driver_data; - idefloppy_bcount_reg_t bcount; - int dma_ok = 0; - -#if IDEFLOPPY_DEBUG_BUGS - if (floppy->pc->c[0] == IDEFLOPPY_REQUEST_SENSE_CMD && pc->c[0] == IDEFLOPPY_REQUEST_SENSE_CMD) { - printk (KERN_ERR "ide-floppy: possible ide-floppy.c bug - Two request sense in serial were issued\n"); - } -#endif /* IDEFLOPPY_DEBUG_BUGS */ - - if (floppy->failed_pc == NULL && pc->c[0] != IDEFLOPPY_REQUEST_SENSE_CMD) - floppy->failed_pc=pc; - floppy->pc=pc; /* Set the current packet command */ - - if (pc->retries > IDEFLOPPY_MAX_PC_RETRIES || test_bit (PC_ABORT, &pc->flags)) { - /* - * We will "abort" retrying a packet command in case - * a legitimate error code was received. - */ - if (!test_bit (PC_ABORT, &pc->flags)) { - printk (KERN_ERR "ide-floppy: %s: I/O error, pc = %2x, key = %2x, asc = %2x, ascq = %2x\n", - drive->name, pc->c[0], floppy->sense_key, floppy->asc, floppy->ascq); - pc->error = IDEFLOPPY_ERROR_GENERAL; /* Giving up */ - } - floppy->failed_pc=NULL; - pc->callback(drive); - return ide_stopped; - } -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "Retry number - %d\n",pc->retries); -#endif /* IDEFLOPPY_DEBUG_LOG */ - - pc->retries++; - pc->actually_transferred=0; /* We haven't transferred any data yet */ - pc->current_position=pc->buffer; - bcount.all = IDE_MIN(pc->request_transfer, 63 * 1024); - -#ifdef CONFIG_BLK_DEV_IDEDMA - if (test_and_clear_bit (PC_DMA_ERROR, &pc->flags)) { - (void) HWIF(drive)->dmaproc(ide_dma_off, drive); - } - if (test_bit (PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma) - dma_ok=!HWIF(drive)->dmaproc(test_bit (PC_WRITING, &pc->flags) ? ide_dma_write : ide_dma_read, drive); -#endif /* CONFIG_BLK_DEV_IDEDMA */ - - if (IDE_CONTROL_REG) - OUT_BYTE (drive->ctl,IDE_CONTROL_REG); - OUT_BYTE (dma_ok ? 1:0,IDE_FEATURE_REG); /* Use PIO/DMA */ - OUT_BYTE (bcount.b.high,IDE_BCOUNTH_REG); - OUT_BYTE (bcount.b.low,IDE_BCOUNTL_REG); - OUT_BYTE (drive->select.all,IDE_SELECT_REG); - -#ifdef CONFIG_BLK_DEV_IDEDMA - if (dma_ok) { /* Begin DMA, if necessary */ - set_bit (PC_DMA_IN_PROGRESS, &pc->flags); - (void) (HWIF(drive)->dmaproc(ide_dma_begin, drive)); - } -#endif /* CONFIG_BLK_DEV_IDEDMA */ - - if (test_bit (IDEFLOPPY_DRQ_INTERRUPT, &floppy->flags)) { - ide_set_handler (drive, &idefloppy_transfer_pc, IDEFLOPPY_WAIT_CMD, NULL); - OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* Issue the packet command */ - return ide_started; - } else { - OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); - return idefloppy_transfer_pc (drive); - } -} - -static void idefloppy_rw_callback (ide_drive_t *drive) -{ -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "ide-floppy: Reached idefloppy_rw_callback\n"); -#endif /* IDEFLOPPY_DEBUG_LOG */ - - idefloppy_end_request(1, HWGROUP(drive)); - return; -} - -static void idefloppy_create_prevent_cmd (idefloppy_pc_t *pc, int prevent) -{ -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "ide-floppy: creating prevent removal command, prevent = %d\n", prevent); -#endif /* IDEFLOPPY_DEBUG_LOG */ - - idefloppy_init_pc (pc); - pc->c[0] = IDEFLOPPY_PREVENT_REMOVAL_CMD; - pc->c[4] = prevent; -} - -static void idefloppy_create_read_capacity_cmd (idefloppy_pc_t *pc) -{ - idefloppy_init_pc (pc); - pc->c[0] = IDEFLOPPY_READ_CAPACITY_CMD; - pc->c[7] = 255; - pc->c[8] = 255; - pc->request_transfer = 255; -} - -/* - * A mode sense command is used to "sense" floppy parameters. - */ -static void idefloppy_create_mode_sense_cmd (idefloppy_pc_t *pc, byte page_code, byte type) -{ - unsigned short length = sizeof (idefloppy_mode_parameter_header_t); - - idefloppy_init_pc (pc); - pc->c[0] = IDEFLOPPY_MODE_SENSE_CMD; - pc->c[1] = 0; - pc->c[2] = page_code + (type << 6); - - switch (page_code) { - case IDEFLOPPY_CAPABILITIES_PAGE: - length += 12; - break; - case IDEFLOPPY_FLEXIBLE_DISK_PAGE: - length += 32; - break; - default: - printk (KERN_ERR "ide-floppy: unsupported page code in create_mode_sense_cmd\n"); - } - put_unaligned (htons (length), (unsigned short *) &pc->c[7]); - pc->request_transfer = length; -} - -static void idefloppy_create_start_stop_cmd (idefloppy_pc_t *pc, int start) -{ - idefloppy_init_pc (pc); - pc->c[0] = IDEFLOPPY_START_STOP_CMD; - pc->c[4] = start; -} - -static void idefloppy_create_test_unit_ready_cmd(idefloppy_pc_t *pc) -{ - idefloppy_init_pc(pc); - pc->c[0] = IDEFLOPPY_TEST_UNIT_READY_CMD; -} - -static void idefloppy_create_rw_cmd (idefloppy_floppy_t *floppy, idefloppy_pc_t *pc, struct request *rq, unsigned long sector) -{ - int block = sector / floppy->bs_factor; - int blocks = rq->nr_sectors / floppy->bs_factor; - -#if IDEFLOPPY_DEBUG_LOG - printk ("create_rw1%d_cmd: block == %d, blocks == %d\n", - 2 * test_bit (IDEFLOPPY_USE_READ12, &floppy->flags), block, blocks); -#endif /* IDEFLOPPY_DEBUG_LOG */ - - idefloppy_init_pc (pc); - if (test_bit (IDEFLOPPY_USE_READ12, &floppy->flags)) { - pc->c[0] = rq->cmd == READ ? IDEFLOPPY_READ12_CMD : IDEFLOPPY_WRITE12_CMD; - put_unaligned (htonl (blocks), (unsigned int *) &pc->c[6]); - } else { - pc->c[0] = rq->cmd == READ ? IDEFLOPPY_READ10_CMD : IDEFLOPPY_WRITE10_CMD; - put_unaligned (htons (blocks), (unsigned short *) &pc->c[7]); - } - put_unaligned (htonl (block), (unsigned int *) &pc->c[2]); - pc->callback = &idefloppy_rw_callback; - pc->rq = rq; - pc->b_data = rq->buffer; - pc->b_count = rq->cmd == READ ? 0 : rq->bh->b_size; - if (rq->cmd == WRITE) - set_bit (PC_WRITING, &pc->flags); - pc->buffer = NULL; - pc->request_transfer = pc->buffer_size = blocks * floppy->block_size; - set_bit (PC_DMA_RECOMMENDED, &pc->flags); -} - -/* - * idefloppy_do_request is our request handling function. - */ -static ide_startstop_t idefloppy_do_request (ide_drive_t *drive, struct request *rq, unsigned long block) -{ - idefloppy_floppy_t *floppy = drive->driver_data; - idefloppy_pc_t *pc; - -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "rq_status: %d, rq_dev: %u, cmd: %d, errors: %d\n",rq->rq_status,(unsigned int) rq->rq_dev,rq->cmd,rq->errors); - printk (KERN_INFO "sector: %ld, nr_sectors: %ld, current_nr_sectors: %ld\n",rq->sector,rq->nr_sectors,rq->current_nr_sectors); -#endif /* IDEFLOPPY_DEBUG_LOG */ - - if (rq->errors >= ERROR_MAX) { - if (floppy->failed_pc != NULL) - printk (KERN_ERR "ide-floppy: %s: I/O error, pc = %2x, key = %2x, asc = %2x, ascq = %2x\n", - drive->name, floppy->failed_pc->c[0], floppy->sense_key, floppy->asc, floppy->ascq); - else - printk (KERN_ERR "ide-floppy: %s: I/O error\n", drive->name); - idefloppy_end_request (0, HWGROUP(drive)); - return ide_stopped; - } - switch (rq->cmd) { - case READ: - case WRITE: - if (rq->sector % floppy->bs_factor || rq->nr_sectors % floppy->bs_factor) { - printk ("%s: unsupported r/w request size\n", drive->name); - idefloppy_end_request (0, HWGROUP(drive)); - return ide_stopped; - } - pc = idefloppy_next_pc_storage (drive); - idefloppy_create_rw_cmd (floppy, pc, rq, block); - break; - case IDEFLOPPY_PC_RQ: - pc = (idefloppy_pc_t *) rq->buffer; - break; - default: - printk (KERN_ERR "ide-floppy: unsupported command %x in request queue\n", rq->cmd); - idefloppy_end_request (0,HWGROUP (drive)); - return ide_stopped; - } - pc->rq = rq; - return idefloppy_issue_pc (drive, pc); -} - -/* - * idefloppy_queue_pc_tail adds a special packet command request to the - * tail of the request queue, and waits for it to be serviced. - */ -static int idefloppy_queue_pc_tail (ide_drive_t *drive,idefloppy_pc_t *pc) -{ - struct request rq; - - ide_init_drive_cmd (&rq); - rq.buffer = (char *) pc; - rq.cmd = IDEFLOPPY_PC_RQ; - return ide_do_drive_cmd (drive, &rq, ide_wait); -} - -/* - * Look at the flexible disk page parameters. We will ignore the CHS - * capacity parameters and use the LBA parameters instead. - */ -static int idefloppy_get_flexible_disk_page (ide_drive_t *drive) -{ - idefloppy_floppy_t *floppy = drive->driver_data; - idefloppy_pc_t pc; - idefloppy_mode_parameter_header_t *header; - idefloppy_flexible_disk_page_t *page; - int capacity, lba_capacity; - - idefloppy_create_mode_sense_cmd (&pc, IDEFLOPPY_FLEXIBLE_DISK_PAGE, MODE_SENSE_CURRENT); - if (idefloppy_queue_pc_tail (drive,&pc)) { - printk (KERN_ERR "ide-floppy: Can't get flexible disk page parameters\n"); - return 1; - } - header = (idefloppy_mode_parameter_header_t *) pc.buffer; - floppy->wp = header->wp; - page = (idefloppy_flexible_disk_page_t *) (header + 1); - - page->transfer_rate = ntohs (page->transfer_rate); - page->sector_size = ntohs (page->sector_size); - page->cyls = ntohs (page->cyls); - page->rpm = ntohs (page->rpm); - capacity = page->cyls * page->heads * page->sectors * page->sector_size; - if (memcmp (page, &floppy->flexible_disk_page, sizeof (idefloppy_flexible_disk_page_t))) - printk (KERN_INFO "%s: %dkB, %d/%d/%d CHS, %d kBps, %d sector size, %d rpm\n", - drive->name, capacity / 1024, page->cyls, page->heads, page->sectors, - page->transfer_rate / 8, page->sector_size, page->rpm); - - floppy->flexible_disk_page = *page; - drive->bios_cyl = page->cyls; - drive->bios_head = page->heads; - drive->bios_sect = page->sectors; - lba_capacity = floppy->blocks * floppy->block_size; - if (capacity != lba_capacity) { - printk (KERN_NOTICE "%s: The drive reports both %d and %d bytes as its capacity\n", - drive->name, capacity, lba_capacity); - capacity = IDEFLOPPY_MIN(capacity, lba_capacity); - floppy->blocks = floppy->block_size ? capacity / floppy->block_size : 0; - } - return 0; -} - -/* - * Determine if a media is present in the floppy drive, and if so, - * its LBA capacity. - */ -static int idefloppy_get_capacity (ide_drive_t *drive) -{ - idefloppy_floppy_t *floppy = drive->driver_data; - idefloppy_pc_t pc; - idefloppy_capacity_header_t *header; - idefloppy_capacity_descriptor_t *descriptor; - int i, descriptors, rc = 1, blocks, length; - - drive->bios_cyl = 0; - drive->bios_head = drive->bios_sect = 0; - floppy->blocks = floppy->bs_factor = 0; - drive->part[0].nr_sects = 0; - - idefloppy_create_read_capacity_cmd (&pc); - if (idefloppy_queue_pc_tail (drive, &pc)) { - printk (KERN_ERR "ide-floppy: Can't get floppy parameters\n"); - return 1; - } - header = (idefloppy_capacity_header_t *) pc.buffer; - descriptors = header->length / sizeof (idefloppy_capacity_descriptor_t); - descriptor = (idefloppy_capacity_descriptor_t *) (header + 1); - for (i = 0; i < descriptors; i++, descriptor++) { - blocks = descriptor->blocks = ntohl (descriptor->blocks); - length = descriptor->length = ntohs (descriptor->length); - if (!i && descriptor->dc == CAPACITY_CURRENT) { - if (memcmp (descriptor, &floppy->capacity, sizeof (idefloppy_capacity_descriptor_t))) { - printk (KERN_INFO "%s: %dkB, %d blocks, %d sector size, %s \n", - drive->name, blocks * length / 1024, blocks, length, - drive->using_dma ? ", DMA":""); - } - floppy->capacity = *descriptor; - if (!length || length % 512) - printk (KERN_ERR "%s: %d bytes block size not supported\n", drive->name, length); - else { - floppy->blocks = blocks; - floppy->block_size = length; - if ((floppy->bs_factor = length / 512) != 1) - printk (KERN_NOTICE "%s: warning: non 512 bytes block size not fully supported\n", drive->name); - rc = 0; - } - } -#if IDEFLOPPY_DEBUG_INFO - if (!i) printk (KERN_INFO "Descriptor 0 Code: %d\n", descriptor->dc); - printk (KERN_INFO "Descriptor %d: %dkB, %d blocks, %d sector size\n", i, blocks * length / 1024, blocks, length); -#endif /* IDEFLOPPY_DEBUG_INFO */ - } - (void) idefloppy_get_flexible_disk_page (drive); - drive->part[0].nr_sects = floppy->blocks * floppy->bs_factor; - return rc; -} - -/* - * Our special ide-floppy ioctl's. - * - * Currently there aren't any ioctl's. - */ -static int idefloppy_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - idefloppy_pc_t pc; - - if (cmd == CDROMEJECT) { - if (drive->usage > 1) - return -EBUSY; - idefloppy_create_prevent_cmd (&pc, 0); - (void) idefloppy_queue_pc_tail (drive, &pc); - idefloppy_create_start_stop_cmd (&pc, 2); - (void) idefloppy_queue_pc_tail (drive, &pc); - return 0; - } - return -EIO; -} - -/* - * Our open/release functions - */ -static int idefloppy_open (struct inode *inode, struct file *filp, ide_drive_t *drive) -{ - idefloppy_floppy_t *floppy = drive->driver_data; - idefloppy_pc_t pc; - -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "Reached idefloppy_open\n"); -#endif /* IDEFLOPPY_DEBUG_LOG */ - - MOD_INC_USE_COUNT; - if (drive->usage == 1) { - idefloppy_create_test_unit_ready_cmd(&pc); - if (idefloppy_queue_pc_tail(drive, &pc)) { - idefloppy_create_start_stop_cmd (&pc, 1); - (void) idefloppy_queue_pc_tail (drive, &pc); - } - if (idefloppy_get_capacity (drive)) { - drive->usage--; - MOD_DEC_USE_COUNT; - return -EIO; - } - if (floppy->wp && (filp->f_mode & 2)) { - drive->usage--; - MOD_DEC_USE_COUNT; - return -EROFS; - } - set_bit (IDEFLOPPY_MEDIA_CHANGED, &floppy->flags); - idefloppy_create_prevent_cmd (&pc, 1); - (void) idefloppy_queue_pc_tail (drive, &pc); - check_disk_change(inode->i_rdev); - } - return 0; -} - -static void idefloppy_release (struct inode *inode, struct file *filp, ide_drive_t *drive) -{ - idefloppy_pc_t pc; - -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "Reached idefloppy_release\n"); -#endif /* IDEFLOPPY_DEBUG_LOG */ - - if (!drive->usage) { - invalidate_buffers (inode->i_rdev); - idefloppy_create_prevent_cmd (&pc, 0); - (void) idefloppy_queue_pc_tail (drive, &pc); - } - MOD_DEC_USE_COUNT; -} - -/* - * Check media change. Use a simple algorithm for now. - */ -static int idefloppy_media_change (ide_drive_t *drive) -{ - idefloppy_floppy_t *floppy = drive->driver_data; - - return test_and_clear_bit (IDEFLOPPY_MEDIA_CHANGED, &floppy->flags); -} - -/* - * Return the current floppy capacity to ide.c. - */ -static unsigned long idefloppy_capacity (ide_drive_t *drive) -{ - idefloppy_floppy_t *floppy = drive->driver_data; - unsigned long capacity = floppy->blocks * floppy->bs_factor; - - return capacity; -} - -/* - * idefloppy_identify_device checks if we can support a drive, - * based on the ATAPI IDENTIFY command results. - */ -static int idefloppy_identify_device (ide_drive_t *drive,struct hd_driveid *id) -{ - struct idefloppy_id_gcw gcw; -#if IDEFLOPPY_DEBUG_INFO - unsigned short mask,i; - char buffer[80]; -#endif /* IDEFLOPPY_DEBUG_INFO */ - - *((unsigned short *) &gcw) = id->config; - -#ifdef CONFIG_PPC - /* kludge for Apple PowerBook internal zip */ - if ((gcw.device_type == 5) && !strstr(id->model, "CD-ROM") - && strstr(id->model, "ZIP")) - gcw.device_type = 0; -#endif - -#if IDEFLOPPY_DEBUG_INFO - printk (KERN_INFO "Dumping ATAPI Identify Device floppy parameters\n"); - switch (gcw.protocol) { - case 0: case 1: sprintf (buffer, "ATA");break; - case 2: sprintf (buffer, "ATAPI");break; - case 3: sprintf (buffer, "Reserved (Unknown to ide-floppy)");break; - } - printk (KERN_INFO "Protocol Type: %s\n", buffer); - switch (gcw.device_type) { - case 0: sprintf (buffer, "Direct-access Device");break; - case 1: sprintf (buffer, "Streaming Tape Device");break; - case 2: case 3: case 4: sprintf (buffer, "Reserved");break; - case 5: sprintf (buffer, "CD-ROM Device");break; - case 6: sprintf (buffer, "Reserved"); - case 7: sprintf (buffer, "Optical memory Device");break; - case 0x1f: sprintf (buffer, "Unknown or no Device type");break; - default: sprintf (buffer, "Reserved"); - } - printk (KERN_INFO "Device Type: %x - %s\n", gcw.device_type, buffer); - printk (KERN_INFO "Removable: %s\n",gcw.removable ? "Yes":"No"); - switch (gcw.drq_type) { - case 0: sprintf (buffer, "Microprocessor DRQ");break; - case 1: sprintf (buffer, "Interrupt DRQ");break; - case 2: sprintf (buffer, "Accelerated DRQ");break; - case 3: sprintf (buffer, "Reserved");break; - } - printk (KERN_INFO "Command Packet DRQ Type: %s\n", buffer); - switch (gcw.packet_size) { - case 0: sprintf (buffer, "12 bytes");break; - case 1: sprintf (buffer, "16 bytes");break; - default: sprintf (buffer, "Reserved");break; - } - printk (KERN_INFO "Command Packet Size: %s\n", buffer); - printk (KERN_INFO "Model: %.40s\n",id->model); - printk (KERN_INFO "Firmware Revision: %.8s\n",id->fw_rev); - printk (KERN_INFO "Serial Number: %.20s\n",id->serial_no); - printk (KERN_INFO "Write buffer size(?): %d bytes\n",id->buf_size*512); - printk (KERN_INFO "DMA: %s",id->capability & 0x01 ? "Yes\n":"No\n"); - printk (KERN_INFO "LBA: %s",id->capability & 0x02 ? "Yes\n":"No\n"); - printk (KERN_INFO "IORDY can be disabled: %s",id->capability & 0x04 ? "Yes\n":"No\n"); - printk (KERN_INFO "IORDY supported: %s",id->capability & 0x08 ? "Yes\n":"Unknown\n"); - printk (KERN_INFO "ATAPI overlap supported: %s",id->capability & 0x20 ? "Yes\n":"No\n"); - printk (KERN_INFO "PIO Cycle Timing Category: %d\n",id->tPIO); - printk (KERN_INFO "DMA Cycle Timing Category: %d\n",id->tDMA); - printk (KERN_INFO "Single Word DMA supported modes:\n"); - for (i=0,mask=1;i<8;i++,mask=mask << 1) { - if (id->dma_1word & mask) - printk (KERN_INFO " Mode %d%s\n", i, (id->dma_1word & (mask << 8)) ? " (active)" : ""); - } - printk (KERN_INFO "Multi Word DMA supported modes:\n"); - for (i=0,mask=1;i<8;i++,mask=mask << 1) { - if (id->dma_mword & mask) - printk (KERN_INFO " Mode %d%s\n", i, (id->dma_mword & (mask << 8)) ? " (active)" : ""); - } - if (id->field_valid & 0x0002) { - printk (KERN_INFO "Enhanced PIO Modes: %s\n",id->eide_pio_modes & 1 ? "Mode 3":"None"); - if (id->eide_dma_min == 0) - sprintf (buffer, "Not supported"); - else - sprintf (buffer, "%d ns",id->eide_dma_min); - printk (KERN_INFO "Minimum Multi-word DMA cycle per word: %s\n", buffer); - if (id->eide_dma_time == 0) - sprintf (buffer, "Not supported"); - else - sprintf (buffer, "%d ns",id->eide_dma_time); - printk (KERN_INFO "Manufacturer\'s Recommended Multi-word cycle: %s\n", buffer); - if (id->eide_pio == 0) - sprintf (buffer, "Not supported"); - else - sprintf (buffer, "%d ns",id->eide_pio); - printk (KERN_INFO "Minimum PIO cycle without IORDY: %s\n", buffer); - if (id->eide_pio_iordy == 0) - sprintf (buffer, "Not supported"); - else - sprintf (buffer, "%d ns",id->eide_pio_iordy); - printk (KERN_INFO "Minimum PIO cycle with IORDY: %s\n", buffer); - } else - printk (KERN_INFO "According to the device, fields 64-70 are not valid.\n"); -#endif /* IDEFLOPPY_DEBUG_INFO */ - - if (gcw.protocol != 2) - printk (KERN_ERR "ide-floppy: Protocol is not ATAPI\n"); - else if (gcw.device_type != 0) - printk (KERN_ERR "ide-floppy: Device type is not set to floppy\n"); - else if (!gcw.removable) - printk (KERN_ERR "ide-floppy: The removable flag is not set\n"); - else if (gcw.drq_type == 3) { - printk (KERN_ERR "ide-floppy: Sorry, DRQ type %d not supported\n", gcw.drq_type); - } else if (gcw.packet_size != 0) { - printk (KERN_ERR "ide-floppy: Packet size is not 12 bytes long\n"); - } else - return 1; - return 0; -} - -static void idefloppy_add_settings(ide_drive_t *drive) -{ - int major = HWIF(drive)->major; - int minor = drive->select.b.unit << PARTN_BITS; - - ide_add_setting(drive, "bios_cyl", SETTING_RW, -1, -1, TYPE_INT, 0, 1023, 1, 1, &drive->bios_cyl, NULL); - ide_add_setting(drive, "bios_head", SETTING_RW, -1, -1, TYPE_BYTE, 0, 255, 1, 1, &drive->bios_head, NULL); - ide_add_setting(drive, "bios_sect", SETTING_RW, -1, -1, TYPE_BYTE, 0, 63, 1, 1, &drive->bios_sect, NULL); - ide_add_setting(drive, "breada_readahead", SETTING_RW, BLKRAGET, BLKRASET, TYPE_INT, 0, 255, 1, 2, &read_ahead[major], NULL); - ide_add_setting(drive, "file_readahead", SETTING_RW, BLKFRAGET, BLKFRASET, TYPE_INTA, 0, INT_MAX, 1, 1024, &max_readahead[major][minor], NULL); - ide_add_setting(drive, "max_kb_per_request", SETTING_RW, BLKSECTGET, BLKSECTSET, TYPE_INTA, 1, 255, 1, 2, &max_sectors[major][minor], NULL); - -} - -/* - * Driver initialization. - */ -static void idefloppy_setup (ide_drive_t *drive, idefloppy_floppy_t *floppy) -{ - struct idefloppy_id_gcw gcw; - int major = HWIF(drive)->major, i; - int minor = drive->select.b.unit << PARTN_BITS; - - *((unsigned short *) &gcw) = drive->id->config; - drive->driver_data = floppy; - drive->ready_stat = 0; - memset (floppy, 0, sizeof (idefloppy_floppy_t)); - floppy->drive = drive; - floppy->pc = floppy->pc_stack; - if (gcw.drq_type == 1) - set_bit (IDEFLOPPY_DRQ_INTERRUPT, &floppy->flags); - /* - * We used to check revisions here. At this point however - * I'm giving up. Just assume they are all broken, its easier. - * - * The actual reason for the workarounds was likely - * a driver bug after all rather than a firmware bug, - * and the workaround below used to hide it. It should - * be fixed as of version 1.9, but to be on the safe side - * we'll leave the limitation below for the 2.2.x tree. - */ - - if (strcmp(drive->id->model, "IOMEGA ZIP 100 ATAPI") == 0) - { - for (i = 0; i < 1 << PARTN_BITS; i++) - max_sectors[major][minor + i] = 64; - } - - (void) idefloppy_get_capacity (drive); - idefloppy_add_settings(drive); - for (i = 0; i < MAX_DRIVES; ++i) { - ide_hwif_t *hwif = HWIF(drive); - - if (drive != &hwif->drives[i]) continue; - hwif->gd->de_arr[i] = drive->de; - if (drive->removable) - hwif->gd->flags[i] |= GENHD_FL_REMOVABLE; - break; - } -} - -static int idefloppy_cleanup (ide_drive_t *drive) -{ - idefloppy_floppy_t *floppy = drive->driver_data; - - if (ide_unregister_subdriver (drive)) - return 1; - drive->driver_data = NULL; - kfree (floppy); - return 0; -} - -#ifdef CONFIG_PROC_FS - -static ide_proc_entry_t idefloppy_proc[] = { - { "geometry", S_IFREG|S_IRUGO, proc_ide_read_geometry, NULL }, - { NULL, 0, NULL, NULL } -}; - -#else - -#define idefloppy_proc NULL - -#endif /* CONFIG_PROC_FS */ - -/* - * IDE subdriver functions, registered with ide.c - */ -static ide_driver_t idefloppy_driver = { - "ide-floppy", /* name */ - IDEFLOPPY_VERSION, /* version */ - ide_floppy, /* media */ - 0, /* busy */ - 1, /* supports_dma */ - 0, /* supports_dsc_overlap */ - idefloppy_cleanup, /* cleanup */ - idefloppy_do_request, /* do_request */ - idefloppy_end_request, /* end_request */ - idefloppy_ioctl, /* ioctl */ - idefloppy_open, /* open */ - idefloppy_release, /* release */ - idefloppy_media_change, /* media_change */ - NULL, /* pre_reset */ - idefloppy_capacity, /* capacity */ - NULL, /* special */ - idefloppy_proc /* proc */ -}; - -int idefloppy_init (void); -static ide_module_t idefloppy_module = { - IDE_DRIVER_MODULE, - idefloppy_init, - &idefloppy_driver, - NULL -}; - -/* - * idefloppy_init will register the driver for each floppy. - */ -int idefloppy_init (void) -{ - ide_drive_t *drive; - idefloppy_floppy_t *floppy; - int failed = 0; - - MOD_INC_USE_COUNT; - while ((drive = ide_scan_devices (ide_floppy, idefloppy_driver.name, NULL, failed++)) != NULL) { - if (!idefloppy_identify_device (drive, drive->id)) { - printk (KERN_ERR "ide-floppy: %s: not supported by this version of ide-floppy\n", drive->name); - continue; - } - if (drive->scsi) { - printk("ide-floppy: passing drive %s to ide-scsi emulation.\n", drive->name); - continue; - } - if ((floppy = (idefloppy_floppy_t *) kmalloc (sizeof (idefloppy_floppy_t), GFP_KERNEL)) == NULL) { - printk (KERN_ERR "ide-floppy: %s: Can't allocate a floppy structure\n", drive->name); - continue; - } - if (ide_register_subdriver (drive, &idefloppy_driver, IDE_SUBDRIVER_VERSION)) { - printk (KERN_ERR "ide-floppy: %s: Failed to register the driver with ide.c\n", drive->name); - kfree (floppy); - continue; - } - idefloppy_setup (drive, floppy); - failed--; - } - ide_register_module(&idefloppy_module); - MOD_DEC_USE_COUNT; - return 0; -} - -#ifdef MODULE -int init_module (void) -{ - return idefloppy_init (); -} - -void cleanup_module (void) -{ - ide_drive_t *drive; - int failed = 0; - - while ((drive = ide_scan_devices (ide_floppy, idefloppy_driver.name, &idefloppy_driver, failed)) != NULL) { - if (idefloppy_cleanup (drive)) { - printk ("%s: cleanup_module() called while still busy\n", drive->name); - failed++; - } - /* We must remove proc entries defined in this module. - Otherwise we oops while accessing these entries */ - if (drive->proc) - ide_remove_proc_entries(drive->proc, idefloppy_proc); - } - ide_unregister_module(&idefloppy_module); -} -#endif /* MODULE */ diff --git a/drivers/block/ide-geometry.c b/drivers/block/ide-geometry.c deleted file mode 100644 index 6ebf20fe1..000000000 --- a/drivers/block/ide-geometry.c +++ /dev/null @@ -1,214 +0,0 @@ -/* - * linux/drivers/block/ide-geometry.c - */ -#include <linux/config.h> - -#ifdef CONFIG_BLK_DEV_IDE -#include <linux/ide.h> - -#include <asm/io.h> - -extern ide_drive_t * get_info_ptr(kdev_t); -extern unsigned long current_capacity (ide_drive_t *); - -/* - * We query CMOS about hard disks : it could be that we have a SCSI/ESDI/etc - * controller that is BIOS compatible with ST-506, and thus showing up in our - * BIOS table, but not register compatible, and therefore not present in CMOS. - * - * Furthermore, we will assume that our ST-506 drives <if any> are the primary - * drives in the system -- the ones reflected as drive 1 or 2. The first - * drive is stored in the high nibble of CMOS byte 0x12, the second in the low - * nibble. This will be either a 4 bit drive type or 0xf indicating use byte - * 0x19 for an 8 bit type, drive 1, 0x1a for drive 2 in CMOS. A non-zero value - * means we have an AT controller hard disk for that drive. - * - * Of course, there is no guarantee that either drive is actually on the - * "primary" IDE interface, but we don't bother trying to sort that out here. - * If a drive is not actually on the primary interface, then these parameters - * will be ignored. This results in the user having to supply the logical - * drive geometry as a boot parameter for each drive not on the primary i/f. - */ -/* - * The only "perfect" way to handle this would be to modify the setup.[cS] code - * to do BIOS calls Int13h/Fn08h and Int13h/Fn48h to get all of the drive info - * for us during initialization. I have the necessary docs -- any takers? -ml - */ -/* - * I did this, but it doesnt work - there is no reasonable way to find the - * correspondence between the BIOS numbering of the disks and the Linux - * numbering. -aeb - * - * The code below is bad. One of the problems is that drives 1 and 2 - * may be SCSI disks (even when IDE disks are present), so that - * the geometry we read here from BIOS is attributed to the wrong disks. - * Consequently, also the "drive->present = 1" below is a mistake. - * - * Eventually the entire routine below should be removed. - */ -void probe_cmos_for_drives (ide_hwif_t *hwif) -{ -#ifdef __i386__ - extern struct drive_info_struct drive_info; - byte cmos_disks, *BIOS = (byte *) &drive_info; - int unit; - -#ifdef CONFIG_BLK_DEV_PDC4030 - if (hwif->chipset == ide_pdc4030 && hwif->channel != 0) - return; -#endif /* CONFIG_BLK_DEV_PDC4030 */ - outb_p(0x12,0x70); /* specify CMOS address 0x12 */ - cmos_disks = inb_p(0x71); /* read the data from 0x12 */ - /* Extract drive geometry from CMOS+BIOS if not already setup */ - for (unit = 0; unit < MAX_DRIVES; ++unit) { - ide_drive_t *drive = &hwif->drives[unit]; - - if ((cmos_disks & (0xf0 >> (unit*4))) - && !drive->present && !drive->nobios) { - unsigned short cyl = *(unsigned short *)BIOS; - unsigned char head = *(BIOS+2); - unsigned char sect = *(BIOS+14); - if (cyl > 0 && head > 0 && sect > 0 && sect < 64) { - drive->cyl = drive->bios_cyl = cyl; - drive->head = drive->bios_head = head; - drive->sect = drive->bios_sect = sect; - drive->ctl = *(BIOS+8); - } else { - printk("hd%d: C/H/S=%d/%d/%d from BIOS ignored\n", unit, cyl, head, sect); - } - } - - BIOS += 16; - } -#endif -} - - -/* - * If heads is nonzero: find a translation with this many heads and S=63. - * Otherwise: find out how OnTrack Disk Manager would translate the disk. - */ -static void -ontrack(ide_drive_t *drive, int heads, unsigned int *c, int *h, int *s) { - static const byte dm_head_vals[] = {4, 8, 16, 32, 64, 128, 255, 0}; - const byte *headp = dm_head_vals; - unsigned long total; - - /* - * The specs say: take geometry as obtained from Identify, - * compute total capacity C*H*S from that, and truncate to - * 1024*255*63. Now take S=63, H the first in the sequence - * 4, 8, 16, 32, 64, 128, 255 such that 63*H*1024 >= total. - * [Please tell aeb@cwi.nl in case this computes a - * geometry different from what OnTrack uses.] - */ - total = DRIVER(drive)->capacity(drive); - - *s = 63; - - if (heads) { - *h = heads; - *c = total / (63 * heads); - return; - } - - while (63 * headp[0] * 1024 < total && headp[1] != 0) - headp++; - *h = headp[0]; - *c = total / (63 * headp[0]); -} - -/* - * This routine is called from the partition-table code in pt/msdos.c. - * It has two tasks: - * (i) to handle Ontrack DiskManager by offsetting everything by 63 sectors, - * or to handle EZdrive by remapping sector 0 to sector 1. - * (ii) to invent a translated geometry. - * Part (i) is suppressed if the user specifies the "noremap" option - * on the command line. - * Part (ii) is suppressed if the user specifies an explicit geometry. - * - * The ptheads parameter is either 0 or tells about the number of - * heads shown by the end of the first nonempty partition. - * If this is either 16, 32, 64, 128, 240 or 255 we'll believe it. - * - * The xparm parameter has the following meaning: - * 0 = convert to CHS with fewer than 1024 cyls - * using the same method as Ontrack DiskManager. - * 1 = same as "0", plus offset everything by 63 sectors. - * -1 = similar to "0", plus redirect sector 0 to sector 1. - * 2 = convert to a CHS geometry with "ptheads" heads. - * - * Returns 0 if the translation was not possible, if the device was not - * an IDE disk drive, or if a geometry was "forced" on the commandline. - * Returns 1 if the geometry translation was successful. - */ -int ide_xlate_1024 (kdev_t i_rdev, int xparm, int ptheads, const char *msg) -{ - ide_drive_t *drive; - const char *msg1 = ""; - int heads = 0; - int c, h, s; - int transl = 1; /* try translation */ - int ret = 0; - - drive = get_info_ptr(i_rdev); - if (!drive) - return 0; - - /* remap? */ - if (drive->remap_0_to_1 != 2) { - if (xparm == 1) { /* DM */ - drive->sect0 = 63; - msg1 = " [remap +63]"; - ret = 1; - } else if (xparm == -1) { /* EZ-Drive */ - if (drive->remap_0_to_1 == 0) { - drive->remap_0_to_1 = 1; - msg1 = " [remap 0->1]"; - ret = 1; - } - } - } - - /* There used to be code here that assigned drive->id->CHS - to drive->CHS and that to drive->bios_CHS. However, - some disks have id->C/H/S = 4092/16/63 but are larger than 2.1 GB. - In such cases that code was wrong. Moreover, - there seems to be no reason to do any of these things. */ - - /* translate? */ - if (drive->forced_geom) - transl = 0; - - /* does ptheads look reasonable? */ - if (ptheads == 32 || ptheads == 64 || ptheads == 128 || - ptheads == 240 || ptheads == 255) - heads = ptheads; - - if (xparm == 2) { - if (!heads || - (drive->bios_head >= heads && drive->bios_sect == 63)) - transl = 0; - } - if (xparm == -1) { - if (drive->bios_head > 16) - transl = 0; /* we already have a translation */ - } - - if (transl) { - ontrack(drive, heads, &c, &h, &s); - drive->bios_cyl = c; - drive->bios_head = h; - drive->bios_sect = s; - ret = 1; - } - - drive->part[0].nr_sects = current_capacity(drive); - - if (ret) - printk("%s%s [%d/%d/%d]", msg, msg1, - drive->bios_cyl, drive->bios_head, drive->bios_sect); - return ret; -} -#endif /* CONFIG_BLK_DEV_IDE */ diff --git a/drivers/block/ide-pci.c b/drivers/block/ide-pci.c deleted file mode 100644 index f667ee6dd..000000000 --- a/drivers/block/ide-pci.c +++ /dev/null @@ -1,728 +0,0 @@ -/* - * linux/drivers/block/ide-pci.c Version 1.04 July 27, 1999 - * - * Copyright (c) 1998-1999 Andre Hedrick - * - * Copyright (c) 1995-1998 Mark Lord - * May be copied or modified under the terms of the GNU General Public License - */ - -/* - * This module provides support for automatic detection and - * configuration of all PCI IDE interfaces present in a system. - */ - -#include <linux/config.h> -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/timer.h> -#include <linux/mm.h> -#include <linux/interrupt.h> -#include <linux/pci.h> -#include <linux/init.h> -#include <linux/ide.h> - -#include <asm/io.h> -#include <asm/irq.h> - -#define DEVID_PIIXa ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371FB_0}) -#define DEVID_PIIXb ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371FB_1}) -#define DEVID_PIIX3 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_1}) -#define DEVID_PIIX4 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB}) -#define DEVID_PIIX4E ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_1}) -#define DEVID_PIIX4U ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_1}) -#define DEVID_PIIX4U2 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82372FB_1}) -#define DEVID_VIA_IDE ((ide_pci_devid_t){PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C561}) -#define DEVID_VP_IDE ((ide_pci_devid_t){PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1}) -#define DEVID_PDC20246 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20246}) -#define DEVID_PDC20262 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20262}) -#define DEVID_RZ1000 ((ide_pci_devid_t){PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1000}) -#define DEVID_RZ1001 ((ide_pci_devid_t){PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1001}) -#define DEVID_SAMURAI ((ide_pci_devid_t){PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_SAMURAI_IDE}) -#define DEVID_CMD640 ((ide_pci_devid_t){PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_640}) -#define DEVID_CMD643 ((ide_pci_devid_t){PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_643}) -#define DEVID_CMD646 ((ide_pci_devid_t){PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_646}) -#define DEVID_CMD648 ((ide_pci_devid_t){PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_648}) -#define DEVID_SIS5513 ((ide_pci_devid_t){PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5513}) -#define DEVID_OPTI621 ((ide_pci_devid_t){PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C621}) -#define DEVID_OPTI621V ((ide_pci_devid_t){PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C558}) -#define DEVID_OPTI621X ((ide_pci_devid_t){PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C825}) -#define DEVID_TRM290 ((ide_pci_devid_t){PCI_VENDOR_ID_TEKRAM, PCI_DEVICE_ID_TEKRAM_DC290}) -#define DEVID_NS87410 ((ide_pci_devid_t){PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410}) -#define DEVID_NS87415 ((ide_pci_devid_t){PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87415}) -#define DEVID_HT6565 ((ide_pci_devid_t){PCI_VENDOR_ID_HOLTEK, PCI_DEVICE_ID_HOLTEK_6565}) -#define DEVID_AEC6210 ((ide_pci_devid_t){PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP850UF}) -#define DEVID_W82C105 ((ide_pci_devid_t){PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105}) -#define DEVID_UM8673F ((ide_pci_devid_t){PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8673F}) -#define DEVID_UM8886A ((ide_pci_devid_t){PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886A}) -#define DEVID_UM8886BF ((ide_pci_devid_t){PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF}) -#define DEVID_HPT34X ((ide_pci_devid_t){PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT343}) -#define DEVID_HPT366 ((ide_pci_devid_t){PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT366}) -#define DEVID_ALI15X3 ((ide_pci_devid_t){PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5229}) -#define DEVID_CY82C693 ((ide_pci_devid_t){PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693}) -#define DEVID_HINT ((ide_pci_devid_t){0x3388, 0x8013}) -#define DEVID_CS5530 ((ide_pci_devid_t){PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_IDE}) -#define DEVID_AMD7409 ((ide_pci_devid_t){PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7409}) - -#define IDE_IGNORE ((void *)-1) - -#ifdef CONFIG_BLK_DEV_AEC6210 -extern unsigned int pci_init_aec6210(struct pci_dev *, const char *); -extern void ide_init_aec6210(ide_hwif_t *); -extern void ide_dmacapable_aec6210(ide_hwif_t *, unsigned long); -#define PCI_AEC6210 &pci_init_aec6210 -#define INIT_AEC6210 &ide_init_aec6210 -#define DMA_AEC6210 &ide_dmacapable_aec6210 -#else -#define PCI_AEC6210 NULL -#define INIT_AEC6210 NULL -#define DMA_AEC6210 NULL -#endif - -#ifdef CONFIG_BLK_DEV_ALI15X3 -extern unsigned int pci_init_ali15x3(struct pci_dev *, const char *); -extern unsigned int ata66_ali15x3(ide_hwif_t *); -extern void ide_init_ali15x3(ide_hwif_t *); -extern void ide_dmacapable_ali15x3(ide_hwif_t *, unsigned long); -#define PCI_ALI15X3 &pci_init_ali15x3 -#define ATA66_ALI15X3 &ata66_ali15x3 -#define INIT_ALI15X3 &ide_init_ali15x3 -#define DMA_ALI15X3 &ide_dmacapable_ali15x3 -#else -#define PCI_ALI15X3 NULL -#define ATA66_ALI15X3 NULL -#define INIT_ALI15X3 NULL -#define DMA_ALI15X3 NULL -#endif - -#ifdef CONFIG_BLK_DEV_AMD7409 -extern unsigned int pci_init_amd7409(struct pci_dev *, const char *); -extern unsigned int ata66_amd7409(ide_hwif_t *); -extern void ide_init_amd7409(ide_hwif_t *); -extern void ide_dmacapable_amd7409(ide_hwif_t *, unsigned long); -#define PCI_AMD7409 &pci_init_amd7409 -#define ATA66_AMD7409 &ata66_amd7409 -#define INIT_AMD7409 &ide_init_amd7409 -#define DMA_AMD7409 &ide_dmacapable_amd7409 -#else -#define PCI_AMD7409 NULL -#define ATA66_AMD7409 NULL -#define INIT_AMD7409 NULL -#define DMA_AMD7409 NULL -#endif - -#ifdef CONFIG_BLK_DEV_CMD64X -extern unsigned int pci_init_cmd64x(struct pci_dev *, const char *); -extern unsigned int ata66_cmd64x(ide_hwif_t *); -extern void ide_init_cmd64x(ide_hwif_t *); -extern void ide_dmacapable_cmd64x(ide_hwif_t *, unsigned long); -#define PCI_CMD64X &pci_init_cmd64x -#define ATA66_CMD64X &ata66_cmd64x -#define INIT_CMD64X &ide_init_cmd64x -#else -#define PCI_CMD64X NULL -#define ATA66_CMD64X NULL -#ifdef __sparc_v9__ -#define INIT_CMD64X IDE_IGNORE -#else -#define INIT_CMD64X NULL -#endif -#endif - -#ifdef CONFIG_BLK_DEV_CY82C693 -extern unsigned int pci_init_cy82c693(struct pci_dev *, const char *); -extern void ide_init_cy82c693(ide_hwif_t *); -#define PCI_CY82C693 &pci_init_cy82c693 -#define INIT_CY82C693 &ide_init_cy82c693 -#else -#define PCI_CY82C693 NULL -#define INIT_CY82C693 NULL -#endif - -#ifdef CONFIG_BLK_DEV_CS5530 -extern unsigned int pci_init_cs5530(struct pci_dev *, const char *); -extern void ide_init_cs5530(ide_hwif_t *); -#define PCI_CS5530 &pci_init_cs5530 -#define INIT_CS5530 &ide_init_cs5530 -#else -#define PCI_CS5530 NULL -#define INIT_CS5530 NULL -#endif - -#ifdef CONFIG_BLK_DEV_HPT34X -extern unsigned int pci_init_hpt34x(struct pci_dev *, const char *); -extern void ide_init_hpt34x(ide_hwif_t *); -#define PCI_HPT34X &pci_init_hpt34x -#define INIT_HPT34X &ide_init_hpt34x -#else -#define PCI_HPT34X NULL -#define INIT_HPT34X IDE_IGNORE -#endif - -#ifdef CONFIG_BLK_DEV_HPT366 -extern byte hpt363_shared_irq; -extern byte hpt363_shared_pin; -extern unsigned int pci_init_hpt366(struct pci_dev *, const char *); -extern unsigned int ata66_hpt366(ide_hwif_t *); -extern void ide_init_hpt366(ide_hwif_t *); -extern void ide_dmacapable_hpt366(ide_hwif_t *, unsigned long); -#define PCI_HPT366 &pci_init_hpt366 -#define ATA66_HPT366 &ata66_hpt366 -#define INIT_HPT366 &ide_init_hpt366 -#define DMA_HPT366 &ide_dmacapable_hpt366 -#else -static byte hpt363_shared_irq = 0; -static byte hpt363_shared_pin = 0; -#define PCI_HPT366 NULL -#define ATA66_HPT366 NULL -#define INIT_HPT366 NULL -#define DMA_HPT366 NULL -#endif - -#ifdef CONFIG_BLK_DEV_NS87415 -extern void ide_init_ns87415(ide_hwif_t *); -#define INIT_NS87415 &ide_init_ns87415 -#else -#define INIT_NS87415 IDE_IGNORE -#endif - -#ifdef CONFIG_BLK_DEV_OPTI621 -extern void ide_init_opti621(ide_hwif_t *); -#define INIT_OPTI621 &ide_init_opti621 -#else -#define INIT_OPTI621 NULL -#endif - -#ifdef CONFIG_BLK_DEV_PDC202XX -extern unsigned int pci_init_pdc202xx(struct pci_dev *, const char *); -extern unsigned int ata66_pdc202xx(ide_hwif_t *); -extern void ide_init_pdc202xx(ide_hwif_t *); -#define PCI_PDC202XX &pci_init_pdc202xx -#define ATA66_PDC202XX &ata66_pdc202xx -#define INIT_PDC202XX &ide_init_pdc202xx -#else -#define PCI_PDC202XX NULL -#define ATA66_PDC202XX NULL -#define INIT_PDC202XX NULL -#endif - -#ifdef CONFIG_BLK_DEV_PIIX -extern unsigned int pci_init_piix(struct pci_dev *, const char *); -extern unsigned int ata66_piix(ide_hwif_t *); -extern void ide_init_piix(ide_hwif_t *); -#define PCI_PIIX &pci_init_piix -#define ATA66_PIIX &ata66_piix -#define INIT_PIIX &ide_init_piix -#else -#define PCI_PIIX NULL -#define ATA66_PIIX NULL -#define INIT_PIIX NULL -#endif - -#ifdef CONFIG_BLK_DEV_RZ1000 -extern void ide_init_rz1000(ide_hwif_t *); -#define INIT_RZ1000 &ide_init_rz1000 -#else -#define INIT_RZ1000 IDE_IGNORE -#endif - -#define INIT_SAMURAI NULL - -#ifdef CONFIG_BLK_DEV_SIS5513 -extern unsigned int pci_init_sis5513(struct pci_dev *, const char *); -extern unsigned int ata66_sis5513(ide_hwif_t *); -extern void ide_init_sis5513(ide_hwif_t *); -#define PCI_SIS5513 &pci_init_sis5513 -#define ATA66_SIS5513 &ata66_sis5513 -#define INIT_SIS5513 &ide_init_sis5513 -#else -#define PCI_SIS5513 NULL -#define ATA66_SIS5513 NULL -#define INIT_SIS5513 NULL -#endif - -#ifdef CONFIG_BLK_DEV_SL82C105 -extern void ide_init_sl82c105(ide_hwif_t *); -extern void ide_dmacapable_sl82c105(ide_hwif_t *, unsigned long); -#define INIT_W82C105 &ide_init_sl82c105 -#define DMA_W82C105 &ide_dmacapable_sl82c105 -#else -#define INIT_W82C105 IDE_IGNORE -#define DMA_W82C105 NULL -#endif - -#ifdef CONFIG_BLK_DEV_TRM290 -extern void ide_init_trm290(ide_hwif_t *); -#define INIT_TRM290 &ide_init_trm290 -#else -#define INIT_TRM290 IDE_IGNORE -#endif - -#ifdef CONFIG_BLK_DEV_VIA82CXXX -extern unsigned int pci_init_via82cxxx(struct pci_dev *, const char *); -extern unsigned int ata66_via82cxxx(ide_hwif_t *); -extern void ide_init_via82cxxx(ide_hwif_t *); -extern void ide_dmacapable_via82cxxx(ide_hwif_t *, unsigned long); -#define PCI_VIA82CXXX &pci_init_via82cxxx -#define ATA66_VIA82CXXX &ata66_via82cxxx -#define INIT_VIA82CXXX &ide_init_via82cxxx -#define DMA_VIA82CXXX &ide_dmacapable_via82cxxx -#else -#define PCI_VIA82CXXX NULL -#define ATA66_VIA82CXXX NULL -#define INIT_VIA82CXXX NULL -#define DMA_VIA82CXXX NULL -#endif - -typedef struct ide_pci_enablebit_s { - byte reg; /* byte pci reg holding the enable-bit */ - byte mask; /* mask to isolate the enable-bit */ - byte val; /* value of masked reg when "enabled" */ -} ide_pci_enablebit_t; - -typedef struct ide_pci_device_s { - ide_pci_devid_t devid; - const char *name; - unsigned int (*init_chipset)(struct pci_dev *dev, const char *name); - unsigned int (*ata66_check)(ide_hwif_t *hwif); - void (*init_hwif)(ide_hwif_t *hwif); - void (*dma_init)(ide_hwif_t *hwif, unsigned long dmabase); - ide_pci_enablebit_t enablebits[2]; - byte bootable; - unsigned int extra; -} ide_pci_device_t; - -static ide_pci_device_t ide_pci_chipsets[] __initdata = { - {DEVID_PIIXa, "PIIX", NULL, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_PIIXb, "PIIX", NULL, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_PIIX3, "PIIX3", PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_PIIX4, "PIIX4", PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_PIIX4E, "PIIX4", PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_PIIX4U, "PIIX4", PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_PIIX4U2, "PIIX4", PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_VIA_IDE, "VIA_IDE", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_VP_IDE, "VP_IDE", PCI_VIA82CXXX, ATA66_VIA82CXXX,INIT_VIA82CXXX, DMA_VIA82CXXX, {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, ON_BOARD, 0 }, - {DEVID_PDC20246,"PDC20246", PCI_PDC202XX, NULL, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 16 }, - {DEVID_PDC20262,"PDC20262", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 48 }, - {DEVID_RZ1000, "RZ1000", NULL, NULL, INIT_RZ1000, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_RZ1001, "RZ1001", NULL, NULL, INIT_RZ1000, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_SAMURAI, "SAMURAI", NULL, NULL, INIT_SAMURAI, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_CMD640, "CMD640", NULL, NULL, IDE_IGNORE, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_NS87410, "NS87410", NULL, NULL, NULL, NULL, {{0x43,0x08,0x08}, {0x47,0x08,0x08}}, ON_BOARD, 0 }, - {DEVID_SIS5513, "SIS5513", PCI_SIS5513, ATA66_SIS5513, INIT_SIS5513, NULL, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, ON_BOARD, 0 }, - {DEVID_CMD643, "CMD643", PCI_CMD64X, NULL, INIT_CMD64X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_CMD646, "CMD646", PCI_CMD64X, NULL, INIT_CMD64X, NULL, {{0x00,0x00,0x00}, {0x51,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_CMD648, "CMD648", PCI_CMD64X, ATA66_CMD64X, INIT_CMD64X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_HT6565, "HT6565", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_OPTI621, "OPTI621", NULL, NULL, INIT_OPTI621, NULL, {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, ON_BOARD, 0 }, - {DEVID_OPTI621X,"OPTI621X", NULL, NULL, INIT_OPTI621, NULL, {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, ON_BOARD, 0 }, - {DEVID_TRM290, "TRM290", NULL, NULL, INIT_TRM290, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_NS87415, "NS87415", NULL, NULL, INIT_NS87415, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_AEC6210, "AEC6210", PCI_AEC6210, NULL, INIT_AEC6210, DMA_AEC6210, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, - {DEVID_W82C105, "W82C105", NULL, NULL, INIT_W82C105, DMA_W82C105, {{0x40,0x01,0x01}, {0x40,0x10,0x10}}, ON_BOARD, 0 }, - {DEVID_UM8673F, "UM8673F", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_UM8886A, "UM8886A", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_UM8886BF,"UM8886BF", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_HPT34X, "HPT34X", PCI_HPT34X, NULL, INIT_HPT34X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, NEVER_BOARD, 16 }, - {DEVID_HPT366, "HPT366", PCI_HPT366, ATA66_HPT366, INIT_HPT366, DMA_HPT366, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 240 }, - {DEVID_ALI15X3, "ALI15X3", PCI_ALI15X3, ATA66_ALI15X3, INIT_ALI15X3, DMA_ALI15X3, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_CY82C693,"CY82C693", PCI_CY82C693, NULL, INIT_CY82C693, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_HINT, "HINT_IDE", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_CS5530, "CS5530", PCI_CS5530, NULL, INIT_CS5530, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_AMD7409, "AMD7409", PCI_AMD7409, ATA66_AMD7409, INIT_AMD7409, DMA_AMD7409, {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, ON_BOARD, 0 }, - {IDE_PCI_DEVID_NULL, "PCI_IDE", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }}; - -/* - * This allows offboard ide-pci cards the enable a BIOS, verify interrupt - * settings of split-mirror pci-config space, place chipset into init-mode, - * and/or preserve an interrupt if the card is not native ide support. - */ -static unsigned int __init ide_special_settings (struct pci_dev *dev, const char *name) -{ - switch(dev->device) { - case PCI_DEVICE_ID_TTI_HPT366: - case PCI_DEVICE_ID_PROMISE_20246: - case PCI_DEVICE_ID_PROMISE_20262: - case PCI_DEVICE_ID_ARTOP_ATP850UF: - return dev->irq; - default: - break; - } - return 0; -} - -/* - * Match a PCI IDE port against an entry in ide_hwifs[], - * based on io_base port if possible. - */ -static ide_hwif_t __init *ide_match_hwif (unsigned long io_base, byte bootable, const char *name) -{ - int h; - ide_hwif_t *hwif; - - /* - * Look for a hwif with matching io_base specified using - * parameters to ide_setup(). - */ - for (h = 0; h < MAX_HWIFS; ++h) { - hwif = &ide_hwifs[h]; - if (hwif->io_ports[IDE_DATA_OFFSET] == io_base) { - if (hwif->chipset == ide_generic) - return hwif; /* a perfect match */ - } - } - /* - * Look for a hwif with matching io_base default value. - * If chipset is "ide_unknown", then claim that hwif slot. - * Otherwise, some other chipset has already claimed it.. :( - */ - for (h = 0; h < MAX_HWIFS; ++h) { - hwif = &ide_hwifs[h]; - if (hwif->io_ports[IDE_DATA_OFFSET] == io_base) { - if (hwif->chipset == ide_unknown) - return hwif; /* match */ - printk("%s: port 0x%04lx already claimed by %s\n", name, io_base, hwif->name); - return NULL; /* already claimed */ - } - } - /* - * Okay, there is no hwif matching our io_base, - * so we'll just claim an unassigned slot. - * Give preference to claiming other slots before claiming ide0/ide1, - * just in case there's another interface yet-to-be-scanned - * which uses ports 1f0/170 (the ide0/ide1 defaults). - * - * Unless there is a bootable card that does not use the standard - * ports 1f0/170 (the ide0/ide1 defaults). The (bootable) flag. - */ - if (bootable) { - for (h = 0; h < MAX_HWIFS; ++h) { - hwif = &ide_hwifs[h]; - if (hwif->chipset == ide_unknown) - return hwif; /* pick an unused entry */ - } - } else { - for (h = 2; h < MAX_HWIFS; ++h) { - hwif = ide_hwifs + h; - if (hwif->chipset == ide_unknown) - return hwif; /* pick an unused entry */ - } - } - for (h = 0; h < 2; ++h) { - hwif = ide_hwifs + h; - if (hwif->chipset == ide_unknown) - return hwif; /* pick an unused entry */ - } - printk("%s: too many IDE interfaces, no room in table\n", name); - return NULL; -} - -static int __init ide_setup_pci_baseregs (struct pci_dev *dev, const char *name) -{ - byte reg, progif = 0; - - /* - * Place both IDE interfaces into PCI "native" mode: - */ - if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif) || (progif & 5) != 5) { - if ((progif & 0xa) != 0xa) { - printk("%s: device not capable of full native PCI mode\n", name); - return 1; - } - printk("%s: placing both ports into native PCI mode\n", name); - (void) pci_write_config_byte(dev, PCI_CLASS_PROG, progif|5); - if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif) || (progif & 5) != 5) { - printk("%s: rewrite of PROGIF failed, wanted 0x%04x, got 0x%04x\n", name, progif|5, progif); - return 1; - } - } - /* - * Setup base registers for IDE command/control spaces for each interface: - */ - for (reg = 0; reg < 4; reg++) { - struct resource *res = dev->resource + reg; - if (!(res->flags & PCI_BASE_ADDRESS_SPACE_IO)) - continue; - if (!res->start) { - printk("%s: Missing I/O address #%d\n", name, reg); - return 1; - } - } - return 0; -} - -/* - * ide_setup_pci_device() looks at the primary/secondary interfaces - * on a PCI IDE device and, if they are enabled, prepares the IDE driver - * for use with them. This generic code works for most PCI chipsets. - * - * One thing that is not standardized is the location of the - * primary/secondary interface "enable/disable" bits. For chipsets that - * we "know" about, this information is in the ide_pci_device_t struct; - * for all other chipsets, we just assume both interfaces are enabled. - */ -static void __init ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d) -{ - unsigned int port, at_least_one_hwif_enabled = 0, autodma = 0, pciirq = 0; - unsigned short pcicmd = 0, tried_config = 0; - byte tmp = 0; - ide_hwif_t *hwif, *mate = NULL; - -#ifdef CONFIG_IDEDMA_AUTO - autodma = 1; -#endif -check_if_enabled: - if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd)) { - printk("%s: error accessing PCI regs\n", d->name); - return; - } - if (!(pcicmd & PCI_COMMAND_IO)) { /* is device disabled? */ - /* - * PnP BIOS was *supposed* to have set this device up for us, - * but we can do it ourselves, so long as the BIOS has assigned an IRQ - * (or possibly the device is using a "legacy header" for IRQs). - * Maybe the user deliberately *disabled* the device, - * but we'll eventually ignore it again if no drives respond. - */ - if (tried_config++ - || ide_setup_pci_baseregs(dev, d->name) - || pci_write_config_word(dev, PCI_COMMAND, pcicmd | PCI_COMMAND_IO)) { - printk("%s: device disabled (BIOS)\n", d->name); - return; - } - autodma = 0; /* default DMA off if we had to configure it here */ - goto check_if_enabled; - } - if (tried_config) - printk("%s: device enabled (Linux)\n", d->name); - /* - * Can we trust the reported IRQ? - */ - pciirq = dev->irq; - if ((dev->class & ~(0xfa)) != ((PCI_CLASS_STORAGE_IDE << 8) | 5)) { - printk("%s: not 100%% native mode: will probe irqs later\n", d->name); - /* - * This allows offboard ide-pci cards the enable a BIOS, - * verify interrupt settings of split-mirror pci-config - * space, place chipset into init-mode, and/or preserve - * an interrupt if the card is not native ide support. - */ - pciirq = (d->init_chipset) ? d->init_chipset(dev, d->name) : ide_special_settings(dev, d->name); - } else if (tried_config) { - printk("%s: will probe irqs later\n", d->name); - pciirq = 0; - } else if (!pciirq) { - printk("%s: bad irq (%d): will probe later\n", d->name, pciirq); - pciirq = 0; - } else { - if (d->init_chipset) - (void) d->init_chipset(dev, d->name); -#ifdef __sparc__ - printk("%s: 100%% native mode on irq %s\n", - d->name, __irq_itoa(pciirq)); -#else - printk("%s: 100%% native mode on irq %d\n", d->name, pciirq); -#endif - } - if (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT34X)) { - /* see comments in hpt34x.c on why..... */ - d->bootable = (pcicmd & PCI_COMMAND_MEMORY) ? OFF_BOARD : NEVER_BOARD; - } - /* - * Set up the IDE ports - */ - for (port = 0; port <= 1; ++port) { - unsigned long base = 0, ctl = 0; - ide_pci_enablebit_t *e = &(d->enablebits[port]); - if (e->reg && (pci_read_config_byte(dev, e->reg, &tmp) || (tmp & e->mask) != e->val)) - continue; /* port not enabled */ - if (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366) && (port)) - return; - if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE || (dev->class & (port ? 4 : 1)) != 0) { - ctl = dev->resource[(2*port)+1].start; - base = dev->resource[2*port].start; - if (!(ctl & PCI_BASE_ADDRESS_IO_MASK) || - !(base & PCI_BASE_ADDRESS_IO_MASK)) { - printk("%s: IO baseregs (BIOS) are reported as MEM, report to <andre@suse.com>.\n", d->name); -#if 0 - /* FIXME! This really should check that it really gets the IO/MEM part right! */ - continue; -#endif - } - } - if ((ctl && !base) || (base && !ctl)) { - printk("%s: inconsistent baseregs (BIOS) for port %d, skipping\n", d->name, port); - continue; - } - if (!ctl) - ctl = port ? 0x374 : 0x3f4; /* use default value */ - if (!base) - base = port ? 0x170 : 0x1f0; /* use default value */ - if ((hwif = ide_match_hwif(base, d->bootable, d->name)) == NULL) - continue; /* no room in ide_hwifs[] */ - if (hwif->io_ports[IDE_DATA_OFFSET] != base) { - ide_init_hwif_ports(&hwif->hw, base, (ctl | 2), NULL); - memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports)); - hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET]; - } - hwif->chipset = ide_pci; - hwif->pci_dev = dev; - hwif->pci_devid = d->devid; - hwif->channel = port; - if (!hwif->irq) - hwif->irq = pciirq; - if (mate) { - hwif->mate = mate; - mate->mate = hwif; - if (IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6210)) { - hwif->serialized = 1; - mate->serialized = 1; - } - } - if (IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8886A) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8886BF) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8673F)) { - hwif->irq = hwif->channel ? 15 : 14; - goto bypass_umc_dma; - } - if (hwif->udma_four) { - printk("%s: ATA-66 forced bit set (WARNING)!!\n", d->name); - } else { - hwif->udma_four = (d->ata66_check) ? d->ata66_check(hwif) : 0; - } -#ifdef CONFIG_BLK_DEV_IDEDMA - if (IDE_PCI_DEVID_EQ(d->devid, DEVID_SIS5513) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT34X)) - autodma = 0; - if (autodma) - hwif->autodma = 1; - if (IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20246) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20262) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6210) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT34X) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_CS5530) || - IDE_PCI_DEVID_EQ(d->devid, DEVID_CY82C693) || - ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && (dev->class & 0x80))) { - unsigned long dma_base = ide_get_or_set_dma_base(hwif, (!mate && d->extra) ? d->extra : 0, d->name); - if (dma_base && !(pcicmd & PCI_COMMAND_MASTER)) { - /* - * Set up BM-DMA capability (PnP BIOS should have done this) - */ - hwif->autodma = 0; /* default DMA off if we had to configure it here */ - (void) pci_write_config_word(dev, PCI_COMMAND, pcicmd | PCI_COMMAND_MASTER); - if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd) || !(pcicmd & PCI_COMMAND_MASTER)) { - printk("%s: %s error updating PCICMD\n", hwif->name, d->name); - dma_base = 0; - } - } - if (dma_base) { - if (d->dma_init) { - d->dma_init(hwif, dma_base); - } else { - ide_setup_dma(hwif, dma_base, 8); - } - } else { - printk("%s: %s Bus-Master DMA disabled (BIOS)\n", hwif->name, d->name); - } - } -#endif /* CONFIG_BLK_DEV_IDEDMA */ -bypass_umc_dma: - if (d->init_hwif) /* Call chipset-specific routine for each enabled hwif */ - d->init_hwif(hwif); - mate = hwif; - at_least_one_hwif_enabled = 1; - } - if (!at_least_one_hwif_enabled) - printk("%s: neither IDE port enabled (BIOS)\n", d->name); -} - -static void __init hpt366_device_order_fixup (struct pci_dev *dev, ide_pci_device_t *d) -{ - struct pci_dev *dev2 = NULL, *findev; - ide_pci_device_t *d2; - unsigned char pin1 = 0, pin2 = 0; - - if (PCI_FUNC(dev->devfn) & 1) - return; - pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin1); - pci_for_each_dev(findev) { - if ((findev->vendor == dev->vendor) && - (findev->device == dev->device) && - ((findev->devfn - dev->devfn) == 1) && - (PCI_FUNC(findev->devfn) & 1)) { - dev2 = findev; - pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin2); - hpt363_shared_pin = (pin1 != pin2) ? 1 : 0; - hpt363_shared_irq = (dev->irq == dev2->irq) ? 1 : 0; - if (hpt363_shared_pin && hpt363_shared_irq) { - d->bootable = ON_BOARD; - printk("%s: onboard version of chipset, pin1=%d pin2=%d\n", d->name, pin1, pin2); - } - break; - } - } - printk("%s: IDE controller on PCI bus %02x dev %02x\n", d->name, dev->bus->number, dev->devfn); - ide_setup_pci_device(dev, d); - if (!dev2) - return; - d2 = d; - printk("%s: IDE controller on PCI bus %02x dev %02x\n", d2->name, dev2->bus->number, dev2->devfn); - if (hpt363_shared_pin && !hpt363_shared_irq) { - printk("%s: IDE controller run unsupported mode three!!!\n", d2->name); -#ifndef CONFIG_HPT366_MODE3 - printk("%s: IDE controller report to <andre@suse.com>\n", d->name); - return; -#else /* CONFIG_HPT366_MODE3 */ - printk("%s: OVERRIDE IDE controller not advisable this mode!!!\n", d2->name); -#endif /* CONFIG_HPT366_MODE3 */ - } - ide_setup_pci_device(dev2, d2); -} - -/* - * ide_scan_pcibus() gets invoked at boot time from ide.c. - * It finds all PCI IDE controllers and calls ide_setup_pci_device for them. - */ -void __init ide_scan_pcidev (struct pci_dev *dev) -{ - ide_pci_devid_t devid; - ide_pci_device_t *d; - - devid.vid = dev->vendor; - devid.did = dev->device; - for (d = ide_pci_chipsets; d->devid.vid && !IDE_PCI_DEVID_EQ(d->devid, devid); ++d); - if (d->init_hwif == IDE_IGNORE) - printk("%s: ignored by ide_scan_pci_device() (uses own driver)\n", d->name); - else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_OPTI621V) && !(PCI_FUNC(dev->devfn) & 1)) - return; - else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_CY82C693) && (!(PCI_FUNC(dev->devfn) & 1) || !((dev->class >> 8) == PCI_CLASS_STORAGE_IDE))) - return; /* CY82C693 is more than only a IDE controller */ - else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8886A) && !(PCI_FUNC(dev->devfn) & 1)) - return; /* UM8886A/BF pair */ - else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366)) - hpt366_device_order_fixup(dev, d); - else if (!IDE_PCI_DEVID_EQ(d->devid, IDE_PCI_DEVID_NULL) || (dev->class >> 8) == PCI_CLASS_STORAGE_IDE) { - if (IDE_PCI_DEVID_EQ(d->devid, IDE_PCI_DEVID_NULL)) - printk("%s: unknown IDE controller on PCI bus %02x device %02x, VID=%04x, DID=%04x\n", - d->name, dev->bus->number, dev->devfn, devid.vid, devid.did); - else - printk("%s: IDE controller on PCI bus %02x dev %02x\n", d->name, dev->bus->number, dev->devfn); - ide_setup_pci_device(dev, d); - } -} - -void __init ide_scan_pcibus (int scan_direction) -{ - struct pci_dev *dev; - - if (!scan_direction) { - pci_for_each_dev(dev) { - ide_scan_pcidev(dev); - } - } else { - pci_for_each_dev_reverse(dev) { - ide_scan_pcidev(dev); - } - } -} diff --git a/drivers/block/ide-pmac.c b/drivers/block/ide-pmac.c deleted file mode 100644 index e0803e6fa..000000000 --- a/drivers/block/ide-pmac.c +++ /dev/null @@ -1,969 +0,0 @@ -/* - * Support for IDE interfaces on PowerMacs. - * These IDE interfaces are memory-mapped and have a DBDMA channel - * for doing DMA. - * - * Copyright (C) 1998 Paul Mackerras. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * Some code taken from drivers/block/ide-dma.c: - * - * Copyright (c) 1995-1998 Mark Lord - * - * BenH: I began adding more complete timing setup code, mostly because DMA - * won't work on new machines unless timings are setup correctly. This - * code was mainly stolen from Cmd646 driver and should be completed to - * include real timing calc. instead of hard coded values. The format of - * the timing register can be found in Darwin's source code, except for - * Keylargo ATA-4 controller. - */ -#include <linux/config.h> -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/ide.h> - -#include <asm/prom.h> -#include <asm/io.h> -#include <asm/dbdma.h> -#include <asm/ide.h> -#include <asm/mediabay.h> -#include <asm/feature.h> -#ifdef CONFIG_PMAC_PBOOK -#include <linux/adb.h> -#include <linux/pmu.h> -#include <asm/irq.h> -#endif -#include "ide_modes.h" - -#undef IDE_PMAC_DEBUG - -#define IDE_SYSCLK_NS 30 - -struct pmac_ide_hwif { - ide_ioreg_t regbase; - int irq; - int kind; - struct device_node* node; - u32 timings[2]; -#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC - volatile struct dbdma_regs* dma_regs; - struct dbdma_cmd* dma_table; -#endif - -} pmac_ide[MAX_HWIFS]; - -static int pmac_ide_count; - -enum { - controller_ohare, /* OHare based */ - controller_heathrow, /* Heathrow/Paddington */ - controller_kl_ata3, /* KeyLargo ATA-3 */ - controller_kl_ata4 /* KeyLargo ATA-4 */ -}; - - -#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC - -typedef struct { - int accessTime; - int cycleTime; -} pmac_ide_timing; - -/* Multiword DMA timings */ -static pmac_ide_timing mdma_timings[] = -{ - { 215, 480 }, /* Mode 0 */ - { 80, 150 }, /* 1 */ - { 70, 120 } /* 2 */ -}; - -/* Ultra DMA timings (for use when I know how to calculate them */ -static pmac_ide_timing udma_timings[] = -{ - { 0, 114 }, /* Mode 0 */ - { 0, 73 }, /* 1 */ - { 0, 54 }, /* 2 */ - { 0, 39 }, /* 3 */ - { 0, 25 } /* 4 */ -}; - -#define MAX_DCMDS 256 /* allow up to 256 DBDMA commands per xfer */ - -static void pmac_ide_setup_dma(struct device_node *np, int ix); -static int pmac_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive); -static int pmac_ide_build_dmatable(ide_drive_t *drive, int ix, int wr); -static void pmac_ide_tuneproc(ide_drive_t *drive, byte pio); -static void pmac_ide_selectproc(ide_drive_t *drive); - -#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ - -#ifdef CONFIG_PMAC_PBOOK -static int idepmac_notify_sleep(struct pmu_sleep_notifier *self, int when); -struct pmu_sleep_notifier idepmac_sleep_notifier = { - idepmac_notify_sleep, SLEEP_LEVEL_BLOCK, -}; -#endif /* CONFIG_PMAC_PBOOK */ - -static int -pmac_ide_find(ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - ide_ioreg_t base; - int i; - - for (i=0; i<pmac_ide_count; i++) { - base = pmac_ide[i].regbase; - if (base && base == hwif->io_ports[0]) - return i; - } - return -1; -} - -/* - * N.B. this can't be an initfunc, because the media-bay task can - * call ide_[un]register at any time. - */ -void pmac_ide_init_hwif_ports(hw_regs_t *hw, - ide_ioreg_t data_port, ide_ioreg_t ctrl_port, - int *irq) -{ - int i, ix; - - if (data_port == 0) - return; - - for (ix = 0; ix < MAX_HWIFS; ++ix) - if (data_port == pmac_ide[ix].regbase) - break; - - if (ix >= MAX_HWIFS) { - /* Probably a PCI interface... */ - for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; ++i) - hw->io_ports[i] = data_port + i - IDE_DATA_OFFSET; - /* XXX is this right? */ - hw->io_ports[IDE_CONTROL_OFFSET] = 0; - if (irq != 0) - *irq = 0; - return; - } - - /* we check only for -EINVAL meaning that we have found a matching - bay but with the wrong device type */ - i = check_media_bay_by_base(data_port, MB_CD); - if (i == -EINVAL) { - hw->io_ports[IDE_DATA_OFFSET] = 0; - return; - } - - for (i = 0; i < 8; ++i) - hw->io_ports[i] = data_port + i * 0x10; - hw->io_ports[8] = data_port + 0x160; - - if (irq != NULL) - *irq = pmac_ide[ix].irq; - - ide_hwifs[ix].tuneproc = pmac_ide_tuneproc; - ide_hwifs[ix].selectproc = pmac_ide_selectproc; - if (pmac_ide[ix].dma_regs && pmac_ide[ix].dma_table) { - ide_hwifs[ix].dmaproc = &pmac_ide_dmaproc; -#ifdef CONFIG_PMAC_IDEDMA_AUTO - ide_hwifs[ix].autodma = 1; -#endif - } -} - -#if 0 -/* This one could be later extended to handle CMD IDE and be used by some kind - * of /proc interface. I want to be able to get the devicetree path of a block - * device for yaboot configuration - */ -struct device_node* -pmac_ide_get_devnode(ide_drive_t *drive) -{ - int i = pmac_ide_find(drive); - if (i < 0) - return NULL; - return pmac_ide[i].node; -} -#endif - -/* Setup timings for the selected drive (master/slave). I still need to verify if this - * is enough, I beleive selectproc will be called whenever an IDE command is started, - * but... */ -static void -pmac_ide_selectproc(ide_drive_t *drive) -{ - int i = pmac_ide_find(drive); - if (i < 0) - return; - - if (drive->select.all & 0x10) - out_le32((unsigned *)(IDE_DATA_REG + 0x200 + _IO_BASE), pmac_ide[i].timings[1]); - else - out_le32((unsigned *)(IDE_DATA_REG + 0x200 + _IO_BASE), pmac_ide[i].timings[0]); -} - -/* Number of IDE_SYSCLK_NS ticks, argument is in nanoseconds */ -#define SYSCLK_TICKS(t) (((t) + IDE_SYSCLK_NS - 1) / IDE_SYSCLK_NS) - -static void -pmac_ide_tuneproc(ide_drive_t *drive, byte pio) -{ - ide_pio_data_t d; - int i; - u32 *timings; - int accessTicks, recTicks; - - i = pmac_ide_find(drive); - if (i < 0) - return; - - /* The "ata-4" IDE controller of UMA machines is a bit different. - * We don't do anything for PIO modes until we know how to do the - * calculation. - */ - if (pmac_ide[i].kind == controller_kl_ata4) - return; - - pio = ide_get_best_pio_mode(drive, pio, 4, &d); - accessTicks = SYSCLK_TICKS(ide_pio_timings[pio].active_time); - if (accessTicks < 4) - accessTicks = 4; - recTicks = SYSCLK_TICKS(d.cycle_time) - accessTicks - 4; - if (recTicks < 1) - recTicks = 1; - if (drive->select.all & 0x10) - timings = &pmac_ide[i].timings[1]; - else - timings = &pmac_ide[i].timings[0]; - - *timings = ((*timings) & 0xFFFFFF800) | accessTicks | (recTicks << 5); -#ifdef IDE_PMAC_DEBUG - printk("ide_pmac: Set PIO timing for mode %d, reg: 0x%08x\n", - pio, *timings); -#endif - - if (drive->select.all == IN_BYTE(IDE_SELECT_REG)) - pmac_ide_selectproc(drive); -} - -ide_ioreg_t -pmac_ide_get_base(int index) -{ - return pmac_ide[index].regbase; -} - -static int ide_majors[] = { 3, 22, 33, 34, 56, 57 }; - -kdev_t __init -pmac_find_ide_boot(char *bootdevice, int n) -{ - int i; - - /* - * Look through the list of IDE interfaces for this one. - */ - for (i = 0; i < pmac_ide_count; ++i) { - char *name; - if (!pmac_ide[i].node || !pmac_ide[i].node->full_name) - continue; - name = pmac_ide[i].node->full_name; - if (memcmp(name, bootdevice, n) == 0 && name[n] == 0) { - /* XXX should cope with the 2nd drive as well... */ - return MKDEV(ide_majors[i], 0); - } - } - - return 0; -} - -void __init -pmac_ide_probe(void) -{ - struct device_node *np; - int i; - struct device_node *atas; - struct device_node *p, **pp, *removables, **rp; - unsigned long base; - int irq; - ide_hwif_t *hwif; - - if (_machine != _MACH_Pmac) - return; - pp = &atas; - rp = &removables; - p = find_devices("ATA"); - if (p == NULL) - p = find_devices("IDE"); - if (p == NULL) - p = find_type_devices("ide"); - if (p == NULL) - p = find_type_devices("ata"); - /* Move removable devices such as the media-bay CDROM - on the PB3400 to the end of the list. */ - for (; p != NULL; p = p->next) { - if (p->parent && p->parent->type - && strcasecmp(p->parent->type, "media-bay") == 0) { - *rp = p; - rp = &p->next; - } else { - *pp = p; - pp = &p->next; - } - } - *rp = NULL; - *pp = removables; - - for (i = 0, np = atas; i < MAX_HWIFS && np != NULL; np = np->next) { - struct device_node *tp; - - /* - * If this node is not under a mac-io or dbdma node, - * leave it to the generic PCI driver. - */ - for (tp = np->parent; tp != 0; tp = tp->parent) - if (tp->type && (strcmp(tp->type, "mac-io") == 0 - || strcmp(tp->type, "dbdma") == 0)) - break; - if (tp == 0) - continue; - - if (np->n_addrs == 0) { - printk(KERN_WARNING "ide: no address for device %s\n", - np->full_name); - continue; - } - - /* - * If this slot is taken (e.g. by ide-pci.c) try the next one. - */ - while (i < MAX_HWIFS - && ide_hwifs[i].io_ports[IDE_DATA_OFFSET] != 0) - ++i; - if (i >= MAX_HWIFS) - break; - - base = (unsigned long) ioremap(np->addrs[0].address, 0x200) - _IO_BASE; - - /* XXX This is bogus. Should be fixed in the registry by checking - the kind of host interrupt controller, a bit like gatwick - fixes in irq.c - */ - if (np->n_intrs == 0) { - printk("ide: no intrs for device %s, using 13\n", - np->full_name); - irq = 13; - } else { - irq = np->intrs[0].line; - } - pmac_ide[i].regbase = base; - pmac_ide[i].irq = irq; - pmac_ide[i].node = np; - if (device_is_compatible(np, "keylargo-ata")) { - if (strcmp(np->name, "ata-4") == 0) - pmac_ide[i].kind = controller_kl_ata4; - else - pmac_ide[i].kind = controller_kl_ata3; - } else if (device_is_compatible(np, "heathrow-ata")) - pmac_ide[i].kind = controller_heathrow; - else - pmac_ide[i].kind = controller_ohare; - - if (np->parent && np->parent->name - && strcasecmp(np->parent->name, "media-bay") == 0) { - media_bay_set_ide_infos(np->parent,base,irq,i); - } else if (pmac_ide[i].kind == controller_ohare) { - /* The code below is having trouble on some ohare machines - * (timing related ?). Until I can put my hand on one of these - * units, I keep the old way - */ - feature_set(np, FEATURE_IDE0_enable); - } else { - /* This is necessary to enable IDE when net-booting */ - int *bidp = (int *)get_property(np, "AAPL,bus-id", NULL); - int bid = bidp ? *bidp : 0; - printk("pmac_ide: enabling IDE bus ID %d\n", bid); - switch(bid) { - case 0: - feature_set(np, FEATURE_IDE0_reset); - feature_set(np, FEATURE_IOBUS_enable); - mdelay(10); - feature_set(np, FEATURE_IDE0_enable); - mdelay(10); - feature_clear(np, FEATURE_IDE0_reset); - break; - case 1: - feature_set(np, FEATURE_Mediabay_IDE_reset); - mdelay(10); - feature_set(np, FEATURE_Mediabay_IDE_enable); - mdelay(10); - feature_clear(np, FEATURE_Mediabay_IDE_reset); - break; - case 2: - /* This one exists only for KL, I don't know about any - enable bit */ - feature_set(np, FEATURE_IDE2_reset); - mdelay(10); - feature_clear(np, FEATURE_IDE2_reset); - break; - } - mdelay(1000); - } - - hwif = &ide_hwifs[i]; - pmac_ide_init_hwif_ports(&hwif->hw, base, 0, &hwif->irq); - memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports)); - hwif->chipset = ide_pmac; - hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET]; - -#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC - if (np->n_addrs >= 2) { - /* has a DBDMA controller channel */ - pmac_ide_setup_dma(np, i); - } -#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ - - ++i; - } - pmac_ide_count = i; - -#ifdef CONFIG_PMAC_PBOOK - pmu_register_sleep_notifier(&idepmac_sleep_notifier); -#endif /* CONFIG_PMAC_PBOOK */ -} - -#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC - -static void __init -pmac_ide_setup_dma(struct device_node *np, int ix) -{ - pmac_ide[ix].dma_regs = - (volatile struct dbdma_regs*)ioremap(np->addrs[1].address, 0x200); - - /* - * Allocate space for the DBDMA commands. - * The +2 is +1 for the stop command and +1 to allow for - * aligning the start address to a multiple of 16 bytes. - */ - pmac_ide[ix].dma_table = (struct dbdma_cmd*) - kmalloc((MAX_DCMDS + 2) * sizeof(struct dbdma_cmd), GFP_KERNEL); - if (pmac_ide[ix].dma_table == 0) { - printk(KERN_ERR "%s: unable to allocate DMA command list\n", - ide_hwifs[ix].name); - return; - } - - ide_hwifs[ix].dmaproc = &pmac_ide_dmaproc; -#ifdef CONFIG_PMAC_IDEDMA_AUTO - ide_hwifs[ix].autodma = 1; -#endif -} - -/* - * pmac_ide_build_dmatable builds the DBDMA command list - * for a transfer and sets the DBDMA channel to point to it. - */ -static int -pmac_ide_build_dmatable(ide_drive_t *drive, int ix, int wr) -{ - struct dbdma_cmd *table, *tstart; - int count = 0; - struct request *rq = HWGROUP(drive)->rq; - struct buffer_head *bh = rq->bh; - unsigned int size, addr; - volatile struct dbdma_regs *dma = pmac_ide[ix].dma_regs; - - table = tstart = (struct dbdma_cmd *) DBDMA_ALIGN(pmac_ide[ix].dma_table); - out_le32(&dma->control, (RUN|PAUSE|FLUSH|WAKE|DEAD) << 16); - while (in_le32(&dma->status) & RUN) - udelay(1); - - do { - /* - * Determine addr and size of next buffer area. We assume that - * individual virtual buffers are always composed linearly in - * physical memory. For example, we assume that any 8kB buffer - * is always composed of two adjacent physical 4kB pages rather - * than two possibly non-adjacent physical 4kB pages. - */ - if (bh == NULL) { /* paging requests have (rq->bh == NULL) */ - addr = virt_to_bus(rq->buffer); - size = rq->nr_sectors << 9; - } else { - /* group sequential buffers into one large buffer */ - addr = virt_to_bus(bh->b_data); - size = bh->b_size; - while ((bh = bh->b_reqnext) != NULL) { - if ((addr + size) != virt_to_bus(bh->b_data)) - break; - size += bh->b_size; - } - } - - /* - * Fill in the next DBDMA command block. - * Note that one DBDMA command can transfer - * at most 65535 bytes. - */ - while (size) { - unsigned int tc = (size < 0xfe00)? size: 0xfe00; - - if (++count >= MAX_DCMDS) { - printk("%s: DMA table too small\n", - drive->name); - return 0; /* revert to PIO for this request */ - } - st_le16(&table->command, wr? OUTPUT_MORE: INPUT_MORE); - st_le16(&table->req_count, tc); - st_le32(&table->phy_addr, addr); - table->cmd_dep = 0; - table->xfer_status = 0; - table->res_count = 0; - addr += tc; - size -= tc; - ++table; - } - } while (bh != NULL); - - /* convert the last command to an input/output last command */ - if (count) - st_le16(&table[-1].command, wr? OUTPUT_LAST: INPUT_LAST); - else - printk(KERN_DEBUG "%s: empty DMA table?\n", drive->name); - - /* add the stop command to the end of the list */ - memset(table, 0, sizeof(struct dbdma_cmd)); - out_le16(&table->command, DBDMA_STOP); - - out_le32(&dma->cmdptr, virt_to_bus(tstart)); - return 1; -} - - -/* This is fun. -DaveM */ -#define IDE_SETXFER 0x03 -#define IDE_SETFEATURE 0xef -#define IDE_DMA2_ENABLE 0x22 -#define IDE_DMA1_ENABLE 0x21 -#define IDE_DMA0_ENABLE 0x20 -#define IDE_UDMA4_ENABLE 0x44 -#define IDE_UDMA3_ENABLE 0x43 -#define IDE_UDMA2_ENABLE 0x42 -#define IDE_UDMA1_ENABLE 0x41 -#define IDE_UDMA0_ENABLE 0x40 - -static __inline__ unsigned char -dma_bits_to_command(unsigned char bits) -{ - if(bits & 0x04) - return IDE_DMA2_ENABLE; - if(bits & 0x02) - return IDE_DMA1_ENABLE; - return IDE_DMA0_ENABLE; -} - -static __inline__ unsigned char -udma_bits_to_command(unsigned char bits) -{ - if(bits & 0x10) - return IDE_UDMA4_ENABLE; - if(bits & 0x08) - return IDE_UDMA3_ENABLE; - if(bits & 0x04) - return IDE_UDMA2_ENABLE; - if(bits & 0x02) - return IDE_UDMA1_ENABLE; - if(bits & 0x01) - return IDE_UDMA0_ENABLE; - return 0; -} - -static __inline__ int -wait_for_ready(ide_drive_t *drive) -{ - /* Timeout bumped for some powerbooks */ - int timeout = 2000; - byte stat; - - while(--timeout) { - stat = GET_STAT(); - if(!(stat & BUSY_STAT)) { - if (drive->ready_stat == 0) - break; - else if((stat & drive->ready_stat) || (stat & ERR_STAT)) - break; - } - mdelay(1); - } - if((stat & ERR_STAT) || timeout <= 0) { - if (stat & ERR_STAT) { - printk("ide_pmace: wait_for_ready, error status: %x\n", stat); - } - return 1; - } - return 0; -} - -static int -pmac_ide_do_setfeature(ide_drive_t *drive, byte command) -{ - unsigned long flags; - byte old_select; - int result = 1; - - save_flags(flags); - cli(); - old_select = IN_BYTE(IDE_SELECT_REG); - OUT_BYTE(drive->select.all, IDE_SELECT_REG); - udelay(10); - OUT_BYTE(IDE_SETXFER, IDE_FEATURE_REG); - OUT_BYTE(command, IDE_NSECTOR_REG); - if(wait_for_ready(drive)) { - printk("pmac_ide_do_setfeature disk not ready before SET_FEATURE!\n"); - goto out; - } - OUT_BYTE(IDE_SETFEATURE, IDE_COMMAND_REG); - result = wait_for_ready(drive); - if (result) - printk("pmac_ide_do_setfeature disk not ready after SET_FEATURE !\n"); -out: - OUT_BYTE(old_select, IDE_SELECT_REG); - restore_flags(flags); - - return result; -} - -static int -pmac_ide_mdma_enable(ide_drive_t *drive, int idx) -{ - byte bits = drive->id->dma_mword & 0x07; - byte feature = dma_bits_to_command(bits); - u32 *timings; - int cycleTime, accessTime; - int accessTicks, recTicks; - struct hd_driveid *id = drive->id; - - /* For now, we don't know these values */ - if (pmac_ide[idx].kind == controller_kl_ata4 && feature != IDE_DMA2_ENABLE) - return 0; - if (pmac_ide[idx].kind != controller_kl_ata4 && feature == IDE_DMA0_ENABLE) - return 0; - - /* Set feature on drive */ - printk("%s: Enabling MultiWord DMA %d\n", drive->name, feature & 0xf); - if (pmac_ide_do_setfeature(drive, feature)) { - printk("%s: Failed !\n", drive->name); - return 0; - } - - /* which drive is it ? */ - if (drive->select.all & 0x10) - timings = &pmac_ide[idx].timings[1]; - else - timings = &pmac_ide[idx].timings[0]; - - /* Calculate accesstime and cycle time */ - cycleTime = mdma_timings[feature & 0xf].cycleTime; - accessTime = mdma_timings[feature & 0xf].accessTime; - if ((id->field_valid & 2) && (id->eide_dma_time)) - cycleTime = id->eide_dma_time; - if ((pmac_ide[idx].kind == controller_ohare) && (cycleTime < 150)) - cycleTime = 150; - - /* For ata-4 controller, we don't know the calculation */ - if (pmac_ide[idx].kind == controller_kl_ata4) { - *timings = 0x00019465; /* MDMA2 */ - } else { - int halfTick = 0; - int origAccessTime = accessTime; - int origCycleTime = cycleTime; - - accessTicks = SYSCLK_TICKS(accessTime); - if (accessTicks < 1) - accessTicks = 1; - accessTime = accessTicks * IDE_SYSCLK_NS; - recTicks = SYSCLK_TICKS(cycleTime - accessTime) - 1; - if (recTicks < 1) - recTicks = 1; - cycleTime = (recTicks + 1 + accessTicks) * IDE_SYSCLK_NS; - - if ((accessTicks > 1) && - ((accessTime - IDE_SYSCLK_NS/2) >= origAccessTime) && - ((cycleTime - IDE_SYSCLK_NS) >= origCycleTime)) { - halfTick = 1; - accessTicks--; - } - *timings = ((*timings) & 0x7FF) | - (accessTicks | (recTicks << 5) | (halfTick << 10)) << 11; - } -#ifdef IDE_PMAC_DEBUG - printk("ide_pmac: Set MDMA timing for mode %d, reg: 0x%08x\n", - feature & 0xf, *timings); -#endif - return 1; -} - -static int -pmac_ide_udma_enable(ide_drive_t *drive, int idx) -{ - byte bits = drive->id->dma_ultra & 0x1f; - byte feature = udma_bits_to_command(bits); - u32 timings; - - /* We support only those values */ - if (feature != IDE_UDMA4_ENABLE && feature != IDE_UDMA2_ENABLE) - return 0; - - /* Set feature on drive */ - printk("%s: Enabling Ultra DMA %d\n", drive->name, feature & 0xf); - if (pmac_ide_do_setfeature(drive, feature)) { - printk("%s: Failed !\n", drive->name); - return 0; - } - - /* Put this channel into UDMA mode. - * This value is set by MacOS on the iBook for U/DMA2 - */ - switch(feature) { - case IDE_UDMA4_ENABLE: - timings = 0x0cd00065; - break; - case IDE_UDMA2_ENABLE: - timings = 0x11100065; - break; - } - - if (drive->select.all & 0x10) - pmac_ide[idx].timings[1] = timings; - else - pmac_ide[idx].timings[0] = timings; - - return 1; -} - -static int -pmac_ide_dma_onoff(ide_drive_t *drive, int enable) -{ - int ata4, udma, idx; - struct hd_driveid *id = drive->id; - - drive->using_dma = 0; - - idx = pmac_ide_find(drive); - if (idx < 0) - return 0; - - if (drive->media == ide_floppy) - enable = 0; - if (((id->capability & 1) == 0) && !check_drive_lists(drive, GOOD_DMA_DRIVE)) - enable = 0; - if (check_drive_lists(drive, BAD_DMA_DRIVE)) - enable = 0; - - udma = 0; - ata4 = (pmac_ide[idx].kind == controller_kl_ata4); - - if(enable) { - if (ata4 && (drive->media == ide_disk) && - (id->field_valid & 0x0004) && (id->dma_ultra & 0x17)) { - /* UltraDMA modes. */ - drive->using_dma = pmac_ide_udma_enable(drive, idx); - } - if (!drive->using_dma && (id->dma_mword & 0x0007)) { - /* Normal MultiWord DMA modes. */ - drive->using_dma = pmac_ide_mdma_enable(drive, idx); - } - /* Without this, strange things will happen on Keylargo-based - * machines - */ - OUT_BYTE(0, IDE_CONTROL_REG); - if (drive->select.all == IN_BYTE(IDE_SELECT_REG)) - pmac_ide_selectproc(drive); - } - return 0; -} - -int pmac_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - int ix, dstat; - volatile struct dbdma_regs *dma; - - /* Can we stuff a pointer to our intf structure in config_data - * or select_data in hwif ? - */ - ix = pmac_ide_find(drive); - if (ix < 0) - return 0; - dma = pmac_ide[ix].dma_regs; - - switch (func) { - case ide_dma_on: - case ide_dma_off: - case ide_dma_off_quietly: - pmac_ide_dma_onoff(drive, (func == ide_dma_on)); - break; - case ide_dma_check: - if (hwif->autodma) - pmac_ide_dma_onoff(drive, 1); - break; - case ide_dma_read: - case ide_dma_write: - if (!pmac_ide_build_dmatable(drive, ix, func==ide_dma_write)) - return 1; - drive->waiting_for_dma = 1; - if (drive->media != ide_disk) - return 0; - ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL); - OUT_BYTE(func==ide_dma_write? WIN_WRITEDMA: WIN_READDMA, - IDE_COMMAND_REG); - case ide_dma_begin: - out_le32(&dma->control, (RUN << 16) | RUN); - break; - case ide_dma_end: - drive->waiting_for_dma = 0; - dstat = in_le32(&dma->status); - out_le32(&dma->control, ((RUN|WAKE|DEAD) << 16)); - /* verify good dma status */ - return (dstat & (RUN|DEAD|ACTIVE)) != RUN; - case ide_dma_test_irq: - return (in_le32(&dma->status) & (RUN|ACTIVE)) == RUN; - default: - printk(KERN_ERR "pmac_ide_dmaproc: bad func %d\n", func); - } - return 0; -} -#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ - -#ifdef CONFIG_PMAC_PBOOK -static void idepmac_sleep_disk(int i, unsigned long base) -{ - struct device_node* np = pmac_ide[i].node; - int j; - - /* FIXME: We only handle the master IDE */ - if (ide_hwifs[i].drives[0].media == ide_disk) { - /* Spin down the drive */ - outb(0xa0, base+0x60); - outb(0x0, base+0x30); - outb(0x0, base+0x20); - outb(0x0, base+0x40); - outb(0x0, base+0x50); - outb(0xe0, base+0x70); - outb(0x2, base+0x160); - for (j = 0; j < 10; j++) { - int status; - mdelay(100); - status = inb(base+0x70); - if (!(status & BUSY_STAT) && (status & DRQ_STAT)) - break; - } - } - feature_set(np, FEATURE_IDE0_reset); - feature_clear(np, FEATURE_IOBUS_enable); - feature_clear(np, FEATURE_IDE0_enable); - pmac_ide[i].timings[0] = 0; - pmac_ide[i].timings[1] = 0; -} - -static void idepmac_wake_disk(int i, unsigned long base) -{ - struct device_node* np = pmac_ide[i].node; - int j; - - /* Revive IDE disk and controller */ - feature_set(np, FEATURE_IOBUS_enable); - mdelay(10); - feature_set(np, FEATURE_IDE0_enable); - mdelay(10); - feature_clear(np, FEATURE_IDE0_reset); - mdelay(100); - - /* Reset timings */ - pmac_ide_selectproc(&ide_hwifs[i].drives[0]); - mdelay(10); - - /* Wait up to 10 seconds (enough for recent drives) */ - for (j = 0; j < 100; j++) { - int status; - mdelay(100); - status = inb(base + 0x70); - if (!(status & BUSY_STAT)) - break; - } -} - -/* Here we handle media bay devices */ -static void -idepmac_wake_bay(int i, unsigned long base) -{ - int timeout; - - /* Reset timings */ - pmac_ide_selectproc(&ide_hwifs[i].drives[0]); - mdelay(10); - - timeout = 10000; - while ((inb(base + 0x70) & BUSY_STAT) && timeout) { - mdelay(1); - --timeout; - } -} - -/* Note: We support only master drives for now. This will have to be - * improved if we want to handle sleep on the iMacDV where the CD-ROM - * is a slave - */ -static int idepmac_notify_sleep(struct pmu_sleep_notifier *self, int when) -{ - int i, ret; - unsigned long base; - - switch (when) { - case PBOOK_SLEEP_REQUEST: - break; - case PBOOK_SLEEP_REJECT: - break; - case PBOOK_SLEEP_NOW: - for (i = 0; i < pmac_ide_count; ++i) { - if ((base = pmac_ide[i].regbase) == 0) - continue; - /* Disable irq during sleep */ - disable_irq(pmac_ide[i].irq); - ret = check_media_bay_by_base(base, MB_CD); - if (ret == -ENODEV) - /* not media bay - put the disk to sleep */ - idepmac_sleep_disk(i, base); - } - break; - case PBOOK_WAKE: - for (i = 0; i < pmac_ide_count; ++i) { - ide_hwif_t *hwif; - if ((base = pmac_ide[i].regbase) == 0) - continue; - hwif = &ide_hwifs[i]; - /* We don't handle media bay devices this way */ - ret = check_media_bay_by_base(base, MB_CD); - if (ret == -ENODEV) - idepmac_wake_disk(i, base); - else if (ret == 0) - idepmac_wake_bay(i, base); - enable_irq(pmac_ide[i].irq); - -#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC - if (hwif->drives[0].present && hwif->drives[0].using_dma) - pmac_ide_dma_onoff(&hwif->drives[0], 1); -#endif - } - break; - } - return PBOOK_SLEEP_OK; -} -#endif /* CONFIG_PMAC_PBOOK */ diff --git a/drivers/block/ide-pnp.c b/drivers/block/ide-pnp.c deleted file mode 100644 index ffa3ade56..000000000 --- a/drivers/block/ide-pnp.c +++ /dev/null @@ -1,158 +0,0 @@ -/* - * linux/drivers/block/ide-pnp.c - * - * This file provides autodetection for ISA PnP IDE interfaces. - * It was tested with "ESS ES1868 Plug and Play AudioDrive" IDE interface. - * - * Copyright (C) 2000 Andrey Panin <pazke@orbita.don.sitek.net> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * You should have received a copy of the GNU General Public License - * (for example /usr/src/linux/COPYING); if not, write to the Free - * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/ide.h> -#include <linux/isapnp.h> - -#ifndef PREPARE_FUNC -#define PREPARE_FUNC(dev) (dev->prepare) -#define ACTIVATE_FUNC(dev) (dev->activate) -#define DEACTIVATE_FUNC(dev) (dev->deactivate) -#endif - -#define DEV_IO(dev, index) (dev->resource[index].start) -#define DEV_IRQ(dev, index) (dev->irq_resource[index].start) - -#define DEV_NAME(dev) (dev->bus->name ? dev->bus->name : "ISA PnP") - -#define GENERIC_HD_DATA 0 -#define GENERIC_HD_ERROR 1 -#define GENERIC_HD_NSECTOR 2 -#define GENERIC_HD_SECTOR 3 -#define GENERIC_HD_LCYL 4 -#define GENERIC_HD_HCYL 5 -#define GENERIC_HD_SELECT 6 -#define GENERIC_HD_STATUS 7 - -static int generic_ide_offsets[IDE_NR_PORTS] __initdata = { - GENERIC_HD_DATA, GENERIC_HD_ERROR, GENERIC_HD_NSECTOR, - GENERIC_HD_SECTOR, GENERIC_HD_LCYL, GENERIC_HD_HCYL, - GENERIC_HD_SELECT, GENERIC_HD_STATUS, -1, -1 -}; - -/* ISA PnP device table entry */ -struct pnp_dev_t { - unsigned int vendor, device; - int (*init_fn)(struct pci_dev *dev, int enable); -}; - -/* Generic initialisation function for ISA PnP IDE interface */ -static int __init pnpide_generic_init(struct pci_dev *dev, int enable) -{ - hw_regs_t hw; - int index; - - if (!enable) - return 0; - - if (!(DEV_IO(dev, 0) && DEV_IO(dev, 1) && DEV_IRQ(dev, 0))) - return 1; - - ide_setup_ports(&hw, (ide_ioreg_t) DEV_IO(dev, 0), - generic_ide_offsets, (ide_ioreg_t) DEV_IO(dev, 1), - 0, NULL, DEV_IRQ(dev, 0)); - - index = ide_register_hw(&hw, NULL); - - if (index != -1) { - printk("ide%d: %s IDE interface\n", index, DEV_NAME(dev)); - return 0; - } - - return 1; -} - -/* Add your devices here :)) */ -struct pnp_dev_t idepnp_devices[] __initdata = { - /* Generic ESDI/IDE/ATA compatible hard disk controller
*/ - { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0x0600), - pnpide_generic_init }, - { 0 } -}; - -#ifdef MODULE -#define NR_PNP_DEVICES 8 -struct pnp_dev_inst { - struct pci_dev *dev; - struct pnp_dev_t *dev_type; -}; -static struct pnp_dev_inst devices[NR_PNP_DEVICES]; -static int pnp_ide_dev_idx = 0; -#endif - -/* - * Probe for ISA PnP IDE interfaces. - */ -void pnpide_init(int enable) -{ - struct pci_dev *dev = NULL; - struct pnp_dev_t *dev_type; - - if (!isapnp_present()) - return; - -#ifdef MODULE - /* Module unload, deactivate all registered devices. */ - if (!enable) { - int i; - for (i = 0; i < pnp_ide_dev_idx; i++) { - devices[i].dev_type->init_fn(dev, 0); - - if (DEACTIVATE_FUNC(devices[i].dev)) - DEACTIVATE_FUNC(devices[i].dev)(devices[i].dev); - } - return; - } -#endif - for (dev_type = idepnp_devices; dev_type->vendor; dev_type++) { - while ((dev = isapnp_find_dev(NULL, dev_type->vendor, - dev_type->device, dev))) { - - if (dev->active) - continue; - - if (PREPARE_FUNC(dev) && (PREPARE_FUNC(dev))(dev) < 0) { - printk("ide: %s prepare failed\n", DEV_NAME(dev)); - continue; - } - - if (ACTIVATE_FUNC(dev) && (ACTIVATE_FUNC(dev))(dev) < 0) { - printk("ide: %s activate failed\n", DEV_NAME(dev)); - continue; - } - - /* Call device initialization function */ - if (dev_type->init_fn(dev, 1)) { - if (DEACTIVATE_FUNC(dev)) - DEACTIVATE_FUNC(dev)(dev); - } else { -#ifdef MODULE - /* - * Register device in the array to - * deactivate it on a module unload. - */ - if (pnp_ide_dev_idx >= NR_PNP_DEVICES) - return; - devices[pnp_ide_dev_idx].dev = dev; - devices[pnp_ide_dev_idx].dev_type = dev_type; - pnp_ide_dev_idx++; -#endif - } - } - } -} diff --git a/drivers/block/ide-probe.c b/drivers/block/ide-probe.c deleted file mode 100644 index 311bcfa25..000000000 --- a/drivers/block/ide-probe.c +++ /dev/null @@ -1,929 +0,0 @@ -/* - * linux/drivers/block/ide-probe.c Version 1.05 July 3, 1999 - * - * Copyright (C) 1994-1998 Linus Torvalds & authors (see below) - */ - -/* - * Mostly written by Mark Lord <mlord@pobox.com> - * and Gadi Oxman <gadio@netvision.net.il> - * - * See linux/MAINTAINERS for address of current maintainer. - * - * This is the IDE probe module, as evolved from hd.c and ide.c. - * - * Version 1.00 move drive probing code from ide.c to ide-probe.c - * Version 1.01 fix compilation problem for m68k - * Version 1.02 increase WAIT_PIDENTIFY to avoid CD-ROM locking at boot - * by Andrea Arcangeli - * Version 1.03 fix for (hwif->chipset == ide_4drives) - * Version 1.04 fixed buggy treatments of known flash memory cards - * - * Version 1.05 fix for (hwif->chipset == ide_pdc4030) - * added ide6/7/8/9 - * allowed for secondary flash card to be detectable - * with new flag : drive->ata_flash : 1; - */ - -#undef REALLY_SLOW_IO /* most systems can safely undef this */ - -#include <linux/config.h> -#include <linux/module.h> -#include <linux/types.h> -#include <linux/string.h> -#include <linux/kernel.h> -#include <linux/timer.h> -#include <linux/mm.h> -#include <linux/interrupt.h> -#include <linux/major.h> -#include <linux/errno.h> -#include <linux/genhd.h> -#include <linux/malloc.h> -#include <linux/delay.h> -#include <linux/ide.h> - -#include <asm/byteorder.h> -#include <asm/irq.h> -#include <asm/uaccess.h> -#include <asm/io.h> - -static inline void do_identify (ide_drive_t *drive, byte cmd) -{ - int bswap = 1; - struct hd_driveid *id; - - id = drive->id = kmalloc (SECTOR_WORDS*4, GFP_ATOMIC); /* called with interrupts disabled! */ - ide_input_data(drive, id, SECTOR_WORDS); /* read 512 bytes of id info */ - ide__sti(); /* local CPU only */ - ide_fix_driveid(id); - if (!drive->forced_lun) - drive->last_lun = id->last_lun & 0x7; -#if defined (CONFIG_SCSI_EATA_DMA) || defined (CONFIG_SCSI_EATA_PIO) || defined (CONFIG_SCSI_EATA) - /* - * EATA SCSI controllers do a hardware ATA emulation: - * Ignore them if there is a driver for them available. - */ - if ((id->model[0] == 'P' && id->model[1] == 'M') - || (id->model[0] == 'S' && id->model[1] == 'K')) { - printk("%s: EATA SCSI HBA %.10s\n", drive->name, id->model); - drive->present = 0; - return; - } -#endif /* CONFIG_SCSI_EATA_DMA || CONFIG_SCSI_EATA_PIO */ - - /* - * WIN_IDENTIFY returns little-endian info, - * WIN_PIDENTIFY *usually* returns little-endian info. - */ - if (cmd == WIN_PIDENTIFY) { - if ((id->model[0] == 'N' && id->model[1] == 'E') /* NEC */ - || (id->model[0] == 'F' && id->model[1] == 'X') /* Mitsumi */ - || (id->model[0] == 'P' && id->model[1] == 'i'))/* Pioneer */ - bswap ^= 1; /* Vertos drives may still be weird */ - } - ide_fixstring (id->model, sizeof(id->model), bswap); - ide_fixstring (id->fw_rev, sizeof(id->fw_rev), bswap); - ide_fixstring (id->serial_no, sizeof(id->serial_no), bswap); - - if (strstr(id->model, "E X A B Y T E N E S T")) - return; - - id->model[sizeof(id->model)-1] = '\0'; /* we depend on this a lot! */ - printk("%s: %s, ", drive->name, id->model); - drive->present = 1; - - /* - * Check for an ATAPI device - */ - if (cmd == WIN_PIDENTIFY) { - byte type = (id->config >> 8) & 0x1f; - printk("ATAPI "); -#ifdef CONFIG_BLK_DEV_PDC4030 - if (HWIF(drive)->channel == 1 && HWIF(drive)->chipset == ide_pdc4030) { - printk(" -- not supported on 2nd Promise port\n"); - drive->present = 0; - return; - } -#endif /* CONFIG_BLK_DEV_PDC4030 */ - switch (type) { - case ide_floppy: - if (!strstr(id->model, "CD-ROM")) { - if (!strstr(id->model, "oppy") && !strstr(id->model, "poyp") && !strstr(id->model, "ZIP")) - printk("cdrom or floppy?, assuming "); - if (drive->media != ide_cdrom) { - printk ("FLOPPY"); - break; - } - } - type = ide_cdrom; /* Early cdrom models used zero */ - case ide_cdrom: - drive->removable = 1; -#ifdef CONFIG_PPC - /* kludge for Apple PowerBook internal zip */ - if (!strstr(id->model, "CD-ROM") && strstr(id->model, "ZIP")) { - printk ("FLOPPY"); - type = ide_floppy; - break; - } -#endif - printk ("CDROM"); - break; - case ide_tape: - printk ("TAPE"); - break; - case ide_optical: - printk ("OPTICAL"); - drive->removable = 1; - break; - default: - printk("UNKNOWN (type %d)", type); - break; - } - printk (" drive\n"); - drive->media = type; - return; - } - - /* - * Not an ATAPI device: looks like a "regular" hard disk - */ - if (id->config & (1<<7)) - drive->removable = 1; - /* - * Prevent long system lockup probing later for non-existant - * slave drive if the hwif is actually a flash memory card of some variety: - */ - if (drive_is_flashcard(drive)) { - ide_drive_t *mate = &HWIF(drive)->drives[1^drive->select.b.unit]; - if (!mate->ata_flash) { - mate->present = 0; - mate->noprobe = 1; - } - } - drive->media = ide_disk; - printk("ATA DISK drive\n"); - return; -} - -/* - * try_to_identify() sends an ATA(PI) IDENTIFY request to a drive - * and waits for a response. It also monitors irqs while this is - * happening, in hope of automatically determining which one is - * being used by the interface. - * - * Returns: 0 device was identified - * 1 device timed-out (no response to identify request) - * 2 device aborted the command (refused to identify itself) - */ -static int try_to_identify (ide_drive_t *drive, byte cmd) -{ - int rc; - ide_ioreg_t hd_status; - unsigned long timeout; - unsigned long irqs = 0; - byte s, a; - - if (IDE_CONTROL_REG) { - if (!HWIF(drive)->irq) { /* already got an IRQ? */ - probe_irq_off(probe_irq_on()); /* clear dangling irqs */ - irqs = probe_irq_on(); /* start monitoring irqs */ - OUT_BYTE(drive->ctl,IDE_CONTROL_REG); /* enable device irq */ - } - - ide_delay_50ms(); /* take a deep breath */ - a = IN_BYTE(IDE_ALTSTATUS_REG); - s = IN_BYTE(IDE_STATUS_REG); - if ((a ^ s) & ~INDEX_STAT) { - printk("%s: probing with STATUS(0x%02x) instead of ALTSTATUS(0x%02x)\n", drive->name, s, a); - hd_status = IDE_STATUS_REG; /* ancient Seagate drives, broken interfaces */ - } else { - hd_status = IDE_ALTSTATUS_REG; /* use non-intrusive polling */ - } - } else { - ide_delay_50ms(); - hd_status = IDE_STATUS_REG; - } - -#if CONFIG_BLK_DEV_PDC4030 - if (HWIF(drive)->chipset == ide_pdc4030) { - /* DC4030 hosted drives need their own identify... */ - extern int pdc4030_identify(ide_drive_t *); - if (pdc4030_identify(drive)) { - if (irqs) - (void) probe_irq_off(irqs); - return 1; - } - } else -#endif /* CONFIG_BLK_DEV_PDC4030 */ - OUT_BYTE(cmd,IDE_COMMAND_REG); /* ask drive for ID */ - timeout = ((cmd == WIN_IDENTIFY) ? WAIT_WORSTCASE : WAIT_PIDENTIFY) / 2; - timeout += jiffies; - do { - if (0 < (signed long)(jiffies - timeout)) { - if (irqs) - (void) probe_irq_off(irqs); - return 1; /* drive timed-out */ - } - ide_delay_50ms(); /* give drive a breather */ - } while (IN_BYTE(hd_status) & BUSY_STAT); - - ide_delay_50ms(); /* wait for IRQ and DRQ_STAT */ - if (OK_STAT(GET_STAT(),DRQ_STAT,BAD_R_STAT)) { - unsigned long flags; - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only; some systems need this */ - do_identify(drive, cmd); /* drive returned ID */ - rc = 0; /* drive responded with ID */ - (void) GET_STAT(); /* clear drive IRQ */ - __restore_flags(flags); /* local CPU only */ - } else - rc = 2; /* drive refused ID */ - if (IDE_CONTROL_REG && !HWIF(drive)->irq) { - irqs = probe_irq_off(irqs); /* get our irq number */ - if (irqs > 0) { - HWIF(drive)->irq = irqs; /* save it for later */ - irqs = probe_irq_on(); - OUT_BYTE(drive->ctl|2,IDE_CONTROL_REG); /* mask device irq */ - udelay(5); - (void) probe_irq_off(irqs); - (void) probe_irq_off(probe_irq_on()); /* clear self-inflicted irq */ - (void) GET_STAT(); /* clear drive IRQ */ - - } else { /* Mmmm.. multiple IRQs.. don't know which was ours */ - printk("%s: IRQ probe failed (%ld)\n", drive->name, irqs); -#ifdef CONFIG_BLK_DEV_CMD640 -#ifdef CMD640_DUMP_REGS - if (HWIF(drive)->chipset == ide_cmd640) { - printk("%s: Hmmm.. probably a driver problem.\n", drive->name); - CMD640_DUMP_REGS; - } -#endif /* CMD640_DUMP_REGS */ -#endif /* CONFIG_BLK_DEV_CMD640 */ - } - } - return rc; -} - -/* - * do_probe() has the difficult job of finding a drive if it exists, - * without getting hung up if it doesn't exist, without trampling on - * ethernet cards, and without leaving any IRQs dangling to haunt us later. - * - * If a drive is "known" to exist (from CMOS or kernel parameters), - * but does not respond right away, the probe will "hang in there" - * for the maximum wait time (about 30 seconds), otherwise it will - * exit much more quickly. - * - * Returns: 0 device was identified - * 1 device timed-out (no response to identify request) - * 2 device aborted the command (refused to identify itself) - * 3 bad status from device (possible for ATAPI drives) - * 4 probe was not attempted because failure was obvious - */ -static int do_probe (ide_drive_t *drive, byte cmd) -{ - int rc; - ide_hwif_t *hwif = HWIF(drive); - if (drive->present) { /* avoid waiting for inappropriate probes */ - if ((drive->media != ide_disk) && (cmd == WIN_IDENTIFY)) - return 4; - } -#ifdef DEBUG - printk("probing for %s: present=%d, media=%d, probetype=%s\n", - drive->name, drive->present, drive->media, - (cmd == WIN_IDENTIFY) ? "ATA" : "ATAPI"); -#endif - ide_delay_50ms(); /* needed for some systems (e.g. crw9624 as drive0 with disk as slave) */ - SELECT_DRIVE(hwif,drive); - ide_delay_50ms(); - if (IN_BYTE(IDE_SELECT_REG) != drive->select.all && !drive->present) { - if (drive->select.b.unit != 0) { - SELECT_DRIVE(hwif,&hwif->drives[0]); /* exit with drive0 selected */ - ide_delay_50ms(); /* allow BUSY_STAT to assert & clear */ - } - return 3; /* no i/f present: mmm.. this should be a 4 -ml */ - } - - if (OK_STAT(GET_STAT(),READY_STAT,BUSY_STAT) - || drive->present || cmd == WIN_PIDENTIFY) - { - if ((rc = try_to_identify(drive,cmd))) /* send cmd and wait */ - rc = try_to_identify(drive,cmd); /* failed: try again */ - if (rc == 1 && cmd == WIN_PIDENTIFY && drive->autotune != 2) { - unsigned long timeout; - printk("%s: no response (status = 0x%02x), resetting drive\n", drive->name, GET_STAT()); - ide_delay_50ms(); - OUT_BYTE (drive->select.all, IDE_SELECT_REG); - ide_delay_50ms(); - OUT_BYTE(WIN_SRST, IDE_COMMAND_REG); - timeout = jiffies; - while ((GET_STAT() & BUSY_STAT) && time_before(jiffies, timeout + WAIT_WORSTCASE)) - ide_delay_50ms(); - rc = try_to_identify(drive, cmd); - } - if (rc == 1) - printk("%s: no response (status = 0x%02x)\n", drive->name, GET_STAT()); - (void) GET_STAT(); /* ensure drive irq is clear */ - } else { - rc = 3; /* not present or maybe ATAPI */ - } - if (drive->select.b.unit != 0) { - SELECT_DRIVE(hwif,&hwif->drives[0]); /* exit with drive0 selected */ - ide_delay_50ms(); - (void) GET_STAT(); /* ensure drive irq is clear */ - } - return rc; -} - -/* - * - */ -static void enable_nest (ide_drive_t *drive) -{ - unsigned long timeout; - - printk("%s: enabling %s -- ", HWIF(drive)->name, drive->id->model); - SELECT_DRIVE(HWIF(drive), drive); - ide_delay_50ms(); - OUT_BYTE(EXABYTE_ENABLE_NEST, IDE_COMMAND_REG); - timeout = jiffies + WAIT_WORSTCASE; - do { - if (jiffies > timeout) { - printk("failed (timeout)\n"); - return; - } - ide_delay_50ms(); - } while (GET_STAT() & BUSY_STAT); - ide_delay_50ms(); - if (!OK_STAT(GET_STAT(), 0, BAD_STAT)) - printk("failed (status = 0x%02x)\n", GET_STAT()); - else - printk("success\n"); - if (do_probe(drive, WIN_IDENTIFY) >= 2) { /* if !(success||timed-out) */ - (void) do_probe(drive, WIN_PIDENTIFY); /* look for ATAPI device */ - } -} - -/* - * probe_for_drive() tests for existence of a given drive using do_probe(). - * - * Returns: 0 no device was found - * 1 device was found (note: drive->present might still be 0) - */ -static inline byte probe_for_drive (ide_drive_t *drive) -{ - if (drive->noprobe) /* skip probing? */ - return drive->present; - if (do_probe(drive, WIN_IDENTIFY) >= 2) { /* if !(success||timed-out) */ - (void) do_probe(drive, WIN_PIDENTIFY); /* look for ATAPI device */ - } - if (drive->id && strstr(drive->id->model, "E X A B Y T E N E S T")) - enable_nest(drive); - if (!drive->present) - return 0; /* drive not found */ - if (drive->id == NULL) { /* identification failed? */ - if (drive->media == ide_disk) { - printk ("%s: non-IDE drive, CHS=%d/%d/%d\n", - drive->name, drive->cyl, drive->head, drive->sect); - } else if (drive->media == ide_cdrom) { - printk("%s: ATAPI cdrom (?)\n", drive->name); - } else { - drive->present = 0; /* nuke it */ - } - } - return 1; /* drive was found */ -} - -/* - * Calculate the region that this interface occupies, - * handling interfaces where the registers may not be - * ordered sanely. We deal with the CONTROL register - * separately. - */ -static int hwif_check_regions (ide_hwif_t *hwif) -{ - int region_errors = 0; - - hwif->straight8 = 0; - region_errors = ide_check_region(hwif->io_ports[IDE_DATA_OFFSET], 1); - region_errors += ide_check_region(hwif->io_ports[IDE_ERROR_OFFSET], 1); - region_errors += ide_check_region(hwif->io_ports[IDE_NSECTOR_OFFSET], 1); - region_errors += ide_check_region(hwif->io_ports[IDE_SECTOR_OFFSET], 1); - region_errors += ide_check_region(hwif->io_ports[IDE_LCYL_OFFSET], 1); - region_errors += ide_check_region(hwif->io_ports[IDE_HCYL_OFFSET], 1); - region_errors += ide_check_region(hwif->io_ports[IDE_SELECT_OFFSET], 1); - region_errors += ide_check_region(hwif->io_ports[IDE_STATUS_OFFSET], 1); - - if (hwif->io_ports[IDE_CONTROL_OFFSET]) - region_errors += ide_check_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1); - - if (hwif->io_ports[IDE_IRQ_OFFSET]) - region_errors += ide_check_region(hwif->io_ports[IDE_IRQ_OFFSET], 1); - - /* - * If any errors are return, we drop the hwif interface. - */ - return(region_errors); -} - -static void hwif_register (ide_hwif_t *hwif) -{ - if ((hwif->io_ports[IDE_DATA_OFFSET] | 7) == - (hwif->io_ports[IDE_STATUS_OFFSET])) { - ide_request_region(hwif->io_ports[IDE_DATA_OFFSET], 8, hwif->name); - hwif->straight8 = 1; - goto jump_straight8; - } - - if (hwif->io_ports[IDE_DATA_OFFSET]) - ide_request_region(hwif->io_ports[IDE_DATA_OFFSET], 1, hwif->name); - if (hwif->io_ports[IDE_ERROR_OFFSET]) - ide_request_region(hwif->io_ports[IDE_ERROR_OFFSET], 1, hwif->name); - if (hwif->io_ports[IDE_NSECTOR_OFFSET]) - ide_request_region(hwif->io_ports[IDE_NSECTOR_OFFSET], 1, hwif->name); - if (hwif->io_ports[IDE_SECTOR_OFFSET]) - ide_request_region(hwif->io_ports[IDE_SECTOR_OFFSET], 1, hwif->name); - if (hwif->io_ports[IDE_LCYL_OFFSET]) - ide_request_region(hwif->io_ports[IDE_LCYL_OFFSET], 1, hwif->name); - if (hwif->io_ports[IDE_HCYL_OFFSET]) - ide_request_region(hwif->io_ports[IDE_HCYL_OFFSET], 1, hwif->name); - if (hwif->io_ports[IDE_SELECT_OFFSET]) - ide_request_region(hwif->io_ports[IDE_SELECT_OFFSET], 1, hwif->name); - if (hwif->io_ports[IDE_STATUS_OFFSET]) - ide_request_region(hwif->io_ports[IDE_STATUS_OFFSET], 1, hwif->name); - -jump_straight8: - if (hwif->io_ports[IDE_CONTROL_OFFSET]) - ide_request_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1, hwif->name); - if (hwif->io_ports[IDE_IRQ_OFFSET]) - ide_request_region(hwif->io_ports[IDE_IRQ_OFFSET], 1, hwif->name); -} - -/* - * This routine only knows how to look for drive units 0 and 1 - * on an interface, so any setting of MAX_DRIVES > 2 won't work here. - */ -static void probe_hwif (ide_hwif_t *hwif) -{ - unsigned int unit; - unsigned long flags; - - if (hwif->noprobe) - return; - if (hwif->io_ports[IDE_DATA_OFFSET] == HD_DATA) { - extern void probe_cmos_for_drives(ide_hwif_t *); - - probe_cmos_for_drives (hwif); - } - - if ((hwif->chipset != ide_4drives || !hwif->mate->present) && -#if CONFIG_BLK_DEV_PDC4030 - (hwif->chipset != ide_pdc4030 || hwif->channel == 0) && -#endif /* CONFIG_BLK_DEV_PDC4030 */ - (hwif_check_regions(hwif))) { - int msgout = 0; - for (unit = 0; unit < MAX_DRIVES; ++unit) { - ide_drive_t *drive = &hwif->drives[unit]; - if (drive->present) { - drive->present = 0; - printk("%s: ERROR, PORTS ALREADY IN USE\n", drive->name); - msgout = 1; - } - } - if (!msgout) - printk("%s: ports already in use, skipping probe\n", hwif->name); - return; - } - - __save_flags(flags); /* local CPU only */ - __sti(); /* local CPU only; needed for jiffies and irq probing */ - /* - * Second drive should only exist if first drive was found, - * but a lot of cdrom drives are configured as single slaves. - */ - for (unit = 0; unit < MAX_DRIVES; ++unit) { - ide_drive_t *drive = &hwif->drives[unit]; - (void) probe_for_drive (drive); - if (drive->present && !hwif->present) { - hwif->present = 1; - if (hwif->chipset != ide_4drives || !hwif->mate->present) { - hwif_register(hwif); - } - } - } - if (hwif->io_ports[IDE_CONTROL_OFFSET] && hwif->reset) { - unsigned long timeout = jiffies + WAIT_WORSTCASE; - byte stat; - - printk("%s: reset\n", hwif->name); - OUT_BYTE(12, hwif->io_ports[IDE_CONTROL_OFFSET]); - udelay(10); - OUT_BYTE(8, hwif->io_ports[IDE_CONTROL_OFFSET]); - do { - ide_delay_50ms(); - stat = IN_BYTE(hwif->io_ports[IDE_STATUS_OFFSET]); - } while ((stat & BUSY_STAT) && 0 < (signed long)(timeout - jiffies)); - - } - __restore_flags(flags); /* local CPU only */ - for (unit = 0; unit < MAX_DRIVES; ++unit) { - ide_drive_t *drive = &hwif->drives[unit]; - if (drive->present) { - ide_tuneproc_t *tuneproc = HWIF(drive)->tuneproc; - if (tuneproc != NULL && drive->autotune == 1) - tuneproc(drive, 255); /* auto-tune PIO mode */ - } - } -} - -#if MAX_HWIFS > 1 -/* - * save_match() is used to simplify logic in init_irq() below. - * - * A loophole here is that we may not know about a particular - * hwif's irq until after that hwif is actually probed/initialized.. - * This could be a problem for the case where an hwif is on a - * dual interface that requires serialization (eg. cmd640) and another - * hwif using one of the same irqs is initialized beforehand. - * - * This routine detects and reports such situations, but does not fix them. - */ -static void save_match (ide_hwif_t *hwif, ide_hwif_t *new, ide_hwif_t **match) -{ - ide_hwif_t *m = *match; - - if (m && m->hwgroup && m->hwgroup != new->hwgroup) { - if (!new->hwgroup) - return; - printk("%s: potential irq problem with %s and %s\n", hwif->name, new->name, m->name); - } - if (!m || m->irq != hwif->irq) /* don't undo a prior perfect match */ - *match = new; -} -#endif /* MAX_HWIFS > 1 */ - -/* - * This routine sets up the irq for an ide interface, and creates a new - * hwgroup for the irq/hwif if none was previously assigned. - * - * Much of the code is for correctly detecting/handling irq sharing - * and irq serialization situations. This is somewhat complex because - * it handles static as well as dynamic (PCMCIA) IDE interfaces. - * - * The SA_INTERRUPT in sa_flags means ide_intr() is always entered with - * interrupts completely disabled. This can be bad for interrupt latency, - * but anything else has led to problems on some machines. We re-enable - * interrupts as much as we can safely do in most places. - */ -static int init_irq (ide_hwif_t *hwif) -{ - unsigned long flags; - unsigned int index; - ide_hwgroup_t *hwgroup; - ide_hwif_t *match = NULL; - - save_flags(flags); /* all CPUs */ - cli(); /* all CPUs */ - - hwif->hwgroup = NULL; -#if MAX_HWIFS > 1 - /* - * Group up with any other hwifs that share our irq(s). - */ - for (index = 0; index < MAX_HWIFS; index++) { - ide_hwif_t *h = &ide_hwifs[index]; - if (h->hwgroup) { /* scan only initialized hwif's */ - if (hwif->irq == h->irq) { - hwif->sharing_irq = h->sharing_irq = 1; - if (hwif->chipset != ide_pci || h->chipset != ide_pci) { - save_match(hwif, h, &match); - } - } - if (hwif->serialized) { - if (hwif->mate && hwif->mate->irq == h->irq) - save_match(hwif, h, &match); - } - if (h->serialized) { - if (h->mate && hwif->irq == h->mate->irq) - save_match(hwif, h, &match); - } - } - } -#endif /* MAX_HWIFS > 1 */ - /* - * If we are still without a hwgroup, then form a new one - */ - if (match) { - hwgroup = match->hwgroup; - } else { - hwgroup = kmalloc(sizeof(ide_hwgroup_t), GFP_KERNEL); - memset(hwgroup, 0, sizeof(ide_hwgroup_t)); - hwgroup->hwif = hwif->next = hwif; - hwgroup->rq = NULL; - hwgroup->handler = NULL; - hwgroup->drive = NULL; - hwgroup->busy = 0; - init_timer(&hwgroup->timer); - hwgroup->timer.function = &ide_timer_expiry; - hwgroup->timer.data = (unsigned long) hwgroup; - } - - /* - * Allocate the irq, if not already obtained for another hwif - */ - if (!match || match->irq != hwif->irq) { -#ifdef CONFIG_IDEPCI_SHARE_IRQ - int sa = (hwif->chipset == ide_pci) ? SA_SHIRQ : SA_INTERRUPT; -#else /* !CONFIG_IDEPCI_SHARE_IRQ */ - int sa = (hwif->chipset == ide_pci) ? SA_INTERRUPT|SA_SHIRQ : SA_INTERRUPT; -#endif /* CONFIG_IDEPCI_SHARE_IRQ */ - if (ide_request_irq(hwif->irq, &ide_intr, sa, hwif->name, hwgroup)) { - if (!match) - kfree(hwgroup); - restore_flags(flags); /* all CPUs */ - return 1; - } - } - - /* - * Everything is okay, so link us into the hwgroup - */ - hwif->hwgroup = hwgroup; - hwif->next = hwgroup->hwif->next; - hwgroup->hwif->next = hwif; - - for (index = 0; index < MAX_DRIVES; ++index) { - ide_drive_t *drive = &hwif->drives[index]; - if (!drive->present) - continue; - if (!hwgroup->drive) - hwgroup->drive = drive; - drive->next = hwgroup->drive->next; - hwgroup->drive->next = drive; - } - if (!hwgroup->hwif) { - hwgroup->hwif = HWIF(hwgroup->drive); -#ifdef DEBUG - printk("%s : Adding missed hwif to hwgroup!!\n", hwif->name); -#endif - } - restore_flags(flags); /* all CPUs; safe now that hwif->hwgroup is set up */ - -#if !defined(__mc68000__) && !defined(CONFIG_APUS) && !defined(__sparc__) - printk("%s at 0x%03x-0x%03x,0x%03x on irq %d", hwif->name, - hwif->io_ports[IDE_DATA_OFFSET], - hwif->io_ports[IDE_DATA_OFFSET]+7, - hwif->io_ports[IDE_CONTROL_OFFSET], hwif->irq); -#elif defined(__sparc__) - printk("%s at 0x%03lx-0x%03lx,0x%03lx on irq %s", hwif->name, - hwif->io_ports[IDE_DATA_OFFSET], - hwif->io_ports[IDE_DATA_OFFSET]+7, - hwif->io_ports[IDE_CONTROL_OFFSET], __irq_itoa(hwif->irq)); -#else - printk("%s at %p on irq 0x%08x", hwif->name, - hwif->io_ports[IDE_DATA_OFFSET], hwif->irq); -#endif /* __mc68000__ && CONFIG_APUS */ - if (match) - printk(" (%sed with %s)", - hwif->sharing_irq ? "shar" : "serializ", match->name); - printk("\n"); - return 0; -} - -/* - * init_gendisk() (as opposed to ide_geninit) is called for each major device, - * after probing for drives, to allocate partition tables and other data - * structures needed for the routines in genhd.c. ide_geninit() gets called - * somewhat later, during the partition check. - */ -static void init_gendisk (ide_hwif_t *hwif) -{ - struct gendisk *gd, **gdp; - unsigned int unit, units, minors; - int *bs, *max_sect, *max_ra; - extern devfs_handle_t ide_devfs_handle; - - /* figure out maximum drive number on the interface */ - for (units = MAX_DRIVES; units > 0; --units) { - if (hwif->drives[units-1].present) - break; - } - minors = units * (1<<PARTN_BITS); - gd = kmalloc (sizeof(struct gendisk), GFP_KERNEL); - gd->sizes = kmalloc (minors * sizeof(int), GFP_KERNEL); - gd->part = kmalloc (minors * sizeof(struct hd_struct), GFP_KERNEL); - bs = kmalloc (minors*sizeof(int), GFP_KERNEL); - max_sect = kmalloc (minors*sizeof(int), GFP_KERNEL); - max_ra = kmalloc (minors*sizeof(int), GFP_KERNEL); - - memset(gd->part, 0, minors * sizeof(struct hd_struct)); - - /* cdroms and msdos f/s are examples of non-1024 blocksizes */ - blksize_size[hwif->major] = bs; - max_sectors[hwif->major] = max_sect; - max_readahead[hwif->major] = max_ra; - for (unit = 0; unit < minors; ++unit) { - *bs++ = BLOCK_SIZE; -#ifdef CONFIG_BLK_DEV_PDC4030 - *max_sect++ = ((hwif->chipset == ide_pdc4030) ? 127 : MAX_SECTORS); -#else - *max_sect++ = MAX_SECTORS; -#endif - *max_ra++ = MAX_READAHEAD; - } - - for (unit = 0; unit < units; ++unit) - hwif->drives[unit].part = &gd->part[unit << PARTN_BITS]; - - gd->major = hwif->major; /* our major device number */ - gd->major_name = IDE_MAJOR_NAME; /* treated special in genhd.c */ - gd->minor_shift = PARTN_BITS; /* num bits for partitions */ - gd->max_p = 1<<PARTN_BITS; /* 1 + max partitions / drive */ - gd->nr_real = units; /* current num real drives */ - gd->real_devices= hwif; /* ptr to internal data */ - gd->next = NULL; /* linked list of major devs */ - gd->fops = ide_fops; /* file operations */ - gd->de_arr = kmalloc (sizeof *gd->de_arr * units, GFP_KERNEL); - gd->flags = kmalloc (sizeof *gd->flags * units, GFP_KERNEL); - if (gd->de_arr) - memset (gd->de_arr, 0, sizeof *gd->de_arr * units); - if (gd->flags) - memset (gd->flags, 0, sizeof *gd->flags * units); - - for (gdp = &gendisk_head; *gdp; gdp = &((*gdp)->next)) ; - hwif->gd = *gdp = gd; /* link onto tail of list */ - - for (unit = 0; unit < units; ++unit) { - if (hwif->drives[unit].present) { - char name[64]; - - ide_add_generic_settings(hwif->drives + unit); - sprintf (name, "host%d/bus%d/target%d/lun%d", - (hwif->channel && hwif->mate) ? hwif->mate->index : hwif->index, - hwif->channel, unit, 0); - hwif->drives[unit].de = - devfs_mk_dir (ide_devfs_handle, name, 0, NULL); - } - } -} - -static int hwif_init (ide_hwif_t *hwif) -{ - ide_drive_t *drive; - void (*rfn)(request_queue_t *); - - if (!hwif->present) - return 0; - if (!hwif->irq) { - if (!(hwif->irq = ide_default_irq(hwif->io_ports[IDE_DATA_OFFSET]))) - { - printk("%s: DISABLED, NO IRQ\n", hwif->name); - return (hwif->present = 0); - } - } -#ifdef CONFIG_BLK_DEV_HD - if (hwif->irq == HD_IRQ && hwif->io_ports[IDE_DATA_OFFSET] != HD_DATA) { - printk("%s: CANNOT SHARE IRQ WITH OLD HARDDISK DRIVER (hd.c)\n", hwif->name); - return (hwif->present = 0); - } -#endif /* CONFIG_BLK_DEV_HD */ - - hwif->present = 0; /* we set it back to 1 if all is ok below */ - switch (hwif->major) { - case IDE0_MAJOR: rfn = &do_ide0_request; break; -#if MAX_HWIFS > 1 - case IDE1_MAJOR: rfn = &do_ide1_request; break; -#endif -#if MAX_HWIFS > 2 - case IDE2_MAJOR: rfn = &do_ide2_request; break; -#endif -#if MAX_HWIFS > 3 - case IDE3_MAJOR: rfn = &do_ide3_request; break; -#endif -#if MAX_HWIFS > 4 - case IDE4_MAJOR: rfn = &do_ide4_request; break; -#endif -#if MAX_HWIFS > 5 - case IDE5_MAJOR: rfn = &do_ide5_request; break; -#endif -#if MAX_HWIFS > 6 - case IDE6_MAJOR: rfn = &do_ide6_request; break; -#endif -#if MAX_HWIFS > 7 - case IDE7_MAJOR: rfn = &do_ide7_request; break; -#endif -#if MAX_HWIFS > 8 - case IDE8_MAJOR: rfn = &do_ide8_request; break; -#endif -#if MAX_HWIFS > 9 - case IDE9_MAJOR: rfn = &do_ide9_request; break; -#endif - default: - printk("%s: request_fn NOT DEFINED\n", hwif->name); - return (hwif->present = 0); - } - if (devfs_register_blkdev (hwif->major, hwif->name, ide_fops)) { - printk("%s: UNABLE TO GET MAJOR NUMBER %d\n", hwif->name, hwif->major); - return (hwif->present = 0); - } - - if (init_irq(hwif)) { - int i = hwif->irq; - /* - * It failed to initialise. Find the default IRQ for - * this port and try that. - */ - if (!(hwif->irq = ide_default_irq(hwif->io_ports[IDE_DATA_OFFSET]))) { - printk("%s: Disabled unable to get IRQ %d.\n", hwif->name, i); - (void) unregister_blkdev (hwif->major, hwif->name); - return (hwif->present = 0); - } - if (init_irq(hwif)) { - printk("%s: probed IRQ %d and default IRQ %d failed.\n", - hwif->name, i, hwif->irq); - (void) unregister_blkdev (hwif->major, hwif->name); - return (hwif->present = 0); - } - printk("%s: probed IRQ %d failed, using default.\n", - hwif->name, hwif->irq); - } - - init_gendisk(hwif); - blk_dev[hwif->major].data = hwif; - blk_dev[hwif->major].queue = ide_get_queue; - read_ahead[hwif->major] = 8; /* (4kB) */ - hwif->present = 1; /* success */ - - /* - * FIXME(eric) - This needs to be tested. I *think* that this - * is correct. Also, I believe that there is no longer any - * reason to have multiple functions (do_ide[0-7]_request) - * functions - the queuedata field could be used to indicate - * the correct hardware group - either this, or we could add - * a new field to request_queue_t to hold this information. - */ - drive = &hwif->drives[0]; - blk_init_queue(&drive->queue, rfn); - - drive = &hwif->drives[1]; - blk_init_queue(&drive->queue, rfn); - -#if (DEBUG_SPINLOCK > 0) -{ - static int done = 0; - if (!done++) - printk("io_request_lock is %p\n", &io_request_lock); /* FIXME */ -} -#endif - return hwif->present; -} - -int ideprobe_init (void); -static ide_module_t ideprobe_module = { - IDE_PROBE_MODULE, - ideprobe_init, - NULL -}; - -int ideprobe_init (void) -{ - unsigned int index; - int probe[MAX_HWIFS]; - - MOD_INC_USE_COUNT; - memset(probe, 0, MAX_HWIFS * sizeof(int)); - for (index = 0; index < MAX_HWIFS; ++index) - probe[index] = !ide_hwifs[index].present; - - /* - * Probe for drives in the usual way.. CMOS/BIOS, then poke at ports - */ - for (index = 0; index < MAX_HWIFS; ++index) - if (probe[index]) - probe_hwif(&ide_hwifs[index]); - for (index = 0; index < MAX_HWIFS; ++index) - if (probe[index]) - hwif_init(&ide_hwifs[index]); - if (!ide_probe) - ide_probe = &ideprobe_module; - MOD_DEC_USE_COUNT; - return 0; -} - -#ifdef MODULE -int init_module (void) -{ - unsigned int index; - - for (index = 0; index < MAX_HWIFS; ++index) - ide_unregister(index); - ideprobe_init(); - create_proc_ide_interfaces(); - return 0; -} - -void cleanup_module (void) -{ - ide_probe = NULL; -} -#endif /* MODULE */ diff --git a/drivers/block/ide-proc.c b/drivers/block/ide-proc.c deleted file mode 100644 index 753597e9c..000000000 --- a/drivers/block/ide-proc.c +++ /dev/null @@ -1,904 +0,0 @@ -/* - * linux/drivers/block/ide-proc.c Version 1.03 January 2, 1998 - * - * Copyright (C) 1997-1998 Mark Lord - */ - -/* - * This is the /proc/ide/ filesystem implementation. - * - * The major reason this exists is to provide sufficient access - * to driver and config data, such that user-mode programs can - * be developed to handle chipset tuning for most PCI interfaces. - * This should provide better utilities, and less kernel bloat. - * - * The entire pci config space for a PCI interface chipset can be - * retrieved by just reading it. e.g. "cat /proc/ide3/config" - * - * To modify registers *safely*, do something like: - * echo "P40:88" >/proc/ide/ide3/config - * That expression writes 0x88 to pci config register 0x40 - * on the chip which controls ide3. Multiple tuples can be issued, - * and the writes will be completed as an atomic set: - * echo "P40:88 P41:35 P42:00 P43:00" >/proc/ide/ide3/config - * - * All numbers must be specified using pairs of ascii hex digits. - * It is important to note that these writes will be performed - * after waiting for the IDE controller (both interfaces) - * to be completely idle, to ensure no corruption of I/O in progress. - * - * Non-PCI registers can also be written, using "R" in place of "P" - * in the above examples. The size of the port transfer is determined - * by the number of pairs of hex digits given for the data. If a two - * digit value is given, the write will be a byte operation; if four - * digits are used, the write will be performed as a 16-bit operation; - * and if eight digits are specified, a 32-bit "dword" write will be - * performed. Odd numbers of digits are not permitted. - * - * If there is an error *anywhere* in the string of registers/data - * then *none* of the writes will be performed. - * - * Drive/Driver settings can be retrieved by reading the drive's - * "settings" files. e.g. "cat /proc/ide0/hda/settings" - * To write a new value "val" into a specific setting "name", use: - * echo "name:val" >/proc/ide/ide0/hda/settings - * - * Also useful, "cat /proc/ide0/hda/[identify, smart_values, - * smart_thresholds, capabilities]" will issue an IDENTIFY / - * PACKET_IDENTIFY / SMART_READ_VALUES / SMART_READ_THRESHOLDS / - * SENSE CAPABILITIES command to /dev/hda, and then dump out the - * returned data as 256 16-bit words. The "hdparm" utility will - * be updated someday soon to use this mechanism. - * - * Feel free to develop and distribute fancy GUI configuration - * utilities for your favorite PCI chipsets. I'll be working on - * one for the Promise 20246 someday soon. -ml - * - */ - -#include <linux/config.h> -#include <asm/uaccess.h> -#include <linux/errno.h> -#include <linux/sched.h> -#include <linux/proc_fs.h> -#include <linux/stat.h> -#include <linux/mm.h> -#include <linux/pci.h> -#include <linux/ctype.h> -#include <linux/ide.h> - -#include <asm/io.h> - -#ifndef MIN -#define MIN(a,b) (((a) < (b)) ? (a) : (b)) -#endif - -#ifdef CONFIG_BLK_DEV_AEC6210 -extern byte aec6210_proc; -int (*aec6210_display_info)(char *, char **, off_t, int) = NULL; -#endif /* CONFIG_BLK_DEV_AEC6210 */ -#ifdef CONFIG_BLK_DEV_ALI15X3 -extern byte ali_proc; -int (*ali_display_info)(char *, char **, off_t, int) = NULL; -#endif /* CONFIG_BLK_DEV_ALI15X3 */ -#ifdef CONFIG_BLK_DEV_AMD7409 -extern byte amd7409_proc; -int (*amd7409_display_info)(char *, char **, off_t, int) = NULL; -#endif /* CONFIG_BLK_DEV_AMD7409 */ -#ifdef CONFIG_BLK_DEV_CMD64X -extern byte cmd64x_proc; -int (*cmd64x_display_info)(char *, char **, off_t, int) = NULL; -#endif /* CONFIG_BLK_DEV_CMD64X */ -#ifdef CONFIG_BLK_DEV_CS5530 -extern byte cs5530_proc; -int (*cs5530_display_info)(char *, char **, off_t, int) = NULL; -#endif /* CONFIG_BLK_DEV_CS5530 */ -#ifdef CONFIG_BLK_DEV_HPT34X -extern byte hpt34x_proc; -int (*hpt34x_display_info)(char *, char **, off_t, int) = NULL; -#endif /* CONFIG_BLK_DEV_HPT34X */ -#ifdef CONFIG_BLK_DEV_HPT366 -extern byte hpt366_proc; -int (*hpt366_display_info)(char *, char **, off_t, int) = NULL; -#endif /* CONFIG_BLK_DEV_HPT366 */ -#ifdef CONFIG_BLK_DEV_PDC202XX -extern byte pdc202xx_proc; -int (*pdc202xx_display_info)(char *, char **, off_t, int) = NULL; -#endif /* CONFIG_BLK_DEV_PDC202XX */ -#ifdef CONFIG_BLK_DEV_PIIX -extern byte piix_proc; -int (*piix_display_info)(char *, char **, off_t, int) = NULL; -#endif /* CONFIG_BLK_DEV_PIIX */ -#ifdef CONFIG_BLK_DEV_SIS5513 -extern byte sis_proc; -int (*sis_display_info)(char *, char **, off_t, int) = NULL; -#endif /* CONFIG_BLK_DEV_SIS5513 */ -#ifdef CONFIG_BLK_DEV_VIA82CXXX -extern byte via_proc; -int (*via_display_info)(char *, char **, off_t, int) = NULL; -#endif /* CONFIG_BLK_DEV_VIA82CXXX */ - -static int ide_getxdigit(char c) -{ - int digit; - if (isdigit(c)) - digit = c - '0'; - else if (isxdigit(c)) - digit = tolower(c) - 'a' + 10; - else - digit = -1; - return digit; -} - -static int xx_xx_parse_error (const char *data, unsigned long len, const char *msg) -{ - char errbuf[16]; - int i; - if (len >= sizeof(errbuf)) - len = sizeof(errbuf) - 1; - for (i = 0; i < len; ++i) { - char c = data[i]; - if (!c || c == '\n') - c = '\0'; - else if (iscntrl(c)) - c = '?'; - errbuf[i] = c; - } - errbuf[i] = '\0'; - printk("proc_ide: error: %s: '%s'\n", msg, errbuf); - return -EINVAL; -} - -static struct proc_dir_entry * proc_ide_root = NULL; - -static int proc_ide_write_config - (struct file *file, const char *buffer, unsigned long count, void *data) -{ - ide_hwif_t *hwif = (ide_hwif_t *)data; - int for_real = 0; - unsigned long startn = 0, n, flags; - const char *start = NULL, *msg = NULL; - - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - /* - * Skip over leading whitespace - */ - while (count && isspace(*buffer)) { - --count; - ++buffer; - } - /* - * Do one full pass to verify all parameters, - * then do another to actually write the regs. - */ - save_flags(flags); /* all CPUs */ - do { - const char *p; - if (for_real) { - unsigned long timeout = jiffies + (3 * HZ); - ide_hwgroup_t *mygroup = (ide_hwgroup_t *)(hwif->hwgroup); - ide_hwgroup_t *mategroup = NULL; - if (hwif->mate && hwif->mate->hwgroup) - mategroup = (ide_hwgroup_t *)(hwif->mate->hwgroup); - cli(); /* all CPUs; ensure all writes are done together */ - while (mygroup->busy || (mategroup && mategroup->busy)) { - sti(); /* all CPUs */ - if (0 < (signed long)(jiffies - timeout)) { - printk("/proc/ide/%s/config: channel(s) busy, cannot write\n", hwif->name); - restore_flags(flags); /* all CPUs */ - return -EBUSY; - } - cli(); /* all CPUs */ - } - } - p = buffer; - n = count; - while (n > 0) { - int d, digits; - unsigned int reg = 0, val = 0, is_pci; - start = p; - startn = n--; - switch (*p++) { - case 'R': is_pci = 0; - break; - case 'P': is_pci = 1; -#ifdef CONFIG_BLK_DEV_IDEPCI - if (hwif->pci_dev && !IDE_PCI_DEVID_EQ(hwif->pci_devid, IDE_PCI_DEVID_NULL)) - break; -#endif /* CONFIG_BLK_DEV_IDEPCI */ - msg = "not a PCI device"; - goto parse_error; - default: msg = "expected 'R' or 'P'"; - goto parse_error; - } - digits = 0; - while (n > 0 && (d = ide_getxdigit(*p)) >= 0) { - reg = (reg << 4) | d; - --n; - ++p; - ++digits; - } - if (!digits || (digits > 4) || (is_pci && reg > 0xff)) { - msg = "bad/missing register number"; - goto parse_error; - } - if (n-- == 0 || *p++ != ':') { - msg = "missing ':'"; - goto parse_error; - } - digits = 0; - while (n > 0 && (d = ide_getxdigit(*p)) >= 0) { - val = (val << 4) | d; - --n; - ++p; - ++digits; - } - if (digits != 2 && digits != 4 && digits != 8) { - msg = "bad data, 2/4/8 digits required"; - goto parse_error; - } - if (n > 0 && !isspace(*p)) { - msg = "expected whitespace after data"; - goto parse_error; - } - while (n > 0 && isspace(*p)) { - --n; - ++p; - } -#ifdef CONFIG_BLK_DEV_IDEPCI - if (is_pci && (reg & ((digits >> 1) - 1))) { - msg = "misaligned access"; - goto parse_error; - } -#endif /* CONFIG_BLK_DEV_IDEPCI */ - if (for_real) { -#if 0 - printk("proc_ide_write_config: type=%c, reg=0x%x, val=0x%x, digits=%d\n", is_pci ? "PCI" : "non-PCI", reg, val, digits); -#endif - if (is_pci) { -#ifdef CONFIG_BLK_DEV_IDEPCI - int rc = 0; - struct pci_dev *dev = hwif->pci_dev; - switch (digits) { - case 2: msg = "byte"; - rc = pci_write_config_byte(dev, reg, val); - break; - case 4: msg = "word"; - rc = pci_write_config_word(dev, reg, val); - break; - case 8: msg = "dword"; - rc = pci_write_config_dword(dev, reg, val); - break; - } - if (rc) { - restore_flags(flags); /* all CPUs */ - printk("proc_ide_write_config: error writing %s at bus %02x dev %02x reg 0x%x value 0x%x\n", - msg, dev->bus->number, dev->devfn, reg, val); - printk("proc_ide_write_config: error %d\n", rc); - return -EIO; - } -#endif /* CONFIG_BLK_DEV_IDEPCI */ - } else { /* not pci */ -#if !defined(__mc68000__) && !defined(CONFIG_APUS) - -/* - * Geert Uytterhoeven - * - * unless you can explain me what it really does. - * On m68k, we don't have outw() and outl() yet, - * and I need a good reason to implement it. - * - * BTW, IMHO the main remaining portability problem with the IDE driver - * is that it mixes IO (ioport) and MMIO (iomem) access on different platforms. - * - * I think all accesses should be done using - * - * ide_in[bwl](ide_device_instance, offset) - * ide_out[bwl](ide_device_instance, value, offset) - * - * so the architecture specific code can #define ide_{in,out}[bwl] to the - * appropriate function. - * - */ - switch (digits) { - case 2: outb(val, reg); - break; - case 4: outw(val, reg); - break; - case 8: outl(val, reg); - break; - } -#endif /* !__mc68000__ && !CONFIG_APUS */ - } - } - } - } while (!for_real++); - restore_flags(flags); /* all CPUs */ - return count; -parse_error: - restore_flags(flags); /* all CPUs */ - printk("parse error\n"); - return xx_xx_parse_error(start, startn, msg); -} - -static int proc_ide_read_config - (char *page, char **start, off_t off, int count, int *eof, void *data) -{ - char *out = page; - int len; - -#ifdef CONFIG_BLK_DEV_IDEPCI - ide_hwif_t *hwif = (ide_hwif_t *)data; - struct pci_dev *dev = hwif->pci_dev; - if (!IDE_PCI_DEVID_EQ(hwif->pci_devid, IDE_PCI_DEVID_NULL) && dev && dev->bus) { - int reg = 0; - - out += sprintf(out, "pci bus %02x device %02x vid %04x did %04x channel %d\n", - dev->bus->number, dev->devfn, hwif->pci_devid.vid, hwif->pci_devid.did, hwif->channel); - do { - byte val; - int rc = pci_read_config_byte(dev, reg, &val); - if (rc) { - printk("proc_ide_read_config: error %d reading bus %02x dev %02x reg 0x%02x\n", - rc, dev->bus->number, dev->devfn, reg); - out += sprintf(out, "??%c", (++reg & 0xf) ? ' ' : '\n'); - } else - out += sprintf(out, "%02x%c", val, (++reg & 0xf) ? ' ' : '\n'); - } while (reg < 0x100); - } else -#endif /* CONFIG_BLK_DEV_IDEPCI */ - out += sprintf(out, "(none)\n"); - len = out - page; - PROC_IDE_READ_RETURN(page,start,off,count,eof,len); -} - - -static int ide_getdigit(char c) -{ - int digit; - if (isdigit(c)) - digit = c - '0'; - else - digit = -1; - return digit; -} - -static int proc_ide_read_drivers - (char *page, char **start, off_t off, int count, int *eof, void *data) -{ - char *out = page; - int len; - ide_module_t *p = ide_modules; - ide_driver_t *driver; - - while (p) { - driver = (ide_driver_t *) p->info; - if (driver) - out += sprintf(out, "%s version %s\n", driver->name, driver->version); - p = p->next; - } - len = out - page; - PROC_IDE_READ_RETURN(page,start,off,count,eof,len); -} - -static int proc_ide_read_imodel - (char *page, char **start, off_t off, int count, int *eof, void *data) -{ - ide_hwif_t *hwif = (ide_hwif_t *) data; - int len; - const char *name; - - switch (hwif->chipset) { - case ide_unknown: name = "(none)"; break; - case ide_generic: name = "generic"; break; - case ide_pci: name = "pci"; break; - case ide_cmd640: name = "cmd640"; break; - case ide_dtc2278: name = "dtc2278"; break; - case ide_ali14xx: name = "ali14xx"; break; - case ide_qd6580: name = "qd6580"; break; - case ide_umc8672: name = "umc8672"; break; - case ide_ht6560b: name = "ht6560b"; break; - case ide_pdc4030: name = "pdc4030"; break; - case ide_rz1000: name = "rz1000"; break; - case ide_trm290: name = "trm290"; break; - case ide_cmd646: name = "cmd646"; break; - case ide_cy82c693: name = "cy82c693"; break; - case ide_4drives: name = "4drives"; break; - case ide_pmac: name = "mac-io"; break; - default: name = "(unknown)"; break; - } - len = sprintf(page, "%s\n", name); - PROC_IDE_READ_RETURN(page,start,off,count,eof,len); -} - -static int proc_ide_read_mate - (char *page, char **start, off_t off, int count, int *eof, void *data) -{ - ide_hwif_t *hwif = (ide_hwif_t *) data; - int len; - - if (hwif && hwif->mate && hwif->mate->present) - len = sprintf(page, "%s\n", hwif->mate->name); - else - len = sprintf(page, "(none)\n"); - PROC_IDE_READ_RETURN(page,start,off,count,eof,len); -} - -static int proc_ide_read_channel - (char *page, char **start, off_t off, int count, int *eof, void *data) -{ - ide_hwif_t *hwif = (ide_hwif_t *) data; - int len; - - page[0] = hwif->channel ? '1' : '0'; - page[1] = '\n'; - len = 2; - PROC_IDE_READ_RETURN(page,start,off,count,eof,len); -} - -static int proc_ide_get_identify(ide_drive_t *drive, byte *buf) -{ - return ide_wait_cmd(drive, (drive->media == ide_disk) ? WIN_IDENTIFY : WIN_PIDENTIFY, 0, 0, 1, buf); -} - -static int proc_ide_read_identify - (char *page, char **start, off_t off, int count, int *eof, void *data) -{ - ide_drive_t *drive = (ide_drive_t *)data; - int len = 0, i = 0; - - if (drive && !proc_ide_get_identify(drive, page)) { - unsigned short *val = ((unsigned short *)page) + 2; - char *out = ((char *)val) + (SECTOR_WORDS * 4); - page = out; - do { - out += sprintf(out, "%04x%c", le16_to_cpu(*val), (++i & 7) ? ' ' : '\n'); - val += 1; - } while (i < (SECTOR_WORDS * 2)); - len = out - page; - } - else - len = sprintf(page, "\n"); - PROC_IDE_READ_RETURN(page,start,off,count,eof,len); -} - -static int proc_ide_read_settings - (char *page, char **start, off_t off, int count, int *eof, void *data) -{ - ide_drive_t *drive = (ide_drive_t *) data; - ide_settings_t *setting = (ide_settings_t *) drive->settings; - char *out = page; - int len, rc, mul_factor, div_factor; - - out += sprintf(out, "name\t\t\tvalue\t\tmin\t\tmax\t\tmode\n"); - out += sprintf(out, "----\t\t\t-----\t\t---\t\t---\t\t----\n"); - while(setting) { - mul_factor = setting->mul_factor; - div_factor = setting->div_factor; - out += sprintf(out, "%-24s", setting->name); - if ((rc = ide_read_setting(drive, setting)) >= 0) - out += sprintf(out, "%-16d", rc * mul_factor / div_factor); - else - out += sprintf(out, "%-16s", "write-only"); - out += sprintf(out, "%-16d%-16d", (setting->min * mul_factor + div_factor - 1) / div_factor, setting->max * mul_factor / div_factor); - if (setting->rw & SETTING_READ) - out += sprintf(out, "r"); - if (setting->rw & SETTING_WRITE) - out += sprintf(out, "w"); - out += sprintf(out, "\n"); - setting = setting->next; - } - len = out - page; - PROC_IDE_READ_RETURN(page,start,off,count,eof,len); -} - -#define MAX_LEN 30 - -static int proc_ide_write_settings - (struct file *file, const char *buffer, unsigned long count, void *data) -{ - ide_drive_t *drive = (ide_drive_t *) data; - char name[MAX_LEN + 1]; - int for_real = 0, len; - unsigned long n; - const char *start = NULL; - ide_settings_t *setting; - - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - /* - * Skip over leading whitespace - */ - while (count && isspace(*buffer)) { - --count; - ++buffer; - } - /* - * Do one full pass to verify all parameters, - * then do another to actually write the new settings. - */ - do { - const char *p; - p = buffer; - n = count; - while (n > 0) { - int d, digits; - unsigned int val = 0; - start = p; - - while (n > 0 && *p != ':') { - --n; - p++; - } - if (*p != ':') - goto parse_error; - len = IDE_MIN(p - start, MAX_LEN); - strncpy(name, start, IDE_MIN(len, MAX_LEN)); - name[len] = 0; - - if (n > 0) { - --n; - p++; - } else - goto parse_error; - - digits = 0; - while (n > 0 && (d = ide_getdigit(*p)) >= 0) { - val = (val * 10) + d; - --n; - ++p; - ++digits; - } - if (n > 0 && !isspace(*p)) - goto parse_error; - while (n > 0 && isspace(*p)) { - --n; - ++p; - } - setting = ide_find_setting_by_name(drive, name); - if (!setting) - goto parse_error; - - if (for_real) - ide_write_setting(drive, setting, val * setting->div_factor / setting->mul_factor); - } - } while (!for_real++); - return count; -parse_error: - printk("proc_ide_write_settings(): parse error\n"); - return -EINVAL; -} - -int proc_ide_read_capacity - (char *page, char **start, off_t off, int count, int *eof, void *data) -{ - ide_drive_t *drive = (ide_drive_t *) data; - ide_driver_t *driver = (ide_driver_t *) drive->driver; - int len; - - if (!driver) - len = sprintf(page, "(none)\n"); - else - len = sprintf(page,"%li\n", ((ide_driver_t *)drive->driver)->capacity(drive)); - PROC_IDE_READ_RETURN(page,start,off,count,eof,len); -} - -int proc_ide_read_geometry - (char *page, char **start, off_t off, int count, int *eof, void *data) -{ - ide_drive_t *drive = (ide_drive_t *) data; - char *out = page; - int len; - - out += sprintf(out,"physical %d/%d/%d\n", drive->cyl, drive->head, drive->sect); - out += sprintf(out,"logical %d/%d/%d\n", drive->bios_cyl, drive->bios_head, drive->bios_sect); - len = out - page; - PROC_IDE_READ_RETURN(page,start,off,count,eof,len); -} - -static int proc_ide_read_dmodel - (char *page, char **start, off_t off, int count, int *eof, void *data) -{ - ide_drive_t *drive = (ide_drive_t *) data; - struct hd_driveid *id = drive->id; - int len; - - len = sprintf(page, "%.40s\n", (id && id->model[0]) ? (char *)id->model : "(none)"); - PROC_IDE_READ_RETURN(page,start,off,count,eof,len); -} - -static int proc_ide_read_driver - (char *page, char **start, off_t off, int count, int *eof, void *data) -{ - ide_drive_t *drive = (ide_drive_t *) data; - ide_driver_t *driver = (ide_driver_t *) drive->driver; - int len; - - if (!driver) - len = sprintf(page, "(none)\n"); - else - len = sprintf(page, "%s version %s\n", driver->name, driver->version); - PROC_IDE_READ_RETURN(page,start,off,count,eof,len); -} - -static int proc_ide_write_driver - (struct file *file, const char *buffer, unsigned long count, void *data) -{ - ide_drive_t *drive = (ide_drive_t *) data; - - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - if (ide_replace_subdriver(drive, buffer)) - return -EINVAL; - return count; -} - -static int proc_ide_read_media - (char *page, char **start, off_t off, int count, int *eof, void *data) -{ - ide_drive_t *drive = (ide_drive_t *) data; - const char *media; - int len; - - switch (drive->media) { - case ide_disk: media = "disk\n"; - break; - case ide_cdrom: media = "cdrom\n"; - break; - case ide_tape: media = "tape\n"; - break; - case ide_floppy:media = "floppy\n"; - break; - default: media = "UNKNOWN\n"; - break; - } - strcpy(page,media); - len = strlen(media); - PROC_IDE_READ_RETURN(page,start,off,count,eof,len); -} - -static ide_proc_entry_t generic_drive_entries[] = { - { "driver", S_IFREG|S_IRUGO, proc_ide_read_driver, proc_ide_write_driver }, - { "identify", S_IFREG|S_IRUSR, proc_ide_read_identify, NULL }, - { "media", S_IFREG|S_IRUGO, proc_ide_read_media, NULL }, - { "model", S_IFREG|S_IRUGO, proc_ide_read_dmodel, NULL }, - { "settings", S_IFREG|S_IRUSR|S_IWUSR,proc_ide_read_settings, proc_ide_write_settings }, - { NULL, 0, NULL, NULL } -}; - -void ide_add_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t *p, void *data) -{ - struct proc_dir_entry *ent; - - if (!dir || !p) - return; - while (p->name != NULL) { - ent = create_proc_entry(p->name, p->mode, dir); - if (!ent) return; - ent->nlink = 1; - ent->data = data; - ent->read_proc = p->read_proc; - ent->write_proc = p->write_proc; - p++; - } -} - -void ide_remove_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t *p) -{ - if (!dir || !p) - return; - while (p->name != NULL) { - remove_proc_entry(p->name, dir); - p++; - } -} - -static void create_proc_ide_drives(ide_hwif_t *hwif) -{ - int d; - struct proc_dir_entry *ent; - struct proc_dir_entry *parent = hwif->proc; - char name[64]; - - for (d = 0; d < MAX_DRIVES; d++) { - ide_drive_t *drive = &hwif->drives[d]; - ide_driver_t *driver = drive->driver; - - if (!drive->present) - continue; - if (drive->proc) - continue; - - drive->proc = proc_mkdir(drive->name, parent); - if (drive->proc) { - ide_add_proc_entries(drive->proc, generic_drive_entries, drive); - if (driver) { - ide_add_proc_entries(drive->proc, generic_subdriver_entries, drive); - ide_add_proc_entries(drive->proc, driver->proc, drive); - } - } - sprintf(name,"ide%d/%s", (drive->name[2]-'a')/2, drive->name); - ent = proc_symlink(drive->name, proc_ide_root, name); - if (!ent) return; - } -} - -void destroy_proc_ide_drives(ide_hwif_t *hwif) -{ - int d; - - for (d = 0; d < MAX_DRIVES; d++) { - ide_drive_t *drive = &hwif->drives[d]; - ide_driver_t *driver = drive->driver; - - if (!drive->proc) - continue; - if (driver) - ide_remove_proc_entries(drive->proc, driver->proc); - ide_remove_proc_entries(drive->proc, generic_drive_entries); - remove_proc_entry(drive->name, proc_ide_root); - remove_proc_entry(drive->name, hwif->proc); - drive->proc = NULL; - } -} - -static ide_proc_entry_t hwif_entries[] = { - { "channel", S_IFREG|S_IRUGO, proc_ide_read_channel, NULL }, - { "config", S_IFREG|S_IRUGO|S_IWUSR,proc_ide_read_config, proc_ide_write_config }, - { "mate", S_IFREG|S_IRUGO, proc_ide_read_mate, NULL }, - { "model", S_IFREG|S_IRUGO, proc_ide_read_imodel, NULL }, - { NULL, 0, NULL, NULL } -}; - -void create_proc_ide_interfaces(void) -{ - int h; - - for (h = 0; h < MAX_HWIFS; h++) { - ide_hwif_t *hwif = &ide_hwifs[h]; - - if (!hwif->present) - continue; - if (!hwif->proc) { - hwif->proc = proc_mkdir(hwif->name, proc_ide_root); - if (!hwif->proc) - return; - ide_add_proc_entries(hwif->proc, hwif_entries, hwif); - } - create_proc_ide_drives(hwif); - } -} - -static void destroy_proc_ide_interfaces(void) -{ - int h; - - for (h = 0; h < MAX_HWIFS; h++) { - ide_hwif_t *hwif = &ide_hwifs[h]; - int exist = (hwif->proc != NULL); -#if 0 - if (!hwif->present) - continue; -#endif - if (exist) { - destroy_proc_ide_drives(hwif); - ide_remove_proc_entries(hwif->proc, hwif_entries); - remove_proc_entry(hwif->name, proc_ide_root); - hwif->proc = NULL; - } else - continue; - } -} - -void proc_ide_create(void) -{ - proc_ide_root = proc_mkdir("ide", 0); - if (!proc_ide_root) return; - - create_proc_ide_interfaces(); - - create_proc_read_entry("drivers", 0, proc_ide_root, - proc_ide_read_drivers, NULL); - -#ifdef CONFIG_BLK_DEV_AEC6210 - if ((aec6210_display_info) && (aec6210_proc)) - create_proc_info_entry("aec6210", 0, proc_ide_root, aec6210_display_info); -#endif /* CONFIG_BLK_DEV_AEC6210 */ -#ifdef CONFIG_BLK_DEV_ALI15X3 - if ((ali_display_info) && (ali_proc)) - create_proc_info_entry("ali", 0, proc_ide_root, ali_display_info); -#endif /* CONFIG_BLK_DEV_ALI15X3 */ -#ifdef CONFIG_BLK_DEV_AMD7409 - if ((amd7409_display_info) && (amd7409_proc)) - create_proc_info_entry("amd7409", 0, proc_ide_root, amd7409_display_info); -#endif /* CONFIG_BLK_DEV_AMD7409 */ -#ifdef CONFIG_BLK_DEV_CMD64X - if ((cmd64x_display_info) && (cmd64x_proc)) - create_proc_info_entry("cmd64x", 0, proc_ide_root, cmd64x_display_info); -#endif /* CONFIG_BLK_DEV_CMD64X */ -#ifdef CONFIG_BLK_DEV_CS5530 - if ((cs5530_display_info) && (cs5530_proc)) - create_proc_info_entry("cs5530", 0, proc_ide_root, cs5530_display_info); -#endif /* CONFIG_BLK_DEV_CS5530 */ -#ifdef CONFIG_BLK_DEV_HPT34X - if ((hpt34x_display_info) && (hpt34x_proc)) - create_proc_info_entry("hpt34x", 0, proc_ide_root, hpt34x_display_info); -#endif /* CONFIG_BLK_DEV_HPT34X */ -#ifdef CONFIG_BLK_DEV_HPT366 - if ((hpt366_display_info) && (hpt366_proc)) - create_proc_info_entry("hpt366", 0, proc_ide_root, hpt366_display_info); -#endif /* CONFIG_BLK_DEV_HPT366 */ -#ifdef CONFIG_BLK_DEV_PDC202XX - if ((pdc202xx_display_info) && (pdc202xx_proc)) - create_proc_info_entry("pdc202xx", 0, proc_ide_root, pdc202xx_display_info); -#endif /* CONFIG_BLK_DEV_PDC202XX */ -#ifdef CONFIG_BLK_DEV_PIIX - if ((piix_display_info) && (piix_proc)) - create_proc_info_entry("piix", 0, proc_ide_root, piix_display_info); -#endif /* CONFIG_BLK_DEV_PIIX */ -#ifdef CONFIG_BLK_DEV_SIS5513 - if ((sis_display_info) && (sis_proc)) - create_proc_info_entry("sis", 0, proc_ide_root, sis_display_info); -#endif /* CONFIG_BLK_DEV_SIS5513 */ -#ifdef CONFIG_BLK_DEV_VIA82CXXX - if ((via_display_info) && (via_proc)) - create_proc_info_entry("via", 0, proc_ide_root, via_display_info); -#endif /* CONFIG_BLK_DEV_VIA82CXXX */ -} - -void proc_ide_destroy(void) -{ - /* - * Mmmm.. does this free up all resources, - * or do we need to do a more proper cleanup here ?? - */ -#ifdef CONFIG_BLK_DEV_AEC6210 - if ((aec6210_display_info) && (aec6210_proc)) - remove_proc_entry("ide/aec6210",0); -#endif /* CONFIG_BLK_DEV_AEC6210 */ -#ifdef CONFIG_BLK_DEV_ALI15X3 - if ((ali_display_info) && (ali_proc)) - remove_proc_entry("ide/ali",0); -#endif /* CONFIG_BLK_DEV_ALI15X3 */ -#ifdef CONFIG_BLK_DEV_AMD7409 - if ((amd7409_display_info) && (amd7409_proc)) - remove_proc_entry("ide/amd7409",0); -#endif /* CONFIG_BLK_DEV_AMD7409 */ -#ifdef CONFIG_BLK_DEV_CMD64X - if ((cmd64x_display_info) && (cmd64x_proc)) - remove_proc_entry("ide/cmd64x",0); -#endif /* CONFIG_BLK_DEV_CMD64X */ -#ifdef CONFIG_BLK_DEV_CS5530 - if ((cs5530_display_info) && (cs5530_proc)) - remove_proc_entry("ide/cs5530",0); -#endif /* CONFIG_BLK_DEV_CS5530 */ -#ifdef CONFIG_BLK_DEV_HPT34X - if ((hpt34x_display_info) && (hpt34x_proc)) - remove_proc_entry("ide/hpt34x",0); -#endif /* CONFIG_BLK_DEV_HPT34X */ -#ifdef CONFIG_BLK_DEV_HPT366 - if ((hpt366_display_info) && (hpt366_proc)) - remove_proc_entry("ide/hpt366",0); -#endif /* CONFIG_BLK_DEV_HPT366 */ -#ifdef CONFIG_BLK_DEV_PDC202XX - if ((pdc202xx_display_info) && (pdc202xx_proc)) - remove_proc_entry("ide/pdc202xx",0); -#endif /* CONFIG_BLK_DEV_PDC202XX */ -#ifdef CONFIG_BLK_DEV_PIIX - if ((piix_display_info) && (piix_proc)) - remove_proc_entry("ide/piix",0); -#endif /* CONFIG_BLK_DEV_PIIX */ -#ifdef CONFIG_BLK_DEV_SIS5513 - if ((sis_display_info) && (sis_proc)) - remove_proc_entry("ide/sis", 0); -#endif /* CONFIG_BLK_DEV_SIS5513 */ -#ifdef CONFIG_BLK_DEV_VIA82CXXX - if ((via_display_info) && (via_proc)) - remove_proc_entry("ide/via",0); -#endif /* CONFIG_BLK_DEV_VIA82CXXX */ - - remove_proc_entry("ide/drivers", 0); - destroy_proc_ide_interfaces(); - remove_proc_entry("ide", 0); -} diff --git a/drivers/block/ide-tape.c b/drivers/block/ide-tape.c deleted file mode 100644 index 95e780abf..000000000 --- a/drivers/block/ide-tape.c +++ /dev/null @@ -1,6031 +0,0 @@ -/* - * linux/drivers/block/ide-tape.c Version 1.16f Dec 15, 1999 - * - * Copyright (C) 1995 - 1999 Gadi Oxman <gadio@netvision.net.il> - * - * This driver was constructed as a student project in the software laboratory - * of the faculty of electrical engineering in the Technion - Israel's - * Institute Of Technology, with the guide of Avner Lottem and Dr. Ilana David. - * - * It is hereby placed under the terms of the GNU general public license. - * (See linux/COPYING). - */ - -/* - * IDE ATAPI streaming tape driver. - * - * This driver is a part of the Linux ide driver and works in co-operation - * with linux/drivers/block/ide.c. - * - * The driver, in co-operation with ide.c, basically traverses the - * request-list for the block device interface. The character device - * interface, on the other hand, creates new requests, adds them - * to the request-list of the block device, and waits for their completion. - * - * Pipelined operation mode is now supported on both reads and writes. - * - * The block device major and minor numbers are determined from the - * tape's relative position in the ide interfaces, as explained in ide.c. - * - * The character device interface consists of the following devices: - * - * ht0 major 37, minor 0 first IDE tape, rewind on close. - * ht1 major 37, minor 1 second IDE tape, rewind on close. - * ... - * nht0 major 37, minor 128 first IDE tape, no rewind on close. - * nht1 major 37, minor 129 second IDE tape, no rewind on close. - * ... - * - * Run linux/scripts/MAKEDEV.ide to create the above entries. - * - * The general magnetic tape commands compatible interface, as defined by - * include/linux/mtio.h, is accessible through the character device. - * - * General ide driver configuration options, such as the interrupt-unmask - * flag, can be configured by issuing an ioctl to the block device interface, - * as any other ide device. - * - * Our own ide-tape ioctl's can be issued to either the block device or - * the character device interface. - * - * Maximal throughput with minimal bus load will usually be achieved in the - * following scenario: - * - * 1. ide-tape is operating in the pipelined operation mode. - * 2. No buffering is performed by the user backup program. - * - * Testing was done with a 2 GB CONNER CTMA 4000 IDE ATAPI Streaming Tape Drive. - * - * Ver 0.1 Nov 1 95 Pre-working code :-) - * Ver 0.2 Nov 23 95 A short backup (few megabytes) and restore procedure - * was successful ! (Using tar cvf ... on the block - * device interface). - * A longer backup resulted in major swapping, bad - * overall Linux performance and eventually failed as - * we received non serial read-ahead requests from the - * buffer cache. - * Ver 0.3 Nov 28 95 Long backups are now possible, thanks to the - * character device interface. Linux's responsiveness - * and performance doesn't seem to be much affected - * from the background backup procedure. - * Some general mtio.h magnetic tape operations are - * now supported by our character device. As a result, - * popular tape utilities are starting to work with - * ide tapes :-) - * The following configurations were tested: - * 1. An IDE ATAPI TAPE shares the same interface - * and irq with an IDE ATAPI CDROM. - * 2. An IDE ATAPI TAPE shares the same interface - * and irq with a normal IDE disk. - * Both configurations seemed to work just fine ! - * However, to be on the safe side, it is meanwhile - * recommended to give the IDE TAPE its own interface - * and irq. - * The one thing which needs to be done here is to - * add a "request postpone" feature to ide.c, - * so that we won't have to wait for the tape to finish - * performing a long media access (DSC) request (such - * as a rewind) before we can access the other device - * on the same interface. This effect doesn't disturb - * normal operation most of the time because read/write - * requests are relatively fast, and once we are - * performing one tape r/w request, a lot of requests - * from the other device can be queued and ide.c will - * service all of them after this single tape request. - * Ver 1.0 Dec 11 95 Integrated into Linux 1.3.46 development tree. - * On each read / write request, we now ask the drive - * if we can transfer a constant number of bytes - * (a parameter of the drive) only to its buffers, - * without causing actual media access. If we can't, - * we just wait until we can by polling the DSC bit. - * This ensures that while we are not transferring - * more bytes than the constant referred to above, the - * interrupt latency will not become too high and - * we won't cause an interrupt timeout, as happened - * occasionally in the previous version. - * While polling for DSC, the current request is - * postponed and ide.c is free to handle requests from - * the other device. This is handled transparently to - * ide.c. The hwgroup locking method which was used - * in the previous version was removed. - * Use of new general features which are provided by - * ide.c for use with atapi devices. - * (Programming done by Mark Lord) - * Few potential bug fixes (Again, suggested by Mark) - * Single character device data transfers are now - * not limited in size, as they were before. - * We are asking the tape about its recommended - * transfer unit and send a larger data transfer - * as several transfers of the above size. - * For best results, use an integral number of this - * basic unit (which is shown during driver - * initialization). I will soon add an ioctl to get - * this important parameter. - * Our data transfer buffer is allocated on startup, - * rather than before each data transfer. This should - * ensure that we will indeed have a data buffer. - * Ver 1.1 Dec 14 95 Fixed random problems which occurred when the tape - * shared an interface with another device. - * (poll_for_dsc was a complete mess). - * Removed some old (non-active) code which had - * to do with supporting buffer cache originated - * requests. - * The block device interface can now be opened, so - * that general ide driver features like the unmask - * interrupts flag can be selected with an ioctl. - * This is the only use of the block device interface. - * New fast pipelined operation mode (currently only on - * writes). When using the pipelined mode, the - * throughput can potentially reach the maximum - * tape supported throughput, regardless of the - * user backup program. On my tape drive, it sometimes - * boosted performance by a factor of 2. Pipelined - * mode is enabled by default, but since it has a few - * downfalls as well, you may want to disable it. - * A short explanation of the pipelined operation mode - * is available below. - * Ver 1.2 Jan 1 96 Eliminated pipelined mode race condition. - * Added pipeline read mode. As a result, restores - * are now as fast as backups. - * Optimized shared interface behavior. The new behavior - * typically results in better IDE bus efficiency and - * higher tape throughput. - * Pre-calculation of the expected read/write request - * service time, based on the tape's parameters. In - * the pipelined operation mode, this allows us to - * adjust our polling frequency to a much lower value, - * and thus to dramatically reduce our load on Linux, - * without any decrease in performance. - * Implemented additional mtio.h operations. - * The recommended user block size is returned by - * the MTIOCGET ioctl. - * Additional minor changes. - * Ver 1.3 Feb 9 96 Fixed pipelined read mode bug which prevented the - * use of some block sizes during a restore procedure. - * The character device interface will now present a - * continuous view of the media - any mix of block sizes - * during a backup/restore procedure is supported. The - * driver will buffer the requests internally and - * convert them to the tape's recommended transfer - * unit, making performance almost independent of the - * chosen user block size. - * Some improvements in error recovery. - * By cooperating with ide-dma.c, bus mastering DMA can - * now sometimes be used with IDE tape drives as well. - * Bus mastering DMA has the potential to dramatically - * reduce the CPU's overhead when accessing the device, - * and can be enabled by using hdparm -d1 on the tape's - * block device interface. For more info, read the - * comments in ide-dma.c. - * Ver 1.4 Mar 13 96 Fixed serialize support. - * Ver 1.5 Apr 12 96 Fixed shared interface operation, broken in 1.3.85. - * Fixed pipelined read mode inefficiency. - * Fixed nasty null dereferencing bug. - * Ver 1.6 Aug 16 96 Fixed FPU usage in the driver. - * Fixed end of media bug. - * Ver 1.7 Sep 10 96 Minor changes for the CONNER CTT8000-A model. - * Ver 1.8 Sep 26 96 Attempt to find a better balance between good - * interactive response and high system throughput. - * Ver 1.9 Nov 5 96 Automatically cross encountered filemarks rather - * than requiring an explicit FSF command. - * Abort pending requests at end of media. - * MTTELL was sometimes returning incorrect results. - * Return the real block size in the MTIOCGET ioctl. - * Some error recovery bug fixes. - * Ver 1.10 Nov 5 96 Major reorganization. - * Reduced CPU overhead a bit by eliminating internal - * bounce buffers. - * Added module support. - * Added multiple tape drives support. - * Added partition support. - * Rewrote DSC handling. - * Some portability fixes. - * Removed ide-tape.h. - * Additional minor changes. - * Ver 1.11 Dec 2 96 Bug fix in previous DSC timeout handling. - * Use ide_stall_queue() for DSC overlap. - * Use the maximum speed rather than the current speed - * to compute the request service time. - * Ver 1.12 Dec 7 97 Fix random memory overwriting and/or last block data - * corruption, which could occur if the total number - * of bytes written to the tape was not an integral - * number of tape blocks. - * Add support for INTERRUPT DRQ devices. - * Ver 1.13 Jan 2 98 Add "speed == 0" work-around for HP COLORADO 5GB - * Ver 1.14 Dec 30 98 Partial fixes for the Sony/AIWA tape drives. - * Replace cli()/sti() with hwgroup spinlocks. - * Ver 1.15 Mar 25 99 Fix SMP race condition by replacing hwgroup - * spinlock with private per-tape spinlock. - * Ver 1.16 Sep 1 99 Add OnStream tape support. - * Abort read pipeline on EOD. - * Wait for the tape to become ready in case it returns - * "in the process of becoming ready" on open(). - * Fix zero padding of the last written block in - * case the tape block size is larger than PAGE_SIZE. - * Decrease the default disconnection time to tn. - * Ver 1.16e Oct 3 99 Minor fixes. - * Ver 1.16e1 Oct 13 99 Patches by Arnold Niessen, - * niessen@iae.nl / arnold.niessen@philips.com - * GO-1) Undefined code in idetape_read_position - * according to Gadi's email - * AJN-1) Minor fix asc == 11 should be asc == 0x11 - * in idetape_issue_packet_command (did effect - * debugging output only) - * AJN-2) Added more debugging output, and - * added ide-tape: where missing. I would also - * like to add tape->name where possible - * AJN-3) Added different debug_level's - * via /proc/ide/hdc/settings - * "debug_level" determines amount of debugging output; - * can be changed using /proc/ide/hdx/settings - * 0 : almost no debugging output - * 1 : 0+output errors only - * 2 : 1+output all sensekey/asc - * 3 : 2+follow all chrdev related procedures - * 4 : 3+follow all procedures - * 5 : 4+include pc_stack rq_stack info - * 6 : 5+USE_COUNT updates - * AJN-4) Fixed timeout for retension in idetape_queue_pc_tail - * from 5 to 10 minutes - * AJN-5) Changed maximum number of blocks to skip when - * reading tapes with multiple consecutive write - * errors from 100 to 1000 in idetape_get_logical_blk - * Proposed changes to code: - * 1) output "logical_blk_num" via /proc - * 2) output "current_operation" via /proc - * 3) Either solve or document the fact that `mt rewind' is - * required after reading from /dev/nhtx to be - * able to rmmod the idetape module; - * Also, sometimes an application finishes but the - * device remains `busy' for some time. Same cause ? - * Proposed changes to release-notes: - * 4) write a simple `quickstart' section in the - * release notes; I volunteer if you don't want to - * 5) include a pointer to video4linux in the doc - * to stimulate video applications - * 6) release notes lines 331 and 362: explain what happens - * if the application data rate is higher than 1100 KB/s; - * similar approach to lower-than-500 kB/s ? - * 7) 6.6 Comparison; wouldn't it be better to allow different - * strategies for read and write ? - * Wouldn't it be better to control the tape buffer - * contents instead of the bandwidth ? - * 8) line 536: replace will by would (if I understand - * this section correctly, a hypothetical and unwanted situation - * is being described) - * Ver 1.16f Dec 15 99 Change place of the secondary OnStream header frames. - * - * - * Here are some words from the first releases of hd.c, which are quoted - * in ide.c and apply here as well: - * - * | Special care is recommended. Have Fun! - * - */ - -/* - * An overview of the pipelined operation mode. - * - * In the pipelined write mode, we will usually just add requests to our - * pipeline and return immediately, before we even start to service them. The - * user program will then have enough time to prepare the next request while - * we are still busy servicing previous requests. In the pipelined read mode, - * the situation is similar - we add read-ahead requests into the pipeline, - * before the user even requested them. - * - * The pipeline can be viewed as a "safety net" which will be activated when - * the system load is high and prevents the user backup program from keeping up - * with the current tape speed. At this point, the pipeline will get - * shorter and shorter but the tape will still be streaming at the same speed. - * Assuming we have enough pipeline stages, the system load will hopefully - * decrease before the pipeline is completely empty, and the backup program - * will be able to "catch up" and refill the pipeline again. - * - * When using the pipelined mode, it would be best to disable any type of - * buffering done by the user program, as ide-tape already provides all the - * benefits in the kernel, where it can be done in a more efficient way. - * As we will usually not block the user program on a request, the most - * efficient user code will then be a simple read-write-read-... cycle. - * Any additional logic will usually just slow down the backup process. - * - * Using the pipelined mode, I get a constant over 400 KBps throughput, - * which seems to be the maximum throughput supported by my tape. - * - * However, there are some downfalls: - * - * 1. We use memory (for data buffers) in proportional to the number - * of pipeline stages (each stage is about 26 KB with my tape). - * 2. In the pipelined write mode, we cheat and postpone error codes - * to the user task. In read mode, the actual tape position - * will be a bit further than the last requested block. - * - * Concerning (1): - * - * 1. We allocate stages dynamically only when we need them. When - * we don't need them, we don't consume additional memory. In - * case we can't allocate stages, we just manage without them - * (at the expense of decreased throughput) so when Linux is - * tight in memory, we will not pose additional difficulties. - * - * 2. The maximum number of stages (which is, in fact, the maximum - * amount of memory) which we allocate is limited by the compile - * time parameter IDETAPE_MAX_PIPELINE_STAGES. - * - * 3. The maximum number of stages is a controlled parameter - We - * don't start from the user defined maximum number of stages - * but from the lower IDETAPE_MIN_PIPELINE_STAGES (again, we - * will not even allocate this amount of stages if the user - * program can't handle the speed). We then implement a feedback - * loop which checks if the pipeline is empty, and if it is, we - * increase the maximum number of stages as necessary until we - * reach the optimum value which just manages to keep the tape - * busy with minimum allocated memory or until we reach - * IDETAPE_MAX_PIPELINE_STAGES. - * - * Concerning (2): - * - * In pipelined write mode, ide-tape can not return accurate error codes - * to the user program since we usually just add the request to the - * pipeline without waiting for it to be serviced. In case an error - * occurs, I will report it on the next user request. - * - * In the pipelined read mode, subsequent read requests or forward - * filemark spacing will perform correctly, as we preserve all blocks - * and filemarks which we encountered during our excess read-ahead. - * - * For accurate tape positioning and error reporting, disabling - * pipelined mode might be the best option. - * - * You can enable/disable/tune the pipelined operation mode by adjusting - * the compile time parameters below. - */ - -/* - * Possible improvements. - * - * 1. Support for the ATAPI overlap protocol. - * - * In order to maximize bus throughput, we currently use the DSC - * overlap method which enables ide.c to service requests from the - * other device while the tape is busy executing a command. The - * DSC overlap method involves polling the tape's status register - * for the DSC bit, and servicing the other device while the tape - * isn't ready. - * - * In the current QIC development standard (December 1995), - * it is recommended that new tape drives will *in addition* - * implement the ATAPI overlap protocol, which is used for the - * same purpose - efficient use of the IDE bus, but is interrupt - * driven and thus has much less CPU overhead. - * - * ATAPI overlap is likely to be supported in most new ATAPI - * devices, including new ATAPI cdroms, and thus provides us - * a method by which we can achieve higher throughput when - * sharing a (fast) ATA-2 disk with any (slow) new ATAPI device. - */ - -#define IDETAPE_VERSION "1.16f" - -#include <linux/config.h> -#include <linux/module.h> -#include <linux/types.h> -#include <linux/string.h> -#include <linux/kernel.h> -#include <linux/delay.h> -#include <linux/timer.h> -#include <linux/mm.h> -#include <linux/interrupt.h> -#include <linux/major.h> -#include <linux/devfs_fs_kernel.h> -#include <linux/errno.h> -#include <linux/genhd.h> -#include <linux/malloc.h> -#include <linux/pci.h> -#include <linux/ide.h> - -#include <asm/byteorder.h> -#include <asm/irq.h> -#include <asm/uaccess.h> -#include <asm/io.h> -#include <asm/unaligned.h> -#include <asm/bitops.h> - - -#define NO_LONGER_REQUIRED (1) - -/* - * OnStream support - */ -#define ONSTREAM_DEBUG (0) -#define OS_CONFIG_PARTITION (0xff) -#define OS_DATA_PARTITION (0) -#define OS_PARTITION_VERSION (1) - -/* - * partition - */ -typedef struct os_partition_s { - __u8 partition_num; - __u8 par_desc_ver; - __u16 wrt_pass_cntr; - __u32 first_frame_addr; - __u32 last_frame_addr; - __u32 eod_frame_addr; -} os_partition_t; - -/* - * DAT entry - */ -typedef struct os_dat_entry_s { - __u32 blk_sz; - __u16 blk_cnt; - __u8 flags; - __u8 reserved; -} os_dat_entry_t; - -/* - * DAT - */ -#define OS_DAT_FLAGS_DATA (0xc) -#define OS_DAT_FLAGS_MARK (0x1) - -typedef struct os_dat_s { - __u8 dat_sz; - __u8 reserved1; - __u8 entry_cnt; - __u8 reserved3; - os_dat_entry_t dat_list[16]; -} os_dat_t; - -/* - * Frame types - */ -#define OS_FRAME_TYPE_FILL (0) -#define OS_FRAME_TYPE_EOD (1 << 0) -#define OS_FRAME_TYPE_MARKER (1 << 1) -#define OS_FRAME_TYPE_HEADER (1 << 3) -#define OS_FRAME_TYPE_DATA (1 << 7) - -/* - * AUX - */ -typedef struct os_aux_s { - __u32 format_id; /* hardware compability AUX is based on */ - char application_sig[4]; /* driver used to write this media */ - __u32 hdwr; /* reserved */ - __u32 update_frame_cntr; /* for configuration frame */ - __u8 frame_type; - __u8 frame_type_reserved; - __u8 reserved_18_19[2]; - os_partition_t partition; - __u8 reserved_36_43[8]; - __u32 frame_seq_num; - __u32 logical_blk_num_high; - __u32 logical_blk_num; - os_dat_t dat; - __u8 reserved188_191[4]; - __u32 filemark_cnt; - __u32 phys_fm; - __u32 last_mark_addr; - __u8 reserved204_223[20]; - - /* - * __u8 app_specific[32]; - * - * Linux specific fields: - */ - __u32 next_mark_addr; /* when known, points to next marker */ - __u8 linux_specific[28]; - - __u8 reserved_256_511[256]; -} os_aux_t; - -typedef struct os_header_s { - char ident_str[8]; - __u8 major_rev; - __u8 minor_rev; - __u8 reserved10_15[6]; - __u8 par_num; - __u8 reserved1_3[3]; - os_partition_t partition; -} os_header_t; - -/* - * OnStream ADRL frame - */ -#define OS_FRAME_SIZE (32 * 1024 + 512) -#define OS_DATA_SIZE (32 * 1024) -#define OS_AUX_SIZE (512) - -#include <linux/mtio.h> - -/**************************** Tunable parameters *****************************/ - - -/* - * Pipelined mode parameters. - * - * We try to use the minimum number of stages which is enough to - * keep the tape constantly streaming. To accomplish that, we implement - * a feedback loop around the maximum number of stages: - * - * We start from MIN maximum stages (we will not even use MIN stages - * if we don't need them), increment it by RATE*(MAX-MIN) - * whenever we sense that the pipeline is empty, until we reach - * the optimum value or until we reach MAX. - * - * Setting the following parameter to 0 will disable the pipelined mode. - */ -#define IDETAPE_MIN_PIPELINE_STAGES 200 -#define IDETAPE_MAX_PIPELINE_STAGES 400 -#define IDETAPE_INCREASE_STAGES_RATE 20 - -/* - * The following are used to debug the driver: - * - * Setting IDETAPE_DEBUG_INFO to 1 will report device capabilities. - * Setting IDETAPE_DEBUG_LOG to 1 will log driver flow control. - * Setting IDETAPE_DEBUG_BUGS to 1 will enable self-sanity checks in - * some places. - * - * Setting them to 0 will restore normal operation mode: - * - * 1. Disable logging normal successful operations. - * 2. Disable self-sanity checks. - * 3. Errors will still be logged, of course. - * - * All the #if DEBUG code will be removed some day, when the driver - * is verified to be stable enough. This will make it much more - * esthetic. - */ -#define IDETAPE_DEBUG_INFO 0 -#define IDETAPE_DEBUG_LOG 1 -#define IDETAPE_DEBUG_LOG_VERBOSE 0 -#define IDETAPE_DEBUG_BUGS 1 - -/* - * After each failed packet command we issue a request sense command - * and retry the packet command IDETAPE_MAX_PC_RETRIES times. - * - * Setting IDETAPE_MAX_PC_RETRIES to 0 will disable retries. - */ -#define IDETAPE_MAX_PC_RETRIES 3 - -/* - * With each packet command, we allocate a buffer of - * IDETAPE_PC_BUFFER_SIZE bytes. This is used for several packet - * commands (Not for READ/WRITE commands). - */ -#define IDETAPE_PC_BUFFER_SIZE 256 - -/* - * In various places in the driver, we need to allocate storage - * for packet commands and requests, which will remain valid while - * we leave the driver to wait for an interrupt or a timeout event. - */ -#define IDETAPE_PC_STACK (10 + IDETAPE_MAX_PC_RETRIES) - -/* - * Some tape drives require a long irq timeout - */ -#define IDETAPE_WAIT_CMD (60*HZ) - -/* - * The following parameter is used to select the point in the internal - * tape fifo in which we will start to refill the buffer. Decreasing - * the following parameter will improve the system's latency and - * interactive response, while using a high value might improve sytem - * throughput. - */ -#define IDETAPE_FIFO_THRESHOLD 2 - -/* - * DSC polling parameters. - * - * Polling for DSC (a single bit in the status register) is a very - * important function in ide-tape. There are two cases in which we - * poll for DSC: - * - * 1. Before a read/write packet command, to ensure that we - * can transfer data from/to the tape's data buffers, without - * causing an actual media access. In case the tape is not - * ready yet, we take out our request from the device - * request queue, so that ide.c will service requests from - * the other device on the same interface meanwhile. - * - * 2. After the successful initialization of a "media access - * packet command", which is a command which can take a long - * time to complete (it can be several seconds or even an hour). - * - * Again, we postpone our request in the middle to free the bus - * for the other device. The polling frequency here should be - * lower than the read/write frequency since those media access - * commands are slow. We start from a "fast" frequency - - * IDETAPE_DSC_MA_FAST (one second), and if we don't receive DSC - * after IDETAPE_DSC_MA_THRESHOLD (5 minutes), we switch it to a - * lower frequency - IDETAPE_DSC_MA_SLOW (1 minute). - * - * We also set a timeout for the timer, in case something goes wrong. - * The timeout should be longer then the maximum execution time of a - * tape operation. - */ - -/* - * DSC timings. - */ -#define IDETAPE_DSC_RW_MIN 5*HZ/100 /* 50 msec */ -#define IDETAPE_DSC_RW_MAX 40*HZ/100 /* 400 msec */ -#define IDETAPE_DSC_RW_TIMEOUT 2*60*HZ /* 2 minutes */ -#define IDETAPE_DSC_MA_FAST 2*HZ /* 2 seconds */ -#define IDETAPE_DSC_MA_THRESHOLD 5*60*HZ /* 5 minutes */ -#define IDETAPE_DSC_MA_SLOW 30*HZ /* 30 seconds */ -#define IDETAPE_DSC_MA_TIMEOUT 2*60*60*HZ /* 2 hours */ - -/*************************** End of tunable parameters ***********************/ - -/* - * Debugging/Performance analysis - * - * I/O trace support - */ -#define USE_IOTRACE 0 -#if USE_IOTRACE -#include <linux/io_trace.h> -#define IO_IDETAPE_FIFO 500 -#endif - -/* - * Read/Write error simulation - */ -#define SIMULATE_ERRORS 0 - -/* - * For general magnetic tape device compatibility. - */ -typedef enum { - idetape_direction_none, - idetape_direction_read, - idetape_direction_write -} idetape_chrdev_direction_t; - -/* - * Our view of a packet command. - */ -typedef struct idetape_packet_command_s { - u8 c[12]; /* Actual packet bytes */ - int retries; /* On each retry, we increment retries */ - int error; /* Error code */ - int request_transfer; /* Bytes to transfer */ - int actually_transferred; /* Bytes actually transferred */ - int buffer_size; /* Size of our data buffer */ - struct buffer_head *bh; - char *b_data; - int b_count; - byte *buffer; /* Data buffer */ - byte *current_position; /* Pointer into the above buffer */ - ide_startstop_t (*callback) (ide_drive_t *); /* Called when this packet command is completed */ - byte pc_buffer[IDETAPE_PC_BUFFER_SIZE]; /* Temporary buffer */ - unsigned int flags; /* Status/Action bit flags */ -} idetape_pc_t; - -/* - * Packet command flag bits. - */ -#define PC_ABORT 0 /* Set when an error is considered normal - We won't retry */ -#define PC_WAIT_FOR_DSC 1 /* 1 When polling for DSC on a media access command */ -#define PC_DMA_RECOMMENDED 2 /* 1 when we prefer to use DMA if possible */ -#define PC_DMA_IN_PROGRESS 3 /* 1 while DMA in progress */ -#define PC_DMA_ERROR 4 /* 1 when encountered problem during DMA */ -#define PC_WRITING 5 /* Data direction */ - -/* - * Capabilities and Mechanical Status Page - */ -typedef struct { - unsigned page_code :6; /* Page code - Should be 0x2a */ - __u8 reserved0_6 :1; - __u8 ps :1; /* parameters saveable */ - __u8 page_length; /* Page Length - Should be 0x12 */ - __u8 reserved2, reserved3; - unsigned ro :1; /* Read Only Mode */ - unsigned reserved4_1234 :4; - unsigned sprev :1; /* Supports SPACE in the reverse direction */ - unsigned reserved4_67 :2; - unsigned reserved5_012 :3; - unsigned efmt :1; /* Supports ERASE command initiated formatting */ - unsigned reserved5_4 :1; - unsigned qfa :1; /* Supports the QFA two partition formats */ - unsigned reserved5_67 :2; - unsigned lock :1; /* Supports locking the volume */ - unsigned locked :1; /* The volume is locked */ - unsigned prevent :1; /* The device defaults in the prevent state after power up */ - unsigned eject :1; /* The device can eject the volume */ - __u8 disconnect :1; /* The device can break request > ctl */ - __u8 reserved6_5 :1; - unsigned ecc :1; /* Supports error correction */ - unsigned cmprs :1; /* Supports data compression */ - unsigned reserved7_0 :1; - unsigned blk512 :1; /* Supports 512 bytes block size */ - unsigned blk1024 :1; /* Supports 1024 bytes block size */ - unsigned reserved7_3_6 :4; - unsigned blk32768 :1; /* slowb - the device restricts the byte count for PIO */ - /* transfers for slow buffer memory ??? */ - /* Also 32768 block size in some cases */ - __u16 max_speed; /* Maximum speed supported in KBps */ - __u8 reserved10, reserved11; - __u16 ctl; /* Continuous Transfer Limit in blocks */ - __u16 speed; /* Current Speed, in KBps */ - __u16 buffer_size; /* Buffer Size, in 512 bytes */ - __u8 reserved18, reserved19; -} idetape_capabilities_page_t; - -/* - * Block Size Page - */ -typedef struct { - unsigned page_code :6; /* Page code - Should be 0x30 */ - unsigned reserved1_6 :1; - unsigned ps :1; - __u8 page_length; /* Page Length - Should be 2 */ - __u8 reserved2; - unsigned play32 :1; - unsigned play32_5 :1; - unsigned reserved2_23 :2; - unsigned record32 :1; - unsigned record32_5 :1; - unsigned reserved2_6 :1; - unsigned one :1; -} idetape_block_size_page_t; - -/* - * A pipeline stage. - */ -typedef struct idetape_stage_s { - struct request rq; /* The corresponding request */ - struct buffer_head *bh; /* The data buffers */ - struct idetape_stage_s *next; /* Pointer to the next stage */ - os_aux_t *aux; /* OnStream aux ptr */ -} idetape_stage_t; - -/* - * REQUEST SENSE packet command result - Data Format. - */ -typedef struct { - unsigned error_code :7; /* Current of deferred errors */ - unsigned valid :1; /* The information field conforms to QIC-157C */ - __u8 reserved1 :8; /* Segment Number - Reserved */ - unsigned sense_key :4; /* Sense Key */ - unsigned reserved2_4 :1; /* Reserved */ - unsigned ili :1; /* Incorrect Length Indicator */ - unsigned eom :1; /* End Of Medium */ - unsigned filemark :1; /* Filemark */ - __u32 information __attribute__ ((packed)); - __u8 asl; /* Additional sense length (n-7) */ - __u32 command_specific; /* Additional command specific information */ - __u8 asc; /* Additional Sense Code */ - __u8 ascq; /* Additional Sense Code Qualifier */ - __u8 replaceable_unit_code; /* Field Replaceable Unit Code */ - unsigned sk_specific1 :7; /* Sense Key Specific */ - unsigned sksv :1; /* Sense Key Specific information is valid */ - __u8 sk_specific2; /* Sense Key Specific */ - __u8 sk_specific3; /* Sense Key Specific */ - __u8 pad[2]; /* Padding to 20 bytes */ -} idetape_request_sense_result_t; - - -/* - * Most of our global data which we need to save even as we leave the - * driver due to an interrupt or a timer event is stored in a variable - * of type idetape_tape_t, defined below. - */ -typedef struct { - ide_drive_t *drive; - devfs_handle_t de_r, de_n; - - /* - * Since a typical character device operation requires more - * than one packet command, we provide here enough memory - * for the maximum of interconnected packet commands. - * The packet commands are stored in the circular array pc_stack. - * pc_stack_index points to the last used entry, and warps around - * to the start when we get to the last array entry. - * - * pc points to the current processed packet command. - * - * failed_pc points to the last failed packet command, or contains - * NULL if we do not need to retry any packet command. This is - * required since an additional packet command is needed before the - * retry, to get detailed information on what went wrong. - */ - idetape_pc_t *pc; /* Current packet command */ - idetape_pc_t *failed_pc; /* Last failed packet command */ - idetape_pc_t pc_stack[IDETAPE_PC_STACK];/* Packet command stack */ - int pc_stack_index; /* Next free packet command storage space */ - struct request rq_stack[IDETAPE_PC_STACK]; - int rq_stack_index; /* We implement a circular array */ - - /* - * DSC polling variables. - * - * While polling for DSC we use postponed_rq to postpone the - * current request so that ide.c will be able to service - * pending requests on the other device. Note that at most - * we will have only one DSC (usually data transfer) request - * in the device request queue. Additional requests can be - * queued in our internal pipeline, but they will be visible - * to ide.c only one at a time. - */ - struct request *postponed_rq; - unsigned long dsc_polling_start; /* The time in which we started polling for DSC */ - struct timer_list dsc_timer; /* Timer used to poll for dsc */ - unsigned long best_dsc_rw_frequency; /* Read/Write dsc polling frequency */ - unsigned long dsc_polling_frequency; /* The current polling frequency */ - unsigned long dsc_timeout; /* Maximum waiting time */ - - /* - * Read position information - */ - byte partition; - unsigned int first_frame_position; /* Current block */ - unsigned int last_frame_position; - unsigned int blocks_in_buffer; - - /* - * Last error information - */ - byte sense_key, asc, ascq; - - /* - * Character device operation - */ - unsigned int minor; - char name[4]; /* device name */ - idetape_chrdev_direction_t chrdev_direction; /* Current character device data transfer direction */ - - /* - * Device information - */ - unsigned short tape_block_size; /* Usually 512 or 1024 bytes */ - int user_bs_factor; - idetape_capabilities_page_t capabilities; /* Copy of the tape's Capabilities and Mechanical Page */ - - /* - * Active data transfer request parameters. - * - * At most, there is only one ide-tape originated data transfer - * request in the device request queue. This allows ide.c to - * easily service requests from the other device when we - * postpone our active request. In the pipelined operation - * mode, we use our internal pipeline structure to hold - * more data requests. - * - * The data buffer size is chosen based on the tape's - * recommendation. - */ - struct request *active_data_request; /* Pointer to the request which is waiting in the device request queue */ - int stage_size; /* Data buffer size (chosen based on the tape's recommendation */ - idetape_stage_t *merge_stage; - int merge_stage_size; - struct buffer_head *bh; - char *b_data; - int b_count; - - /* - * Pipeline parameters. - * - * To accomplish non-pipelined mode, we simply set the following - * variables to zero (or NULL, where appropriate). - */ - int nr_stages; /* Number of currently used stages */ - int nr_pending_stages; /* Number of pending stages */ - int max_stages, min_pipeline, max_pipeline; /* We will not allocate more than this number of stages */ - idetape_stage_t *first_stage; /* The first stage which will be removed from the pipeline */ - idetape_stage_t *active_stage; /* The currently active stage */ - idetape_stage_t *next_stage; /* Will be serviced after the currently active request */ - idetape_stage_t *last_stage; /* New requests will be added to the pipeline here */ - idetape_stage_t *cache_stage; /* Optional free stage which we can use */ - int pages_per_stage; - int excess_bh_size; /* Wasted space in each stage */ - - unsigned int flags; /* Status/Action flags */ - spinlock_t spinlock; /* protects the ide-tape queue */ - - /* - * Measures average tape speed - */ - unsigned long avg_time; - int avg_size; - int avg_speed; - - idetape_request_sense_result_t sense; /* last sense information */ - - char vendor_id[10]; - char product_id[18]; - char firmware_revision[6]; - int firmware_revision_num; - - int door_locked; /* the door is currently locked */ - - /* - * OnStream flags - */ - int onstream; /* the tape is an OnStream tape */ - int raw; /* OnStream raw access (32.5KB block size) */ - int cur_frames; /* current number of frames in internal buffer */ - int max_frames; /* max number of frames in internal buffer */ - int logical_blk_num; /* logical block number */ - __u16 wrt_pass_cntr; /* write pass counter */ - __u32 update_frame_cntr; /* update frame counter */ - struct semaphore *sem; - int onstream_write_error; /* write error recovery active */ - int header_ok; /* header frame verified ok */ - int linux_media; /* reading linux-specifc media */ - int linux_media_version; - char application_sig[5]; /* application signature */ - int filemark_cnt; - int first_mark_addr; - int last_mark_addr; - int eod_frame_addr; - unsigned long cmd_start_time; - unsigned long max_cmd_time; - - /* - * Optimize the number of "buffer filling" - * mode sense commands. - */ - unsigned long last_buffer_fill; /* last time in which we issued fill cmd */ - int req_buffer_fill; /* buffer fill command requested */ - int writes_since_buffer_fill; - int reads_since_buffer_fill; - - /* - * Limit the number of times a request can - * be postponed, to avoid an infinite postpone - * deadlock. - */ - int postpone_cnt; /* request postpone count limit */ - - /* - * Measures number of frames: - * - * 1. written/read to/from the driver pipeline (pipeline_head). - * 2. written/read to/from the tape buffers (buffer_head). - * 3. written/read by the tape to/from the media (tape_head). - */ - int pipeline_head; - int buffer_head; - int tape_head; - int last_tape_head; - - /* - * Speed control at the tape buffers input/output - */ - unsigned long insert_time; - int insert_size; - int insert_speed; - int max_insert_speed; - int measure_insert_time; - - /* - * Measure tape still time, in milliseconds - */ - unsigned long tape_still_time_begin; - int tape_still_time; - - /* - * Speed regulation negative feedback loop - */ - int speed_control; - int pipeline_head_speed, controlled_pipeline_head_speed, uncontrolled_pipeline_head_speed; - int controlled_last_pipeline_head, uncontrolled_last_pipeline_head; - unsigned long uncontrolled_pipeline_head_time, controlled_pipeline_head_time; - int controlled_previous_pipeline_head, uncontrolled_previous_pipeline_head; - unsigned long controlled_previous_head_time, uncontrolled_previous_head_time; - int restart_speed_control_req; - - /* - * Debug_level determines amount of debugging output; - * can be changed using /proc/ide/hdx/settings - * 0 : almost no debugging output - * 1 : 0+output errors only - * 2 : 1+output all sensekey/asc - * 3 : 2+follow all chrdev related procedures - * 4 : 3+follow all procedures - * 5 : 4+include pc_stack rq_stack info - * 6 : 5+USE_COUNT updates - */ - int debug_level; -} idetape_tape_t; - -/* - * Tape door status - */ -#define DOOR_UNLOCKED 0 -#define DOOR_LOCKED 1 -#define DOOR_EXPLICITLY_LOCKED 2 - -/* - * Tape flag bits values. - */ -#define IDETAPE_IGNORE_DSC 0 -#define IDETAPE_ADDRESS_VALID 1 /* 0 When the tape position is unknown */ -#define IDETAPE_BUSY 2 /* Device already opened */ -#define IDETAPE_PIPELINE_ERROR 3 /* Error detected in a pipeline stage */ -#define IDETAPE_DETECT_BS 4 /* Attempt to auto-detect the current user block size */ -#define IDETAPE_FILEMARK 5 /* Currently on a filemark */ -#define IDETAPE_DRQ_INTERRUPT 6 /* DRQ interrupt device */ -#define IDETAPE_READ_ERROR 7 -#define IDETAPE_PIPELINE_ACTIVE 8 /* pipeline active */ - -/* - * Supported ATAPI tape drives packet commands - */ -#define IDETAPE_TEST_UNIT_READY_CMD 0x00 -#define IDETAPE_REWIND_CMD 0x01 -#define IDETAPE_REQUEST_SENSE_CMD 0x03 -#define IDETAPE_READ_CMD 0x08 -#define IDETAPE_WRITE_CMD 0x0a -#define IDETAPE_WRITE_FILEMARK_CMD 0x10 -#define IDETAPE_SPACE_CMD 0x11 -#define IDETAPE_INQUIRY_CMD 0x12 -#define IDETAPE_ERASE_CMD 0x19 -#define IDETAPE_MODE_SENSE_CMD 0x1a -#define IDETAPE_MODE_SELECT_CMD 0x15 -#define IDETAPE_LOAD_UNLOAD_CMD 0x1b -#define IDETAPE_PREVENT_CMD 0x1e -#define IDETAPE_LOCATE_CMD 0x2b -#define IDETAPE_READ_POSITION_CMD 0x34 -#define IDETAPE_READ_BUFFER_CMD 0x3c -#define IDETAPE_SET_SPEED_CMD 0xbb - -/* - * Some defines for the READ BUFFER command - */ -#define IDETAPE_RETRIEVE_FAULTY_BLOCK 6 - -/* - * Some defines for the SPACE command - */ -#define IDETAPE_SPACE_OVER_FILEMARK 1 -#define IDETAPE_SPACE_TO_EOD 3 - -/* - * Some defines for the LOAD UNLOAD command - */ -#define IDETAPE_LU_LOAD_MASK 1 -#define IDETAPE_LU_RETENSION_MASK 2 -#define IDETAPE_LU_EOT_MASK 4 - -/* - * Special requests for our block device strategy routine. - * - * In order to service a character device command, we add special - * requests to the tail of our block device request queue and wait - * for their completion. - * - */ -#define IDETAPE_FIRST_RQ 90 - -/* - * IDETAPE_PC_RQ is used to queue a packet command in the request queue. - */ -#define IDETAPE_PC_RQ1 90 -#define IDETAPE_PC_RQ2 91 - -/* - * IDETAPE_READ_RQ and IDETAPE_WRITE_RQ are used by our - * character device interface to request read/write operations from - * our block device interface. - */ -#define IDETAPE_READ_RQ 92 -#define IDETAPE_WRITE_RQ 93 -#define IDETAPE_ABORTED_WRITE_RQ 94 -#define IDETAPE_ABORTED_READ_RQ 95 -#define IDETAPE_READ_BUFFER_RQ 96 - -#define IDETAPE_LAST_RQ 96 - -/* - * A macro which can be used to check if a we support a given - * request command. - */ -#define IDETAPE_RQ_CMD(cmd) ((cmd >= IDETAPE_FIRST_RQ) && (cmd <= IDETAPE_LAST_RQ)) - -/* - * Error codes which are returned in rq->errors to the higher part - * of the driver. - */ -#define IDETAPE_ERROR_GENERAL 101 -#define IDETAPE_ERROR_FILEMARK 102 -#define IDETAPE_ERROR_EOD 103 - -/* - * The ATAPI Status Register. - */ -typedef union { - unsigned all :8; - struct { - unsigned check :1; /* Error occurred */ - unsigned idx :1; /* Reserved */ - unsigned corr :1; /* Correctable error occurred */ - unsigned drq :1; /* Data is request by the device */ - unsigned dsc :1; /* Buffer availability / Media access command finished */ - unsigned reserved5 :1; /* Reserved */ - unsigned drdy :1; /* Ignored for ATAPI commands (ready to accept ATA command) */ - unsigned bsy :1; /* The device has access to the command block */ - } b; -} idetape_status_reg_t; - -/* - * The ATAPI error register. - */ -typedef union { - unsigned all :8; - struct { - unsigned ili :1; /* Illegal Length Indication */ - unsigned eom :1; /* End Of Media Detected */ - unsigned abrt :1; /* Aborted command - As defined by ATA */ - unsigned mcr :1; /* Media Change Requested - As defined by ATA */ - unsigned sense_key :4; /* Sense key of the last failed packet command */ - } b; -} idetape_error_reg_t; - -/* - * ATAPI Feature Register - */ -typedef union { - unsigned all :8; - struct { - unsigned dma :1; /* Using DMA of PIO */ - unsigned reserved321 :3; /* Reserved */ - unsigned reserved654 :3; /* Reserved (Tag Type) */ - unsigned reserved7 :1; /* Reserved */ - } b; -} idetape_feature_reg_t; - -/* - * ATAPI Byte Count Register. - */ -typedef union { - unsigned all :16; - struct { - unsigned low :8; /* LSB */ - unsigned high :8; /* MSB */ - } b; -} idetape_bcount_reg_t; - -/* - * ATAPI Interrupt Reason Register. - */ -typedef union { - unsigned all :8; - struct { - unsigned cod :1; /* Information transferred is command (1) or data (0) */ - unsigned io :1; /* The device requests us to read (1) or write (0) */ - unsigned reserved :6; /* Reserved */ - } b; -} idetape_ireason_reg_t; - -/* - * ATAPI Drive Select Register - */ -typedef union { - unsigned all :8; - struct { - unsigned sam_lun :4; /* Should be zero with ATAPI (not used) */ - unsigned drv :1; /* The responding drive will be drive 0 (0) or drive 1 (1) */ - unsigned one5 :1; /* Should be set to 1 */ - unsigned reserved6 :1; /* Reserved */ - unsigned one7 :1; /* Should be set to 1 */ - } b; -} idetape_drivesel_reg_t; - -/* - * ATAPI Device Control Register - */ -typedef union { - unsigned all :8; - struct { - unsigned zero0 :1; /* Should be set to zero */ - unsigned nien :1; /* Device interrupt is disabled (1) or enabled (0) */ - unsigned srst :1; /* ATA software reset. ATAPI devices should use the new ATAPI srst. */ - unsigned one3 :1; /* Should be set to 1 */ - unsigned reserved4567 :4; /* Reserved */ - } b; -} idetape_control_reg_t; - -/* - * idetape_chrdev_t provides the link between out character device - * interface and our block device interface and the corresponding - * ide_drive_t structure. - */ -typedef struct { - ide_drive_t *drive; -} idetape_chrdev_t; - -/* - * The following is used to format the general configuration word of - * the ATAPI IDENTIFY DEVICE command. - */ -struct idetape_id_gcw { - unsigned packet_size :2; /* Packet Size */ - unsigned reserved234 :3; /* Reserved */ - unsigned drq_type :2; /* Command packet DRQ type */ - unsigned removable :1; /* Removable media */ - unsigned device_type :5; /* Device type */ - unsigned reserved13 :1; /* Reserved */ - unsigned protocol :2; /* Protocol type */ -}; - -/* - * INQUIRY packet command - Data Format (From Table 6-8 of QIC-157C) - */ -typedef struct { - unsigned device_type :5; /* Peripheral Device Type */ - unsigned reserved0_765 :3; /* Peripheral Qualifier - Reserved */ - unsigned reserved1_6t0 :7; /* Reserved */ - unsigned rmb :1; /* Removable Medium Bit */ - unsigned ansi_version :3; /* ANSI Version */ - unsigned ecma_version :3; /* ECMA Version */ - unsigned iso_version :2; /* ISO Version */ - unsigned response_format :4; /* Response Data Format */ - unsigned reserved3_45 :2; /* Reserved */ - unsigned reserved3_6 :1; /* TrmIOP - Reserved */ - unsigned reserved3_7 :1; /* AENC - Reserved */ - __u8 additional_length; /* Additional Length (total_length-4) */ - __u8 rsv5, rsv6, rsv7; /* Reserved */ - __u8 vendor_id[8]; /* Vendor Identification */ - __u8 product_id[16]; /* Product Identification */ - __u8 revision_level[4]; /* Revision Level */ - __u8 vendor_specific[20]; /* Vendor Specific - Optional */ - __u8 reserved56t95[40]; /* Reserved - Optional */ - /* Additional information may be returned */ -} idetape_inquiry_result_t; - -/* - * READ POSITION packet command - Data Format (From Table 6-57) - */ -typedef struct { - unsigned reserved0_10 :2; /* Reserved */ - unsigned bpu :1; /* Block Position Unknown */ - unsigned reserved0_543 :3; /* Reserved */ - unsigned eop :1; /* End Of Partition */ - unsigned bop :1; /* Beginning Of Partition */ - u8 partition; /* Partition Number */ - u8 reserved2, reserved3; /* Reserved */ - u32 first_block; /* First Block Location */ - u32 last_block; /* Last Block Location (Optional) */ - u8 reserved12; /* Reserved */ - u8 blocks_in_buffer[3]; /* Blocks In Buffer - (Optional) */ - u32 bytes_in_buffer; /* Bytes In Buffer (Optional) */ -} idetape_read_position_result_t; - -/* - * Follows structures which are related to the SELECT SENSE / MODE SENSE - * packet commands. Those packet commands are still not supported - * by ide-tape. - */ -#define IDETAPE_CAPABILITIES_PAGE 0x2a -#define IDETAPE_BLOCK_SIZE_PAGE 0x30 - -/* - * Mode Parameter Header for the MODE SENSE packet command - */ -typedef struct { - __u8 mode_data_length; /* Length of the following data transfer */ - __u8 medium_type; /* Medium Type */ - __u8 dsp; /* Device Specific Parameter */ - __u8 bdl; /* Block Descriptor Length */ -#if 0 - /* data transfer page */ - __u8 page_code :6; - __u8 reserved0_6 :1; - __u8 ps :1; /* parameters saveable */ - __u8 page_length; /* page Length == 0x02 */ - __u8 reserved2; - __u8 read32k :1; /* 32k blk size (data only) */ - __u8 read32k5 :1; /* 32.5k blk size (data&AUX) */ - __u8 reserved3_23 :2; - __u8 write32k :1; /* 32k blk size (data only) */ - __u8 write32k5 :1; /* 32.5k blk size (data&AUX) */ - __u8 reserved3_6 :1; - __u8 streaming :1; /* streaming mode enable */ -#endif -} idetape_mode_parameter_header_t; - -/* - * Mode Parameter Block Descriptor the MODE SENSE packet command - * - * Support for block descriptors is optional. - */ -typedef struct { - __u8 density_code; /* Medium density code */ - __u8 blocks[3]; /* Number of blocks */ - __u8 reserved4; /* Reserved */ - __u8 length[3]; /* Block Length */ -} idetape_parameter_block_descriptor_t; - -/* - * The Data Compression Page, as returned by the MODE SENSE packet command. - */ -typedef struct { - unsigned page_code :6; /* Page Code - Should be 0xf */ - unsigned reserved0 :1; /* Reserved */ - unsigned ps :1; - __u8 page_length; /* Page Length - Should be 14 */ - unsigned reserved2 :6; /* Reserved */ - unsigned dcc :1; /* Data Compression Capable */ - unsigned dce :1; /* Data Compression Enable */ - unsigned reserved3 :5; /* Reserved */ - unsigned red :2; /* Report Exception on Decompression */ - unsigned dde :1; /* Data Decompression Enable */ - __u32 ca; /* Compression Algorithm */ - __u32 da; /* Decompression Algorithm */ - __u8 reserved[4]; /* Reserved */ -} idetape_data_compression_page_t; - -/* - * The Medium Partition Page, as returned by the MODE SENSE packet command. - */ -typedef struct { - unsigned page_code :6; /* Page Code - Should be 0x11 */ - unsigned reserved1_6 :1; /* Reserved */ - unsigned ps :1; - __u8 page_length; /* Page Length - Should be 6 */ - __u8 map; /* Maximum Additional Partitions - Should be 0 */ - __u8 apd; /* Additional Partitions Defined - Should be 0 */ - unsigned reserved4_012 :3; /* Reserved */ - unsigned psum :2; /* Should be 0 */ - unsigned idp :1; /* Should be 0 */ - unsigned sdp :1; /* Should be 0 */ - unsigned fdp :1; /* Fixed Data Partitions */ - __u8 mfr; /* Medium Format Recognition */ - __u8 reserved[2]; /* Reserved */ -} idetape_medium_partition_page_t; - -/* - * Run time configurable parameters. - */ -typedef struct { - int dsc_rw_frequency; - int dsc_media_access_frequency; - int nr_stages; -} idetape_config_t; - -/* - * The variables below are used for the character device interface. - * Additional state variables are defined in our ide_drive_t structure. - */ -static idetape_chrdev_t idetape_chrdevs[MAX_HWIFS * MAX_DRIVES]; -static int idetape_chrdev_present = 0; - -#if IDETAPE_DEBUG_LOG_VERBOSE - -/* - * DO NOT REMOVE, BUILDING A VERBOSE DEBUG SCHEME FOR ATAPI - */ - -char *idetape_sense_key_verbose (byte idetape_sense_key) -{ - switch (idetape_sense_key) { - default: { - char buf[22]; - sprintf(buf, "IDETAPE_SENSE (0x%02x)", idetape_sense_key); - return(buf); - } - - } -} - -char *idetape_command_key_verbose (byte idetape_command_key) -{ - switch (idetape_command_key) { - case IDETAPE_TEST_UNIT_READY_CMD: return("TEST_UNIT_READY_CMD"); - case IDETAPE_REWIND_CMD: return("REWIND_CMD"); - case IDETAPE_REQUEST_SENSE_CMD: return("REQUEST_SENSE_CMD"); - case IDETAPE_READ_CMD: return("READ_CMD"); - case IDETAPE_WRITE_CMD: return("WRITE_CMD"); - case IDETAPE_WRITE_FILEMARK_CMD: return("WRITE_FILEMARK_CMD"); - case IDETAPE_SPACE_CMD: return("SPACE_CMD"); - case IDETAPE_INQUIRY_CMD: return("INQUIRY_CMD"); - case IDETAPE_ERASE_CMD: return("ERASE_CMD") - case IDETAPE_MODE_SENSE_CMD: return("MODE_SENSE_CMD"); - case IDETAPE_MODE_SELECT_CMD: return("MODE_SELECT_CMD"); - case IDETAPE_LOAD_UNLOAD_CMD: return("LOAD_UNLOAD_CMD"); - case IDETAPE_PREVENT_CMD: return("PREVENT_CMD"); - case IDETAPE_LOCATE_CMD: return("LOCATE_CMD"); - case IDETAPE_READ_POSITION_CMD: return("READ_POSITION_CMD"); - case IDETAPE_READ_BUFFER_CMD: return("READ_BUFFER_CMD"); - case IDETAPE_SET_SPEED_CMD: return("SET_SPEED_CMD"); - default: { - char buf[20]; - sprintf(buf, "CMD (0x%02x)", idetape_command_key); - return(buf); - } - } -} -#endif /* IDETAPE_DEBUG_LOG_VERBOSE */ - -/* - * Too bad. The drive wants to send us data which we are not ready to accept. - * Just throw it away. - */ -static void idetape_discard_data (ide_drive_t *drive, unsigned int bcount) -{ - while (bcount--) - IN_BYTE (IDE_DATA_REG); -} - -static void idetape_input_buffers (ide_drive_t *drive, idetape_pc_t *pc, unsigned int bcount) -{ - struct buffer_head *bh = pc->bh; - int count; - - while (bcount) { -#if IDETAPE_DEBUG_BUGS - if (bh == NULL) { - printk (KERN_ERR "ide-tape: bh == NULL in idetape_input_buffers\n"); - idetape_discard_data (drive, bcount); - return; - } -#endif /* IDETAPE_DEBUG_BUGS */ - count = IDE_MIN (bh->b_size - atomic_read(&bh->b_count), bcount); - atapi_input_bytes (drive, bh->b_data + atomic_read(&bh->b_count), count); - bcount -= count; atomic_add(count, &bh->b_count); - if (atomic_read(&bh->b_count) == bh->b_size) { - bh = bh->b_reqnext; - if (bh) - atomic_set(&bh->b_count, 0); - } - } - pc->bh = bh; -} - -static void idetape_output_buffers (ide_drive_t *drive, idetape_pc_t *pc, unsigned int bcount) -{ - struct buffer_head *bh = pc->bh; - int count; - - while (bcount) { -#if IDETAPE_DEBUG_BUGS - if (bh == NULL) { - printk (KERN_ERR "ide-tape: bh == NULL in idetape_output_buffers\n"); - return; - } -#endif /* IDETAPE_DEBUG_BUGS */ - count = IDE_MIN (pc->b_count, bcount); - atapi_output_bytes (drive, pc->b_data, count); - bcount -= count; pc->b_data += count; pc->b_count -= count; - if (!pc->b_count) { - pc->bh = bh = bh->b_reqnext; - if (bh) { - pc->b_data = bh->b_data; - pc->b_count = atomic_read(&bh->b_count); - } - } - } -} - -#ifdef CONFIG_BLK_DEV_IDEDMA -static void idetape_update_buffers (idetape_pc_t *pc) -{ - struct buffer_head *bh = pc->bh; - int count, bcount = pc->actually_transferred; - - if (test_bit (PC_WRITING, &pc->flags)) - return; - while (bcount) { -#if IDETAPE_DEBUG_BUGS - if (bh == NULL) { - printk (KERN_ERR "ide-tape: bh == NULL in idetape_update_buffers\n"); - return; - } -#endif /* IDETAPE_DEBUG_BUGS */ - count = IDE_MIN (bh->b_size, bcount); - atomic_set(&bh->b_count, count); - if (atomic_read(&bh->b_count) == bh->b_size) - bh = bh->b_reqnext; - bcount -= count; - } - pc->bh = bh; -} -#endif /* CONFIG_BLK_DEV_IDEDMA */ - -/* - * idetape_next_pc_storage returns a pointer to a place in which we can - * safely store a packet command, even though we intend to leave the - * driver. A storage space for a maximum of IDETAPE_PC_STACK packet - * commands is allocated at initialization time. - */ -static idetape_pc_t *idetape_next_pc_storage (ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 5) - printk (KERN_INFO "ide-tape: pc_stack_index=%d\n",tape->pc_stack_index); -#endif /* IDETAPE_DEBUG_LOG */ - if (tape->pc_stack_index==IDETAPE_PC_STACK) - tape->pc_stack_index=0; - return (&tape->pc_stack[tape->pc_stack_index++]); -} - -/* - * idetape_next_rq_storage is used along with idetape_next_pc_storage. - * Since we queue packet commands in the request queue, we need to - * allocate a request, along with the allocation of a packet command. - */ - -/************************************************************** - * * - * This should get fixed to use kmalloc(GFP_ATOMIC, ..) * - * followed later on by kfree(). -ml * - * * - **************************************************************/ - -static struct request *idetape_next_rq_storage (ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 5) - printk (KERN_INFO "ide-tape: rq_stack_index=%d\n",tape->rq_stack_index); -#endif /* IDETAPE_DEBUG_LOG */ - if (tape->rq_stack_index==IDETAPE_PC_STACK) - tape->rq_stack_index=0; - return (&tape->rq_stack[tape->rq_stack_index++]); -} - -/* - * idetape_init_pc initializes a packet command. - */ -static void idetape_init_pc (idetape_pc_t *pc) -{ - memset (pc->c, 0, 12); - pc->retries = 0; - pc->flags = 0; - pc->request_transfer = 0; - pc->buffer = pc->pc_buffer; - pc->buffer_size = IDETAPE_PC_BUFFER_SIZE; - pc->bh = NULL; - pc->b_data = NULL; -} - -/* - * idetape_analyze_error is called on each failed packet command retry - * to analyze the request sense. We currently do not utilize this - * information. - */ -static void idetape_analyze_error (ide_drive_t *drive,idetape_request_sense_result_t *result) -{ - idetape_tape_t *tape = drive->driver_data; - idetape_pc_t *pc = tape->failed_pc; - - tape->sense = *result; - tape->sense_key = result->sense_key; tape->asc = result->asc; tape->ascq = result->ascq; -#if IDETAPE_DEBUG_LOG - /* - * Without debugging, we only log an error if we decided to - * give up retrying. - */ - if (tape->debug_level >= 1) - printk (KERN_INFO "ide-tape: pc = %x, sense key = %x, asc = %x, ascq = %x\n",pc->c[0],result->sense_key,result->asc,result->ascq); -#if IDETAPE_DEBUG_LOG_VERBOSE - if (tape->debug_level >= 1) - printk (KERN_INFO "ide-tape: pc = %s, sense key = %x, asc = %x, ascq = %x\n", - idetape_command_key_verbose((byte) pc->c[0]), - result->sense_key, - result->asc, - result->ascq); -#endif /* IDETAPE_DEBUG_LOG_VERBOSE */ -#endif /* IDETAPE_DEBUG_LOG */ - - if (tape->onstream && result->sense_key == 2 && result->asc == 0x53 && result->ascq == 2) { - clear_bit(PC_DMA_ERROR, &pc->flags); - ide_stall_queue(drive, HZ / 2); - return; - } -#ifdef CONFIG_BLK_DEV_IDEDMA - - /* - * Correct pc->actually_transferred by asking the tape. - */ - if (test_bit (PC_DMA_ERROR, &pc->flags)) { - pc->actually_transferred = pc->request_transfer - tape->tape_block_size * ntohl (get_unaligned (&result->information)); - idetape_update_buffers (pc); - } -#endif /* CONFIG_BLK_DEV_IDEDMA */ - if (pc->c[0] == IDETAPE_READ_CMD && result->filemark) { - pc->error = IDETAPE_ERROR_FILEMARK; - set_bit (PC_ABORT, &pc->flags); - } - if (pc->c[0] == IDETAPE_WRITE_CMD) { - if (result->eom || (result->sense_key == 0xd && result->asc == 0x0 && result->ascq == 0x2)) { - pc->error = IDETAPE_ERROR_EOD; - set_bit (PC_ABORT, &pc->flags); - } - } - if (pc->c[0] == IDETAPE_READ_CMD || pc->c[0] == IDETAPE_WRITE_CMD) { - if (result->sense_key == 8) { - pc->error = IDETAPE_ERROR_EOD; - set_bit (PC_ABORT, &pc->flags); - } - if (!test_bit (PC_ABORT, &pc->flags) && (tape->onstream || pc->actually_transferred)) - pc->retries = IDETAPE_MAX_PC_RETRIES + 1; - } -} - -static void idetape_abort_pipeline (ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - idetape_stage_t *stage = tape->next_stage; - -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 4) - printk(KERN_INFO "ide-tape: %s: idetape_abort_pipeline called\n", tape->name); -#endif - while (stage) { - if (stage->rq.cmd == IDETAPE_WRITE_RQ) - stage->rq.cmd = IDETAPE_ABORTED_WRITE_RQ; - else if (stage->rq.cmd == IDETAPE_READ_RQ) - stage->rq.cmd = IDETAPE_ABORTED_READ_RQ; - stage = stage->next; - } -} - -/* - * idetape_active_next_stage will declare the next stage as "active". - */ -static void idetape_active_next_stage (ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - idetape_stage_t *stage=tape->next_stage; - struct request *rq = &stage->rq; - -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 4) - printk (KERN_INFO "ide-tape: Reached idetape_active_next_stage\n"); -#endif /* IDETAPE_DEBUG_LOG */ -#if IDETAPE_DEBUG_BUGS - if (stage == NULL) { - printk (KERN_ERR "ide-tape: bug: Trying to activate a non existing stage\n"); - return; - } -#endif /* IDETAPE_DEBUG_BUGS */ - - rq->buffer = NULL; - rq->bh = stage->bh; - tape->active_data_request=rq; - tape->active_stage=stage; - tape->next_stage=stage->next; -} - -/* - * idetape_increase_max_pipeline_stages is a part of the feedback - * loop which tries to find the optimum number of stages. In the - * feedback loop, we are starting from a minimum maximum number of - * stages, and if we sense that the pipeline is empty, we try to - * increase it, until we reach the user compile time memory limit. - */ -static void idetape_increase_max_pipeline_stages (ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - int increase = (tape->max_pipeline - tape->min_pipeline) / 10; - -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 4) - printk (KERN_INFO "ide-tape: Reached idetape_increase_max_pipeline_stages\n"); -#endif /* IDETAPE_DEBUG_LOG */ - - tape->max_stages += increase; - tape->max_stages = IDE_MAX(tape->max_stages, tape->min_pipeline); - tape->max_stages = IDE_MIN(tape->max_stages, tape->max_pipeline); -} - -/* - * idetape_kfree_stage calls kfree to completely free a stage, along with - * its related buffers. - */ -static void __idetape_kfree_stage (idetape_stage_t *stage) -{ - struct buffer_head *prev_bh, *bh = stage->bh; - int size; - - while (bh != NULL) { - if (bh->b_data != NULL) { - size = (int) bh->b_size; - while (size > 0) { - free_page ((unsigned long) bh->b_data); - size -= PAGE_SIZE; - bh->b_data += PAGE_SIZE; - } - } - prev_bh = bh; - bh = bh->b_reqnext; - kfree (prev_bh); - } - kfree (stage); -} - -static void idetape_kfree_stage (idetape_tape_t *tape, idetape_stage_t *stage) -{ - __idetape_kfree_stage (stage); -} - -/* - * idetape_remove_stage_head removes tape->first_stage from the pipeline. - * The caller should avoid race conditions. - */ -static void idetape_remove_stage_head (ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - idetape_stage_t *stage; - -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 4) - printk (KERN_INFO "ide-tape: Reached idetape_remove_stage_head\n"); -#endif /* IDETAPE_DEBUG_LOG */ -#if IDETAPE_DEBUG_BUGS - if (tape->first_stage == NULL) { - printk (KERN_ERR "ide-tape: bug: tape->first_stage is NULL\n"); - return; - } - if (tape->active_stage == tape->first_stage) { - printk (KERN_ERR "ide-tape: bug: Trying to free our active pipeline stage\n"); - return; - } -#endif /* IDETAPE_DEBUG_BUGS */ - stage=tape->first_stage; - tape->first_stage=stage->next; - idetape_kfree_stage (tape, stage); - tape->nr_stages--; - if (tape->first_stage == NULL) { - tape->last_stage=NULL; -#if IDETAPE_DEBUG_BUGS - if (tape->next_stage != NULL) - printk (KERN_ERR "ide-tape: bug: tape->next_stage != NULL\n"); - if (tape->nr_stages) - printk (KERN_ERR "ide-tape: bug: nr_stages should be 0 now\n"); -#endif /* IDETAPE_DEBUG_BUGS */ - } -} - -/* - * idetape_end_request is used to finish servicing a request, and to - * insert a pending pipeline request into the main device queue. - */ -static void idetape_end_request (byte uptodate, ide_hwgroup_t *hwgroup) -{ - ide_drive_t *drive = hwgroup->drive; - struct request *rq = hwgroup->rq; - idetape_tape_t *tape = drive->driver_data; - unsigned long flags; - int error; - int remove_stage = 0; -#if ONSTREAM_DEBUG - idetape_stage_t *stage; - os_aux_t *aux; - unsigned char *p; -#endif - -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 4) - printk (KERN_INFO "ide-tape: Reached idetape_end_request\n"); -#endif /* IDETAPE_DEBUG_LOG */ - - switch (uptodate) { - case 0: error = IDETAPE_ERROR_GENERAL; break; - case 1: error = 0; break; - default: error = uptodate; - } - rq->errors = error; - if (error) - tape->failed_pc = NULL; - - spin_lock_irqsave(&tape->spinlock, flags); - if (tape->active_data_request == rq) { /* The request was a pipelined data transfer request */ - tape->active_stage = NULL; - tape->active_data_request = NULL; - tape->nr_pending_stages--; - if (rq->cmd == IDETAPE_WRITE_RQ) { -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) { - if (tape->onstream) { - stage = tape->first_stage; - aux = stage->aux; - p = stage->bh->b_data; - if (ntohl(aux->logical_blk_num) < 11300 && ntohl(aux->logical_blk_num) > 11100) - printk(KERN_INFO "ide-tape: finished writing logical blk %u (data %x %x %x %x)\n", ntohl(aux->logical_blk_num), *p++, *p++, *p++, *p++); - } - } -#endif - if (tape->onstream && !tape->raw) { - if (tape->first_frame_position == 0xba4) { -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk("ide-tape: %s: skipping over config parition..\n", tape->name); -#endif - tape->onstream_write_error = 2; - if (tape->sem) - up(tape->sem); - } - } - remove_stage = 1; - if (error) { - set_bit (IDETAPE_PIPELINE_ERROR, &tape->flags); - if (error == IDETAPE_ERROR_EOD) - idetape_abort_pipeline (drive); - if (tape->onstream && !tape->raw && error == IDETAPE_ERROR_GENERAL && tape->sense.sense_key == 3) { - clear_bit (IDETAPE_PIPELINE_ERROR, &tape->flags); - printk(KERN_ERR "ide-tape: %s: write error, enabling error recovery\n", tape->name); - tape->onstream_write_error = 1; - remove_stage = 0; - tape->nr_pending_stages++; - tape->next_stage = tape->first_stage; - rq->current_nr_sectors = rq->nr_sectors; - if (tape->sem) - up(tape->sem); - } - } - } else if (rq->cmd == IDETAPE_READ_RQ) { - if (error == IDETAPE_ERROR_EOD) { - set_bit (IDETAPE_PIPELINE_ERROR, &tape->flags); - idetape_abort_pipeline(drive); - } - } - if (tape->next_stage != NULL && !tape->onstream_write_error) { - idetape_active_next_stage (drive); - - /* - * Insert the next request into the request queue. - */ - (void) ide_do_drive_cmd (drive, tape->active_data_request, ide_end); - } else if (!error) { - if (!tape->onstream) - idetape_increase_max_pipeline_stages (drive); - } - } - ide_end_drive_cmd (drive, 0, 0); - if (remove_stage) - idetape_remove_stage_head (drive); - if (tape->active_data_request == NULL) - clear_bit(IDETAPE_PIPELINE_ACTIVE, &tape->flags); - spin_unlock_irqrestore(&tape->spinlock, flags); -} - -static ide_startstop_t idetape_request_sense_callback (ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 4) - printk (KERN_INFO "ide-tape: Reached idetape_request_sense_callback\n"); -#endif /* IDETAPE_DEBUG_LOG */ - if (!tape->pc->error) { - idetape_analyze_error (drive,(idetape_request_sense_result_t *) tape->pc->buffer); - idetape_end_request (1,HWGROUP (drive)); - } else { - printk (KERN_ERR "ide-tape: Error in REQUEST SENSE itself - Aborting request!\n"); - idetape_end_request (0,HWGROUP (drive)); - } - return ide_stopped; -} - -static void idetape_create_request_sense_cmd (idetape_pc_t *pc) -{ - idetape_init_pc (pc); - pc->c[0] = IDETAPE_REQUEST_SENSE_CMD; - pc->c[4] = 20; - pc->request_transfer = 18; - pc->callback = &idetape_request_sense_callback; -} - -/* - * idetape_queue_pc_head generates a new packet command request in front - * of the request queue, before the current request, so that it will be - * processed immediately, on the next pass through the driver. - * - * idetape_queue_pc_head is called from the request handling part of - * the driver (the "bottom" part). Safe storage for the request should - * be allocated with idetape_next_pc_storage and idetape_next_rq_storage - * before calling idetape_queue_pc_head. - * - * Memory for those requests is pre-allocated at initialization time, and - * is limited to IDETAPE_PC_STACK requests. We assume that we have enough - * space for the maximum possible number of inter-dependent packet commands. - * - * The higher level of the driver - The ioctl handler and the character - * device handling functions should queue request to the lower level part - * and wait for their completion using idetape_queue_pc_tail or - * idetape_queue_rw_tail. - */ -static void idetape_queue_pc_head (ide_drive_t *drive,idetape_pc_t *pc,struct request *rq) -{ - ide_init_drive_cmd (rq); - rq->buffer = (char *) pc; - rq->cmd = IDETAPE_PC_RQ1; - (void) ide_do_drive_cmd (drive, rq, ide_preempt); -} - -/* - * idetape_retry_pc is called when an error was detected during the - * last packet command. We queue a request sense packet command in - * the head of the request list. - */ -static ide_startstop_t idetape_retry_pc (ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - idetape_pc_t *pc; - struct request *rq; - idetape_error_reg_t error; - - error.all = IN_BYTE (IDE_ERROR_REG); - pc = idetape_next_pc_storage (drive); - rq = idetape_next_rq_storage (drive); - idetape_create_request_sense_cmd (pc); - set_bit (IDETAPE_IGNORE_DSC, &tape->flags); - idetape_queue_pc_head (drive, pc, rq); - return ide_stopped; -} - -/* - * idetape_postpone_request postpones the current request so that - * ide.c will be able to service requests from another device on - * the same hwgroup while we are polling for DSC. - */ -static void idetape_postpone_request (ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 4) - printk(KERN_INFO "ide-tape: idetape_postpone_request\n"); -#endif - tape->postponed_rq = HWGROUP(drive)->rq; - ide_stall_queue(drive, tape->dsc_polling_frequency); -} - -/* - * idetape_pc_intr is the usual interrupt handler which will be called - * during a packet command. We will transfer some of the data (as - * requested by the drive) and will re-point interrupt handler to us. - * When data transfer is finished, we will act according to the - * algorithm described before idetape_issue_packet_command. - * - */ -static ide_startstop_t idetape_pc_intr (ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - idetape_status_reg_t status; - idetape_bcount_reg_t bcount; - idetape_ireason_reg_t ireason; - idetape_pc_t *pc=tape->pc; - - unsigned int temp; - unsigned long cmd_time; -#if SIMULATE_ERRORS - static int error_sim_count = 0; -#endif - -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 4) - printk (KERN_INFO "ide-tape: Reached idetape_pc_intr interrupt handler\n"); -#endif /* IDETAPE_DEBUG_LOG */ - - status.all = GET_STAT(); /* Clear the interrupt */ - -#ifdef CONFIG_BLK_DEV_IDEDMA - if (test_bit (PC_DMA_IN_PROGRESS, &pc->flags)) { - if (HWIF(drive)->dmaproc(ide_dma_end, drive)) { - /* - * A DMA error is sometimes expected. For example, - * if the tape is crossing a filemark during a - * READ command, it will issue an irq and position - * itself before the filemark, so that only a partial - * data transfer will occur (which causes the DMA - * error). In that case, we will later ask the tape - * how much bytes of the original request were - * actually transferred (we can't receive that - * information from the DMA engine on most chipsets). - */ - set_bit (PC_DMA_ERROR, &pc->flags); - } else if (!status.b.check) { - pc->actually_transferred=pc->request_transfer; - idetape_update_buffers (pc); - } -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 4) - printk (KERN_INFO "ide-tape: DMA finished\n"); -#endif /* IDETAPE_DEBUG_LOG */ - } -#endif /* CONFIG_BLK_DEV_IDEDMA */ - - if (!status.b.drq) { /* No more interrupts */ - cmd_time = (jiffies - tape->cmd_start_time) * 1000 / HZ; - tape->max_cmd_time = IDE_MAX(cmd_time, tape->max_cmd_time); -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 2) - printk (KERN_INFO "ide-tape: Packet command completed, %d bytes transferred\n", pc->actually_transferred); -#endif /* IDETAPE_DEBUG_LOG */ - clear_bit (PC_DMA_IN_PROGRESS, &pc->flags); - - ide__sti(); /* local CPU only */ - -#if SIMULATE_ERRORS - if ((pc->c[0] == IDETAPE_WRITE_CMD || pc->c[0] == IDETAPE_READ_CMD) && (++error_sim_count % 100) == 0) { - printk(KERN_INFO "ide-tape: %s: simulating error\n", tape->name); - status.b.check = 1; - } -#endif - if (status.b.check && pc->c[0] == IDETAPE_REQUEST_SENSE_CMD) - status.b.check = 0; - if (status.b.check || test_bit (PC_DMA_ERROR, &pc->flags)) { /* Error detected */ -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 1) - printk (KERN_INFO "ide-tape: %s: I/O error, ",tape->name); -#endif /* IDETAPE_DEBUG_LOG */ - if (pc->c[0] == IDETAPE_REQUEST_SENSE_CMD) { - printk (KERN_ERR "ide-tape: I/O error in request sense command\n"); - return ide_do_reset (drive); - } -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 1) - printk(KERN_INFO "ide-tape: [cmd %x]: check condition\n", pc->c[0]); -#endif - return idetape_retry_pc (drive); /* Retry operation */ - } - pc->error = 0; - if (!tape->onstream && test_bit (PC_WAIT_FOR_DSC, &pc->flags) && !status.b.dsc) { /* Media access command */ - tape->dsc_polling_start = jiffies; - tape->dsc_polling_frequency = IDETAPE_DSC_MA_FAST; - tape->dsc_timeout = jiffies + IDETAPE_DSC_MA_TIMEOUT; - idetape_postpone_request (drive); /* Allow ide.c to handle other requests */ - return ide_stopped; - } - if (tape->failed_pc == pc) - tape->failed_pc=NULL; - return pc->callback(drive); /* Command finished - Call the callback function */ - } -#ifdef CONFIG_BLK_DEV_IDEDMA - if (test_and_clear_bit (PC_DMA_IN_PROGRESS, &pc->flags)) { - printk (KERN_ERR "ide-tape: The tape wants to issue more interrupts in DMA mode\n"); - printk (KERN_ERR "ide-tape: DMA disabled, reverting to PIO\n"); - (void) HWIF(drive)->dmaproc(ide_dma_off, drive); - return ide_do_reset (drive); - } -#endif /* CONFIG_BLK_DEV_IDEDMA */ - bcount.b.high=IN_BYTE (IDE_BCOUNTH_REG); /* Get the number of bytes to transfer */ - bcount.b.low=IN_BYTE (IDE_BCOUNTL_REG); /* on this interrupt */ - ireason.all=IN_BYTE (IDE_IREASON_REG); - - if (ireason.b.cod) { - printk (KERN_ERR "ide-tape: CoD != 0 in idetape_pc_intr\n"); - return ide_do_reset (drive); - } - if (ireason.b.io == test_bit (PC_WRITING, &pc->flags)) { /* Hopefully, we will never get here */ - printk (KERN_ERR "ide-tape: We wanted to %s, ", ireason.b.io ? "Write":"Read"); - printk (KERN_ERR "ide-tape: but the tape wants us to %s !\n",ireason.b.io ? "Read":"Write"); - return ide_do_reset (drive); - } - if (!test_bit (PC_WRITING, &pc->flags)) { /* Reading - Check that we have enough space */ - temp = pc->actually_transferred + bcount.all; - if ( temp > pc->request_transfer) { - if (temp > pc->buffer_size) { - printk (KERN_ERR "ide-tape: The tape wants to send us more data than expected - discarding data\n"); - idetape_discard_data (drive,bcount.all); - ide_set_handler (drive,&idetape_pc_intr,IDETAPE_WAIT_CMD,NULL); - return ide_started; - } -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 2) - printk (KERN_NOTICE "ide-tape: The tape wants to send us more data than expected - allowing transfer\n"); -#endif /* IDETAPE_DEBUG_LOG */ - } - } - if (test_bit (PC_WRITING, &pc->flags)) { - if (pc->bh != NULL) - idetape_output_buffers (drive, pc, bcount.all); - else - atapi_output_bytes (drive,pc->current_position,bcount.all); /* Write the current buffer */ - } else { - if (pc->bh != NULL) - idetape_input_buffers (drive, pc, bcount.all); - else - atapi_input_bytes (drive,pc->current_position,bcount.all); /* Read the current buffer */ - } - pc->actually_transferred+=bcount.all; /* Update the current position */ - pc->current_position+=bcount.all; -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: [cmd %x] transferred %d bytes on that interrupt\n", pc->c[0], bcount.all); -#endif - ide_set_handler (drive,&idetape_pc_intr,IDETAPE_WAIT_CMD,NULL); /* And set the interrupt handler again */ - return ide_started; -} - -/* - * Packet Command Interface - * - * The current Packet Command is available in tape->pc, and will not - * change until we finish handling it. Each packet command is associated - * with a callback function that will be called when the command is - * finished. - * - * The handling will be done in three stages: - * - * 1. idetape_issue_packet_command will send the packet command to the - * drive, and will set the interrupt handler to idetape_pc_intr. - * - * 2. On each interrupt, idetape_pc_intr will be called. This step - * will be repeated until the device signals us that no more - * interrupts will be issued. - * - * 3. ATAPI Tape media access commands have immediate status with a - * delayed process. In case of a successful initiation of a - * media access packet command, the DSC bit will be set when the - * actual execution of the command is finished. - * Since the tape drive will not issue an interrupt, we have to - * poll for this event. In this case, we define the request as - * "low priority request" by setting rq_status to - * IDETAPE_RQ_POSTPONED, set a timer to poll for DSC and exit - * the driver. - * - * ide.c will then give higher priority to requests which - * originate from the other device, until will change rq_status - * to RQ_ACTIVE. - * - * 4. When the packet command is finished, it will be checked for errors. - * - * 5. In case an error was found, we queue a request sense packet command - * in front of the request queue and retry the operation up to - * IDETAPE_MAX_PC_RETRIES times. - * - * 6. In case no error was found, or we decided to give up and not - * to retry again, the callback function will be called and then - * we will handle the next request. - * - */ -static ide_startstop_t idetape_transfer_pc(ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - idetape_pc_t *pc = tape->pc; - idetape_ireason_reg_t ireason; - int retries = 100; - ide_startstop_t startstop; - - if (ide_wait_stat (&startstop,drive,DRQ_STAT,BUSY_STAT,WAIT_READY)) { - printk (KERN_ERR "ide-tape: Strange, packet command initiated yet DRQ isn't asserted\n"); - return startstop; - } - ireason.all=IN_BYTE (IDE_IREASON_REG); - while (retries-- && (!ireason.b.cod || ireason.b.io)) { - printk(KERN_ERR "ide-tape: (IO,CoD != (0,1) while issuing a packet command, retrying\n"); - udelay(100); - ireason.all = IN_BYTE(IDE_IREASON_REG); - if (retries == 0) { - printk(KERN_ERR "ide-tape: (IO,CoD != (0,1) while issuing a packet command, ignoring\n"); - ireason.b.cod = 1; - ireason.b.io = 0; - } - } - if (!ireason.b.cod || ireason.b.io) { - printk (KERN_ERR "ide-tape: (IO,CoD) != (0,1) while issuing a packet command\n"); - return ide_do_reset (drive); - } - tape->cmd_start_time = jiffies; - ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL); /* Set the interrupt routine */ - atapi_output_bytes (drive,pc->c,12); /* Send the actual packet */ - return ide_started; -} - -static ide_startstop_t idetape_issue_packet_command (ide_drive_t *drive, idetape_pc_t *pc) -{ - idetape_tape_t *tape = drive->driver_data; - idetape_bcount_reg_t bcount; - int dma_ok=0; - -#if IDETAPE_DEBUG_BUGS - if (tape->pc->c[0] == IDETAPE_REQUEST_SENSE_CMD && pc->c[0] == IDETAPE_REQUEST_SENSE_CMD) { - printk (KERN_ERR "ide-tape: possible ide-tape.c bug - Two request sense in serial were issued\n"); - } -#endif /* IDETAPE_DEBUG_BUGS */ - - if (tape->failed_pc == NULL && pc->c[0] != IDETAPE_REQUEST_SENSE_CMD) - tape->failed_pc=pc; - tape->pc=pc; /* Set the current packet command */ - - if (pc->retries > IDETAPE_MAX_PC_RETRIES || test_bit (PC_ABORT, &pc->flags)) { - /* - * We will "abort" retrying a packet command in case - * a legitimate error code was received (crossing a - * filemark, or DMA error in the end of media, for - * example). - */ - if (!test_bit (PC_ABORT, &pc->flags)) { - if (!(pc->c[0] == 0 && tape->sense_key == 2 && tape->asc == 4 && (tape->ascq == 1 || tape->ascq == 8))) { - printk (KERN_ERR "ide-tape: %s: I/O error, pc = %2x, key = %2x, asc = %2x, ascq = %2x\n", - tape->name, pc->c[0], tape->sense_key, tape->asc, tape->ascq); - if (tape->onstream && pc->c[0] == 8 && tape->sense_key == 3 && tape->asc == 0x11) /* AJN-1: 11 should be 0x11 */ - printk(KERN_ERR "ide-tape: %s: enabling read error recovery\n", tape->name); - } - pc->error = IDETAPE_ERROR_GENERAL; /* Giving up */ - } - tape->failed_pc=NULL; - return pc->callback(drive); - } -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 2) - printk (KERN_INFO "ide-tape: Retry number - %d\n",pc->retries); -#endif /* IDETAPE_DEBUG_LOG */ - - pc->retries++; - pc->actually_transferred=0; /* We haven't transferred any data yet */ - pc->current_position=pc->buffer; - bcount.all=pc->request_transfer; /* Request to transfer the entire buffer at once */ - -#ifdef CONFIG_BLK_DEV_IDEDMA - if (test_and_clear_bit (PC_DMA_ERROR, &pc->flags)) { - printk (KERN_WARNING "ide-tape: DMA disabled, reverting to PIO\n"); - (void) HWIF(drive)->dmaproc(ide_dma_off, drive); - } - if (test_bit (PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma) - dma_ok=!HWIF(drive)->dmaproc(test_bit (PC_WRITING, &pc->flags) ? ide_dma_write : ide_dma_read, drive); -#endif /* CONFIG_BLK_DEV_IDEDMA */ - - if (IDE_CONTROL_REG) - OUT_BYTE (drive->ctl,IDE_CONTROL_REG); - OUT_BYTE (dma_ok ? 1:0,IDE_FEATURE_REG); /* Use PIO/DMA */ - OUT_BYTE (bcount.b.high,IDE_BCOUNTH_REG); - OUT_BYTE (bcount.b.low,IDE_BCOUNTL_REG); - OUT_BYTE (drive->select.all,IDE_SELECT_REG); -#ifdef CONFIG_BLK_DEV_IDEDMA - if (dma_ok) { /* Begin DMA, if necessary */ - set_bit (PC_DMA_IN_PROGRESS, &pc->flags); - (void) (HWIF(drive)->dmaproc(ide_dma_begin, drive)); - } -#endif /* CONFIG_BLK_DEV_IDEDMA */ - if (test_bit(IDETAPE_DRQ_INTERRUPT, &tape->flags)) { - ide_set_handler(drive, &idetape_transfer_pc, IDETAPE_WAIT_CMD, NULL); - OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG); - return ide_started; - } else { - OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG); - return idetape_transfer_pc(drive); - } -} - -/* - * General packet command callback function. - */ -static ide_startstop_t idetape_pc_callback (ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 4) - printk (KERN_INFO "ide-tape: Reached idetape_pc_callback\n"); -#endif /* IDETAPE_DEBUG_LOG */ - - idetape_end_request (tape->pc->error ? 0:1, HWGROUP(drive)); - return ide_stopped; -} - -/* - * A mode sense command is used to "sense" tape parameters. - */ -static void idetape_create_mode_sense_cmd (idetape_pc_t *pc, byte page_code) -{ - idetape_init_pc (pc); - pc->c[0] = IDETAPE_MODE_SENSE_CMD; - pc->c[1] = 8; /* DBD = 1 - Don't return block descriptors for now */ - pc->c[2] = page_code; - pc->c[3] = 255; /* Don't limit the returned information */ - pc->c[4] = 255; /* (We will just discard data in that case) */ - if (page_code == IDETAPE_CAPABILITIES_PAGE) - pc->request_transfer = 24; - else - pc->request_transfer = 50; - pc->callback = &idetape_pc_callback; -} - -static ide_startstop_t idetape_onstream_buffer_fill_callback (ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - - tape->max_frames = tape->pc->buffer[4 + 2]; - tape->cur_frames = tape->pc->buffer[4 + 3]; - if (tape->chrdev_direction == idetape_direction_write) - tape->tape_head = tape->buffer_head - tape->cur_frames; - else - tape->tape_head = tape->buffer_head + tape->cur_frames; - if (tape->tape_head != tape->last_tape_head) { - tape->last_tape_head = tape->tape_head; - tape->tape_still_time_begin = jiffies; - if (tape->tape_still_time > 200) - tape->measure_insert_time = 1; - } - tape->tape_still_time = (jiffies - tape->tape_still_time_begin) * 1000 / HZ; -#if USE_IOTRACE - IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head, tape->tape_head, tape->minor); -#endif -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 1) - printk(KERN_INFO "ide-tape: buffer fill callback, %d/%d\n", tape->cur_frames, tape->max_frames); -#endif - idetape_end_request (tape->pc->error ? 0:1, HWGROUP(drive)); - return ide_stopped; -} - -static void idetape_queue_onstream_buffer_fill (ide_drive_t *drive) -{ - idetape_pc_t *pc; - struct request *rq; - - pc = idetape_next_pc_storage (drive); - rq = idetape_next_rq_storage (drive); - idetape_create_mode_sense_cmd (pc, 0x33); - pc->callback = idetape_onstream_buffer_fill_callback; - idetape_queue_pc_head (drive, pc, rq); -} - -static void calculate_speeds(ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - int full = 125, empty = 75; - - if (jiffies > tape->controlled_pipeline_head_time + 120 * HZ) { - tape->controlled_previous_pipeline_head = tape->controlled_last_pipeline_head; - tape->controlled_previous_head_time = tape->controlled_pipeline_head_time; - tape->controlled_last_pipeline_head = tape->pipeline_head; - tape->controlled_pipeline_head_time = jiffies; - } - if (jiffies > tape->controlled_pipeline_head_time + 60 * HZ) - tape->controlled_pipeline_head_speed = (tape->pipeline_head - tape->controlled_last_pipeline_head) * 32 * HZ / (jiffies - tape->controlled_pipeline_head_time); - else if (jiffies > tape->controlled_previous_head_time) - tape->controlled_pipeline_head_speed = (tape->pipeline_head - tape->controlled_previous_pipeline_head) * 32 * HZ / (jiffies - tape->controlled_previous_head_time); - - if (tape->nr_pending_stages < tape->max_stages /*- 1 */) { /* -1 for read mode error recovery */ - if (jiffies > tape->uncontrolled_previous_head_time + 10 * HZ) { - tape->uncontrolled_pipeline_head_time = jiffies; - tape->uncontrolled_pipeline_head_speed = (tape->pipeline_head - tape->uncontrolled_previous_pipeline_head) * 32 * HZ / (jiffies - tape->uncontrolled_previous_head_time); - } - } else { - tape->uncontrolled_previous_head_time = jiffies; - tape->uncontrolled_previous_pipeline_head = tape->pipeline_head; - if (jiffies > tape->uncontrolled_pipeline_head_time + 30 * HZ) { - tape->uncontrolled_pipeline_head_time = jiffies; - } - } - tape->pipeline_head_speed = IDE_MAX(tape->uncontrolled_pipeline_head_speed, tape->controlled_pipeline_head_speed); - if (tape->speed_control == 0) { - tape->max_insert_speed = 5000; - } else if (tape->speed_control == 1) { - if (tape->nr_pending_stages >= tape->max_stages / 2) - tape->max_insert_speed = tape->pipeline_head_speed + - (1100 - tape->pipeline_head_speed) * 2 * (tape->nr_pending_stages - tape->max_stages / 2) / tape->max_stages; - else - tape->max_insert_speed = 500 + - (tape->pipeline_head_speed - 500) * 2 * tape->nr_pending_stages / tape->max_stages; - if (tape->nr_pending_stages >= tape->max_stages * 99 / 100) - tape->max_insert_speed = 5000; - } else if (tape->speed_control == 2) { - tape->max_insert_speed = tape->pipeline_head_speed * empty / 100 + - (tape->pipeline_head_speed * full / 100 - tape->pipeline_head_speed * empty / 100) * tape->nr_pending_stages / tape->max_stages; - } else - tape->max_insert_speed = tape->speed_control; - tape->max_insert_speed = IDE_MAX(tape->max_insert_speed, 500); -} - -static ide_startstop_t idetape_media_access_finished (ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - idetape_pc_t *pc = tape->pc; - idetape_status_reg_t status; - - if (tape->onstream) - printk(KERN_INFO "ide-tape: bug: onstream, media_access_finished\n"); - status.all = GET_STAT(); - if (status.b.dsc) { - if (status.b.check) { /* Error detected */ - printk (KERN_ERR "ide-tape: %s: I/O error, ",tape->name); - return idetape_retry_pc (drive); /* Retry operation */ - } - pc->error = 0; - if (tape->failed_pc == pc) - tape->failed_pc = NULL; - } else { - pc->error = IDETAPE_ERROR_GENERAL; - tape->failed_pc = NULL; - } - return pc->callback (drive); -} - -static ide_startstop_t idetape_rw_callback (ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - struct request *rq = HWGROUP(drive)->rq; - int blocks = tape->pc->actually_transferred / tape->tape_block_size; - - tape->avg_size += blocks * tape->tape_block_size; - tape->insert_size += blocks * tape->tape_block_size; - if (tape->insert_size > 1024 * 1024) - tape->measure_insert_time = 1; - if (tape->measure_insert_time) { - tape->measure_insert_time = 0; - tape->insert_time = jiffies; - tape->insert_size = 0; - } - if (jiffies > tape->insert_time) - tape->insert_speed = tape->insert_size / 1024 * HZ / (jiffies - tape->insert_time); - if (jiffies - tape->avg_time >= HZ) { - tape->avg_speed = tape->avg_size * HZ / (jiffies - tape->avg_time) / 1024; - tape->avg_size = 0; - tape->avg_time = jiffies; - } - -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 4) - printk (KERN_INFO "ide-tape: Reached idetape_rw_callback\n"); -#endif /* IDETAPE_DEBUG_LOG */ - - tape->first_frame_position += blocks; - rq->current_nr_sectors -= blocks; - - if (!tape->pc->error) - idetape_end_request (1, HWGROUP (drive)); - else - idetape_end_request (tape->pc->error, HWGROUP (drive)); - return ide_stopped; -} - -static void idetape_create_read_cmd (idetape_tape_t *tape, idetape_pc_t *pc, unsigned int length, struct buffer_head *bh) -{ - struct buffer_head *p = bh; - idetape_init_pc (pc); - pc->c[0] = IDETAPE_READ_CMD; - put_unaligned (htonl (length), (unsigned int *) &pc->c[1]); - pc->c[1] = 1; - pc->callback = &idetape_rw_callback; - pc->bh = bh; - atomic_set(&bh->b_count, 0); - pc->buffer = NULL; - if (tape->onstream) { - while (p) { - atomic_set(&p->b_count, 0); - p = p->b_reqnext; - } - } - if (!tape->onstream) { - pc->request_transfer = pc->buffer_size = length * tape->tape_block_size; - if (pc->request_transfer == tape->stage_size) - set_bit (PC_DMA_RECOMMENDED, &pc->flags); - } else { - if (length) { - pc->request_transfer = pc->buffer_size = 32768 + 512; - set_bit (PC_DMA_RECOMMENDED, &pc->flags); - } else - pc->request_transfer = 0; - } -} - -static void idetape_create_read_buffer_cmd(idetape_tape_t *tape, idetape_pc_t *pc, unsigned int length, struct buffer_head *bh) -{ - int size = 32768; - - struct buffer_head *p = bh; - idetape_init_pc (pc); - pc->c[0] = IDETAPE_READ_BUFFER_CMD; - pc->c[1] = IDETAPE_RETRIEVE_FAULTY_BLOCK; - pc->c[7] = size >> 8; - pc->c[8] = size & 0xff; - pc->callback = &idetape_pc_callback; - pc->bh = bh; - atomic_set(&bh->b_count, 0); - pc->buffer = NULL; - while (p) { - atomic_set(&p->b_count, 0); - p = p->b_reqnext; - } - pc->request_transfer = pc->buffer_size = size; -} - -static void idetape_create_write_cmd (idetape_tape_t *tape, idetape_pc_t *pc, unsigned int length, struct buffer_head *bh) -{ - struct buffer_head *p = bh; - idetape_init_pc (pc); - pc->c[0] = IDETAPE_WRITE_CMD; - put_unaligned (htonl (length), (unsigned int *) &pc->c[1]); - pc->c[1] = 1; - pc->callback = &idetape_rw_callback; - set_bit (PC_WRITING, &pc->flags); - if (tape->onstream) { - while (p) { - atomic_set(&p->b_count, p->b_size); - p = p->b_reqnext; - } - } - pc->bh = bh; - pc->b_data = bh->b_data; - pc->b_count = atomic_read(&bh->b_count); - pc->buffer = NULL; - if (!tape->onstream) { - pc->request_transfer = pc->buffer_size = length * tape->tape_block_size; - if (pc->request_transfer == tape->stage_size) - set_bit (PC_DMA_RECOMMENDED, &pc->flags); - } else { - if (length) { - pc->request_transfer = pc->buffer_size = 32768 + 512; - set_bit (PC_DMA_RECOMMENDED, &pc->flags); - } else - pc->request_transfer = 0; - } -} - -/* - * idetape_do_request is our request handling function. - */ -static ide_startstop_t idetape_do_request (ide_drive_t *drive, struct request *rq, unsigned long block) -{ - idetape_tape_t *tape = drive->driver_data; - idetape_pc_t *pc; - struct request *postponed_rq = tape->postponed_rq; - idetape_status_reg_t status; - -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 5) - printk (KERN_INFO "ide-tape: rq_status: %d, rq_dev: %u, cmd: %d, errors: %d\n",rq->rq_status,(unsigned int) rq->rq_dev,rq->cmd,rq->errors); - if (tape->debug_level >= 2) - printk (KERN_INFO "ide-tape: sector: %ld, nr_sectors: %ld, current_nr_sectors: %ld\n",rq->sector,rq->nr_sectors,rq->current_nr_sectors); -#endif /* IDETAPE_DEBUG_LOG */ - - if (!IDETAPE_RQ_CMD (rq->cmd)) { - /* - * We do not support buffer cache originated requests. - */ - printk (KERN_NOTICE "ide-tape: %s: Unsupported command in request queue (%d)\n", drive->name, rq->cmd); - ide_end_request (0,HWGROUP (drive)); /* Let the common code handle it */ - return ide_stopped; - } - - /* - * Retry a failed packet command - */ - if (tape->failed_pc != NULL && tape->pc->c[0] == IDETAPE_REQUEST_SENSE_CMD) { - return idetape_issue_packet_command (drive, tape->failed_pc); - } -#if IDETAPE_DEBUG_BUGS - if (postponed_rq != NULL) - if (rq != postponed_rq) { - printk (KERN_ERR "ide-tape: ide-tape.c bug - Two DSC requests were queued\n"); - idetape_end_request (0,HWGROUP (drive)); - return ide_stopped; - } -#endif /* IDETAPE_DEBUG_BUGS */ - - tape->postponed_rq = NULL; - - /* - * If the tape is still busy, postpone our request and service - * the other device meanwhile. - */ - status.all = GET_STAT(); - - /* - * The OnStream tape drive doesn't support DSC. Assume - * that DSC is always set. - */ - if (tape->onstream) - status.b.dsc = 1; - if (!drive->dsc_overlap && rq->cmd != IDETAPE_PC_RQ2) - set_bit (IDETAPE_IGNORE_DSC, &tape->flags); - - /* - * For the OnStream tape, check the current status of the tape - * internal buffer using data gathered from the buffer fill - * mode page, and postpone our request, effectively "disconnecting" - * from the IDE bus, in case the buffer is full (writing) or - * empty (reading), and there is a danger that our request will - * hold the IDE bus during actual media access. - */ - if (tape->tape_still_time > 100 && tape->tape_still_time < 200) - tape->measure_insert_time = 1; - if (tape->req_buffer_fill && (rq->cmd == IDETAPE_WRITE_RQ || rq->cmd == IDETAPE_READ_RQ)) { - tape->req_buffer_fill = 0; - tape->writes_since_buffer_fill = 0; - tape->reads_since_buffer_fill = 0; - tape->last_buffer_fill = jiffies; - idetape_queue_onstream_buffer_fill(drive); - if (jiffies > tape->insert_time) - tape->insert_speed = tape->insert_size / 1024 * HZ / (jiffies - tape->insert_time); - return ide_stopped; - } - if (jiffies > tape->insert_time) - tape->insert_speed = tape->insert_size / 1024 * HZ / (jiffies - tape->insert_time); - calculate_speeds(drive); - if (tape->onstream && tape->max_frames && - ((rq->cmd == IDETAPE_WRITE_RQ && (tape->cur_frames == tape->max_frames || (tape->speed_control && tape->cur_frames > 5 && (tape->insert_speed > tape->max_insert_speed || (0 /* tape->cur_frames > 30 && tape->tape_still_time > 200 */))))) || - (rq->cmd == IDETAPE_READ_RQ && (tape->cur_frames == 0 || (tape->speed_control && (tape->cur_frames < tape->max_frames - 5) && tape->insert_speed > tape->max_insert_speed)) && rq->nr_sectors))) { -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 4) - printk(KERN_INFO "ide-tape: postponing request, cmd %d, cur %d, max %d\n", - rq->cmd, tape->cur_frames, tape->max_frames); -#endif - if (tape->postpone_cnt++ < 500) { - status.b.dsc = 0; - tape->req_buffer_fill = 1; - } -#if ONSTREAM_DEBUG - else if (tape->debug_level >= 4) - printk(KERN_INFO "ide-tape: %s: postpone_cnt %d\n", tape->name, tape->postpone_cnt); -#endif - } - if (!test_and_clear_bit (IDETAPE_IGNORE_DSC, &tape->flags) && !status.b.dsc) { - if (postponed_rq == NULL) { - tape->dsc_polling_start = jiffies; - tape->dsc_polling_frequency = tape->best_dsc_rw_frequency; - tape->dsc_timeout = jiffies + IDETAPE_DSC_RW_TIMEOUT; - } else if ((signed long) (jiffies - tape->dsc_timeout) > 0) { - printk (KERN_ERR "ide-tape: %s: DSC timeout\n", tape->name); - if (rq->cmd == IDETAPE_PC_RQ2) { - idetape_media_access_finished (drive); - return ide_stopped; - } else { - return ide_do_reset (drive); - } - } else if (jiffies - tape->dsc_polling_start > IDETAPE_DSC_MA_THRESHOLD) - tape->dsc_polling_frequency = IDETAPE_DSC_MA_SLOW; - idetape_postpone_request (drive); - return ide_stopped; - } - switch (rq->cmd) { - case IDETAPE_READ_RQ: - tape->buffer_head++; -#if USE_IOTRACE - IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head, tape->tape_head, tape->minor); -#endif - tape->postpone_cnt = 0; - tape->reads_since_buffer_fill++; - if (tape->onstream) { - if (tape->cur_frames - tape->reads_since_buffer_fill <= 0) - tape->req_buffer_fill = 1; - if (jiffies > tape->last_buffer_fill + 5 * HZ / 100) - tape->req_buffer_fill = 1; - } - pc=idetape_next_pc_storage (drive); - idetape_create_read_cmd (tape, pc, rq->current_nr_sectors, rq->bh); - break; - case IDETAPE_WRITE_RQ: - tape->buffer_head++; -#if USE_IOTRACE - IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head, tape->tape_head, tape->minor); -#endif - tape->postpone_cnt = 0; - tape->writes_since_buffer_fill++; - if (tape->onstream) { - if (tape->cur_frames + tape->writes_since_buffer_fill >= tape->max_frames) - tape->req_buffer_fill = 1; - if (jiffies > tape->last_buffer_fill + 5 * HZ / 100) - tape->req_buffer_fill = 1; - calculate_speeds(drive); - } - pc=idetape_next_pc_storage (drive); - idetape_create_write_cmd (tape, pc, rq->current_nr_sectors, rq->bh); - break; - case IDETAPE_READ_BUFFER_RQ: - tape->postpone_cnt = 0; - pc=idetape_next_pc_storage (drive); - idetape_create_read_buffer_cmd (tape, pc, rq->current_nr_sectors, rq->bh); - break; - case IDETAPE_ABORTED_WRITE_RQ: - rq->cmd = IDETAPE_WRITE_RQ; - idetape_end_request (IDETAPE_ERROR_EOD, HWGROUP(drive)); - return ide_stopped; - case IDETAPE_ABORTED_READ_RQ: -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: detected aborted read rq\n", tape->name); -#endif - rq->cmd = IDETAPE_READ_RQ; - idetape_end_request (IDETAPE_ERROR_EOD, HWGROUP(drive)); - return ide_stopped; - case IDETAPE_PC_RQ1: - pc=(idetape_pc_t *) rq->buffer; - rq->cmd = IDETAPE_PC_RQ2; - break; - case IDETAPE_PC_RQ2: - idetape_media_access_finished (drive); - return ide_stopped; - default: - printk (KERN_ERR "ide-tape: bug in IDETAPE_RQ_CMD macro\n"); - idetape_end_request (0,HWGROUP (drive)); - return ide_stopped; - } - return idetape_issue_packet_command (drive, pc); -} - -/* - * Pipeline related functions - */ -static inline int idetape_pipeline_active (idetape_tape_t *tape) -{ - int rc1, rc2; - - rc1 = test_bit(IDETAPE_PIPELINE_ACTIVE, &tape->flags); - rc2 = (tape->active_data_request != NULL); - return rc1; -} - -/* - * idetape_kmalloc_stage uses __get_free_page to allocate a pipeline - * stage, along with all the necessary small buffers which together make - * a buffer of size tape->stage_size (or a bit more). We attempt to - * combine sequential pages as much as possible. - * - * Returns a pointer to the new allocated stage, or NULL if we - * can't (or don't want to) allocate a stage. - * - * Pipeline stages are optional and are used to increase performance. - * If we can't allocate them, we'll manage without them. - */ -static idetape_stage_t *__idetape_kmalloc_stage (idetape_tape_t *tape, int full, int clear) -{ - idetape_stage_t *stage; - struct buffer_head *prev_bh, *bh; - int pages = tape->pages_per_stage; - char *b_data; - - if ((stage = (idetape_stage_t *) kmalloc (sizeof (idetape_stage_t),GFP_KERNEL)) == NULL) - return NULL; - stage->next = NULL; - - bh = stage->bh = (struct buffer_head *) kmalloc (sizeof (struct buffer_head), GFP_KERNEL); - if (bh == NULL) - goto abort; - bh->b_reqnext = NULL; - if ((bh->b_data = (char *) __get_free_page (GFP_KERNEL)) == NULL) - goto abort; - if (clear) - memset(bh->b_data, 0, PAGE_SIZE); - bh->b_size = PAGE_SIZE; - atomic_set(&bh->b_count, full ? bh->b_size : 0); - set_bit (BH_Lock, &bh->b_state); - - while (--pages) { - if ((b_data = (char *) __get_free_page (GFP_KERNEL)) == NULL) - goto abort; - if (clear) - memset(b_data, 0, PAGE_SIZE); - if (bh->b_data == b_data + PAGE_SIZE) { - bh->b_size += PAGE_SIZE; - bh->b_data -= PAGE_SIZE; - if (full) - atomic_add(PAGE_SIZE, &bh->b_count); - continue; - } - if (b_data == bh->b_data + bh->b_size) { - bh->b_size += PAGE_SIZE; - if (full) - atomic_add(PAGE_SIZE, &bh->b_count); - continue; - } - prev_bh = bh; - if ((bh = (struct buffer_head *) kmalloc (sizeof (struct buffer_head), GFP_KERNEL)) == NULL) { - free_page ((unsigned long) b_data); - goto abort; - } - bh->b_reqnext = NULL; - bh->b_data = b_data; - bh->b_size = PAGE_SIZE; - atomic_set(&bh->b_count, full ? bh->b_size : 0); - set_bit (BH_Lock, &bh->b_state); - prev_bh->b_reqnext = bh; - } - bh->b_size -= tape->excess_bh_size; - if (full) - atomic_sub(tape->excess_bh_size, &bh->b_count); - if (tape->onstream) - stage->aux = (os_aux_t *) (bh->b_data + bh->b_size - OS_AUX_SIZE); - return stage; -abort: - __idetape_kfree_stage (stage); - return NULL; -} - -static idetape_stage_t *idetape_kmalloc_stage (idetape_tape_t *tape) -{ - idetape_stage_t *cache_stage = tape->cache_stage; - -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 4) - printk (KERN_INFO "ide-tape: Reached idetape_kmalloc_stage\n"); -#endif /* IDETAPE_DEBUG_LOG */ - - if (tape->nr_stages >= tape->max_stages) - return NULL; - if (cache_stage != NULL) { - tape->cache_stage = NULL; - return cache_stage; - } - return __idetape_kmalloc_stage (tape, 0, 0); -} - -static void idetape_copy_stage_from_user (idetape_tape_t *tape, idetape_stage_t *stage, const char *buf, int n) -{ - struct buffer_head *bh = tape->bh; - int count; - - while (n) { -#if IDETAPE_DEBUG_BUGS - if (bh == NULL) { - printk (KERN_ERR "ide-tape: bh == NULL in idetape_copy_stage_from_user\n"); - return; - } -#endif /* IDETAPE_DEBUG_BUGS */ - count = IDE_MIN (bh->b_size - atomic_read(&bh->b_count), n); - copy_from_user (bh->b_data + atomic_read(&bh->b_count), buf, count); - n -= count; atomic_add(count, &bh->b_count); buf += count; - if (atomic_read(&bh->b_count) == bh->b_size) { - bh = bh->b_reqnext; - if (bh) - atomic_set(&bh->b_count, 0); - } - } - tape->bh = bh; -} - -static void idetape_copy_stage_to_user (idetape_tape_t *tape, char *buf, idetape_stage_t *stage, int n) -{ - struct buffer_head *bh = tape->bh; - int count; - - while (n) { -#if IDETAPE_DEBUG_BUGS - if (bh == NULL) { - printk (KERN_ERR "ide-tape: bh == NULL in idetape_copy_stage_to_user\n"); - return; - } -#endif /* IDETAPE_DEBUG_BUGS */ - count = IDE_MIN (tape->b_count, n); - copy_to_user (buf, tape->b_data, count); - n -= count; tape->b_data += count; tape->b_count -= count; buf += count; - if (!tape->b_count) { - tape->bh = bh = bh->b_reqnext; - if (bh) { - tape->b_data = bh->b_data; - tape->b_count = atomic_read(&bh->b_count); - } - } - } -} - -static void idetape_init_merge_stage (idetape_tape_t *tape) -{ - struct buffer_head *bh = tape->merge_stage->bh; - - tape->bh = bh; - if (tape->chrdev_direction == idetape_direction_write) - atomic_set(&bh->b_count, 0); - else { - tape->b_data = bh->b_data; - tape->b_count = atomic_read(&bh->b_count); - } -} - -static void idetape_switch_buffers (idetape_tape_t *tape, idetape_stage_t *stage) -{ - struct buffer_head *tmp; - os_aux_t *tmp_aux; - - tmp = stage->bh; tmp_aux = stage->aux; - stage->bh = tape->merge_stage->bh; stage->aux = tape->merge_stage->aux; - tape->merge_stage->bh = tmp; tape->merge_stage->aux = tmp_aux; - idetape_init_merge_stage (tape); -} - -/* - * idetape_add_stage_tail adds a new stage at the end of the pipeline. - */ -static void idetape_add_stage_tail (ide_drive_t *drive,idetape_stage_t *stage) -{ - idetape_tape_t *tape = drive->driver_data; - unsigned long flags; - -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 4) - printk (KERN_INFO "ide-tape: Reached idetape_add_stage_tail\n"); -#endif /* IDETAPE_DEBUG_LOG */ - spin_lock_irqsave(&tape->spinlock, flags); - stage->next=NULL; - if (tape->last_stage != NULL) - tape->last_stage->next=stage; - else - tape->first_stage=tape->next_stage=stage; - tape->last_stage=stage; - if (tape->next_stage == NULL) - tape->next_stage=tape->last_stage; - tape->nr_stages++; - tape->nr_pending_stages++; - spin_unlock_irqrestore(&tape->spinlock, flags); -} - -/* - * Initialize the OnStream AUX - */ -static void idetape_init_stage (ide_drive_t *drive, idetape_stage_t *stage, int frame_type, int logical_blk_num) -{ - idetape_tape_t *tape = drive->driver_data; - os_aux_t *aux = stage->aux; - os_partition_t *par = &aux->partition; - os_dat_t *dat = &aux->dat; - - if (!tape->onstream || tape->raw) - return; - memset(aux, 0, sizeof(*aux)); - aux->format_id = htonl(0); - memcpy(aux->application_sig, "LIN3", 4); - aux->hdwr = htonl(0); - aux->frame_type = frame_type; - - if (frame_type == OS_FRAME_TYPE_HEADER) { - aux->update_frame_cntr = htonl(tape->update_frame_cntr); - par->partition_num = OS_CONFIG_PARTITION; - par->par_desc_ver = OS_PARTITION_VERSION; - par->wrt_pass_cntr = htons(0xffff); - par->first_frame_addr = htonl(0); - par->last_frame_addr = htonl(0xbb7); - } else { - aux->update_frame_cntr = htonl(0); - par->partition_num = OS_DATA_PARTITION; - par->par_desc_ver = OS_PARTITION_VERSION; - par->wrt_pass_cntr = htons(tape->wrt_pass_cntr); - par->first_frame_addr = htonl(0x14); - par->last_frame_addr = htonl(19239 * 24); - } - if (frame_type != OS_FRAME_TYPE_HEADER) { - aux->frame_seq_num = htonl(logical_blk_num); - aux->logical_blk_num_high = htonl(0); - aux->logical_blk_num = htonl(logical_blk_num); - } else { - aux->frame_seq_num = htonl(0); - aux->logical_blk_num_high = htonl(0); - aux->logical_blk_num = htonl(0); - } - - if (frame_type != OS_FRAME_TYPE_HEADER) { - dat->dat_sz = 8; - dat->reserved1 = 0; - dat->entry_cnt = 1; - dat->reserved3 = 0; - if (frame_type == OS_FRAME_TYPE_DATA) - dat->dat_list[0].blk_sz = htonl(32 * 1024); - else - dat->dat_list[0].blk_sz = 0; - dat->dat_list[0].blk_cnt = htons(1); - if (frame_type == OS_FRAME_TYPE_MARKER) - dat->dat_list[0].flags = OS_DAT_FLAGS_MARK; - else - dat->dat_list[0].flags = OS_DAT_FLAGS_DATA; - dat->dat_list[0].reserved = 0; - } else - aux->next_mark_addr = htonl(tape->first_mark_addr); - aux->filemark_cnt = ntohl(tape->filemark_cnt); - aux->phys_fm = ntohl(0xffffffff); - aux->last_mark_addr = ntohl(tape->last_mark_addr); -} - -/* - * idetape_wait_for_request installs a semaphore in a pending request - * and sleeps until it is serviced. - * - * The caller should ensure that the request will not be serviced - * before we install the semaphore (usually by disabling interrupts). - */ -static void idetape_wait_for_request (ide_drive_t *drive, struct request *rq) -{ - DECLARE_MUTEX_LOCKED(sem); - idetape_tape_t *tape = drive->driver_data; - -#if IDETAPE_DEBUG_BUGS - if (rq == NULL || !IDETAPE_RQ_CMD (rq->cmd)) { - printk (KERN_ERR "ide-tape: bug: Trying to sleep on non-valid request\n"); - return; - } -#endif /* IDETAPE_DEBUG_BUGS */ - rq->sem = &sem; - tape->sem = &sem; - spin_unlock(&tape->spinlock); - down(&sem); - rq->sem = NULL; - tape->sem = NULL; - spin_lock_irq(&tape->spinlock); -} - -static ide_startstop_t idetape_read_position_callback (ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - idetape_read_position_result_t *result; - -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 4) - printk (KERN_INFO "ide-tape: Reached idetape_read_position_callback\n"); -#endif /* IDETAPE_DEBUG_LOG */ - - if (!tape->pc->error) { - result = (idetape_read_position_result_t *) tape->pc->buffer; -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 2) - printk (KERN_INFO "ide-tape: BOP - %s\n",result->bop ? "Yes":"No"); - if (tape->debug_level >= 2) - printk (KERN_INFO "ide-tape: EOP - %s\n",result->eop ? "Yes":"No"); -#endif /* IDETAPE_DEBUG_LOG */ - if (result->bpu) { - printk (KERN_INFO "ide-tape: Block location is unknown to the tape\n"); - clear_bit (IDETAPE_ADDRESS_VALID, &tape->flags); - idetape_end_request (0,HWGROUP (drive)); - } else { -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 2) - printk (KERN_INFO "ide-tape: Block Location - %u\n", ntohl (result->first_block)); -#endif /* IDETAPE_DEBUG_LOG */ - tape->partition = result->partition; - tape->first_frame_position = ntohl (result->first_block); - tape->last_frame_position = ntohl (result->last_block); - tape->blocks_in_buffer = result->blocks_in_buffer[2]; - set_bit (IDETAPE_ADDRESS_VALID, &tape->flags); - idetape_end_request (1,HWGROUP (drive)); - } - } else { - idetape_end_request (0,HWGROUP (drive)); - } - return ide_stopped; -} - -/* - * idetape_create_write_filemark_cmd will: - * - * 1. Write a filemark if write_filemark=1. - * 2. Flush the device buffers without writing a filemark - * if write_filemark=0. - * - */ -static void idetape_create_write_filemark_cmd (ide_drive_t *drive, idetape_pc_t *pc,int write_filemark) -{ - idetape_tape_t *tape = drive->driver_data; - - idetape_init_pc (pc); - pc->c[0] = IDETAPE_WRITE_FILEMARK_CMD; - if (tape->onstream) - pc->c[1] = 1; - pc->c[4] = write_filemark; - set_bit (PC_WAIT_FOR_DSC, &pc->flags); - pc->callback = &idetape_pc_callback; -} - -static void idetape_create_test_unit_ready_cmd(idetape_pc_t *pc) -{ - idetape_init_pc(pc); - pc->c[0] = IDETAPE_TEST_UNIT_READY_CMD; - pc->callback = &idetape_pc_callback; -} - -/* - * idetape_queue_pc_tail is based on the following functions: - * - * ide_do_drive_cmd from ide.c - * cdrom_queue_request and cdrom_queue_packet_command from ide-cd.c - * - * We add a special packet command request to the tail of the request queue, - * and wait for it to be serviced. - * - * This is not to be called from within the request handling part - * of the driver ! We allocate here data in the stack, and it is valid - * until the request is finished. This is not the case for the bottom - * part of the driver, where we are always leaving the functions to wait - * for an interrupt or a timer event. - * - * From the bottom part of the driver, we should allocate safe memory - * using idetape_next_pc_storage and idetape_next_rq_storage, and add - * the request to the request list without waiting for it to be serviced ! - * In that case, we usually use idetape_queue_pc_head. - */ -static int __idetape_queue_pc_tail (ide_drive_t *drive,idetape_pc_t *pc) -{ - struct request rq; - - ide_init_drive_cmd (&rq); - rq.buffer = (char *) pc; - rq.cmd = IDETAPE_PC_RQ1; - return ide_do_drive_cmd (drive, &rq, ide_wait); -} - -static void idetape_create_load_unload_cmd (ide_drive_t *drive, idetape_pc_t *pc,int cmd) -{ - idetape_tape_t *tape = drive->driver_data; - - idetape_init_pc (pc); - pc->c[0] = IDETAPE_LOAD_UNLOAD_CMD; - pc->c[4] = cmd; - if (tape->onstream) - pc->c[1] = 1; - set_bit (PC_WAIT_FOR_DSC, &pc->flags); - pc->callback = &idetape_pc_callback; -} - -static int idetape_wait_ready (ide_drive_t *drive, unsigned long long timeout) -{ - idetape_tape_t *tape = drive->driver_data; - idetape_pc_t pc; - - /* - * Wait for the tape to become ready - */ - timeout += jiffies; - while (jiffies < timeout) { - idetape_create_test_unit_ready_cmd(&pc); - if (!__idetape_queue_pc_tail(drive, &pc)) - return 0; - if (tape->sense_key == 2 && tape->asc == 4 && tape->ascq == 2) { - idetape_create_load_unload_cmd (drive, &pc, IDETAPE_LU_LOAD_MASK); - __idetape_queue_pc_tail(drive,&pc); - idetape_create_test_unit_ready_cmd(&pc); - if (!__idetape_queue_pc_tail(drive, &pc)) - return 0; - } - if (!(tape->sense_key == 2 && tape->asc == 4 && (tape->ascq == 1 || tape->ascq == 8))) - break; - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(HZ / 10); - } - return -EIO; -} - -static int idetape_queue_pc_tail (ide_drive_t *drive,idetape_pc_t *pc) -{ - idetape_tape_t *tape = drive->driver_data; - int rc; - - rc = __idetape_queue_pc_tail(drive, pc); - if (rc) return rc; - if (tape->onstream && test_bit(PC_WAIT_FOR_DSC, &pc->flags)) - rc = idetape_wait_ready(drive, 60 * 10 * HZ); /* AJN-4: Changed from 5 to 10 minutes; - because retension takes approx. 8:20 with Onstream 30GB tape */ - return rc; -} - -static int idetape_flush_tape_buffers (ide_drive_t *drive) -{ - idetape_pc_t pc; - int rc; - - idetape_create_write_filemark_cmd(drive, &pc, 0); - if ((rc = idetape_queue_pc_tail (drive,&pc))) - return rc; - idetape_wait_ready(drive, 60 * 5 * HZ); - return 0; -} - -static void idetape_create_read_position_cmd (idetape_pc_t *pc) -{ - idetape_init_pc (pc); - pc->c[0] = IDETAPE_READ_POSITION_CMD; - pc->request_transfer = 20; - pc->callback = &idetape_read_position_callback; -} - -static int idetape_read_position (ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - idetape_pc_t pc; - int position; - -#ifdef NO_LONGER_REQUIRED - idetape_flush_tape_buffers(drive); -#endif - idetape_create_read_position_cmd(&pc); - if (idetape_queue_pc_tail (drive,&pc)) - return -1; - position = tape->first_frame_position; -#ifdef NO_LONGER_REQUIRED - if (tape->onstream) { - if ((position != tape->last_frame_position - tape->blocks_in_buffer) && - (position != tape->last_frame_position + tape->blocks_in_buffer)) { - if (tape->blocks_in_buffer == 0) { - printk("ide-tape: %s: correcting read position %d, %d, %d\n", tape->name, position, tape->last_frame_position, tape->blocks_in_buffer); - position = tape->last_frame_position; - tape->first_frame_position = position; - } - } - } -#endif - return position; -} - -static void idetape_create_locate_cmd (ide_drive_t *drive, idetape_pc_t *pc, unsigned int block, byte partition, int skip) -{ - idetape_tape_t *tape = drive->driver_data; - - idetape_init_pc (pc); - pc->c[0] = IDETAPE_LOCATE_CMD; - if (tape->onstream) - pc->c[1] = 1; - else - pc->c[1] = 2; - put_unaligned (htonl (block), (unsigned int *) &pc->c[3]); - pc->c[8] = partition; - if (tape->onstream) - pc->c[9] = skip << 7; - set_bit (PC_WAIT_FOR_DSC, &pc->flags); - pc->callback = &idetape_pc_callback; -} - -static void idetape_create_prevent_cmd (ide_drive_t *drive, idetape_pc_t *pc, int prevent) -{ - idetape_init_pc(pc); - pc->c[0] = IDETAPE_PREVENT_CMD; - pc->c[4] = prevent; - pc->callback = &idetape_pc_callback; -} - -static int __idetape_discard_read_pipeline (ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - unsigned long flags; - int cnt; - - if (tape->chrdev_direction != idetape_direction_read) - return 0; - tape->merge_stage_size = 0; - if (tape->merge_stage != NULL) { - __idetape_kfree_stage (tape->merge_stage); - tape->merge_stage = NULL; - } - tape->chrdev_direction = idetape_direction_none; - - if (tape->first_stage == NULL) - return 0; - - spin_lock_irqsave(&tape->spinlock, flags); - tape->next_stage = NULL; - if (idetape_pipeline_active (tape)) - idetape_wait_for_request(drive, tape->active_data_request); - spin_unlock_irqrestore(&tape->spinlock, flags); - - cnt = tape->nr_stages - tape->nr_pending_stages; - while (tape->first_stage != NULL) - idetape_remove_stage_head (drive); - tape->nr_pending_stages = 0; - tape->max_stages = tape->min_pipeline; - return cnt; -} - -/* - * idetape_position_tape positions the tape to the requested block - * using the LOCATE packet command. A READ POSITION command is then - * issued to check where we are positioned. - * - * Like all higher level operations, we queue the commands at the tail - * of the request queue and wait for their completion. - * - */ -static int idetape_position_tape (ide_drive_t *drive, unsigned int block, byte partition, int skip) -{ - idetape_tape_t *tape = drive->driver_data; - int retval; - idetape_pc_t pc; - - if (tape->chrdev_direction == idetape_direction_read) - __idetape_discard_read_pipeline(drive); - idetape_wait_ready(drive, 60 * 5 * HZ); - idetape_create_locate_cmd (drive, &pc, block, partition, skip); - retval=idetape_queue_pc_tail (drive,&pc); - if (retval) return (retval); - - idetape_create_read_position_cmd (&pc); - return (idetape_queue_pc_tail (drive,&pc)); -} - -static void idetape_discard_read_pipeline (ide_drive_t *drive, int restore_position) -{ - idetape_tape_t *tape = drive->driver_data; - int cnt; - int seek, position; - - cnt = __idetape_discard_read_pipeline(drive); - if (restore_position) { - position = idetape_read_position(drive); -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: address %u, nr_stages %d\n", position, cnt); -#endif - seek = position > cnt ? position - cnt : 0; - if (idetape_position_tape(drive, seek, 0, 0)) { - printk(KERN_INFO "ide-tape: %s: position_tape failed in discard_pipeline()\n", tape->name); - return; - } - } -} - -static void idetape_update_stats (ide_drive_t *drive) -{ - idetape_pc_t pc; - - idetape_create_mode_sense_cmd (&pc, 0x33); - pc.callback = idetape_onstream_buffer_fill_callback; - (void) idetape_queue_pc_tail(drive, &pc); -} - -/* - * idetape_queue_rw_tail generates a read/write request for the block - * device interface and wait for it to be serviced. - */ -static int idetape_queue_rw_tail (ide_drive_t *drive, int cmd, int blocks, struct buffer_head *bh) -{ - idetape_tape_t *tape = drive->driver_data; - struct request rq; - -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 2) - printk (KERN_INFO "ide-tape: idetape_queue_rw_tail: cmd=%d\n",cmd); -#endif /* IDETAPE_DEBUG_LOG */ -#if IDETAPE_DEBUG_BUGS - if (idetape_pipeline_active (tape)) { - printk (KERN_ERR "ide-tape: bug: the pipeline is active in idetape_queue_rw_tail\n"); - return (0); - } -#endif /* IDETAPE_DEBUG_BUGS */ - - ide_init_drive_cmd (&rq); - rq.bh = bh; - rq.cmd = cmd; - rq.sector = tape->first_frame_position; - rq.nr_sectors = rq.current_nr_sectors = blocks; - if (tape->onstream) - tape->postpone_cnt = 600; - (void) ide_do_drive_cmd (drive, &rq, ide_wait); - - if (cmd != IDETAPE_READ_RQ && cmd != IDETAPE_WRITE_RQ) - return 0; - - if (tape->merge_stage) - idetape_init_merge_stage (tape); - if (rq.errors == IDETAPE_ERROR_GENERAL) - return -EIO; - return (tape->tape_block_size * (blocks-rq.current_nr_sectors)); -} - -/* - * Read back the drive's internal buffer contents, as a part - * of the write error recovery mechanism for old OnStream - * firmware revisions. - */ -static void idetape_onstream_read_back_buffer (ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - int frames, i, logical_blk_num; - idetape_stage_t *stage, *first = NULL, *last = NULL; - os_aux_t *aux; - struct request *rq; - unsigned char *p; - unsigned long flags; - - idetape_update_stats(drive); - frames = tape->cur_frames; - logical_blk_num = ntohl(tape->first_stage->aux->logical_blk_num) - frames; - printk(KERN_INFO "ide-tape: %s: reading back %d frames from the drive's internal buffer\n", tape->name, frames); - for (i = 0; i < frames; i++) { - stage = __idetape_kmalloc_stage(tape, 0, 0); - if (!first) - first = stage; - aux = stage->aux; - p = stage->bh->b_data; - idetape_queue_rw_tail(drive, IDETAPE_READ_BUFFER_RQ, tape->capabilities.ctl, stage->bh); -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: read back logical block %d, data %x %x %x %x\n", tape->name, logical_blk_num, *p++, *p++, *p++, *p++); -#endif - rq = &stage->rq; - ide_init_drive_cmd (rq); - rq->cmd = IDETAPE_WRITE_RQ; - rq->sector = tape->first_frame_position; - rq->nr_sectors = rq->current_nr_sectors = tape->capabilities.ctl; - idetape_init_stage(drive, stage, OS_FRAME_TYPE_DATA, logical_blk_num++); - stage->next = NULL; - if (last) - last->next = stage; - last = stage; - } - if (frames) { - spin_lock_irqsave(&tape->spinlock, flags); - last->next = tape->first_stage; - tape->next_stage = tape->first_stage = first; - tape->nr_stages += frames; - tape->nr_pending_stages += frames; - spin_unlock_irqrestore(&tape->spinlock, flags); - } - idetape_update_stats(drive); -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: frames left in buffer: %d\n", tape->name, tape->cur_frames); -#endif -} - -/* - * Error recovery algorithm for the OnStream tape. - */ -static void idetape_onstream_write_error_recovery (ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - unsigned int block; - - if (tape->onstream_write_error == 1) { - printk(KERN_ERR "ide-tape: %s: detected physical bad block at %u\n", tape->name, ntohl(tape->sense.information)); - block = ntohl(tape->sense.information) + 80; - idetape_update_stats(drive); - printk(KERN_ERR "ide-tape: %s: relocating %d buffered logical blocks to physical block %u\n", tape->name, tape->cur_frames, block); - idetape_update_stats(drive); - if (tape->firmware_revision_num >= 106) - idetape_position_tape(drive, block, 0, 1); - else { - idetape_onstream_read_back_buffer(drive); - idetape_position_tape(drive, block, 0, 0); - } - idetape_read_position(drive); -#if ONSTREAM_DEBUG - if (tape->debug_level >= 1) - printk(KERN_ERR "ide-tape: %s: positioning complete, cur_frames %d, pos %d, tape pos %d\n", tape->name, tape->cur_frames, tape->first_frame_position, tape->last_frame_position); -#endif - } else if (tape->onstream_write_error == 2) { -#if ONSTREAM_DEBUG - if (tape->debug_level >= 1) - printk(KERN_INFO "ide-tape: %s: skipping over config partition\n", tape->name); -#endif - idetape_flush_tape_buffers(drive); - block = idetape_read_position(drive); - if (block != 0xba4) - printk(KERN_ERR "ide-tape: warning, current position %d, expected %d\n", block, 0xba4); - idetape_position_tape(drive, 0xbb8, 0, 0); - } - tape->onstream_write_error = 0; -} - -/* - * idetape_insert_pipeline_into_queue is used to start servicing the - * pipeline stages, starting from tape->next_stage. - */ -static void idetape_insert_pipeline_into_queue (ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - - if (tape->next_stage == NULL) - return; - if (!idetape_pipeline_active (tape)) { - if (tape->onstream_write_error) - idetape_onstream_write_error_recovery(drive); - set_bit(IDETAPE_PIPELINE_ACTIVE, &tape->flags); - idetape_active_next_stage (drive); - (void) ide_do_drive_cmd (drive, tape->active_data_request, ide_end); - } -} - -static void idetape_create_inquiry_cmd (idetape_pc_t *pc) -{ - idetape_init_pc(pc); - pc->c[0] = IDETAPE_INQUIRY_CMD; - pc->c[4] = pc->request_transfer = 254; - pc->callback = &idetape_pc_callback; -} - -static void idetape_create_rewind_cmd (ide_drive_t *drive, idetape_pc_t *pc) -{ - idetape_tape_t *tape = drive->driver_data; - - idetape_init_pc (pc); - pc->c[0] = IDETAPE_REWIND_CMD; - if (tape->onstream) - pc->c[1] = 1; - set_bit (PC_WAIT_FOR_DSC, &pc->flags); - pc->callback = &idetape_pc_callback; -} - -static void idetape_create_mode_select_cmd (idetape_pc_t *pc, int length) -{ - idetape_init_pc (pc); - set_bit (PC_WRITING, &pc->flags); - pc->c[0] = IDETAPE_MODE_SELECT_CMD; - pc->c[1] = 0x10; - put_unaligned (htons(length), (unsigned short *) &pc->c[3]); - pc->request_transfer = 255; - pc->callback = &idetape_pc_callback; -} - -static void idetape_create_erase_cmd (idetape_pc_t *pc) -{ - idetape_init_pc (pc); - pc->c[0] = IDETAPE_ERASE_CMD; - pc->c[1] = 1; - set_bit (PC_WAIT_FOR_DSC, &pc->flags); - pc->callback = &idetape_pc_callback; -} - -static void idetape_create_space_cmd (idetape_pc_t *pc,int count,byte cmd) -{ - idetape_init_pc (pc); - pc->c[0] = IDETAPE_SPACE_CMD; - put_unaligned (htonl (count), (unsigned int *) &pc->c[1]); - pc->c[1] = cmd; - set_bit (PC_WAIT_FOR_DSC, &pc->flags); - pc->callback = &idetape_pc_callback; -} - -/* - * Verify that we have the correct tape frame - */ -static int idetape_verify_stage (ide_drive_t *drive, idetape_stage_t *stage, int logical_blk_num, int quiet) -{ - idetape_tape_t *tape = drive->driver_data; - os_aux_t *aux = stage->aux; - os_partition_t *par = &aux->partition; - struct request *rq = &stage->rq; - struct buffer_head *bh; - - if (!tape->onstream) - return 1; - if (tape->raw) { - if (rq->errors) { - bh = stage->bh; - while (bh) { - memset(bh->b_data, 0, bh->b_size); - bh = bh->b_reqnext; - } - strcpy(stage->bh->b_data, "READ ERROR ON FRAME"); - } - return 1; - } - if (rq->errors == IDETAPE_ERROR_GENERAL) { - printk(KERN_INFO "ide-tape: %s: skipping frame, read error\n", tape->name); - return 0; - } - if (rq->errors == IDETAPE_ERROR_EOD) { - printk(KERN_INFO "ide-tape: %s: skipping frame, eod\n", tape->name); - return 0; - } - if (ntohl(aux->format_id) != 0) { - printk(KERN_INFO "ide-tape: %s: skipping frame, format_id %u\n", tape->name, ntohl(aux->format_id)); - return 0; - } - if (memcmp(aux->application_sig, tape->application_sig, 4) != 0) { - printk(KERN_INFO "ide-tape: %s: skipping frame, incorrect application signature\n", tape->name); - return 0; - } - if (aux->frame_type != OS_FRAME_TYPE_DATA && - aux->frame_type != OS_FRAME_TYPE_EOD && - aux->frame_type != OS_FRAME_TYPE_MARKER) { - printk(KERN_INFO "ide-tape: %s: skipping frame, frame type %x\n", tape->name, aux->frame_type); - return 0; - } - if (par->partition_num != OS_DATA_PARTITION) { - if (!tape->linux_media || tape->linux_media_version != 2) { - printk(KERN_INFO "ide-tape: %s: skipping frame, partition num %d\n", tape->name, par->partition_num); - return 0; - } - } - if (par->par_desc_ver != OS_PARTITION_VERSION) { - printk(KERN_INFO "ide-tape: %s: skipping frame, partition version %d\n", tape->name, par->par_desc_ver); - return 0; - } - if (ntohs(par->wrt_pass_cntr) != tape->wrt_pass_cntr) { - printk(KERN_INFO "ide-tape: %s: skipping frame, wrt_pass_cntr %d (expected %d)(logical_blk_num %u)\n", tape->name, ntohs(par->wrt_pass_cntr), tape->wrt_pass_cntr, ntohl(aux->logical_blk_num)); - return 0; - } - if (aux->frame_seq_num != aux->logical_blk_num) { - printk(KERN_INFO "ide-tape: %s: skipping frame, seq != logical\n", tape->name); - return 0; - } - if (logical_blk_num != -1 && ntohl(aux->logical_blk_num) != logical_blk_num) { - if (!quiet) - printk(KERN_INFO "ide-tape: %s: skipping frame, logical_blk_num %u (expected %d)\n", tape->name, ntohl(aux->logical_blk_num), logical_blk_num); - return 0; - } - if (aux->frame_type == OS_FRAME_TYPE_MARKER) { - rq->errors = IDETAPE_ERROR_FILEMARK; - rq->current_nr_sectors = rq->nr_sectors; - } - return 1; -} - -static void idetape_wait_first_stage (ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - unsigned long flags; - - if (tape->first_stage == NULL) - return; - spin_lock_irqsave(&tape->spinlock, flags); - if (tape->active_stage == tape->first_stage) - idetape_wait_for_request(drive, tape->active_data_request); - spin_unlock_irqrestore(&tape->spinlock, flags); -} - -/* - * idetape_add_chrdev_write_request tries to add a character device - * originated write request to our pipeline. In case we don't succeed, - * we revert to non-pipelined operation mode for this request. - * - * 1. Try to allocate a new pipeline stage. - * 2. If we can't, wait for more and more requests to be serviced - * and try again each time. - * 3. If we still can't allocate a stage, fallback to - * non-pipelined operation mode for this request. - */ -static int idetape_add_chrdev_write_request (ide_drive_t *drive, int blocks) -{ - idetape_tape_t *tape = drive->driver_data; - idetape_stage_t *new_stage; - unsigned long flags; - struct request *rq; - -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 3) - printk (KERN_INFO "ide-tape: Reached idetape_add_chrdev_write_request\n"); -#endif /* IDETAPE_DEBUG_LOG */ - - /* - * Attempt to allocate a new stage. - * Pay special attention to possible race conditions. - */ - while ((new_stage = idetape_kmalloc_stage (tape)) == NULL) { - spin_lock_irqsave(&tape->spinlock, flags); - if (idetape_pipeline_active (tape)) { - idetape_wait_for_request(drive, tape->active_data_request); - spin_unlock_irqrestore(&tape->spinlock, flags); - } else { - spin_unlock_irqrestore(&tape->spinlock, flags); - idetape_insert_pipeline_into_queue (drive); - if (idetape_pipeline_active (tape)) - continue; - /* - * Linux is short on memory. Fallback to - * non-pipelined operation mode for this request. - */ - return idetape_queue_rw_tail (drive, IDETAPE_WRITE_RQ, blocks, tape->merge_stage->bh); - } - } - rq = &new_stage->rq; - ide_init_drive_cmd (rq); - rq->cmd = IDETAPE_WRITE_RQ; - rq->sector = tape->first_frame_position; /* Doesn't actually matter - We always assume sequential access */ - rq->nr_sectors = rq->current_nr_sectors = blocks; - - idetape_switch_buffers (tape, new_stage); - idetape_init_stage(drive, new_stage, OS_FRAME_TYPE_DATA, tape->logical_blk_num); - tape->logical_blk_num++; - idetape_add_stage_tail (drive,new_stage); - tape->pipeline_head++; -#if USE_IOTRACE - IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head, tape->tape_head, tape->minor); -#endif - calculate_speeds(drive); - - /* - * Estimate whether the tape has stopped writing by checking - * if our write pipeline is currently empty. If we are not - * writing anymore, wait for the pipeline to be full enough - * (90%) before starting to service requests, so that we will - * be able to keep up with the higher speeds of the tape. - * - * For the OnStream drive, we can query the number of pending - * frames in the drive's internal buffer. As long as the tape - * is still writing, it is better to write frames immediately - * rather than gather them in the pipeline. This will give the - * tape's firmware the ability to sense the current incoming - * data rate more accurately, and since the OnStream tape - * supports variable speeds, it can try to adjust itself to the - * incoming data rate. - */ - if (!idetape_pipeline_active(tape)) { - if (tape->nr_stages >= tape->max_stages * 9 / 10 || - tape->nr_stages >= tape->max_stages - tape->uncontrolled_pipeline_head_speed * 3 * 1024 / tape->tape_block_size) { - tape->measure_insert_time = 1; - tape->insert_time = jiffies; - tape->insert_size = 0; - tape->insert_speed = 0; - idetape_insert_pipeline_into_queue (drive); - } else if (tape->onstream) { - idetape_update_stats(drive); - if (tape->cur_frames > 5) - idetape_insert_pipeline_into_queue (drive); - } - } - if (test_and_clear_bit (IDETAPE_PIPELINE_ERROR, &tape->flags)) /* Return a deferred error */ - return -EIO; - return blocks; -} - -/* - * idetape_wait_for_pipeline will wait until all pending pipeline - * requests are serviced. Typically called on device close. - */ -static void idetape_wait_for_pipeline (ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - unsigned long flags; - - while (tape->next_stage || idetape_pipeline_active(tape)) { - idetape_insert_pipeline_into_queue (drive); - spin_lock_irqsave(&tape->spinlock, flags); - if (idetape_pipeline_active(tape)) - idetape_wait_for_request(drive, tape->active_data_request); - spin_unlock_irqrestore(&tape->spinlock, flags); - } -} - -static void idetape_empty_write_pipeline (ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - int blocks, i, min; - struct buffer_head *bh; - -#if IDETAPE_DEBUG_BUGS - if (tape->chrdev_direction != idetape_direction_write) { - printk (KERN_ERR "ide-tape: bug: Trying to empty write pipeline, but we are not writing.\n"); - return; - } - if (tape->merge_stage_size > tape->stage_size) { - printk (KERN_ERR "ide-tape: bug: merge_buffer too big\n"); - tape->merge_stage_size = tape->stage_size; - } -#endif /* IDETAPE_DEBUG_BUGS */ - if (tape->merge_stage_size) { - blocks=tape->merge_stage_size/tape->tape_block_size; - if (tape->merge_stage_size % tape->tape_block_size) { - blocks++; - i = tape->tape_block_size - tape->merge_stage_size % tape->tape_block_size; - bh = tape->bh->b_reqnext; - while (bh) { - atomic_set(&bh->b_count, 0); - bh = bh->b_reqnext; - } - bh = tape->bh; - while (i) { - if (bh == NULL) { - printk(KERN_INFO "ide-tape: bug, bh NULL\n"); - break; - } - min = IDE_MIN(i, bh->b_size - atomic_read(&bh->b_count)); - memset(bh->b_data + atomic_read(&bh->b_count), 0, min); - atomic_add(min, &bh->b_count); - i -= min; - bh = bh->b_reqnext; - } - } - (void) idetape_add_chrdev_write_request (drive, blocks); - tape->merge_stage_size = 0; - } - idetape_wait_for_pipeline (drive); - if (tape->merge_stage != NULL) { - __idetape_kfree_stage (tape->merge_stage); - tape->merge_stage = NULL; - } - clear_bit (IDETAPE_PIPELINE_ERROR, &tape->flags); - tape->chrdev_direction=idetape_direction_none; - - /* - * On the next backup, perform the feedback loop again. - * (I don't want to keep sense information between backups, - * as some systems are constantly on, and the system load - * can be totally different on the next backup). - */ - tape->max_stages = tape->min_pipeline; -#if IDETAPE_DEBUG_BUGS - if (tape->first_stage != NULL || tape->next_stage != NULL || tape->last_stage != NULL || tape->nr_stages != 0) { - printk (KERN_ERR "ide-tape: ide-tape pipeline bug, " - "first_stage %p, next_stage %p, last_stage %p, nr_stages %d\n", - tape->first_stage, tape->next_stage, tape->last_stage, tape->nr_stages); - } -#endif /* IDETAPE_DEBUG_BUGS */ -} - -static void idetape_restart_speed_control (ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - - tape->restart_speed_control_req = 0; - tape->pipeline_head = 0; - tape->buffer_head = tape->tape_head = tape->cur_frames; - tape->controlled_last_pipeline_head = tape->uncontrolled_last_pipeline_head = 0; - tape->controlled_previous_pipeline_head = tape->uncontrolled_previous_pipeline_head = 0; - tape->pipeline_head_speed = tape->controlled_pipeline_head_speed = 5000; - tape->uncontrolled_pipeline_head_speed = 0; - tape->controlled_pipeline_head_time = tape->uncontrolled_pipeline_head_time = jiffies; - tape->controlled_previous_head_time = tape->uncontrolled_previous_head_time = jiffies; -} - -static int idetape_initiate_read (ide_drive_t *drive, int max_stages) -{ - idetape_tape_t *tape = drive->driver_data; - idetape_stage_t *new_stage; - struct request rq; - int bytes_read; - int blocks = tape->capabilities.ctl; - - if (tape->chrdev_direction != idetape_direction_read) { /* Initialize read operation */ - if (tape->chrdev_direction == idetape_direction_write) { - idetape_empty_write_pipeline (drive); - idetape_flush_tape_buffers (drive); - } -#if IDETAPE_DEBUG_BUGS - if (tape->merge_stage || tape->merge_stage_size) { - printk (KERN_ERR "ide-tape: merge_stage_size should be 0 now\n"); - tape->merge_stage_size = 0; - } -#endif /* IDETAPE_DEBUG_BUGS */ - if ((tape->merge_stage = __idetape_kmalloc_stage (tape, 0, 0)) == NULL) - return -ENOMEM; - tape->chrdev_direction = idetape_direction_read; - tape->logical_blk_num = 0; - - /* - * Issue a read 0 command to ensure that DSC handshake - * is switched from completion mode to buffer available - * mode. - */ - bytes_read = idetape_queue_rw_tail (drive, IDETAPE_READ_RQ, 0, tape->merge_stage->bh); - if (bytes_read < 0) { - kfree (tape->merge_stage); - tape->merge_stage = NULL; - tape->chrdev_direction = idetape_direction_none; - return bytes_read; - } - } - if (tape->restart_speed_control_req) - idetape_restart_speed_control(drive); - ide_init_drive_cmd (&rq); - rq.cmd = IDETAPE_READ_RQ; - rq.sector = tape->first_frame_position; - rq.nr_sectors = rq.current_nr_sectors = blocks; - if (!test_bit(IDETAPE_PIPELINE_ERROR, &tape->flags) && tape->nr_stages <= max_stages) { - new_stage=idetape_kmalloc_stage (tape); - while (new_stage != NULL) { - new_stage->rq=rq; - idetape_add_stage_tail (drive,new_stage); - if (tape->nr_stages >= max_stages) - break; - new_stage=idetape_kmalloc_stage (tape); - } - } - if (!idetape_pipeline_active(tape)) { - if (tape->nr_pending_stages >= 3 * max_stages / 4) { - tape->measure_insert_time = 1; - tape->insert_time = jiffies; - tape->insert_size = 0; - tape->insert_speed = 0; - idetape_insert_pipeline_into_queue (drive); - } else if (tape->onstream) { - idetape_update_stats(drive); - if (tape->cur_frames < tape->max_frames - 5) - idetape_insert_pipeline_into_queue (drive); - } - } - return 0; -} - -static int idetape_get_logical_blk (ide_drive_t *drive, int logical_blk_num, int max_stages, int quiet) -{ - idetape_tape_t *tape = drive->driver_data; - unsigned long flags; - int cnt = 0, x, position; - - /* - * Search and wait for the next logical tape block - */ - while (1) { - if (cnt++ > 1000) { /* AJN: was 100 */ - printk(KERN_INFO "ide-tape: %s: couldn't find logical block %d, aborting\n", tape->name, logical_blk_num); - return 0; - } - idetape_initiate_read(drive, max_stages); - if (tape->first_stage == NULL) { - if (tape->onstream) { -#if ONSTREAM_DEBUG - if (tape->debug_level >= 1) - printk(KERN_INFO "ide-tape: %s: first_stage == NULL, pipeline error %ld\n", tape->name, (long)test_bit(IDETAPE_PIPELINE_ERROR, &tape->flags)); -#endif - clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags); - position = idetape_read_position(drive); - printk(KERN_INFO "ide-tape: %s: blank block detected, positioning tape to block %d\n", tape->name, position + 60); - idetape_position_tape(drive, position + 60, 0, 1); - cnt += 40; - continue; - } else - return 0; - } - idetape_wait_first_stage(drive); - if (idetape_verify_stage(drive, tape->first_stage, logical_blk_num, quiet)) - break; - if (tape->first_stage->rq.errors == IDETAPE_ERROR_EOD) - cnt--; - if (idetape_verify_stage(drive, tape->first_stage, -1, quiet)) { - x = ntohl(tape->first_stage->aux->logical_blk_num); - if (x > logical_blk_num) { - printk(KERN_ERR "ide-tape: %s: couldn't find logical block %d, aborting (block %d found)\n", tape->name, logical_blk_num, x); - return 0; - } - } - spin_lock_irqsave(&tape->spinlock, flags); - idetape_remove_stage_head(drive); - spin_unlock_irqrestore(&tape->spinlock, flags); - } - if (tape->onstream) - tape->logical_blk_num = ntohl(tape->first_stage->aux->logical_blk_num); - return 1; -} - -/* - * idetape_add_chrdev_read_request is called from idetape_chrdev_read - * to service a character device read request and add read-ahead - * requests to our pipeline. - */ -static int idetape_add_chrdev_read_request (ide_drive_t *drive,int blocks) -{ - idetape_tape_t *tape = drive->driver_data; - unsigned long flags; - struct request *rq_ptr; - int bytes_read; - -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 4) - printk (KERN_INFO "ide-tape: Reached idetape_add_chrdev_read_request, %d blocks\n", blocks); -#endif /* IDETAPE_DEBUG_LOG */ - - /* - * Wait for the next logical block to be available at the head - * of the pipeline - */ - if (!idetape_get_logical_blk(drive, tape->logical_blk_num, tape->max_stages, 0)) { - if (tape->onstream) { - set_bit(IDETAPE_READ_ERROR, &tape->flags); - return 0; - } - if (test_bit(IDETAPE_PIPELINE_ERROR, &tape->flags)) - return 0; - return idetape_queue_rw_tail (drive, IDETAPE_READ_RQ, blocks, tape->merge_stage->bh); - } - rq_ptr = &tape->first_stage->rq; - bytes_read = tape->tape_block_size * (rq_ptr->nr_sectors - rq_ptr->current_nr_sectors); - rq_ptr->nr_sectors = rq_ptr->current_nr_sectors = 0; - - - if (tape->onstream && !tape->raw && tape->first_stage->aux->frame_type == OS_FRAME_TYPE_EOD) { -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: EOD reached\n", tape->name); -#endif - return 0; - } - if (rq_ptr->errors == IDETAPE_ERROR_EOD) - return 0; - else if (rq_ptr->errors == IDETAPE_ERROR_FILEMARK) - set_bit (IDETAPE_FILEMARK, &tape->flags); - else { - idetape_switch_buffers (tape, tape->first_stage); - if (rq_ptr->errors == IDETAPE_ERROR_GENERAL) { -#if ONSTREAM_DEBUG - if (tape->debug_level >= 1) - printk(KERN_INFO "ide-tape: error detected, bytes_read %d\n", bytes_read); -#endif - } - clear_bit (IDETAPE_FILEMARK, &tape->flags); - spin_lock_irqsave(&tape->spinlock, flags); - idetape_remove_stage_head (drive); - spin_unlock_irqrestore(&tape->spinlock, flags); - tape->logical_blk_num++; - tape->pipeline_head++; -#if USE_IOTRACE - IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head, tape->tape_head, tape->minor); -#endif - calculate_speeds(drive); - } -#if IDETAPE_DEBUG_BUGS - if (bytes_read > blocks*tape->tape_block_size) { - printk (KERN_ERR "ide-tape: bug: trying to return more bytes than requested\n"); - bytes_read=blocks*tape->tape_block_size; - } -#endif /* IDETAPE_DEBUG_BUGS */ - return (bytes_read); -} - -static void idetape_pad_zeros (ide_drive_t *drive, int bcount) -{ - idetape_tape_t *tape = drive->driver_data; - struct buffer_head *bh; - int count, blocks; - - while (bcount) { - bh = tape->merge_stage->bh; - count = IDE_MIN (tape->stage_size, bcount); - bcount -= count; - blocks = count / tape->tape_block_size; - while (count) { - atomic_set(&bh->b_count, IDE_MIN (count, bh->b_size)); - memset (bh->b_data, 0, atomic_read(&bh->b_count)); - count -= atomic_read(&bh->b_count); - bh = bh->b_reqnext; - } - idetape_queue_rw_tail (drive, IDETAPE_WRITE_RQ, blocks, tape->merge_stage->bh); - } -} - -static int idetape_pipeline_size (ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - idetape_stage_t *stage; - struct request *rq; - int size = 0; - - idetape_wait_for_pipeline (drive); - stage = tape->first_stage; - while (stage != NULL) { - rq = &stage->rq; - size += tape->tape_block_size * (rq->nr_sectors-rq->current_nr_sectors); - if (rq->errors == IDETAPE_ERROR_FILEMARK) - size += tape->tape_block_size; - stage = stage->next; - } - size += tape->merge_stage_size; - return size; -} - -/* - * Rewinds the tape to the Beginning Of the current Partition (BOP). - * - * We currently support only one partition. - */ -static int idetape_rewind_tape (ide_drive_t *drive) -{ - int retval; - idetape_pc_t pc; - idetape_tape_t *tape = drive->driver_data; -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 2) - printk (KERN_INFO "ide-tape: Reached idetape_rewind_tape\n"); -#endif /* IDETAPE_DEBUG_LOG */ - - idetape_create_rewind_cmd (drive, &pc); - retval=idetape_queue_pc_tail (drive,&pc); - if (retval) return retval; - - idetape_create_read_position_cmd (&pc); - retval = idetape_queue_pc_tail (drive,&pc); - if (retval) return retval; - tape->logical_blk_num = 0; - return 0; -} - -/* - * Our special ide-tape ioctl's. - * - * Currently there aren't any ioctl's. - * mtio.h compatible commands should be issued to the character device - * interface. - */ -static int idetape_blkdev_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - idetape_tape_t *tape = drive->driver_data; - idetape_config_t config; - -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 4) - printk (KERN_INFO "ide-tape: Reached idetape_blkdev_ioctl\n"); -#endif /* IDETAPE_DEBUG_LOG */ - switch (cmd) { - case 0x0340: - if (copy_from_user ((char *) &config, (char *) arg, sizeof (idetape_config_t))) - return -EFAULT; - tape->best_dsc_rw_frequency = config.dsc_rw_frequency; - tape->max_stages = config.nr_stages; - break; - case 0x0350: - config.dsc_rw_frequency = (int) tape->best_dsc_rw_frequency; - config.nr_stages = tape->max_stages; - if (copy_to_user ((char *) arg, (char *) &config, sizeof (idetape_config_t))) - return -EFAULT; - break; - default: - return -EIO; - } - return 0; -} - -/* - * The block device interface should not be used for data transfers. - * However, we still allow opening it so that we can issue general - * ide driver configuration ioctl's, such as the interrupt unmask feature. - */ -static int idetape_blkdev_open (struct inode *inode, struct file *filp, ide_drive_t *drive) -{ - MOD_INC_USE_COUNT; -#if ONSTREAM_DEBUG - printk(KERN_INFO "ide-tape: MOD_INC_USE_COUNT in idetape_blkdev_open\n"); -#endif - return 0; -} - -static void idetape_blkdev_release (struct inode *inode, struct file *filp, ide_drive_t *drive) -{ - MOD_DEC_USE_COUNT; -#if ONSTREAM_DEBUG - printk(KERN_INFO "ide-tape: MOD_DEC_USE_COUNT in idetape_blkdev_release\n"); -#endif -} - -/* - * idetape_pre_reset is called before an ATAPI/ATA software reset. - */ -static void idetape_pre_reset (ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - if (tape != NULL) - set_bit (IDETAPE_IGNORE_DSC, &tape->flags); -} - -/* - * Character device interface functions - */ -static ide_drive_t *get_drive_ptr (kdev_t i_rdev) -{ - unsigned int i = MINOR(i_rdev) & ~0xc0; - - if (i >= MAX_HWIFS * MAX_DRIVES) - return NULL; - return (idetape_chrdevs[i].drive); -} - -static int idetape_onstream_space_over_filemarks_backward (ide_drive_t *drive,short mt_op,int mt_count) -{ - idetape_tape_t *tape = drive->driver_data; - int cnt = 0; - int last_mark_addr; - unsigned long flags; - - if (!idetape_get_logical_blk(drive, -1, 10, 0)) { - printk(KERN_INFO "ide-tape: %s: couldn't get logical blk num in space_filemarks_bwd\n", tape->name); - return -EIO; - } - while (cnt != mt_count) { - last_mark_addr = ntohl(tape->first_stage->aux->last_mark_addr); - if (last_mark_addr == -1) - return -EIO; -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: positioning to last mark at %d\n", last_mark_addr); -#endif - idetape_position_tape(drive, last_mark_addr, 0, 0); - cnt++; - if (!idetape_get_logical_blk(drive, -1, 10, 0)) { - printk(KERN_INFO "ide-tape: %s: couldn't get logical blk num in space_filemarks\n", tape->name); - return -EIO; - } - if (tape->first_stage->aux->frame_type != OS_FRAME_TYPE_MARKER) { - printk(KERN_INFO "ide-tape: %s: expected to find marker at block %d, not found\n", tape->name, last_mark_addr); - return -EIO; - } - } - if (mt_op == MTBSFM) { - spin_lock_irqsave(&tape->spinlock, flags); - idetape_remove_stage_head (drive); - tape->logical_blk_num++; - spin_unlock_irqrestore(&tape->spinlock, flags); - } - return 0; -} - -/* - * ADRL 1.1 compatible "slow" space filemarks fwd version - * - * Just scans for the filemark sequentially. - */ -static int idetape_onstream_space_over_filemarks_forward_slow (ide_drive_t *drive,short mt_op,int mt_count) -{ - idetape_tape_t *tape = drive->driver_data; - int cnt = 0; - unsigned long flags; - - if (!idetape_get_logical_blk(drive, -1, 10, 0)) { - printk(KERN_INFO "ide-tape: %s: couldn't get logical blk num in space_filemarks_fwd\n", tape->name); - return -EIO; - } - while (1) { - if (!idetape_get_logical_blk(drive, -1, 10, 0)) { - printk(KERN_INFO "ide-tape: %s: couldn't get logical blk num in space_filemarks\n", tape->name); - return -EIO; - } - if (tape->first_stage->aux->frame_type == OS_FRAME_TYPE_MARKER) - cnt++; - if (tape->first_stage->aux->frame_type == OS_FRAME_TYPE_EOD) { -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: space_fwd: EOD reached\n", tape->name); -#endif - return -EIO; - } - if (cnt == mt_count) - break; - spin_lock_irqsave(&tape->spinlock, flags); - idetape_remove_stage_head (drive); - spin_unlock_irqrestore(&tape->spinlock, flags); - } - if (mt_op == MTFSF) { - spin_lock_irqsave(&tape->spinlock, flags); - idetape_remove_stage_head (drive); - tape->logical_blk_num++; - spin_unlock_irqrestore(&tape->spinlock, flags); - } - return 0; -} - - -/* - * Fast linux specific version of OnStream FSF - */ -static int idetape_onstream_space_over_filemarks_forward_fast (ide_drive_t *drive,short mt_op,int mt_count) -{ - idetape_tape_t *tape = drive->driver_data; - int cnt = 0, next_mark_addr; - unsigned long flags; - - if (!idetape_get_logical_blk(drive, -1, 10, 0)) { - printk(KERN_INFO "ide-tape: %s: couldn't get logical blk num in space_filemarks_fwd\n", tape->name); - return -EIO; - } - - /* - * Find nearest (usually previous) marker - */ - while (1) { - if (tape->first_stage->aux->frame_type == OS_FRAME_TYPE_MARKER) - break; - if (tape->first_stage->aux->frame_type == OS_FRAME_TYPE_EOD) { -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: space_fwd: EOD reached\n", tape->name); -#endif - return -EIO; - } - if (ntohl(tape->first_stage->aux->filemark_cnt) == 0) { - if (tape->first_mark_addr == -1) { - printk(KERN_INFO "ide-tape: %s: reverting to slow filemark space\n", tape->name); - return idetape_onstream_space_over_filemarks_forward_slow(drive, mt_op, mt_count); - } - idetape_position_tape(drive, tape->first_mark_addr, 0, 0); - if (!idetape_get_logical_blk(drive, -1, 10, 0)) { - printk(KERN_INFO "ide-tape: %s: couldn't get logical blk num in space_filemarks_fwd_fast\n", tape->name); - return -EIO; - } - if (tape->first_stage->aux->frame_type != OS_FRAME_TYPE_MARKER) { - printk(KERN_INFO "ide-tape: %s: expected to find filemark at %d\n", tape->name, tape->first_mark_addr); - return -EIO; - } - } else { - if (idetape_onstream_space_over_filemarks_backward(drive, MTBSF, 1) < 0) - return -EIO; - mt_count++; - } - } - cnt++; - while (cnt != mt_count) { - next_mark_addr = ntohl(tape->first_stage->aux->next_mark_addr); - if (!next_mark_addr || next_mark_addr > tape->eod_frame_addr) { - printk(KERN_INFO "ide-tape: %s: reverting to slow filemark space\n", tape->name); - return idetape_onstream_space_over_filemarks_forward_slow(drive, mt_op, mt_count - cnt); -#if ONSTREAM_DEBUG - } else if (tape->debug_level >= 2) { - printk(KERN_INFO "ide-tape: positioning to next mark at %d\n", next_mark_addr); -#endif - } - idetape_position_tape(drive, next_mark_addr, 0, 0); - cnt++; - if (!idetape_get_logical_blk(drive, -1, 10, 0)) { - printk(KERN_INFO "ide-tape: %s: couldn't get logical blk num in space_filemarks\n", tape->name); - return -EIO; - } - if (tape->first_stage->aux->frame_type != OS_FRAME_TYPE_MARKER) { - printk(KERN_INFO "ide-tape: %s: expected to find marker at block %d, not found\n", tape->name, next_mark_addr); - return -EIO; - } - } - if (mt_op == MTFSF) { - spin_lock_irqsave(&tape->spinlock, flags); - idetape_remove_stage_head (drive); - tape->logical_blk_num++; - spin_unlock_irqrestore(&tape->spinlock, flags); - } - return 0; -} - -/* - * idetape_space_over_filemarks is now a bit more complicated than just - * passing the command to the tape since we may have crossed some - * filemarks during our pipelined read-ahead mode. - * - * As a minor side effect, the pipeline enables us to support MTFSFM when - * the filemark is in our internal pipeline even if the tape doesn't - * support spacing over filemarks in the reverse direction. - */ -static int idetape_space_over_filemarks (ide_drive_t *drive,short mt_op,int mt_count) -{ - idetape_tape_t *tape = drive->driver_data; - idetape_pc_t pc; - unsigned long flags; - int retval,count=0; - int speed_control; - - if (tape->onstream) { - if (tape->raw) - return -EIO; - speed_control = tape->speed_control; - tape->speed_control = 0; - if (mt_op == MTFSF || mt_op == MTFSFM) { - if (tape->linux_media) - retval = idetape_onstream_space_over_filemarks_forward_fast(drive, mt_op, mt_count); - else - retval = idetape_onstream_space_over_filemarks_forward_slow(drive, mt_op, mt_count); - } else - retval = idetape_onstream_space_over_filemarks_backward(drive, mt_op, mt_count); - tape->speed_control = speed_control; - tape->restart_speed_control_req = 1; - return retval; - } - - if (tape->chrdev_direction == idetape_direction_read) { - /* - * We have a read-ahead buffer. Scan it for crossed - * filemarks. - */ - tape->merge_stage_size = 0; - clear_bit (IDETAPE_FILEMARK, &tape->flags); - while (tape->first_stage != NULL) { - idetape_wait_first_stage(drive); - if (tape->first_stage->rq.errors == IDETAPE_ERROR_FILEMARK) - count++; - if (count == mt_count) { - switch (mt_op) { - case MTFSF: - spin_lock_irqsave(&tape->spinlock, flags); - idetape_remove_stage_head (drive); - spin_unlock_irqrestore(&tape->spinlock, flags); - case MTFSFM: - return (0); - default: - break; - } - } - spin_lock_irqsave(&tape->spinlock, flags); - idetape_remove_stage_head (drive); - spin_unlock_irqrestore(&tape->spinlock, flags); - } - idetape_discard_read_pipeline (drive, 1); - } - - /* - * The filemark was not found in our internal pipeline. - * Now we can issue the space command. - */ - switch (mt_op) { - case MTFSF: - idetape_create_space_cmd (&pc,mt_count-count,IDETAPE_SPACE_OVER_FILEMARK); - return (idetape_queue_pc_tail (drive,&pc)); - case MTFSFM: - if (!tape->capabilities.sprev) - return (-EIO); - retval = idetape_space_over_filemarks (drive, MTFSF, mt_count-count); - if (retval) return (retval); - return (idetape_space_over_filemarks (drive, MTBSF, 1)); - case MTBSF: - if (!tape->capabilities.sprev) - return (-EIO); - idetape_create_space_cmd (&pc,-(mt_count+count),IDETAPE_SPACE_OVER_FILEMARK); - return (idetape_queue_pc_tail (drive,&pc)); - case MTBSFM: - if (!tape->capabilities.sprev) - return (-EIO); - retval = idetape_space_over_filemarks (drive, MTBSF, mt_count+count); - if (retval) return (retval); - return (idetape_space_over_filemarks (drive, MTFSF, 1)); - default: - printk (KERN_ERR "ide-tape: MTIO operation %d not supported\n",mt_op); - return (-EIO); - } -} - - -/* - * Our character device read / write functions. - * - * The tape is optimized to maximize throughput when it is transferring - * an integral number of the "continuous transfer limit", which is - * a parameter of the specific tape (26 KB on my particular tape). - * (32 kB for Onstream) - * - * As of version 1.3 of the driver, the character device provides an - * abstract continuous view of the media - any mix of block sizes (even 1 - * byte) on the same backup/restore procedure is supported. The driver - * will internally convert the requests to the recommended transfer unit, - * so that an unmatch between the user's block size to the recommended - * size will only result in a (slightly) increased driver overhead, but - * will no longer hit performance. - * This is not applicable to Onstream. - */ -static ssize_t idetape_chrdev_read (struct file *file, char *buf, - size_t count, loff_t *ppos) -{ - struct inode *inode = file->f_dentry->d_inode; - ide_drive_t *drive = get_drive_ptr (inode->i_rdev); - idetape_tape_t *tape = drive->driver_data; - ssize_t bytes_read,temp,actually_read=0, rc; - - if (ppos != &file->f_pos) { - /* "A request was outside the capabilities of the device." */ - return -ENXIO; - } - if (tape->onstream && (count != tape->tape_block_size)) { - printk(KERN_ERR "ide-tape: %s: use %d bytes as block size (%Zd used)\n", tape->name, tape->tape_block_size, count); - return -EINVAL; - } -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 3) - printk (KERN_INFO "ide-tape: Reached idetape_chrdev_read, count %Zd\n", count); -#endif /* IDETAPE_DEBUG_LOG */ - - if (tape->chrdev_direction != idetape_direction_read) { - if (test_bit (IDETAPE_DETECT_BS, &tape->flags)) - if (count > tape->tape_block_size && (count % tape->tape_block_size) == 0) - tape->user_bs_factor = count / tape->tape_block_size; - } - if ((rc = idetape_initiate_read(drive, tape->max_stages)) < 0) - return rc; - if (count==0) - return (0); - if (tape->merge_stage_size) { - actually_read=IDE_MIN (tape->merge_stage_size,count); - idetape_copy_stage_to_user (tape, buf, tape->merge_stage, actually_read); - buf += actually_read; tape->merge_stage_size -= actually_read; count-=actually_read; - } - while (count >= tape->stage_size) { - bytes_read=idetape_add_chrdev_read_request (drive, tape->capabilities.ctl); - if (bytes_read <= 0) - goto finish; - idetape_copy_stage_to_user (tape, buf, tape->merge_stage, bytes_read); - buf += bytes_read; count -= bytes_read; actually_read += bytes_read; - } - if (count) { - bytes_read=idetape_add_chrdev_read_request (drive, tape->capabilities.ctl); - if (bytes_read <= 0) - goto finish; - temp=IDE_MIN (count,bytes_read); - idetape_copy_stage_to_user (tape, buf, tape->merge_stage, temp); - actually_read+=temp; - tape->merge_stage_size=bytes_read-temp; - } -finish: - if (!actually_read && test_bit (IDETAPE_FILEMARK, &tape->flags)) { -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: spacing over filemark\n", tape->name); -#endif - idetape_space_over_filemarks (drive, MTFSF, 1); - return 0; - } - if (tape->onstream && !actually_read && test_and_clear_bit(IDETAPE_READ_ERROR, &tape->flags)) { - printk(KERN_ERR "ide-tape: %s: unrecovered read error on logical block number %d, skipping\n", tape->name, tape->logical_blk_num); - tape->logical_blk_num++; - return -EIO; - } - return actually_read; -} - -static void idetape_update_last_marker (ide_drive_t *drive, int last_mark_addr, int next_mark_addr) -{ - idetape_tape_t *tape = drive->driver_data; - idetape_stage_t *stage; - os_aux_t *aux; - int position; - - if (!tape->onstream || tape->raw) - return; - if (last_mark_addr == -1) - return; - stage = __idetape_kmalloc_stage(tape, 0, 0); - if (stage == NULL) - return; - idetape_flush_tape_buffers(drive); - position = idetape_read_position(drive); -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: current position (2) %d, lblk %d\n", position, tape->logical_blk_num); - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: current position (2) tape block %d\n", tape->last_frame_position); -#endif - idetape_position_tape(drive, last_mark_addr, 0, 0); - if (!idetape_queue_rw_tail (drive, IDETAPE_READ_RQ, 1, stage->bh)) { - printk(KERN_INFO "ide-tape: %s: couldn't read last marker\n", tape->name); - __idetape_kfree_stage (stage); - idetape_position_tape(drive, position, 0, 0); - return; - } - aux = stage->aux; - if (aux->frame_type != OS_FRAME_TYPE_MARKER) { - printk(KERN_INFO "ide-tape: %s: expected to find marker at addr %d\n", tape->name, last_mark_addr); - __idetape_kfree_stage (stage); - idetape_position_tape(drive, position, 0, 0); - return; - } -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: writing back marker\n"); -#endif - aux->next_mark_addr = htonl(next_mark_addr); - idetape_position_tape(drive, last_mark_addr, 0, 0); - if (!idetape_queue_rw_tail (drive, IDETAPE_WRITE_RQ, 1, stage->bh)) { - printk(KERN_INFO "ide-tape: %s: couldn't write back marker frame at %d\n", tape->name, last_mark_addr); - __idetape_kfree_stage (stage); - idetape_position_tape(drive, position, 0, 0); - return; - } - __idetape_kfree_stage (stage); - idetape_flush_tape_buffers (drive); - idetape_position_tape(drive, position, 0, 0); - return; -} - -static void __idetape_write_header (ide_drive_t *drive, int block, int cnt) -{ - idetape_tape_t *tape = drive->driver_data; - idetape_stage_t *stage; - os_header_t header; - - stage = __idetape_kmalloc_stage(tape, 1, 1); - if (stage == NULL) - return; - idetape_init_stage(drive, stage, OS_FRAME_TYPE_HEADER, tape->logical_blk_num); - idetape_wait_ready(drive, 60 * 5 * HZ); - idetape_position_tape(drive, block, 0, 0); - memset(&header, 0, sizeof(header)); - strcpy(header.ident_str, "ADR_SEQ"); - header.major_rev = 1; - header.minor_rev = 2; - header.par_num = 1; - header.partition.partition_num = OS_DATA_PARTITION; - header.partition.par_desc_ver = OS_PARTITION_VERSION; - header.partition.first_frame_addr = htonl(0x14); - header.partition.last_frame_addr = htonl(19239 * 24); - header.partition.wrt_pass_cntr = htons(tape->wrt_pass_cntr); - header.partition.eod_frame_addr = htonl(tape->eod_frame_addr); - memcpy(stage->bh->b_data, &header, sizeof(header)); - while (cnt--) { - if (!idetape_queue_rw_tail (drive, IDETAPE_WRITE_RQ, 1, stage->bh)) { - printk(KERN_INFO "ide-tape: %s: couldn't write header frame\n", tape->name); - __idetape_kfree_stage (stage); - return; - } - } - __idetape_kfree_stage (stage); - idetape_flush_tape_buffers (drive); -} - -static void idetape_write_header (ide_drive_t *drive, int locate_eod) -{ - idetape_tape_t *tape = drive->driver_data; - -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: writing tape header\n", tape->name); -#endif - if (!tape->onstream || tape->raw) - return; - tape->update_frame_cntr++; - __idetape_write_header(drive, 5, 5); - __idetape_write_header(drive, 0xbae, 5); - if (locate_eod) { -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: locating back to eod frame addr %d\n", tape->name, tape->eod_frame_addr); -#endif - idetape_position_tape(drive, tape->eod_frame_addr, 0, 0); - } -} - -static ssize_t idetape_chrdev_write (struct file *file, const char *buf, - size_t count, loff_t *ppos) -{ - struct inode *inode = file->f_dentry->d_inode; - ide_drive_t *drive = get_drive_ptr (inode->i_rdev); - idetape_tape_t *tape = drive->driver_data; - ssize_t retval,actually_written=0; - int position; - - if (ppos != &file->f_pos) { - /* "A request was outside the capabilities of the device." */ - return -ENXIO; - } - if (tape->onstream && (count != tape->tape_block_size)) { - printk(KERN_ERR "ide-tape: %s: use %d bytes as block size (%Zd used)\n", tape->name, tape->tape_block_size, count); - return -EINVAL; - } -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 3) - printk (KERN_INFO "ide-tape: Reached idetape_chrdev_write, count %Zd\n", count); -#endif /* IDETAPE_DEBUG_LOG */ - - if (tape->chrdev_direction != idetape_direction_write) { /* Initialize write operation */ - if (tape->chrdev_direction == idetape_direction_read) - idetape_discard_read_pipeline (drive, 1); -#if IDETAPE_DEBUG_BUGS - if (tape->merge_stage || tape->merge_stage_size) { - printk (KERN_ERR "ide-tape: merge_stage_size should be 0 now\n"); - tape->merge_stage_size = 0; - } -#endif /* IDETAPE_DEBUG_BUGS */ - if ((tape->merge_stage = __idetape_kmalloc_stage (tape, 0, 0)) == NULL) - return -ENOMEM; - tape->chrdev_direction = idetape_direction_write; - idetape_init_merge_stage (tape); - - if (tape->onstream) { - position = idetape_read_position(drive); - if (position <= 20) { - tape->logical_blk_num = 0; - tape->wrt_pass_cntr++; -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: logical block num 0, setting eod to 20\n", tape->name); - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: allocating new write pass counter %d\n", tape->name, tape->wrt_pass_cntr); -#endif - tape->filemark_cnt = 0; - tape->eod_frame_addr = 20; - tape->first_mark_addr = tape->last_mark_addr = -1; - idetape_write_header(drive, 1); - } -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: positioning tape to eod at %d\n", tape->name, tape->eod_frame_addr); -#endif - position = idetape_read_position(drive); - if (position != tape->eod_frame_addr) - idetape_position_tape(drive, tape->eod_frame_addr, 0, 0); -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: first_frame_position %d\n", tape->name, tape->first_frame_position); -#endif - } - - /* - * Issue a write 0 command to ensure that DSC handshake - * is switched from completion mode to buffer available - * mode. - */ - retval = idetape_queue_rw_tail (drive, IDETAPE_WRITE_RQ, 0, tape->merge_stage->bh); - if (retval < 0) { - kfree (tape->merge_stage); - tape->merge_stage = NULL; - tape->chrdev_direction = idetape_direction_none; - return retval; - } -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk("ide-tape: first_frame_position %d\n", tape->first_frame_position); -#endif - } - if (count==0) - return (0); - if (tape->restart_speed_control_req) - idetape_restart_speed_control(drive); - if (tape->merge_stage_size) { -#if IDETAPE_DEBUG_BUGS - if (tape->merge_stage_size >= tape->stage_size) { - printk (KERN_ERR "ide-tape: bug: merge buffer too big\n"); - tape->merge_stage_size=0; - } -#endif /* IDETAPE_DEBUG_BUGS */ - actually_written=IDE_MIN (tape->stage_size-tape->merge_stage_size,count); - idetape_copy_stage_from_user (tape, tape->merge_stage, buf, actually_written); - buf+=actually_written;tape->merge_stage_size+=actually_written;count-=actually_written; - - if (tape->merge_stage_size == tape->stage_size) { - tape->merge_stage_size = 0; - retval=idetape_add_chrdev_write_request (drive, tape->capabilities.ctl); - if (retval <= 0) - return (retval); - } - } - while (count >= tape->stage_size) { - idetape_copy_stage_from_user (tape, tape->merge_stage, buf, tape->stage_size); - buf+=tape->stage_size;count-=tape->stage_size; - retval=idetape_add_chrdev_write_request (drive, tape->capabilities.ctl); - actually_written+=tape->stage_size; - if (retval <= 0) - return (retval); - } - if (count) { - actually_written+=count; - idetape_copy_stage_from_user (tape, tape->merge_stage, buf, count); - tape->merge_stage_size+=count; - } - return (actually_written); -} - -static int idetape_write_filemark (ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - int last_mark_addr; - idetape_pc_t pc; - - if (!tape->onstream) { - idetape_create_write_filemark_cmd(drive, &pc,1); /* Write a filemark */ - if (idetape_queue_pc_tail (drive,&pc)) { - printk (KERN_ERR "ide-tape: Couldn't write a filemark\n"); - return -EIO; - } - } else if (!tape->raw) { - last_mark_addr = idetape_read_position(drive); - tape->merge_stage = __idetape_kmalloc_stage (tape, 1, 0); - if (tape->merge_stage != NULL) { - idetape_init_stage(drive, tape->merge_stage, OS_FRAME_TYPE_MARKER, tape->logical_blk_num); - idetape_pad_zeros (drive, tape->stage_size); - tape->logical_blk_num++; - __idetape_kfree_stage (tape->merge_stage); - tape->merge_stage = NULL; - } - if (tape->filemark_cnt) - idetape_update_last_marker(drive, tape->last_mark_addr, last_mark_addr); - tape->last_mark_addr = last_mark_addr; - if (tape->filemark_cnt++ == 0) - tape->first_mark_addr = last_mark_addr; - } - return 0; -} - -static void idetape_write_eod (ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - - if (!tape->onstream || tape->raw) - return; - tape->merge_stage = __idetape_kmalloc_stage (tape, 1, 0); - if (tape->merge_stage != NULL) { - tape->eod_frame_addr = idetape_read_position(drive); - idetape_init_stage(drive, tape->merge_stage, OS_FRAME_TYPE_EOD, tape->logical_blk_num); - idetape_pad_zeros (drive, tape->stage_size); - __idetape_kfree_stage (tape->merge_stage); - tape->merge_stage = NULL; - } - return; -} - -int idetape_seek_logical_blk (ide_drive_t *drive, int logical_blk_num) -{ - idetape_tape_t *tape = drive->driver_data; - int estimated_address = logical_blk_num + 20; - int retries = 0; - int speed_control; - - speed_control = tape->speed_control; - tape->speed_control = 0; - if (logical_blk_num < 0) - logical_blk_num = 0; - if (idetape_get_logical_blk(drive, logical_blk_num, 10, 1)) - goto ok; - while (++retries < 10) { - idetape_discard_read_pipeline(drive, 0); - idetape_position_tape(drive, estimated_address, 0, 0); - if (idetape_get_logical_blk(drive, logical_blk_num, 10, 1)) - goto ok; - if (!idetape_get_logical_blk(drive, -1, 10, 1)) - goto error; - if (tape->logical_blk_num < logical_blk_num) - estimated_address += logical_blk_num - tape->logical_blk_num; - else - break; - } -error: - tape->speed_control = speed_control; - tape->restart_speed_control_req = 1; - printk(KERN_INFO "ide-tape: %s: couldn't seek to logical block %d (at %d), %d retries\n", tape->name, logical_blk_num, tape->logical_blk_num, retries); - return -EIO; -ok: - tape->speed_control = speed_control; - tape->restart_speed_control_req = 1; - return 0; -} - -/* - * idetape_mtioctop is called from idetape_chrdev_ioctl when - * the general mtio MTIOCTOP ioctl is requested. - * - * We currently support the following mtio.h operations: - * - * MTFSF - Space over mt_count filemarks in the positive direction. - * The tape is positioned after the last spaced filemark. - * - * MTFSFM - Same as MTFSF, but the tape is positioned before the - * last filemark. - * - * MTBSF - Steps background over mt_count filemarks, tape is - * positioned before the last filemark. - * - * MTBSFM - Like MTBSF, only tape is positioned after the last filemark. - * - * Note: - * - * MTBSF and MTBSFM are not supported when the tape doesn't - * supports spacing over filemarks in the reverse direction. - * In this case, MTFSFM is also usually not supported (it is - * supported in the rare case in which we crossed the filemark - * during our read-ahead pipelined operation mode). - * - * MTWEOF - Writes mt_count filemarks. Tape is positioned after - * the last written filemark. - * - * MTREW - Rewinds tape. - * - * MTLOAD - Loads the tape. - * - * MTOFFL - Puts the tape drive "Offline": Rewinds the tape and - * MTUNLOAD prevents further access until the media is replaced. - * - * MTNOP - Flushes tape buffers. - * - * MTRETEN - Retension media. This typically consists of one end - * to end pass on the media. - * - * MTEOM - Moves to the end of recorded data. - * - * MTERASE - Erases tape. - * - * MTSETBLK - Sets the user block size to mt_count bytes. If - * mt_count is 0, we will attempt to autodetect - * the block size. - * - * MTSEEK - Positions the tape in a specific block number, where - * each block is assumed to contain which user_block_size - * bytes. - * - * MTSETPART - Switches to another tape partition. - * - * MTLOCK - Locks the tape door. - * - * MTUNLOCK - Unlocks the tape door. - * - * The following commands are currently not supported: - * - * MTFSS, MTBSS, MTWSM, MTSETDENSITY, - * MTSETDRVBUFFER, MT_ST_BOOLEANS, MT_ST_WRITE_THRESHOLD. - */ -static int idetape_mtioctop (ide_drive_t *drive,short mt_op,int mt_count) -{ - idetape_tape_t *tape = drive->driver_data; - idetape_pc_t pc; - int i,retval; - -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 1) - printk (KERN_INFO "ide-tape: Handling MTIOCTOP ioctl: mt_op=%d, mt_count=%d\n",mt_op,mt_count); -#endif /* IDETAPE_DEBUG_LOG */ - /* - * Commands which need our pipelined read-ahead stages. - */ - switch (mt_op) { - case MTFSF: - case MTFSFM: - case MTBSF: - case MTBSFM: - if (!mt_count) - return (0); - return (idetape_space_over_filemarks (drive,mt_op,mt_count)); - default: - break; - } - switch (mt_op) { - case MTWEOF: - idetape_discard_read_pipeline (drive, 1); - for (i = 0; i < mt_count; i++) { - retval = idetape_write_filemark(drive); - if (retval) return retval; - } - return (0); - case MTREW: - idetape_discard_read_pipeline (drive, 0); - if (idetape_rewind_tape(drive)) - return -EIO; - if (tape->onstream && !tape->raw) - return idetape_position_tape(drive, 20, 0, 0); - return 0; - case MTLOAD: - idetape_discard_read_pipeline (drive, 0); - idetape_create_load_unload_cmd (drive, &pc, IDETAPE_LU_LOAD_MASK); - return (idetape_queue_pc_tail (drive,&pc)); - case MTUNLOAD: - case MTOFFL: - idetape_discard_read_pipeline (drive, 0); - idetape_create_load_unload_cmd (drive, &pc,!IDETAPE_LU_LOAD_MASK); - return (idetape_queue_pc_tail (drive,&pc)); - case MTNOP: - idetape_discard_read_pipeline (drive, 0); - return (idetape_flush_tape_buffers (drive)); - case MTRETEN: - idetape_discard_read_pipeline (drive, 0); - idetape_create_load_unload_cmd (drive, &pc,IDETAPE_LU_RETENSION_MASK | IDETAPE_LU_LOAD_MASK); - return (idetape_queue_pc_tail (drive,&pc)); - case MTEOM: - if (tape->onstream) { -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: positioning tape to eod at %d\n", tape->name, tape->eod_frame_addr); -#endif - idetape_position_tape(drive, tape->eod_frame_addr, 0, 0); - if (!idetape_get_logical_blk(drive, -1, 10, 0)) - return -EIO; - if (tape->first_stage->aux->frame_type != OS_FRAME_TYPE_EOD) - return -EIO; - return 0; - } - idetape_create_space_cmd (&pc,0,IDETAPE_SPACE_TO_EOD); - return (idetape_queue_pc_tail (drive,&pc)); - case MTERASE: - if (tape->onstream) { - tape->eod_frame_addr = 20; - tape->logical_blk_num = 0; - tape->first_mark_addr = tape->last_mark_addr = -1; - idetape_position_tape(drive, tape->eod_frame_addr, 0, 0); - idetape_write_eod(drive); - idetape_flush_tape_buffers (drive); - idetape_write_header(drive, 0); - idetape_flush_tape_buffers (drive); - (void) idetape_rewind_tape (drive); - return 0; - } - (void) idetape_rewind_tape (drive); - idetape_create_erase_cmd (&pc); - return (idetape_queue_pc_tail (drive,&pc)); - case MTSETBLK: - if (tape->onstream) { - if (mt_count != tape->tape_block_size) { - printk(KERN_INFO "ide-tape: %s: MTSETBLK %d -- only %d bytes block size supported\n", tape->name, mt_count, tape->tape_block_size); - return -EINVAL; - } - return 0; - } - if (mt_count) { - if (mt_count < tape->tape_block_size || mt_count % tape->tape_block_size) - return -EIO; - tape->user_bs_factor = mt_count / tape->tape_block_size; - clear_bit (IDETAPE_DETECT_BS, &tape->flags); - } else - set_bit (IDETAPE_DETECT_BS, &tape->flags); - return 0; - case MTSEEK: - if (!tape->onstream || tape->raw) { - idetape_discard_read_pipeline (drive, 0); - return idetape_position_tape (drive, mt_count * tape->user_bs_factor, tape->partition, 0); - } - return idetape_seek_logical_blk(drive, mt_count); - case MTSETPART: - idetape_discard_read_pipeline (drive, 0); - if (tape->onstream) - return -EIO; - return (idetape_position_tape (drive, 0, mt_count, 0)); - case MTFSR: - case MTBSR: - if (tape->onstream) { - if (!idetape_get_logical_blk(drive, -1, 10, 0)) - return -EIO; - if (mt_op == MTFSR) - return idetape_seek_logical_blk(drive, tape->logical_blk_num + mt_count); - else { - idetape_discard_read_pipeline (drive, 0); - return idetape_seek_logical_blk(drive, tape->logical_blk_num - mt_count); - } - } - case MTLOCK: - idetape_create_prevent_cmd(drive, &pc, 1); - retval = idetape_queue_pc_tail (drive,&pc); - if (retval) return retval; - tape->door_locked = DOOR_EXPLICITLY_LOCKED; - return 0; - case MTUNLOCK: - idetape_create_prevent_cmd(drive, &pc, 0); - retval = idetape_queue_pc_tail (drive,&pc); - if (retval) return retval; - tape->door_locked = DOOR_UNLOCKED; - return 0; - default: - printk (KERN_ERR "ide-tape: MTIO operation %d not supported\n",mt_op); - return (-EIO); - } -} - -/* - * Our character device ioctls. - * - * General mtio.h magnetic io commands are supported here, and not in - * the corresponding block interface. - * - * The following ioctls are supported: - * - * MTIOCTOP - Refer to idetape_mtioctop for detailed description. - * - * MTIOCGET - The mt_dsreg field in the returned mtget structure - * will be set to (user block size in bytes << - * MT_ST_BLKSIZE_SHIFT) & MT_ST_BLKSIZE_MASK. - * - * The mt_blkno is set to the current user block number. - * The other mtget fields are not supported. - * - * MTIOCPOS - The current tape "block position" is returned. We - * assume that each block contains user_block_size - * bytes. - * - * Our own ide-tape ioctls are supported on both interfaces. - */ -static int idetape_chrdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) -{ - ide_drive_t *drive = get_drive_ptr (inode->i_rdev); - idetape_tape_t *tape = drive->driver_data; - struct mtop mtop; - struct mtget mtget; - struct mtpos mtpos; - int block_offset = 0, position = tape->first_frame_position; - -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 3) - printk (KERN_INFO "ide-tape: Reached idetape_chrdev_ioctl, cmd=%u\n",cmd); -#endif /* IDETAPE_DEBUG_LOG */ - - tape->restart_speed_control_req = 1; - if (tape->chrdev_direction == idetape_direction_write) { - idetape_empty_write_pipeline (drive); - idetape_flush_tape_buffers (drive); - } - if (cmd == MTIOCGET || cmd == MTIOCPOS) { - block_offset = idetape_pipeline_size (drive) / (tape->tape_block_size * tape->user_bs_factor); - if ((position = idetape_read_position(drive)) < 0) - return -EIO; - } - switch (cmd) { - case MTIOCTOP: - if (copy_from_user ((char *) &mtop, (char *) arg, sizeof (struct mtop))) - return -EFAULT; - return (idetape_mtioctop (drive,mtop.mt_op,mtop.mt_count)); - case MTIOCGET: - memset (&mtget, 0, sizeof (struct mtget)); - mtget.mt_type = MT_ISSCSI2; - if (!tape->onstream || tape->raw) - mtget.mt_blkno = position / tape->user_bs_factor - block_offset; - else { - if (!idetape_get_logical_blk(drive, -1, 10, 0)) - mtget.mt_blkno = -1; - else - mtget.mt_blkno = tape->logical_blk_num; - } - mtget.mt_dsreg = ((tape->tape_block_size * tape->user_bs_factor) << MT_ST_BLKSIZE_SHIFT) & MT_ST_BLKSIZE_MASK; - if (tape->onstream) { - mtget.mt_gstat |= GMT_ONLINE(0xffffffff); - if (tape->first_stage && tape->first_stage->aux->frame_type == OS_FRAME_TYPE_EOD) - mtget.mt_gstat |= GMT_EOD(0xffffffff); - if (position <= 20) - mtget.mt_gstat |= GMT_BOT(0xffffffff); - } - if (copy_to_user ((char *) arg,(char *) &mtget, sizeof (struct mtget))) - return -EFAULT; - return 0; - case MTIOCPOS: - if (tape->onstream && !tape->raw) { - if (!idetape_get_logical_blk(drive, -1, 10, 0)) - return -EIO; - mtpos.mt_blkno = tape->logical_blk_num; - } else - mtpos.mt_blkno = position / tape->user_bs_factor - block_offset; - if (copy_to_user ((char *) arg,(char *) &mtpos, sizeof (struct mtpos))) - return -EFAULT; - return 0; - default: - if (tape->chrdev_direction == idetape_direction_read) - idetape_discard_read_pipeline (drive, 1); - return (idetape_blkdev_ioctl (drive,inode,file,cmd,arg)); - } -} - -static int __idetape_analyze_headers (ide_drive_t *drive, int block) -{ - idetape_tape_t *tape = drive->driver_data; - idetape_stage_t *stage; - os_header_t *header; - os_aux_t *aux; - - if (!tape->onstream || tape->raw) { - tape->header_ok = tape->linux_media = 1; - return 1; - } - tape->header_ok = tape->linux_media = 0; - tape->update_frame_cntr = 0; - tape->wrt_pass_cntr = 0; - tape->eod_frame_addr = 20; - tape->first_mark_addr = tape->last_mark_addr = -1; - stage = __idetape_kmalloc_stage (tape, 0, 0); - if (stage == NULL) - return 0; -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: reading header\n", tape->name); -#endif - idetape_position_tape(drive, block, 0, 0); - if (!idetape_queue_rw_tail (drive, IDETAPE_READ_RQ, 1, stage->bh)) { - printk(KERN_INFO "ide-tape: %s: couldn't read header frame\n", tape->name); - __idetape_kfree_stage (stage); - return 0; - } - header = (os_header_t *) stage->bh->b_data; - aux = stage->aux; - if (strncmp(header->ident_str, "ADR_SEQ", 7) != 0) { - printk(KERN_INFO "ide-tape: %s: invalid header identification string\n", tape->name); - __idetape_kfree_stage (stage); - return 0; - } - if (header->major_rev != 1 || (header->minor_rev != 1 && header->minor_rev != 2)) - printk(KERN_INFO "ide-tape: warning: revision %d.%d detected (1.1/1.2 supported)\n", header->major_rev, header->minor_rev); - if (header->par_num != 1) - printk(KERN_INFO "ide-tape: warning: %d partitions defined, only one supported\n", header->par_num); - tape->wrt_pass_cntr = ntohs(header->partition.wrt_pass_cntr); - tape->eod_frame_addr = ntohl(header->partition.eod_frame_addr); - tape->filemark_cnt = ntohl(aux->filemark_cnt); - tape->first_mark_addr = ntohl(aux->next_mark_addr); - tape->last_mark_addr = ntohl(aux->last_mark_addr); - tape->update_frame_cntr = ntohl(aux->update_frame_cntr); - memcpy(tape->application_sig, aux->application_sig, 4); tape->application_sig[4] = 0; - if (memcmp(tape->application_sig, "LIN", 3) == 0) { - tape->linux_media = 1; - tape->linux_media_version = tape->application_sig[3] - '0'; - if (tape->linux_media_version != 3) - printk(KERN_INFO "ide-tape: %s: Linux media version %d detected (current 3)\n", tape->name, tape->linux_media_version); - } else { - printk(KERN_INFO "ide-tape: %s: non Linux media detected (%s)\n", tape->name, tape->application_sig); - tape->linux_media = 0; - } -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: detected write pass counter %d, eod frame addr %d\n", tape->name, tape->wrt_pass_cntr, tape->eod_frame_addr); -#endif - __idetape_kfree_stage (stage); - return 1; -} - -static int idetape_analyze_headers (ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - int position, block; - - if (!tape->onstream || tape->raw) { - tape->header_ok = tape->linux_media = 1; - return 1; - } - tape->header_ok = tape->linux_media = 0; - position = idetape_read_position(drive); - for (block = 5; block < 10; block++) - if (__idetape_analyze_headers(drive, block)) - goto ok; -#if 0 - for (block = 0xbae; block < 0xbb8; block++) -#else - for (block = 0xbae; block < 0xbb3; block++) -#endif - if (__idetape_analyze_headers(drive, block)) - goto ok; - printk(KERN_ERR "ide-tape: %s: failed to find valid ADRL header\n", tape->name); - return 0; -ok: - if (position < 20) - position = 20; - idetape_position_tape(drive, position, 0, 0); - tape->header_ok = 1; - return 1; -} - -/* - * Our character device open function. - */ -static int idetape_chrdev_open (struct inode *inode, struct file *filp) -{ - ide_drive_t *drive; - idetape_tape_t *tape; - idetape_pc_t pc; - unsigned int minor=MINOR (inode->i_rdev); - -#if IDETAPE_DEBUG_LOG - printk (KERN_INFO "ide-tape: Reached idetape_chrdev_open\n"); -#endif /* IDETAPE_DEBUG_LOG */ - - if ((drive = get_drive_ptr (inode->i_rdev)) == NULL) - return -ENXIO; - tape = drive->driver_data; - - if (test_and_set_bit (IDETAPE_BUSY, &tape->flags)) - return -EBUSY; - MOD_INC_USE_COUNT; -#if ONSTREAM_DEBUG - if (tape->debug_level >= 6) - printk(KERN_INFO "ide-tape: MOD_INC_USE_COUNT in idetape_chrdev_open-1\n"); -#endif - if (!tape->onstream) { - idetape_read_position(drive); - if (!test_bit (IDETAPE_ADDRESS_VALID, &tape->flags)) - (void) idetape_rewind_tape (drive); - } else { - if (minor & 64) { - tape->tape_block_size = tape->stage_size = 32768 + 512; - tape->raw = 1; - } else { - tape->tape_block_size = tape->stage_size = 32768; - tape->raw = 0; - } - } - if (idetape_wait_ready(drive, 60 * HZ)) { - clear_bit(IDETAPE_BUSY, &tape->flags); - MOD_DEC_USE_COUNT; -#if ONSTREAM_DEBUG - if (tape->debug_level >= 6) - printk(KERN_INFO "ide-tape: MOD_DEC_USE_COUNT in idetape_chrdev_open-1\n"); -#endif - printk(KERN_ERR "ide-tape: %s: drive not ready\n", tape->name); - return -EBUSY; - } - idetape_read_position(drive); - MOD_DEC_USE_COUNT; -#if ONSTREAM_DEBUG - if (tape->debug_level >= 6) - printk(KERN_INFO "ide-tape: MOD_DEC_USE_COUNT in idetape_chrdev_open-2\n"); -#endif - clear_bit (IDETAPE_PIPELINE_ERROR, &tape->flags); - - if (tape->chrdev_direction == idetape_direction_none) { - MOD_INC_USE_COUNT; -#if ONSTREAM_DEBUG - if (tape->debug_level >= 6) - printk(KERN_INFO "ide-tape: MOD_INC_USE_COUNT in idetape_chrdev_open-2\n"); -#endif - idetape_create_prevent_cmd(drive, &pc, 1); - if (!idetape_queue_pc_tail (drive,&pc)) { - if (tape->door_locked != DOOR_EXPLICITLY_LOCKED) - tape->door_locked = DOOR_LOCKED; - } - idetape_analyze_headers(drive); - } - tape->max_frames = tape->cur_frames = tape->req_buffer_fill = 0; - idetape_restart_speed_control(drive); - tape->restart_speed_control_req = 0; - return 0; -} - -/* - * Our character device release function. - */ -static int idetape_chrdev_release (struct inode *inode, struct file *filp) -{ - ide_drive_t *drive = get_drive_ptr (inode->i_rdev); - idetape_tape_t *tape = drive->driver_data; - idetape_pc_t pc; - unsigned int minor=MINOR (inode->i_rdev); - -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 3) - printk (KERN_INFO "ide-tape: Reached idetape_chrdev_release\n"); -#endif /* IDETAPE_DEBUG_LOG */ - - if (tape->chrdev_direction == idetape_direction_write) { - idetape_empty_write_pipeline (drive); - tape->merge_stage = __idetape_kmalloc_stage (tape, 1, 0); - if (tape->merge_stage != NULL) { - idetape_pad_zeros (drive, tape->tape_block_size * (tape->user_bs_factor - 1)); - __idetape_kfree_stage (tape->merge_stage); - tape->merge_stage = NULL; - } - idetape_write_filemark(drive); - idetape_write_eod(drive); - idetape_flush_tape_buffers (drive); - idetape_write_header(drive, minor >= 128); - idetape_flush_tape_buffers (drive); - } - if (tape->chrdev_direction == idetape_direction_read) { - if (minor < 128) - idetape_discard_read_pipeline (drive, 1); - else - idetape_wait_for_pipeline (drive); - } - if (tape->cache_stage != NULL) { - __idetape_kfree_stage (tape->cache_stage); - tape->cache_stage = NULL; - } - if (minor < 128) - (void) idetape_rewind_tape (drive); - if (tape->chrdev_direction == idetape_direction_none) { - if (tape->door_locked != DOOR_EXPLICITLY_LOCKED) { - idetape_create_prevent_cmd(drive, &pc, 0); - if (!idetape_queue_pc_tail (drive,&pc)) - tape->door_locked = DOOR_UNLOCKED; - } - MOD_DEC_USE_COUNT; -#if ONSTREAM_DEBUG - if (tape->debug_level >= 6) - printk(KERN_INFO "ide-tape: MOD_DEC_USE_COUNT in idetape_chrdev_release\n"); -#endif - } - clear_bit (IDETAPE_BUSY, &tape->flags); - return 0; -} - -/* - * idetape_identify_device is called to check the contents of the - * ATAPI IDENTIFY command results. We return: - * - * 1 If the tape can be supported by us, based on the information - * we have so far. - * - * 0 If this tape driver is not currently supported by us. - */ -static int idetape_identify_device (ide_drive_t *drive,struct hd_driveid *id) -{ - struct idetape_id_gcw gcw; -#if IDETAPE_DEBUG_INFO - unsigned short mask,i; -#endif /* IDETAPE_DEBUG_INFO */ - - if (!id) - return 0; - - *((unsigned short *) &gcw) = id->config; - -#if IDETAPE_DEBUG_INFO - printk (KERN_INFO "ide-tape: Dumping ATAPI Identify Device tape parameters\n"); - printk (KERN_INFO "ide-tape: Protocol Type: "); - switch (gcw.protocol) { - case 0: case 1: printk (KERN_INFO "ATA\n");break; - case 2: printk (KERN_INFO "ATAPI\n");break; - case 3: printk (KERN_INFO "Reserved (Unknown to ide-tape)\n");break; - } - printk (KERN_INFO "ide-tape: Device Type: %x - ",gcw.device_type); - switch (gcw.device_type) { - case 0: printk (KERN_INFO "Direct-access Device\n");break; - case 1: printk (KERN_INFO "Streaming Tape Device\n");break; - case 2: case 3: case 4: printk (KERN_INFO "Reserved\n");break; - case 5: printk (KERN_INFO "CD-ROM Device\n");break; - case 6: printk (KERN_INFO "Reserved\n"); - case 7: printk (KERN_INFO "Optical memory Device\n");break; - case 0x1f: printk (KERN_INFO "Unknown or no Device type\n");break; - default: printk (KERN_INFO "Reserved\n"); - } - printk (KERN_INFO "ide-tape: Removable: %s",gcw.removable ? "Yes\n":"No\n"); - printk (KERN_INFO "ide-tape: Command Packet DRQ Type: "); - switch (gcw.drq_type) { - case 0: printk (KERN_INFO "Microprocessor DRQ\n");break; - case 1: printk (KERN_INFO "Interrupt DRQ\n");break; - case 2: printk (KERN_INFO "Accelerated DRQ\n");break; - case 3: printk (KERN_INFO "Reserved\n");break; - } - printk (KERN_INFO "ide-tape: Command Packet Size: "); - switch (gcw.packet_size) { - case 0: printk (KERN_INFO "12 bytes\n");break; - case 1: printk (KERN_INFO "16 bytes\n");break; - default: printk (KERN_INFO "Reserved\n");break; - } - printk (KERN_INFO "ide-tape: Model: %.40s\n",id->model); - printk (KERN_INFO "ide-tape: Firmware Revision: %.8s\n",id->fw_rev); - printk (KERN_INFO "ide-tape: Serial Number: %.20s\n",id->serial_no); - printk (KERN_INFO "ide-tape: Write buffer size: %d bytes\n",id->buf_size*512); - printk (KERN_INFO "ide-tape: DMA: %s",id->capability & 0x01 ? "Yes\n":"No\n"); - printk (KERN_INFO "ide-tape: LBA: %s",id->capability & 0x02 ? "Yes\n":"No\n"); - printk (KERN_INFO "ide-tape: IORDY can be disabled: %s",id->capability & 0x04 ? "Yes\n":"No\n"); - printk (KERN_INFO "ide-tape: IORDY supported: %s",id->capability & 0x08 ? "Yes\n":"Unknown\n"); - printk (KERN_INFO "ide-tape: ATAPI overlap supported: %s",id->capability & 0x20 ? "Yes\n":"No\n"); - printk (KERN_INFO "ide-tape: PIO Cycle Timing Category: %d\n",id->tPIO); - printk (KERN_INFO "ide-tape: DMA Cycle Timing Category: %d\n",id->tDMA); - printk (KERN_INFO "ide-tape: Single Word DMA supported modes: "); - for (i=0,mask=1;i<8;i++,mask=mask << 1) { - if (id->dma_1word & mask) - printk (KERN_INFO "%d ",i); - if (id->dma_1word & (mask << 8)) - printk (KERN_INFO "(active) "); - } - printk (KERN_INFO "\n"); - printk (KERN_INFO "ide-tape: Multi Word DMA supported modes: "); - for (i=0,mask=1;i<8;i++,mask=mask << 1) { - if (id->dma_mword & mask) - printk (KERN_INFO "%d ",i); - if (id->dma_mword & (mask << 8)) - printk (KERN_INFO "(active) "); - } - printk (KERN_INFO "\n"); - if (id->field_valid & 0x0002) { - printk (KERN_INFO "ide-tape: Enhanced PIO Modes: %s\n",id->eide_pio_modes & 1 ? "Mode 3":"None"); - printk (KERN_INFO "ide-tape: Minimum Multi-word DMA cycle per word: "); - if (id->eide_dma_min == 0) - printk (KERN_INFO "Not supported\n"); - else - printk (KERN_INFO "%d ns\n",id->eide_dma_min); - - printk (KERN_INFO "ide-tape: Manufacturer\'s Recommended Multi-word cycle: "); - if (id->eide_dma_time == 0) - printk (KERN_INFO "Not supported\n"); - else - printk (KERN_INFO "%d ns\n",id->eide_dma_time); - - printk (KERN_INFO "ide-tape: Minimum PIO cycle without IORDY: "); - if (id->eide_pio == 0) - printk (KERN_INFO "Not supported\n"); - else - printk (KERN_INFO "%d ns\n",id->eide_pio); - - printk (KERN_INFO "ide-tape: Minimum PIO cycle with IORDY: "); - if (id->eide_pio_iordy == 0) - printk (KERN_INFO "Not supported\n"); - else - printk (KERN_INFO "%d ns\n",id->eide_pio_iordy); - - } else - printk (KERN_INFO "ide-tape: According to the device, fields 64-70 are not valid.\n"); -#endif /* IDETAPE_DEBUG_INFO */ - - /* Check that we can support this device */ - - if (gcw.protocol !=2 ) - printk (KERN_ERR "ide-tape: Protocol is not ATAPI\n"); - else if (gcw.device_type != 1) - printk (KERN_ERR "ide-tape: Device type is not set to tape\n"); - else if (!gcw.removable) - printk (KERN_ERR "ide-tape: The removable flag is not set\n"); - else if (gcw.packet_size != 0) { - printk (KERN_ERR "ide-tape: Packet size is not 12 bytes long\n"); - if (gcw.packet_size == 1) - printk (KERN_ERR "ide-tape: Sorry, padding to 16 bytes is still not supported\n"); - } else - return 1; - return 0; -} - -/* - * Notify vendor ID to the OnStream tape drive - */ -static void idetape_onstream_set_vendor (ide_drive_t *drive, char *vendor) -{ - idetape_pc_t pc; - idetape_mode_parameter_header_t *header; - - idetape_create_mode_select_cmd(&pc, sizeof(*header) + 8); - pc.buffer[0] = 3 + 8; /* Mode Data Length */ - pc.buffer[1] = 0; /* Medium Type - ignoring */ - pc.buffer[2] = 0; /* Reserved */ - pc.buffer[3] = 0; /* Block Descriptor Length */ - pc.buffer[4 + 0] = 0x36 | (1 << 7); - pc.buffer[4 + 1] = 6; - pc.buffer[4 + 2] = vendor[0]; - pc.buffer[4 + 3] = vendor[1]; - pc.buffer[4 + 4] = vendor[2]; - pc.buffer[4 + 5] = vendor[3]; - pc.buffer[4 + 6] = 0; - pc.buffer[4 + 7] = 0; - if (idetape_queue_pc_tail (drive,&pc)) - printk (KERN_ERR "ide-tape: Couldn't set vendor name to %s\n", vendor); - -} - -/* - * Various unused OnStream commands - */ -#if ONSTREAM_DEBUG -static void idetape_onstream_set_retries (ide_drive_t *drive, int retries) -{ - idetape_pc_t pc; - - idetape_create_mode_select_cmd(&pc, sizeof(idetape_mode_parameter_header_t) + 4); - pc.buffer[0] = 3 + 4; - pc.buffer[1] = 0; /* Medium Type - ignoring */ - pc.buffer[2] = 0; /* Reserved */ - pc.buffer[3] = 0; /* Block Descriptor Length */ - pc.buffer[4 + 0] = 0x2f | (1 << 7); - pc.buffer[4 + 1] = 2; - pc.buffer[4 + 2] = 4; - pc.buffer[4 + 3] = retries; - if (idetape_queue_pc_tail (drive,&pc)) - printk (KERN_ERR "ide-tape: Couldn't set retries to %d\n", retries); -} -#endif - -/* - * Configure 32.5KB block size. - */ -static void idetape_onstream_configure_block_size (ide_drive_t *drive) -{ - idetape_pc_t pc; - idetape_mode_parameter_header_t *header; - idetape_block_size_page_t *bs; - - /* - * Get the current block size from the block size mode page - */ - idetape_create_mode_sense_cmd (&pc,IDETAPE_BLOCK_SIZE_PAGE); - if (idetape_queue_pc_tail (drive,&pc)) - printk (KERN_ERR "ide-tape: can't get tape block size mode page\n"); - header = (idetape_mode_parameter_header_t *) pc.buffer; - bs = (idetape_block_size_page_t *) (pc.buffer + sizeof(idetape_mode_parameter_header_t) + header->bdl); - -#if IDETAPE_DEBUG_INFO - printk(KERN_INFO "ide-tape: 32KB play back: %s\n", bs->play32 ? "Yes" : "No"); - printk(KERN_INFO "ide-tape: 32.5KB play back: %s\n", bs->play32_5 ? "Yes" : "No"); - printk(KERN_INFO "ide-tape: 32KB record: %s\n", bs->record32 ? "Yes" : "No"); - printk(KERN_INFO "ide-tape: 32.5KB record: %s\n", bs->record32_5 ? "Yes" : "No"); -#endif /* IDETAPE_DEBUG_INFO */ - - /* - * Configure default auto columns mode, 32.5KB block size - */ - bs->one = 1; - bs->play32 = 0; - bs->play32_5 = 1; - bs->record32 = 0; - bs->record32_5 = 1; - idetape_create_mode_select_cmd(&pc, sizeof(*header) + sizeof(*bs)); - if (idetape_queue_pc_tail (drive,&pc)) - printk (KERN_ERR "ide-tape: Couldn't set tape block size mode page\n"); - -#if ONSTREAM_DEBUG - /* - * In debug mode, we want to see as many errors as possible - * to test the error recovery mechanism. - */ - idetape_onstream_set_retries(drive, 0); -#endif -} - -/* - * Use INQUIRY to get the firmware revision - */ -static void idetape_get_inquiry_results (ide_drive_t *drive) -{ - char *r; - idetape_tape_t *tape = drive->driver_data; - idetape_pc_t pc; - idetape_inquiry_result_t *inquiry; - - idetape_create_inquiry_cmd(&pc); - if (idetape_queue_pc_tail (drive,&pc)) { - printk (KERN_ERR "ide-tape: %s: can't get INQUIRY results\n", tape->name); - return; - } - inquiry = (idetape_inquiry_result_t *) pc.buffer; - memcpy(tape->vendor_id, inquiry->vendor_id, 8); - memcpy(tape->product_id, inquiry->product_id, 16); - memcpy(tape->firmware_revision, inquiry->revision_level, 4); - ide_fixstring(tape->vendor_id, 10, 0); - ide_fixstring(tape->product_id, 18, 0); - ide_fixstring(tape->firmware_revision, 6, 0); - r = tape->firmware_revision; - if (*(r + 1) == '.') - tape->firmware_revision_num = (*r - '0') * 100 + (*(r + 2) - '0') * 10 + *(r + 3) - '0'; - else if (tape->onstream) - tape->firmware_revision_num = (*r - '0') * 100 + (*(r + 1) - '0') * 10 + *(r + 2) - '0'; - printk(KERN_INFO "ide-tape: %s <-> %s: %s %s rev %s\n", drive->name, tape->name, tape->vendor_id, tape->product_id, tape->firmware_revision); -} - -/* - * Configure the OnStream ATAPI tape drive for default operation - */ -static void idetape_configure_onstream (ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - - if (tape->firmware_revision_num < 105) { - printk(KERN_INFO "ide-tape: %s: Old OnStream firmware revision detected (%s)\n", tape->name, tape->firmware_revision); - printk(KERN_INFO "ide-tape: %s: An upgrade to version 1.05 or above is recommended\n", tape->name); - } - - /* - * Configure 32.5KB (data+aux) block size. - */ - idetape_onstream_configure_block_size(drive); - - /* - * Set vendor name to 'LIN3' for "Linux support version 3". - */ - idetape_onstream_set_vendor(drive, "LIN3"); -} - -/* - * idetape_get_mode_sense_results asks the tape about its various - * parameters. In particular, we will adjust our data transfer buffer - * size to the recommended value as returned by the tape. - */ -static void idetape_get_mode_sense_results (ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - idetape_pc_t pc; - idetape_mode_parameter_header_t *header; - idetape_capabilities_page_t *capabilities; - - idetape_create_mode_sense_cmd (&pc,IDETAPE_CAPABILITIES_PAGE); - if (idetape_queue_pc_tail (drive,&pc)) { - printk (KERN_ERR "ide-tape: Can't get tape parameters - assuming some default values\n"); - tape->tape_block_size = 512; tape->capabilities.ctl = 52; - tape->capabilities.speed = 450; tape->capabilities.buffer_size = 6 * 52; - return; - } - header = (idetape_mode_parameter_header_t *) pc.buffer; - capabilities = (idetape_capabilities_page_t *) (pc.buffer + sizeof(idetape_mode_parameter_header_t) + header->bdl); - - capabilities->max_speed = ntohs (capabilities->max_speed); - capabilities->ctl = ntohs (capabilities->ctl); - capabilities->speed = ntohs (capabilities->speed); - capabilities->buffer_size = ntohs (capabilities->buffer_size); - - if (!capabilities->speed) { - printk(KERN_INFO "ide-tape: %s: overriding capabilities->speed (assuming 650KB/sec)\n", drive->name); - capabilities->speed = 650; - } - if (!capabilities->max_speed) { - printk(KERN_INFO "ide-tape: %s: overriding capabilities->max_speed (assuming 650KB/sec)\n", drive->name); - capabilities->max_speed = 650; - } - - tape->capabilities = *capabilities; /* Save us a copy */ - if (capabilities->blk512) - tape->tape_block_size = 512; - else if (capabilities->blk1024) - tape->tape_block_size = 1024; - else if (tape->onstream && capabilities->blk32768) - tape->tape_block_size = 32768; - -#if IDETAPE_DEBUG_INFO - printk (KERN_INFO "ide-tape: Dumping the results of the MODE SENSE packet command\n"); - printk (KERN_INFO "ide-tape: Mode Parameter Header:\n"); - printk (KERN_INFO "ide-tape: Mode Data Length - %d\n",header->mode_data_length); - printk (KERN_INFO "ide-tape: Medium Type - %d\n",header->medium_type); - printk (KERN_INFO "ide-tape: Device Specific Parameter - %d\n",header->dsp); - printk (KERN_INFO "ide-tape: Block Descriptor Length - %d\n",header->bdl); - - printk (KERN_INFO "ide-tape: Capabilities and Mechanical Status Page:\n"); - printk (KERN_INFO "ide-tape: Page code - %d\n",capabilities->page_code); - printk (KERN_INFO "ide-tape: Page length - %d\n",capabilities->page_length); - printk (KERN_INFO "ide-tape: Read only - %s\n",capabilities->ro ? "Yes":"No"); - printk (KERN_INFO "ide-tape: Supports reverse space - %s\n",capabilities->sprev ? "Yes":"No"); - printk (KERN_INFO "ide-tape: Supports erase initiated formatting - %s\n",capabilities->efmt ? "Yes":"No"); - printk (KERN_INFO "ide-tape: Supports QFA two Partition format - %s\n",capabilities->qfa ? "Yes":"No"); - printk (KERN_INFO "ide-tape: Supports locking the medium - %s\n",capabilities->lock ? "Yes":"No"); - printk (KERN_INFO "ide-tape: The volume is currently locked - %s\n",capabilities->locked ? "Yes":"No"); - printk (KERN_INFO "ide-tape: The device defaults in the prevent state - %s\n",capabilities->prevent ? "Yes":"No"); - printk (KERN_INFO "ide-tape: Supports ejecting the medium - %s\n",capabilities->eject ? "Yes":"No"); - printk (KERN_INFO "ide-tape: Supports error correction - %s\n",capabilities->ecc ? "Yes":"No"); - printk (KERN_INFO "ide-tape: Supports data compression - %s\n",capabilities->cmprs ? "Yes":"No"); - printk (KERN_INFO "ide-tape: Supports 512 bytes block size - %s\n",capabilities->blk512 ? "Yes":"No"); - printk (KERN_INFO "ide-tape: Supports 1024 bytes block size - %s\n",capabilities->blk1024 ? "Yes":"No"); - printk (KERN_INFO "ide-tape: Supports 32768 bytes block size / Restricted byte count for PIO transfers - %s\n",capabilities->blk32768 ? "Yes":"No"); - printk (KERN_INFO "ide-tape: Maximum supported speed in KBps - %d\n",capabilities->max_speed); - printk (KERN_INFO "ide-tape: Continuous transfer limits in blocks - %d\n",capabilities->ctl); - printk (KERN_INFO "ide-tape: Current speed in KBps - %d\n",capabilities->speed); - printk (KERN_INFO "ide-tape: Buffer size - %d\n",capabilities->buffer_size*512); -#endif /* IDETAPE_DEBUG_INFO */ -} - -static void idetape_add_settings (ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - -/* - * drive setting name read/write ioctl ioctl data type min max mul_factor div_factor data pointer set function - */ - ide_add_setting(drive, "buffer", SETTING_READ, -1, -1, TYPE_SHORT, 0, 0xffff, 1, 2, &tape->capabilities.buffer_size, NULL); - ide_add_setting(drive, "pipeline_min", SETTING_RW, -1, -1, TYPE_INT, 2, 0xffff, tape->stage_size / 1024, 1, &tape->min_pipeline, NULL); - ide_add_setting(drive, "pipeline", SETTING_RW, -1, -1, TYPE_INT, 2, 0xffff, tape->stage_size / 1024, 1, &tape->max_stages, NULL); - ide_add_setting(drive, "pipeline_max", SETTING_RW, -1, -1, TYPE_INT, 2, 0xffff, tape->stage_size / 1024, 1, &tape->max_pipeline, NULL); - ide_add_setting(drive, "pipeline_used",SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, tape->stage_size / 1024, 1, &tape->nr_stages, NULL); - ide_add_setting(drive, "pipeline_pending",SETTING_READ,-1, -1, TYPE_INT, 0, 0xffff, tape->stage_size / 1024, 1, &tape->nr_pending_stages, NULL); - ide_add_setting(drive, "speed", SETTING_READ, -1, -1, TYPE_SHORT, 0, 0xffff, 1, 1, &tape->capabilities.speed, NULL); - ide_add_setting(drive, "stage", SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, 1, 1024, &tape->stage_size, NULL); - ide_add_setting(drive, "tdsc", SETTING_RW, -1, -1, TYPE_INT, IDETAPE_DSC_RW_MIN, IDETAPE_DSC_RW_MAX, 1000, HZ, &tape->best_dsc_rw_frequency, NULL); - ide_add_setting(drive, "dsc_overlap", SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->dsc_overlap, NULL); - ide_add_setting(drive, "pipeline_head_speed_c",SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->controlled_pipeline_head_speed, NULL); - ide_add_setting(drive, "pipeline_head_speed_u",SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->uncontrolled_pipeline_head_speed, NULL); - ide_add_setting(drive, "avg_speed", SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->avg_speed, NULL); - if (tape->onstream) { - ide_add_setting(drive, "cur_frames", SETTING_READ, -1, -1, TYPE_SHORT, 0, 0xffff, 1, 1, &tape->cur_frames, NULL); - ide_add_setting(drive, "max_frames", SETTING_READ, -1, -1, TYPE_SHORT, 0, 0xffff, 1, 1, &tape->max_frames, NULL); - ide_add_setting(drive, "insert_speed", SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->insert_speed, NULL); - ide_add_setting(drive, "speed_control",SETTING_RW, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->speed_control, NULL); - ide_add_setting(drive, "debug_level",SETTING_RW, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->debug_level, NULL); - ide_add_setting(drive, "tape_still_time",SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->tape_still_time, NULL); - ide_add_setting(drive, "max_insert_speed",SETTING_RW, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->max_insert_speed, NULL); - ide_add_setting(drive, "insert_size", SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->insert_size, NULL); - } -} - -/* - * ide_setup is called to: - * - * 1. Initialize our various state variables. - * 2. Ask the tape for its capabilities. - * 3. Allocate a buffer which will be used for data - * transfer. The buffer size is chosen based on - * the recommendation which we received in step (2). - * - * Note that at this point ide.c already assigned us an irq, so that - * we can queue requests here and wait for their completion. - */ -static void idetape_setup (ide_drive_t *drive, idetape_tape_t *tape, int minor) -{ - unsigned long t1, tmid, tn, t; - int speed; - struct idetape_id_gcw gcw; - int stage_size; - - memset (tape, 0, sizeof (idetape_tape_t)); - spin_lock_init(&tape->spinlock); - drive->driver_data = tape; - drive->ready_stat = 0; /* An ATAPI device ignores DRDY */ - if (strstr(drive->id->model, "OnStream DI-30")) - tape->onstream = 1; - drive->dsc_overlap = 1; -#ifdef CONFIG_BLK_DEV_IDEPCI - if (!tape->onstream && HWIF(drive)->pci_dev != NULL) { - /* - * These two ide-pci host adapters appear to need DSC overlap disabled. - * This probably needs further analysis. - */ - if ((HWIF(drive)->pci_dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) || - (HWIF(drive)->pci_dev->device == PCI_DEVICE_ID_TTI_HPT343)) { - printk(KERN_INFO "ide-tape: %s: disabling DSC overlap\n", tape->name); - drive->dsc_overlap = 0; - } - } -#endif /* CONFIG_BLK_DEV_IDEPCI */ - tape->drive = drive; - tape->minor = minor; - tape->name[0] = 'h'; tape->name[1] = 't'; tape->name[2] = '0' + minor; - tape->chrdev_direction = idetape_direction_none; - tape->pc = tape->pc_stack; - tape->max_insert_speed = 10000; - tape->speed_control = 1; - *((unsigned short *) &gcw) = drive->id->config; - if (gcw.drq_type == 1) - set_bit(IDETAPE_DRQ_INTERRUPT, &tape->flags); - - tape->min_pipeline = tape->max_pipeline = tape->max_stages = 10; - - idetape_get_inquiry_results(drive); - idetape_get_mode_sense_results(drive); - if (tape->onstream) - idetape_configure_onstream(drive); - - tape->user_bs_factor = 1; - tape->stage_size = tape->capabilities.ctl * tape->tape_block_size; - while (tape->stage_size > 0xffff) { - printk (KERN_NOTICE "ide-tape: decreasing stage size\n"); - tape->capabilities.ctl /= 2; - tape->stage_size = tape->capabilities.ctl * tape->tape_block_size; - } - stage_size = tape->stage_size; - if (tape->onstream) - stage_size = 32768 + 512; - tape->pages_per_stage = stage_size / PAGE_SIZE; - if (stage_size % PAGE_SIZE) { - tape->pages_per_stage++; - tape->excess_bh_size = PAGE_SIZE - stage_size % PAGE_SIZE; - } - - /* - * Select the "best" DSC read/write polling frequency - * and pipeline size. - */ - speed = IDE_MAX (tape->capabilities.speed, tape->capabilities.max_speed); - - tape->max_stages = speed * 1000 * 10 / tape->stage_size; - tape->min_pipeline = tape->max_stages; - tape->max_pipeline = tape->max_stages * 2; - - t1 = (tape->stage_size * HZ) / (speed * 1000); - tmid = (tape->capabilities.buffer_size * 32 * HZ) / (speed * 125); - tn = (IDETAPE_FIFO_THRESHOLD * tape->stage_size * HZ) / (speed * 1000); - - if (tape->max_stages) - t = tn; - else - t = t1; - - /* - * Ensure that the number we got makes sense; limit - * it within IDETAPE_DSC_RW_MIN and IDETAPE_DSC_RW_MAX. - */ - tape->best_dsc_rw_frequency = IDE_MAX (IDE_MIN (t, IDETAPE_DSC_RW_MAX), IDETAPE_DSC_RW_MIN); - printk (KERN_INFO "ide-tape: %s <-> %s: %dKBps, %d*%dkB buffer, %dkB pipeline, %lums tDSC%s\n", - drive->name, tape->name, tape->capabilities.speed, (tape->capabilities.buffer_size * 512) / tape->stage_size, - tape->stage_size / 1024, tape->max_stages * tape->stage_size / 1024, - tape->best_dsc_rw_frequency * 1000 / HZ, drive->using_dma ? ", DMA":""); - - idetape_add_settings(drive); -} - -static int idetape_cleanup (ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - int minor = tape->minor; - unsigned long flags; - - save_flags (flags); /* all CPUs (overkill?) */ - cli(); /* all CPUs (overkill?) */ - if (test_bit (IDETAPE_BUSY, &tape->flags) || tape->first_stage != NULL || tape->merge_stage_size || drive->usage) { - restore_flags(flags); /* all CPUs (overkill?) */ - return 1; - } - idetape_chrdevs[minor].drive = NULL; - restore_flags (flags); /* all CPUs (overkill?) */ - DRIVER(drive)->busy = 0; - (void) ide_unregister_subdriver (drive); - drive->driver_data = NULL; - devfs_unregister (tape->de_r); - devfs_unregister (tape->de_n); - kfree (tape); - for (minor = 0; minor < MAX_HWIFS * MAX_DRIVES; minor++) - if (idetape_chrdevs[minor].drive != NULL) - return 0; - devfs_unregister_chrdev (IDETAPE_MAJOR, "ht"); - idetape_chrdev_present = 0; - return 0; -} - -#ifdef CONFIG_PROC_FS - -static int proc_idetape_read_name - (char *page, char **start, off_t off, int count, int *eof, void *data) -{ - ide_drive_t *drive = (ide_drive_t *) data; - idetape_tape_t *tape = drive->driver_data; - char *out = page; - int len; - - len = sprintf(out,"%s\n", tape->name); - PROC_IDE_READ_RETURN(page,start,off,count,eof,len); -} - -static ide_proc_entry_t idetape_proc[] = { - { "name", S_IFREG|S_IRUGO, proc_idetape_read_name, NULL }, - { NULL, 0, NULL, NULL } -}; - -#else - -#define idetape_proc NULL - -#endif - -/* - * IDE subdriver functions, registered with ide.c - */ -static ide_driver_t idetape_driver = { - "ide-tape", /* name */ - IDETAPE_VERSION, /* version */ - ide_tape, /* media */ - 1, /* busy */ - 1, /* supports_dma */ - 1, /* supports_dsc_overlap */ - idetape_cleanup, /* cleanup */ - idetape_do_request, /* do_request */ - idetape_end_request, /* end_request */ - idetape_blkdev_ioctl, /* ioctl */ - idetape_blkdev_open, /* open */ - idetape_blkdev_release, /* release */ - NULL, /* media_change */ - idetape_pre_reset, /* pre_reset */ - NULL, /* capacity */ - NULL, /* special */ - idetape_proc /* proc */ -}; - -int idetape_init (void); -static ide_module_t idetape_module = { - IDE_DRIVER_MODULE, - idetape_init, - &idetape_driver, - NULL -}; - -/* - * Our character device supporting functions, passed to register_chrdev. - */ -static struct file_operations idetape_fops = { - read: idetape_chrdev_read, - write: idetape_chrdev_write, - ioctl: idetape_chrdev_ioctl, - open: idetape_chrdev_open, - release: idetape_chrdev_release, -}; - -/* - * idetape_init will register the driver for each tape. - */ -int idetape_init (void) -{ - ide_drive_t *drive; - idetape_tape_t *tape; - int minor, failed = 0, supported = 0; - - MOD_INC_USE_COUNT; -#if ONSTREAM_DEBUG - printk(KERN_INFO "ide-tape: MOD_INC_USE_COUNT in idetape_init\n"); -#endif - if (!idetape_chrdev_present) - for (minor = 0; minor < MAX_HWIFS * MAX_DRIVES; minor++ ) - idetape_chrdevs[minor].drive = NULL; - - if ((drive = ide_scan_devices (ide_tape, idetape_driver.name, NULL, failed++)) == NULL) { - ide_register_module (&idetape_module); - MOD_DEC_USE_COUNT; -#if ONSTREAM_DEBUG - printk(KERN_INFO "ide-tape: MOD_DEC_USE_COUNT in idetape_init\n"); -#endif - return 0; - } - if (!idetape_chrdev_present && - devfs_register_chrdev (IDETAPE_MAJOR, "ht", &idetape_fops)) { - printk (KERN_ERR "ide-tape: Failed to register character device interface\n"); - MOD_DEC_USE_COUNT; -#if ONSTREAM_DEBUG - printk(KERN_INFO "ide-tape: MOD_DEC_USE_COUNT in idetape_init\n"); -#endif - return -EBUSY; - } - do { - if (!idetape_identify_device (drive, drive->id)) { - printk (KERN_ERR "ide-tape: %s: not supported by this version of ide-tape\n", drive->name); - continue; - } - if (drive->scsi) { - if (strstr(drive->id->model, "OnStream DI-30")) { - printk("ide-tape: ide-scsi emulation is not supported for %s.\n", drive->id->model); - } else { - printk("ide-tape: passing drive %s to ide-scsi emulation.\n", drive->name); - continue; - } - } - tape = (idetape_tape_t *) kmalloc (sizeof (idetape_tape_t), GFP_KERNEL); - if (tape == NULL) { - printk (KERN_ERR "ide-tape: %s: Can't allocate a tape structure\n", drive->name); - continue; - } - if (ide_register_subdriver (drive, &idetape_driver, IDE_SUBDRIVER_VERSION)) { - printk (KERN_ERR "ide-tape: %s: Failed to register the driver with ide.c\n", drive->name); - kfree (tape); - continue; - } - for (minor = 0; idetape_chrdevs[minor].drive != NULL; minor++); - idetape_setup (drive, tape, minor); - idetape_chrdevs[minor].drive = drive; - tape->de_r = - devfs_register (drive->de, "mt", 2, DEVFS_FL_DEFAULT, - HWIF(drive)->major, minor, - S_IFCHR | S_IRUGO | S_IWUGO, 0, 0, - &idetape_fops, NULL); - tape->de_n = - devfs_register (drive->de, "mtn", 3, DEVFS_FL_DEFAULT, - HWIF(drive)->major, minor + 128, - S_IFCHR | S_IRUGO | S_IWUGO, 0, 0, - &idetape_fops, NULL); - devfs_register_tape (tape->de_r); - supported++; failed--; - } while ((drive = ide_scan_devices (ide_tape, idetape_driver.name, NULL, failed++)) != NULL); - if (!idetape_chrdev_present && !supported) { - devfs_unregister_chrdev (IDETAPE_MAJOR, "ht"); - } else - idetape_chrdev_present = 1; - ide_register_module (&idetape_module); - MOD_DEC_USE_COUNT; -#if ONSTREAM_DEBUG - printk(KERN_INFO "ide-tape: MOD_DEC_USE_COUNT in idetape_init\n"); -#endif - return 0; -} - -#ifdef MODULE -int init_module (void) -{ - return idetape_init (); -} - -void cleanup_module (void) -{ - ide_drive_t *drive; - int minor; - - for (minor = 0; minor < MAX_HWIFS * MAX_DRIVES; minor++) { - drive = idetape_chrdevs[minor].drive; - if (drive != NULL && idetape_cleanup (drive)) - printk (KERN_ERR "ide-tape: %s: cleanup_module() called while still busy\n", drive->name); - } - ide_unregister_module(&idetape_module); -} -#endif /* MODULE */ diff --git a/drivers/block/ide.c b/drivers/block/ide.c deleted file mode 100644 index 326533e7f..000000000 --- a/drivers/block/ide.c +++ /dev/null @@ -1,3637 +0,0 @@ -/* - * linux/drivers/block/ide.c Version 6.30 Dec 28, 1999 - * - * Copyright (C) 1994-1998 Linus Torvalds & authors (see below) - */ - -/* - * Mostly written by Mark Lord <mlord@pobox.com> - * and Gadi Oxman <gadio@netvision.net.il> - * - * See linux/MAINTAINERS for address of current maintainer. - * - * This is the multiple IDE interface driver, as evolved from hd.c. - * It supports up to MAX_HWIFS IDE interfaces, on one or more IRQs (usually 14 & 15). - * There can be up to two drives per interface, as per the ATA-2 spec. - * - * Primary: ide0, port 0x1f0; major=3; hda is minor=0; hdb is minor=64 - * Secondary: ide1, port 0x170; major=22; hdc is minor=0; hdd is minor=64 - * Tertiary: ide2, port 0x???; major=33; hde is minor=0; hdf is minor=64 - * Quaternary: ide3, port 0x???; major=34; hdg is minor=0; hdh is minor=64 - * ... - * - * From hd.c: - * | - * | It traverses the request-list, using interrupts to jump between functions. - * | As nearly all functions can be called within interrupts, we may not sleep. - * | Special care is recommended. Have Fun! - * | - * | modified by Drew Eckhardt to check nr of hd's from the CMOS. - * | - * | Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug - * | in the early extended-partition checks and added DM partitions. - * | - * | Early work on error handling by Mika Liljeberg (liljeber@cs.Helsinki.FI). - * | - * | IRQ-unmask, drive-id, multiple-mode, support for ">16 heads", - * | and general streamlining by Mark Lord (mlord@pobox.com). - * - * October, 1994 -- Complete line-by-line overhaul for linux 1.1.x, by: - * - * Mark Lord (mlord@pobox.com) (IDE Perf.Pkg) - * Delman Lee (delman@ieee.org) ("Mr. atdisk2") - * Scott Snyder (snyder@fnald0.fnal.gov) (ATAPI IDE cd-rom) - * - * This was a rewrite of just about everything from hd.c, though some original - * code is still sprinkled about. Think of it as a major evolution, with - * inspiration from lots of linux users, esp. hamish@zot.apana.org.au - * - * Version 1.0 ALPHA initial code, primary i/f working okay - * Version 1.3 BETA dual i/f on shared irq tested & working! - * Version 1.4 BETA added auto probing for irq(s) - * Version 1.5 BETA added ALPHA (untested) support for IDE cd-roms, - * ... - * Version 5.50 allow values as small as 20 for idebus= - * Version 5.51 force non io_32bit in drive_cmd_intr() - * change delay_10ms() to delay_50ms() to fix problems - * Version 5.52 fix incorrect invalidation of removable devices - * add "hdx=slow" command line option - * Version 5.60 start to modularize the driver; the disk and ATAPI - * drivers can be compiled as loadable modules. - * move IDE probe code to ide-probe.c - * move IDE disk code to ide-disk.c - * add support for generic IDE device subdrivers - * add m68k code from Geert Uytterhoeven - * probe all interfaces by default - * add ioctl to (re)probe an interface - * Version 6.00 use per device request queues - * attempt to optimize shared hwgroup performance - * add ioctl to manually adjust bandwidth algorithms - * add kerneld support for the probe module - * fix bug in ide_error() - * fix bug in the first ide_get_lock() call for Atari - * don't flush leftover data for ATAPI devices - * Version 6.01 clear hwgroup->active while the hwgroup sleeps - * support HDIO_GETGEO for floppies - * Version 6.02 fix ide_ack_intr() call - * check partition table on floppies - * Version 6.03 handle bad status bit sequencing in ide_wait_stat() - * Version 6.10 deleted old entries from this list of updates - * replaced triton.c with ide-dma.c generic PCI DMA - * added support for BIOS-enabled UltraDMA - * rename all "promise" things to "pdc4030" - * fix EZ-DRIVE handling on small disks - * Version 6.11 fix probe error in ide_scan_devices() - * fix ancient "jiffies" polling bugs - * mask all hwgroup interrupts on each irq entry - * Version 6.12 integrate ioctl and proc interfaces - * fix parsing of "idex=" command line parameter - * Version 6.13 add support for ide4/ide5 courtesy rjones@orchestream.com - * Version 6.14 fixed IRQ sharing among PCI devices - * Version 6.15 added SMP awareness to IDE drivers - * Version 6.16 fixed various bugs; even more SMP friendly - * Version 6.17 fix for newest EZ-Drive problem - * Version 6.18 default unpartitioned-disk translation now "BIOS LBA" - * Version 6.19 Re-design for a UNIFORM driver for all platforms, - * model based on suggestions from Russell King and - * Geert Uytterhoeven - * Promise DC4030VL now supported. - * add support for ide6/ide7 - * delay_50ms() changed to ide_delay_50ms() and exported. - * Version 6.20 Added/Fixed Generic ATA-66 support and hwif detection. - * Added hdx=flash to allow for second flash disk - * detection w/o the hang loop. - * Added support for ide8/ide9 - * Added idex=ata66 for the quirky chipsets that are - * ATA-66 compliant, but have yet to determine a method - * of verification of the 80c cable presence. - * Specifically Promise's PDC20262 chipset. - * Version 6.21 Fixing/Fixed SMP spinlock issue with insight from an old - * hat that clarified original low level driver design. - * Version 6.30 Added SMP support; fixed multmode issues. -ml - * - * Some additional driver compile-time options are in ./include/linux/ide.h - * - * To do, in likely order of completion: - * - modify kernel to obtain BIOS geometry for drives on 2nd/3rd/4th i/f - * - */ - -#define REVISION "Revision: 6.30" -#define VERSION "Id: ide.c 6.30 1999/12/28" - -#undef REALLY_SLOW_IO /* most systems can safely undef this */ - -#define _IDE_C /* Tell ide.h it's really us */ - -#include <linux/config.h> -#include <linux/module.h> -#include <linux/types.h> -#include <linux/string.h> -#include <linux/kernel.h> -#include <linux/timer.h> -#include <linux/mm.h> -#include <linux/interrupt.h> -#include <linux/major.h> -#include <linux/errno.h> -#include <linux/genhd.h> -#include <linux/blkpg.h> -#include <linux/malloc.h> -#ifndef MODULE -#include <linux/init.h> -#endif /* MODULE */ -#include <linux/pci.h> -#include <linux/delay.h> -#include <linux/ide.h> -#include <linux/devfs_fs_kernel.h> - -#include <asm/byteorder.h> -#include <asm/irq.h> -#include <asm/uaccess.h> -#include <asm/io.h> -#include <asm/bitops.h> - -#include "ide_modes.h" - -#ifdef CONFIG_KMOD -#include <linux/kmod.h> -#endif /* CONFIG_KMOD */ - -#ifdef CONFIG_BLK_DEV_VIA82CXXX -extern byte fifoconfig; /* defined in via82cxxx.c used by ide_setup() */ -#endif /* CONFIG_BLK_DEV_VIA82CXXX */ - -static const byte ide_hwif_to_major[] = { IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR, IDE4_MAJOR, IDE5_MAJOR, IDE6_MAJOR, IDE7_MAJOR, IDE8_MAJOR, IDE9_MAJOR }; - -static int idebus_parameter = 0; /* holds the "idebus=" parameter */ -static int system_bus_speed = 0; /* holds what we think is VESA/PCI bus speed */ -static int initializing; /* set while initializing built-in drivers */ - -#ifdef CONFIG_BLK_DEV_IDEPCI -static int ide_scan_direction = 0; /* THIS was formerly 2.2.x pci=reverse */ -#endif /* CONFIG_BLK_DEV_IDEPCI */ - -#if defined(__mc68000__) || defined(CONFIG_APUS) -/* - * ide_lock is used by the Atari code to obtain access to the IDE interrupt, - * which is shared between several drivers. - */ -static int ide_lock = 0; -#endif /* __mc68000__ || CONFIG_APUS */ - -/* - * ide_modules keeps track of the available IDE chipset/probe/driver modules. - */ -ide_module_t *ide_modules = NULL; -ide_module_t *ide_probe = NULL; - -/* - * This is declared extern in ide.h, for access by other IDE modules: - */ -ide_hwif_t ide_hwifs[MAX_HWIFS]; /* master data repository */ - -#if (DISK_RECOVERY_TIME > 0) -/* - * For really screwy hardware (hey, at least it *can* be used with Linux) - * we can enforce a minimum delay time between successive operations. - */ -static unsigned long read_timer (void) -{ - unsigned long t, flags; - int i; - - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ - t = jiffies * 11932; - outb_p(0, 0x43); - i = inb_p(0x40); - i |= inb(0x40) << 8; - __restore_flags(flags); /* local CPU only */ - return (t - i); -} -#endif /* DISK_RECOVERY_TIME */ - -static inline void set_recovery_timer (ide_hwif_t *hwif) -{ -#if (DISK_RECOVERY_TIME > 0) - hwif->last_time = read_timer(); -#endif /* DISK_RECOVERY_TIME */ -} - -/* - * Do not even *think* about calling this! - */ -static void init_hwif_data (unsigned int index) -{ - unsigned int unit; - hw_regs_t hw; - ide_hwif_t *hwif = &ide_hwifs[index]; - - /* bulk initialize hwif & drive info with zeros */ - memset(hwif, 0, sizeof(ide_hwif_t)); - memset(&hw, 0, sizeof(hw_regs_t)); - - /* fill in any non-zero initial values */ - hwif->index = index; - ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, &hwif->irq); - memcpy(&hwif->hw, &hw, sizeof(hw)); - memcpy(hwif->io_ports, hw.io_ports, sizeof(hw.io_ports)); - hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET]; -#ifdef CONFIG_BLK_DEV_HD - if (hwif->io_ports[IDE_DATA_OFFSET] == HD_DATA) - hwif->noprobe = 1; /* may be overridden by ide_setup() */ -#endif /* CONFIG_BLK_DEV_HD */ - hwif->major = ide_hwif_to_major[index]; - hwif->name[0] = 'i'; - hwif->name[1] = 'd'; - hwif->name[2] = 'e'; - hwif->name[3] = '0' + index; - for (unit = 0; unit < MAX_DRIVES; ++unit) { - ide_drive_t *drive = &hwif->drives[unit]; - - drive->media = ide_disk; - drive->select.all = (unit<<4)|0xa0; - drive->hwif = hwif; - drive->ctl = 0x08; - drive->ready_stat = READY_STAT; - drive->bad_wstat = BAD_W_STAT; - drive->special.b.recalibrate = 1; - drive->special.b.set_geometry = 1; - drive->name[0] = 'h'; - drive->name[1] = 'd'; - drive->name[2] = 'a' + (index * MAX_DRIVES) + unit; - init_waitqueue_head(&drive->wqueue); - } -} - -/* - * init_ide_data() sets reasonable default values into all fields - * of all instances of the hwifs and drives, but only on the first call. - * Subsequent calls have no effect (they don't wipe out anything). - * - * This routine is normally called at driver initialization time, - * but may also be called MUCH earlier during kernel "command-line" - * parameter processing. As such, we cannot depend on any other parts - * of the kernel (such as memory allocation) to be functioning yet. - * - * This is too bad, as otherwise we could dynamically allocate the - * ide_drive_t structs as needed, rather than always consuming memory - * for the max possible number (MAX_HWIFS * MAX_DRIVES) of them. - */ -#define MAGIC_COOKIE 0x12345678 -static void __init init_ide_data (void) -{ - unsigned int index; - static unsigned long magic_cookie = MAGIC_COOKIE; - - if (magic_cookie != MAGIC_COOKIE) - return; /* already initialized */ - magic_cookie = 0; - - /* Initialise all interface structures */ - for (index = 0; index < MAX_HWIFS; ++index) - init_hwif_data(index); - - /* Add default hw interfaces */ - ide_init_default_hwifs(); - - idebus_parameter = 0; - system_bus_speed = 0; -} - -/* - * CompactFlash cards and their brethern pretend to be removable hard disks, except: - * (1) they never have a slave unit, and - * (2) they don't have doorlock mechanisms. - * This test catches them, and is invoked elsewhere when setting appropriate config bits. - * - * FIXME: This treatment is probably applicable for *all* PCMCIA (PC CARD) devices, - * so in linux 2.3.x we should change this to just treat all PCMCIA drives this way, - * and get rid of the model-name tests below (too big of an interface change for 2.2.x). - * At that time, we might also consider parameterizing the timeouts and retries, - * since these are MUCH faster than mechanical drives. -M.Lord - */ -int drive_is_flashcard (ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - - if (drive->removable && id != NULL) { - if (id->config == 0x848a) return 1; /* CompactFlash */ - if (!strncmp(id->model, "KODAK ATA_FLASH", 15) /* Kodak */ - || !strncmp(id->model, "Hitachi CV", 10) /* Hitachi */ - || !strncmp(id->model, "SunDisk SDCFB", 13) /* SunDisk */ - || !strncmp(id->model, "HAGIWARA HPC", 12) /* Hagiwara */ - || !strncmp(id->model, "ATA_FLASH", 9)) /* Simple Tech */ - { - return 1; /* yes, it is a flash memory card */ - } - } - return 0; /* no, it is not a flash memory card */ -} - -/* - * ide_system_bus_speed() returns what we think is the system VESA/PCI - * bus speed (in MHz). This is used for calculating interface PIO timings. - * The default is 40 for known PCI systems, 50 otherwise. - * The "idebus=xx" parameter can be used to override this value. - * The actual value to be used is computed/displayed the first time through. - */ -int ide_system_bus_speed (void) -{ - if (!system_bus_speed) { - if (idebus_parameter) - system_bus_speed = idebus_parameter; /* user supplied value */ -#ifdef CONFIG_PCI - else if (pci_present()) - system_bus_speed = 40; /* safe default value for PCI */ -#endif /* CONFIG_PCI */ - else - system_bus_speed = 50; /* safe default value for VESA and PCI */ - printk("ide: Assuming %dMHz system bus speed for PIO modes%s\n", system_bus_speed, - idebus_parameter ? "" : "; override with idebus=xx"); - } - return system_bus_speed; -} - -#if SUPPORT_VLB_SYNC -/* - * Some localbus EIDE interfaces require a special access sequence - * when using 32-bit I/O instructions to transfer data. We call this - * the "vlb_sync" sequence, which consists of three successive reads - * of the sector count register location, with interrupts disabled - * to ensure that the reads all happen together. - */ -static inline void do_vlb_sync (ide_ioreg_t port) { - (void) inb (port); - (void) inb (port); - (void) inb (port); -} -#endif /* SUPPORT_VLB_SYNC */ - -/* - * This is used for most PIO data transfers *from* the IDE interface - */ -void ide_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount) -{ - byte io_32bit = drive->io_32bit; - - if (io_32bit) { -#if SUPPORT_VLB_SYNC - if (io_32bit & 2) { - unsigned long flags; - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ - do_vlb_sync(IDE_NSECTOR_REG); - insl(IDE_DATA_REG, buffer, wcount); - __restore_flags(flags); /* local CPU only */ - } else -#endif /* SUPPORT_VLB_SYNC */ - insl(IDE_DATA_REG, buffer, wcount); - } else { -#if SUPPORT_SLOW_DATA_PORTS - if (drive->slow) { - unsigned short *ptr = (unsigned short *) buffer; - while (wcount--) { - *ptr++ = inw_p(IDE_DATA_REG); - *ptr++ = inw_p(IDE_DATA_REG); - } - } else -#endif /* SUPPORT_SLOW_DATA_PORTS */ - insw(IDE_DATA_REG, buffer, wcount<<1); - } -} - -/* - * This is used for most PIO data transfers *to* the IDE interface - */ -void ide_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount) -{ - byte io_32bit = drive->io_32bit; - - if (io_32bit) { -#if SUPPORT_VLB_SYNC - if (io_32bit & 2) { - unsigned long flags; - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ - do_vlb_sync(IDE_NSECTOR_REG); - outsl(IDE_DATA_REG, buffer, wcount); - __restore_flags(flags); /* local CPU only */ - } else -#endif /* SUPPORT_VLB_SYNC */ - outsl(IDE_DATA_REG, buffer, wcount); - } else { -#if SUPPORT_SLOW_DATA_PORTS - if (drive->slow) { - unsigned short *ptr = (unsigned short *) buffer; - while (wcount--) { - outw_p(*ptr++, IDE_DATA_REG); - outw_p(*ptr++, IDE_DATA_REG); - } - } else -#endif /* SUPPORT_SLOW_DATA_PORTS */ - outsw(IDE_DATA_REG, buffer, wcount<<1); - } -} - -/* - * The following routines are mainly used by the ATAPI drivers. - * - * These routines will round up any request for an odd number of bytes, - * so if an odd bytecount is specified, be sure that there's at least one - * extra byte allocated for the buffer. - */ -void atapi_input_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount) -{ - ++bytecount; -#if defined(CONFIG_ATARI) || defined(CONFIG_Q40) - if (MACH_IS_ATARI || MACH_IS_Q40) { - /* Atari has a byte-swapped IDE interface */ - insw_swapw(IDE_DATA_REG, buffer, bytecount / 2); - return; - } -#endif /* CONFIG_ATARI */ - ide_input_data (drive, buffer, bytecount / 4); - if ((bytecount & 0x03) >= 2) - insw (IDE_DATA_REG, ((byte *)buffer) + (bytecount & ~0x03), 1); -} - -void atapi_output_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount) -{ - ++bytecount; -#if defined(CONFIG_ATARI) || defined(CONFIG_Q40) - if (MACH_IS_ATARI || MACH_IS_Q40) { - /* Atari has a byte-swapped IDE interface */ - outsw_swapw(IDE_DATA_REG, buffer, bytecount / 2); - return; - } -#endif /* CONFIG_ATARI */ - ide_output_data (drive, buffer, bytecount / 4); - if ((bytecount & 0x03) >= 2) - outsw (IDE_DATA_REG, ((byte *)buffer) + (bytecount & ~0x03), 1); -} - -/* - * Needed for PCI irq sharing - */ -static inline int drive_is_ready (ide_drive_t *drive) -{ - if (drive->waiting_for_dma) - return HWIF(drive)->dmaproc(ide_dma_test_irq, drive); -#if 0 - udelay(1); /* need to guarantee 400ns since last command was issued */ -#endif - if (GET_STAT() & BUSY_STAT) /* Note: this may clear a pending IRQ!! */ - return 0; /* drive busy: definitely not interrupting */ - return 1; /* drive ready: *might* be interrupting */ -} - -/* - * This is our end_request replacement function. - */ -void ide_end_request (byte uptodate, ide_hwgroup_t *hwgroup) -{ - struct request *rq; - unsigned long flags; - - spin_lock_irqsave(&io_request_lock, flags); - rq = hwgroup->rq; - - if (!end_that_request_first(rq, uptodate, hwgroup->drive->name)) { - add_blkdev_randomness(MAJOR(rq->rq_dev)); - blkdev_dequeue_request(rq); - hwgroup->rq = NULL; - end_that_request_last(rq); - } - spin_unlock_irqrestore(&io_request_lock, flags); -} - -/* - * This should get invoked any time we exit the driver to - * wait for an interrupt response from a drive. handler() points - * at the appropriate code to handle the next interrupt, and a - * timer is started to prevent us from waiting forever in case - * something goes wrong (see the ide_timer_expiry() handler later on). - */ -void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, - unsigned int timeout, ide_expiry_t *expiry) -{ - unsigned long flags; - ide_hwgroup_t *hwgroup = HWGROUP(drive); - - spin_lock_irqsave(&io_request_lock, flags); - if (hwgroup->handler != NULL) { - printk("%s: ide_set_handler: handler not null; old=%p, new=%p\n", - drive->name, hwgroup->handler, handler); - } - hwgroup->handler = handler; - hwgroup->expiry = expiry; - hwgroup->timer.expires = jiffies + timeout; - add_timer(&hwgroup->timer); - spin_unlock_irqrestore(&io_request_lock, flags); -} - -/* - * current_capacity() returns the capacity (in sectors) of a drive - * according to its current geometry/LBA settings. - */ -unsigned long current_capacity (ide_drive_t *drive) -{ - if (!drive->present) - return 0; - if (drive->driver != NULL) - return DRIVER(drive)->capacity(drive); - return 0; -} - -extern struct block_device_operations ide_fops[]; -/* - * ide_geninit() is called exactly *once* for each interface. - */ -void ide_geninit (ide_hwif_t *hwif) -{ - unsigned int unit; - struct gendisk *gd = hwif->gd; - - for (unit = 0; unit < MAX_DRIVES; ++unit) { - ide_drive_t *drive = &hwif->drives[unit]; - - if (!drive->present) - continue; - if (drive->media!=ide_disk && drive->media!=ide_floppy) - continue; - register_disk(gd,MKDEV(hwif->major,unit<<PARTN_BITS), -#ifdef CONFIG_BLK_DEV_ISAPNP - (drive->forced_geom && drive->noprobe) ? 1 : -#endif /* CONFIG_BLK_DEV_ISAPNP */ - 1<<PARTN_BITS, ide_fops, - current_capacity(drive)); - } -} - -static ide_startstop_t do_reset1 (ide_drive_t *, int); /* needed below */ - -/* - * atapi_reset_pollfunc() gets invoked to poll the interface for completion every 50ms - * during an atapi drive reset operation. If the drive has not yet responded, - * and we have not yet hit our maximum waiting time, then the timer is restarted - * for another 50ms. - */ -static ide_startstop_t atapi_reset_pollfunc (ide_drive_t *drive) -{ - ide_hwgroup_t *hwgroup = HWGROUP(drive); - byte stat; - - SELECT_DRIVE(HWIF(drive),drive); - udelay (10); - - if (OK_STAT(stat=GET_STAT(), 0, BUSY_STAT)) { - printk("%s: ATAPI reset complete\n", drive->name); - } else { - if (0 < (signed long)(hwgroup->poll_timeout - jiffies)) { - ide_set_handler (drive, &atapi_reset_pollfunc, HZ/20, NULL); - return ide_started; /* continue polling */ - } - hwgroup->poll_timeout = 0; /* end of polling */ - printk("%s: ATAPI reset timed-out, status=0x%02x\n", drive->name, stat); - return do_reset1 (drive, 1); /* do it the old fashioned way */ - } - hwgroup->poll_timeout = 0; /* done polling */ - return ide_stopped; -} - -/* - * reset_pollfunc() gets invoked to poll the interface for completion every 50ms - * during an ide reset operation. If the drives have not yet responded, - * and we have not yet hit our maximum waiting time, then the timer is restarted - * for another 50ms. - */ -static ide_startstop_t reset_pollfunc (ide_drive_t *drive) -{ - ide_hwgroup_t *hwgroup = HWGROUP(drive); - ide_hwif_t *hwif = HWIF(drive); - byte tmp; - - if (!OK_STAT(tmp=GET_STAT(), 0, BUSY_STAT)) { - if (0 < (signed long)(hwgroup->poll_timeout - jiffies)) { - ide_set_handler (drive, &reset_pollfunc, HZ/20, NULL); - return ide_started; /* continue polling */ - } - printk("%s: reset timed-out, status=0x%02x\n", hwif->name, tmp); - } else { - printk("%s: reset: ", hwif->name); - if ((tmp = GET_ERR()) == 1) - printk("success\n"); - else { -#if FANCY_STATUS_DUMPS - printk("master: "); - switch (tmp & 0x7f) { - case 1: printk("passed"); - break; - case 2: printk("formatter device error"); - break; - case 3: printk("sector buffer error"); - break; - case 4: printk("ECC circuitry error"); - break; - case 5: printk("controlling MPU error"); - break; - default:printk("error (0x%02x?)", tmp); - } - if (tmp & 0x80) - printk("; slave: failed"); - printk("\n"); -#else - printk("failed\n"); -#endif /* FANCY_STATUS_DUMPS */ - } - } - hwgroup->poll_timeout = 0; /* done polling */ - return ide_stopped; -} - -static void pre_reset (ide_drive_t *drive) -{ - if (drive->driver != NULL) - DRIVER(drive)->pre_reset(drive); - - if (!drive->keep_settings) { - if (drive->using_dma) { - (void) HWIF(drive)->dmaproc(ide_dma_off, drive); - } else { - drive->unmask = 0; - drive->io_32bit = 0; - } - } -} - -/* - * do_reset1() attempts to recover a confused drive by resetting it. - * Unfortunately, resetting a disk drive actually resets all devices on - * the same interface, so it can really be thought of as resetting the - * interface rather than resetting the drive. - * - * ATAPI devices have their own reset mechanism which allows them to be - * individually reset without clobbering other devices on the same interface. - * - * Unfortunately, the IDE interface does not generate an interrupt to let - * us know when the reset operation has finished, so we must poll for this. - * Equally poor, though, is the fact that this may a very long time to complete, - * (up to 30 seconds worstcase). So, instead of busy-waiting here for it, - * we set a timer to poll at 50ms intervals. - */ -static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi) -{ - unsigned int unit; - unsigned long flags; - ide_hwif_t *hwif = HWIF(drive); - ide_hwgroup_t *hwgroup = HWGROUP(drive); - - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ - - /* For an ATAPI device, first try an ATAPI SRST. */ - if (drive->media != ide_disk && !do_not_try_atapi) { - pre_reset(drive); - SELECT_DRIVE(hwif,drive); - udelay (20); - OUT_BYTE (WIN_SRST, IDE_COMMAND_REG); - hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; - ide_set_handler (drive, &atapi_reset_pollfunc, HZ/20, NULL); - __restore_flags (flags); /* local CPU only */ - return ide_started; - } - - /* - * First, reset any device state data we were maintaining - * for any of the drives on this interface. - */ - for (unit = 0; unit < MAX_DRIVES; ++unit) - pre_reset(&hwif->drives[unit]); - -#if OK_TO_RESET_CONTROLLER - if (!IDE_CONTROL_REG) { - __restore_flags(flags); - return ide_stopped; - } - /* - * Note that we also set nIEN while resetting the device, - * to mask unwanted interrupts from the interface during the reset. - * However, due to the design of PC hardware, this will cause an - * immediate interrupt due to the edge transition it produces. - * This single interrupt gives us a "fast poll" for drives that - * recover from reset very quickly, saving us the first 50ms wait time. - */ - OUT_BYTE(drive->ctl|6,IDE_CONTROL_REG); /* set SRST and nIEN */ - udelay(10); /* more than enough time */ - OUT_BYTE(drive->ctl|2,IDE_CONTROL_REG); /* clear SRST, leave nIEN */ - udelay(10); /* more than enough time */ - hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; - ide_set_handler (drive, &reset_pollfunc, HZ/20, NULL); - - /* - * Some weird controller like resetting themselves to a strange - * state when the disks are reset this way. At least, the Winbond - * 553 documentation says that - */ - if (hwif->resetproc != NULL) - hwif->resetproc(drive); - -#endif /* OK_TO_RESET_CONTROLLER */ - - __restore_flags (flags); /* local CPU only */ - return ide_started; -} - -/* - * ide_do_reset() is the entry point to the drive/interface reset code. - */ -ide_startstop_t ide_do_reset (ide_drive_t *drive) -{ - return do_reset1 (drive, 0); -} - -/* - * Clean up after success/failure of an explicit drive cmd - */ -void ide_end_drive_cmd (ide_drive_t *drive, byte stat, byte err) -{ - unsigned long flags; - struct request *rq = HWGROUP(drive)->rq; - - if (rq->cmd == IDE_DRIVE_CMD) { - byte *args = (byte *) rq->buffer; - rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); - if (args) { - args[0] = stat; - args[1] = err; - args[2] = IN_BYTE(IDE_NSECTOR_REG); - } - } - spin_lock_irqsave(&io_request_lock, flags); - blkdev_dequeue_request(rq); - HWGROUP(drive)->rq = NULL; - rq->rq_status = RQ_INACTIVE; - spin_unlock_irqrestore(&io_request_lock, flags); - if (rq->sem != NULL) - up(rq->sem); /* inform originator that rq has been serviced */ -} - -/* - * Error reporting, in human readable form (luxurious, but a memory hog). - */ -byte ide_dump_status (ide_drive_t *drive, const char *msg, byte stat) -{ - unsigned long flags; - byte err = 0; - - __save_flags (flags); /* local CPU only */ - ide__sti(); /* local CPU only */ - printk("%s: %s: status=0x%02x", drive->name, msg, stat); -#if FANCY_STATUS_DUMPS - printk(" { "); - if (stat & BUSY_STAT) - printk("Busy "); - else { - if (stat & READY_STAT) printk("DriveReady "); - if (stat & WRERR_STAT) printk("DeviceFault "); - if (stat & SEEK_STAT) printk("SeekComplete "); - if (stat & DRQ_STAT) printk("DataRequest "); - if (stat & ECC_STAT) printk("CorrectedError "); - if (stat & INDEX_STAT) printk("Index "); - if (stat & ERR_STAT) printk("Error "); - } - printk("}"); -#endif /* FANCY_STATUS_DUMPS */ - printk("\n"); - if ((stat & (BUSY_STAT|ERR_STAT)) == ERR_STAT) { - err = GET_ERR(); - printk("%s: %s: error=0x%02x", drive->name, msg, err); -#if FANCY_STATUS_DUMPS - if (drive->media == ide_disk) { - printk(" { "); - if (err & ABRT_ERR) printk("DriveStatusError "); - if (err & ICRC_ERR) printk((err & ABRT_ERR) ? "BadCRC " : "BadSector "); - if (err & ECC_ERR) printk("UncorrectableError "); - if (err & ID_ERR) printk("SectorIdNotFound "); - if (err & TRK0_ERR) printk("TrackZeroNotFound "); - if (err & MARK_ERR) printk("AddrMarkNotFound "); - printk("}"); - if ((err & (BBD_ERR | ABRT_ERR)) == BBD_ERR || (err & (ECC_ERR|ID_ERR|MARK_ERR))) { - byte cur = IN_BYTE(IDE_SELECT_REG); - if (cur & 0x40) { /* using LBA? */ - printk(", LBAsect=%ld", (unsigned long) - ((cur&0xf)<<24) - |(IN_BYTE(IDE_HCYL_REG)<<16) - |(IN_BYTE(IDE_LCYL_REG)<<8) - | IN_BYTE(IDE_SECTOR_REG)); - } else { - printk(", CHS=%d/%d/%d", - (IN_BYTE(IDE_HCYL_REG)<<8) + - IN_BYTE(IDE_LCYL_REG), - cur & 0xf, - IN_BYTE(IDE_SECTOR_REG)); - } - if (HWGROUP(drive)->rq) - printk(", sector=%ld", HWGROUP(drive)->rq->sector); - } - } -#endif /* FANCY_STATUS_DUMPS */ - printk("\n"); - } - __restore_flags (flags); /* local CPU only */ - return err; -} - -/* - * try_to_flush_leftover_data() is invoked in response to a drive - * unexpectedly having its DRQ_STAT bit set. As an alternative to - * resetting the drive, this routine tries to clear the condition - * by read a sector's worth of data from the drive. Of course, - * this may not help if the drive is *waiting* for data from *us*. - */ -static void try_to_flush_leftover_data (ide_drive_t *drive) -{ - int i = (drive->mult_count ? drive->mult_count : 1) * SECTOR_WORDS; - - if (drive->media != ide_disk) - return; - while (i > 0) { - u32 buffer[16]; - unsigned int wcount = (i > 16) ? 16 : i; - i -= wcount; - ide_input_data (drive, buffer, wcount); - } -} - -/* - * ide_error() takes action based on the error returned by the drive. - */ -ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, byte stat) -{ - struct request *rq; - byte err; - - err = ide_dump_status(drive, msg, stat); - if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL) - return ide_stopped; - /* retry only "normal" I/O: */ - if (rq->cmd == IDE_DRIVE_CMD) { - rq->errors = 1; - ide_end_drive_cmd(drive, stat, err); - return ide_stopped; - } - if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) { /* other bits are useless when BUSY */ - rq->errors |= ERROR_RESET; - } else { - if (drive->media == ide_disk && (stat & ERR_STAT)) { - /* err has different meaning on cdrom and tape */ - if (err == ABRT_ERR) { - if (drive->select.b.lba && IN_BYTE(IDE_COMMAND_REG) == WIN_SPECIFY) - return ide_stopped; /* some newer drives don't support WIN_SPECIFY */ - } else if ((err & (ABRT_ERR | ICRC_ERR)) == (ABRT_ERR | ICRC_ERR)) - ; /* UDMA crc error -- just retry the operation */ - else if (err & (BBD_ERR | ECC_ERR)) /* retries won't help these */ - rq->errors = ERROR_MAX; - else if (err & TRK0_ERR) /* help it find track zero */ - rq->errors |= ERROR_RECAL; - } - if ((stat & DRQ_STAT) && rq->cmd != WRITE) - try_to_flush_leftover_data(drive); - } - if (GET_STAT() & (BUSY_STAT|DRQ_STAT)) - OUT_BYTE(WIN_IDLEIMMEDIATE,IDE_COMMAND_REG); /* force an abort */ - - if (rq->errors >= ERROR_MAX) { - if (drive->driver != NULL) - DRIVER(drive)->end_request(0, HWGROUP(drive)); - else - ide_end_request(0, HWGROUP(drive)); - } else { - if ((rq->errors & ERROR_RESET) == ERROR_RESET) { - ++rq->errors; - return ide_do_reset(drive); - } - if ((rq->errors & ERROR_RECAL) == ERROR_RECAL) - drive->special.b.recalibrate = 1; - ++rq->errors; - } - return ide_stopped; -} - -/* - * Issue a simple drive command - * The drive must be selected beforehand. - */ -void ide_cmd (ide_drive_t *drive, byte cmd, byte nsect, ide_handler_t *handler) -{ - ide_set_handler (drive, handler, WAIT_CMD, NULL); - if (IDE_CONTROL_REG) - OUT_BYTE(drive->ctl,IDE_CONTROL_REG); /* clear nIEN */ - OUT_BYTE(nsect,IDE_NSECTOR_REG); - OUT_BYTE(cmd,IDE_COMMAND_REG); -} - -/* - * drive_cmd_intr() is invoked on completion of a special DRIVE_CMD. - */ -static ide_startstop_t drive_cmd_intr (ide_drive_t *drive) -{ - struct request *rq = HWGROUP(drive)->rq; - byte *args = (byte *) rq->buffer; - byte stat = GET_STAT(); - int retries = 10; - - ide__sti(); /* local CPU only */ - if ((stat & DRQ_STAT) && args && args[3]) { - byte io_32bit = drive->io_32bit; - drive->io_32bit = 0; - ide_input_data(drive, &args[4], args[3] * SECTOR_WORDS); - drive->io_32bit = io_32bit; - while (((stat = GET_STAT()) & BUSY_STAT) && retries--) - udelay(100); - } - - if (!OK_STAT(stat, READY_STAT, BAD_STAT)) - return ide_error(drive, "drive_cmd", stat); /* calls ide_end_drive_cmd */ - ide_end_drive_cmd (drive, stat, GET_ERR()); - return ide_stopped; -} - -/* - * do_special() is used to issue WIN_SPECIFY, WIN_RESTORE, and WIN_SETMULT - * commands to a drive. It used to do much more, but has been scaled back. - */ -static ide_startstop_t do_special (ide_drive_t *drive) -{ - special_t *s = &drive->special; - -#ifdef DEBUG - printk("%s: do_special: 0x%02x\n", drive->name, s->all); -#endif - if (s->b.set_tune) { - ide_tuneproc_t *tuneproc = HWIF(drive)->tuneproc; - s->b.set_tune = 0; - if (tuneproc != NULL) - tuneproc(drive, drive->tune_req); - } else if (drive->driver != NULL) { - return DRIVER(drive)->special(drive); - } else if (s->all) { - printk("%s: bad special flag: 0x%02x\n", drive->name, s->all); - s->all = 0; - } - return ide_stopped; -} - -/* - * This routine busy-waits for the drive status to be not "busy". - * It then checks the status for all of the "good" bits and none - * of the "bad" bits, and if all is okay it returns 0. All other - * cases return 1 after invoking ide_error() -- caller should just return. - * - * This routine should get fixed to not hog the cpu during extra long waits.. - * That could be done by busy-waiting for the first jiffy or two, and then - * setting a timer to wake up at half second intervals thereafter, - * until timeout is achieved, before timing out. - */ -int ide_wait_stat (ide_startstop_t *startstop, ide_drive_t *drive, byte good, byte bad, unsigned long timeout) { - byte stat; - int i; - unsigned long flags; - - udelay(1); /* spec allows drive 400ns to assert "BUSY" */ - if ((stat = GET_STAT()) & BUSY_STAT) { - __save_flags(flags); /* local CPU only */ - ide__sti(); /* local CPU only */ - timeout += jiffies; - while ((stat = GET_STAT()) & BUSY_STAT) { - if (0 < (signed long)(jiffies - timeout)) { - __restore_flags(flags); /* local CPU only */ - *startstop = ide_error(drive, "status timeout", stat); - return 1; - } - } - __restore_flags(flags); /* local CPU only */ - } - /* - * Allow status to settle, then read it again. - * A few rare drives vastly violate the 400ns spec here, - * so we'll wait up to 10usec for a "good" status - * rather than expensively fail things immediately. - * This fix courtesy of Matthew Faupel & Niccolo Rigacci. - */ - for (i = 0; i < 10; i++) { - udelay(1); - if (OK_STAT((stat = GET_STAT()), good, bad)) - return 0; - } - *startstop = ide_error(drive, "status error", stat); - return 1; -} - -/* - * execute_drive_cmd() issues a special drive command, - * usually initiated by ioctl() from the external hdparm program. - */ -static ide_startstop_t execute_drive_cmd (ide_drive_t *drive, struct request *rq) -{ - byte *args = rq->buffer; - if (args) { -#ifdef DEBUG - printk("%s: DRIVE_CMD cmd=0x%02x sc=0x%02x fr=0x%02x xx=0x%02x\n", - drive->name, args[0], args[1], args[2], args[3]); -#endif - if (args[0] == WIN_SMART) { - OUT_BYTE(0x4f, IDE_LCYL_REG); - OUT_BYTE(0xc2, IDE_HCYL_REG); - OUT_BYTE(args[2],IDE_FEATURE_REG); - OUT_BYTE(args[1],IDE_SECTOR_REG); - ide_cmd(drive, args[0], args[3], &drive_cmd_intr); - return ide_started; - } - OUT_BYTE(args[2],IDE_FEATURE_REG); - ide_cmd(drive, args[0], args[1], &drive_cmd_intr); - return ide_started; - } else { - /* - * NULL is actually a valid way of waiting for - * all current requests to be flushed from the queue. - */ -#ifdef DEBUG - printk("%s: DRIVE_CMD (null)\n", drive->name); -#endif - ide_end_drive_cmd(drive, GET_STAT(), GET_ERR()); - return ide_stopped; - } -} - -/* - * start_request() initiates handling of a new I/O request - */ -static ide_startstop_t start_request (ide_drive_t *drive) -{ - ide_startstop_t startstop; - unsigned long block, blockend; - struct request *rq = blkdev_entry_next_request(&drive->queue.queue_head); - unsigned int minor = MINOR(rq->rq_dev), unit = minor >> PARTN_BITS; - ide_hwif_t *hwif = HWIF(drive); - -#ifdef DEBUG - printk("%s: start_request: current=0x%08lx\n", hwif->name, (unsigned long) rq); -#endif - if (unit >= MAX_DRIVES) { - printk("%s: bad device number: %s\n", hwif->name, kdevname(rq->rq_dev)); - goto kill_rq; - } -#ifdef DEBUG - if (rq->bh && !buffer_locked(rq->bh)) { - printk("%s: block not locked\n", drive->name); - goto kill_rq; - } -#endif - block = rq->sector; - blockend = block + rq->nr_sectors; -#if 0 - if ((rq->cmd == READ || rq->cmd == WRITE) && - (drive->media == ide_disk || drive->media == ide_floppy)) -#endif - { - if ((blockend < block) || (blockend > drive->part[minor&PARTN_MASK].nr_sects)) { - printk("%s%c: bad access: block=%ld, count=%ld\n", drive->name, - (minor&PARTN_MASK)?'0'+(minor&PARTN_MASK):' ', block, rq->nr_sectors); - goto kill_rq; - } - block += drive->part[minor&PARTN_MASK].start_sect + drive->sect0; - } - /* Yecch - this will shift the entire interval, - possibly killing some innocent following sector */ - if (block == 0 && drive->remap_0_to_1 == 1) - block = 1; /* redirect MBR access to EZ-Drive partn table */ - -#if (DISK_RECOVERY_TIME > 0) - while ((read_timer() - hwif->last_time) < DISK_RECOVERY_TIME); -#endif - - SELECT_DRIVE(hwif, drive); - if (ide_wait_stat(&startstop, drive, drive->ready_stat, BUSY_STAT|DRQ_STAT, WAIT_READY)) { - printk("%s: drive not ready for command\n", drive->name); - return startstop; - } - if (!drive->special.all) { - if (rq->cmd == IDE_DRIVE_CMD) { - return execute_drive_cmd(drive, rq); - } - if (drive->driver != NULL) { - return (DRIVER(drive)->do_request(drive, rq, block)); - } - printk("%s: media type %d not supported\n", drive->name, drive->media); - goto kill_rq; - } - return do_special(drive); -kill_rq: - if (drive->driver != NULL) - DRIVER(drive)->end_request(0, HWGROUP(drive)); - else - ide_end_request(0, HWGROUP(drive)); - return ide_stopped; -} - -/* - * ide_stall_queue() can be used by a drive to give excess bandwidth back - * to the hwgroup by sleeping for timeout jiffies. - */ -void ide_stall_queue (ide_drive_t *drive, unsigned long timeout) -{ - if (timeout > WAIT_WORSTCASE) - timeout = WAIT_WORSTCASE; - drive->sleep = timeout + jiffies; -} - -#define WAKEUP(drive) ((drive)->service_start + 2 * (drive)->service_time) - -/* - * choose_drive() selects the next drive which will be serviced. - */ -static inline ide_drive_t *choose_drive (ide_hwgroup_t *hwgroup) -{ - ide_drive_t *drive, *best; - -repeat: - best = NULL; - drive = hwgroup->drive; - do { - if (!list_empty(&drive->queue.queue_head) && (!drive->sleep || 0 <= (signed long)(jiffies - drive->sleep))) { - if (!best - || (drive->sleep && (!best->sleep || 0 < (signed long)(best->sleep - drive->sleep))) - || (!best->sleep && 0 < (signed long)(WAKEUP(best) - WAKEUP(drive)))) - { - if( !drive->queue.plugged ) - best = drive; - } - } - } while ((drive = drive->next) != hwgroup->drive); - if (best && best->nice1 && !best->sleep && best != hwgroup->drive && best->service_time > WAIT_MIN_SLEEP) { - long t = (signed long)(WAKEUP(best) - jiffies); - if (t >= WAIT_MIN_SLEEP) { - /* - * We *may* have some time to spare, but first let's see if - * someone can potentially benefit from our nice mood today.. - */ - drive = best->next; - do { - if (!drive->sleep - && 0 < (signed long)(WAKEUP(drive) - (jiffies - best->service_time)) - && 0 < (signed long)((jiffies + t) - WAKEUP(drive))) - { - ide_stall_queue(best, IDE_MIN(t, 10 * WAIT_MIN_SLEEP)); - goto repeat; - } - } while ((drive = drive->next) != best); - } - } - return best; -} - -/* - * Issue a new request to a drive from hwgroup - * Caller must have already done spin_lock_irqsave(&io_request_lock, ..); - * - * A hwgroup is a serialized group of IDE interfaces. Usually there is - * exactly one hwif (interface) per hwgroup, but buggy controllers (eg. CMD640) - * may have both interfaces in a single hwgroup to "serialize" access. - * Or possibly multiple ISA interfaces can share a common IRQ by being grouped - * together into one hwgroup for serialized access. - * - * Note also that several hwgroups can end up sharing a single IRQ, - * possibly along with many other devices. This is especially common in - * PCI-based systems with off-board IDE controller cards. - * - * The IDE driver uses the single global io_request_lock spinlock to protect - * access to the request queues, and to protect the hwgroup->busy flag. - * - * The first thread into the driver for a particular hwgroup sets the - * hwgroup->busy flag to indicate that this hwgroup is now active, - * and then initiates processing of the top request from the request queue. - * - * Other threads attempting entry notice the busy setting, and will simply - * queue their new requests and exit immediately. Note that hwgroup->busy - * remains set even when the driver is merely awaiting the next interrupt. - * Thus, the meaning is "this hwgroup is busy processing a request". - * - * When processing of a request completes, the completing thread or IRQ-handler - * will start the next request from the queue. If no more work remains, - * the driver will clear the hwgroup->busy flag and exit. - * - * The io_request_lock (spinlock) is used to protect all access to the - * hwgroup->busy flag, but is otherwise not needed for most processing in - * the driver. This makes the driver much more friendlier to shared IRQs - * than previous designs, while remaining 100% (?) SMP safe and capable. - */ -static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq) -{ - ide_drive_t *drive; - ide_hwif_t *hwif; - ide_startstop_t startstop; - - ide_get_lock(&ide_lock, ide_intr, hwgroup); /* for atari only: POSSIBLY BROKEN HERE(?) */ - - __cli(); /* necessary paranoia: ensure IRQs are masked on local CPU */ - - while (!hwgroup->busy) { - hwgroup->busy = 1; - drive = choose_drive(hwgroup); - if (drive == NULL) { - unsigned long sleep = 0; - hwgroup->rq = NULL; - drive = hwgroup->drive; - do { - if (drive->sleep && (!sleep || 0 < (signed long)(sleep - drive->sleep))) - sleep = drive->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 (hwgroup->timer.next || hwgroup->timer.prev) - printk("ide_set_handler: timer already active\n"); -#endif - hwgroup->sleeping = 1; /* so that ide_timer_expiry knows what to do */ - mod_timer(&hwgroup->timer, sleep); - /* we purposely leave hwgroup->busy==1 while sleeping */ - } else { - /* Ugly, but how can we sleep for the lock otherwise? perhaps from tq_scheduler? */ - ide_release_lock(&ide_lock); /* for atari only */ - hwgroup->busy = 0; - } - return; /* no more work for this hwgroup (for now) */ - } - hwif = HWIF(drive); - if (hwgroup->hwif->sharing_irq && hwif != hwgroup->hwif && hwif->io_ports[IDE_CONTROL_OFFSET]) { - /* set nIEN for previous hwif */ - OUT_BYTE(hwgroup->drive->ctl|2, hwgroup->hwif->io_ports[IDE_CONTROL_OFFSET]); - } - hwgroup->hwif = hwif; - hwgroup->drive = drive; - drive->sleep = 0; - drive->service_start = jiffies; - - if ( drive->queue.plugged ) /* paranoia */ - printk("%s: Huh? nuking plugged queue\n", drive->name); - hwgroup->rq = blkdev_entry_next_request(&drive->queue.queue_head); - /* - * 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 (hwif->irq != masked_irq) - disable_irq_nosync(hwif->irq); - spin_unlock(&io_request_lock); - ide__sti(); /* allow other IRQs while we start this request */ - startstop = start_request(drive); - spin_lock_irq(&io_request_lock); - if (hwif->irq != masked_irq) - enable_irq(hwif->irq); - if (startstop == ide_stopped) - hwgroup->busy = 0; - } -} - -/* - * ide_get_queue() returns the queue which corresponds to a given device. - */ -request_queue_t *ide_get_queue (kdev_t dev) -{ - ide_hwif_t *hwif = (ide_hwif_t *)blk_dev[MAJOR(dev)].data; - - return &hwif->drives[DEVICE_NR(dev) & 1].queue; -} - -void do_ide0_request (request_queue_t *q) -{ - ide_do_request (ide_hwifs[0].hwgroup, 0); -} - -#if MAX_HWIFS > 1 -void do_ide1_request (request_queue_t *q) -{ - ide_do_request (ide_hwifs[1].hwgroup, 0); -} -#endif /* MAX_HWIFS > 1 */ - -#if MAX_HWIFS > 2 -void do_ide2_request (request_queue_t *q) -{ - ide_do_request (ide_hwifs[2].hwgroup, 0); -} -#endif /* MAX_HWIFS > 2 */ - -#if MAX_HWIFS > 3 -void do_ide3_request (request_queue_t *q) -{ - ide_do_request (ide_hwifs[3].hwgroup, 0); -} -#endif /* MAX_HWIFS > 3 */ - -#if MAX_HWIFS > 4 -void do_ide4_request (request_queue_t *q) -{ - ide_do_request (ide_hwifs[4].hwgroup, 0); -} -#endif /* MAX_HWIFS > 4 */ - -#if MAX_HWIFS > 5 -void do_ide5_request (request_queue_t *q) -{ - ide_do_request (ide_hwifs[5].hwgroup, 0); -} -#endif /* MAX_HWIFS > 5 */ - -#if MAX_HWIFS > 6 -void do_ide6_request (request_queue_t *q) -{ - ide_do_request (ide_hwifs[6].hwgroup, 0); -} -#endif /* MAX_HWIFS > 6 */ - -#if MAX_HWIFS > 7 -void do_ide7_request (request_queue_t *q) -{ - ide_do_request (ide_hwifs[7].hwgroup, 0); -} -#endif /* MAX_HWIFS > 7 */ - -#if MAX_HWIFS > 8 -void do_ide8_request (request_queue_t *q) -{ - ide_do_request (ide_hwifs[8].hwgroup, 0); -} -#endif /* MAX_HWIFS > 8 */ - -#if MAX_HWIFS > 9 -void do_ide9_request (request_queue_t *q) -{ - ide_do_request (ide_hwifs[9].hwgroup, 0); -} -#endif /* MAX_HWIFS > 9 */ - -/* - * ide_timer_expiry() is our timeout function for all drive operations. - * But note that it can also be invoked as a result of a "sleep" operation - * triggered by the mod_timer() call in ide_do_request. - */ -void ide_timer_expiry (unsigned long data) -{ - ide_hwgroup_t *hwgroup = (ide_hwgroup_t *) data; - ide_handler_t *handler; - ide_expiry_t *expiry; - unsigned long flags; - unsigned long wait; - - spin_lock_irqsave(&io_request_lock, flags); - del_timer(&hwgroup->timer); - - if ((handler = hwgroup->handler) == NULL) { - /* - * Either a marginal timeout occured - * (got the interrupt just as timer expired), - * or we were "sleeping" to give other devices a chance. - * Either way, we don't really want to complain about anything. - */ - if (hwgroup->sleeping) { - hwgroup->sleeping = 0; - hwgroup->busy = 0; - } - } else { - ide_drive_t *drive = hwgroup->drive; - if (!drive) { - printk("ide_timer_expiry: hwgroup->drive was NULL\n"); - hwgroup->handler = NULL; - } else { - ide_hwif_t *hwif; - ide_startstop_t startstop; - if (!hwgroup->busy) { - hwgroup->busy = 1; /* paranoia */ - printk("%s: ide_timer_expiry: hwgroup->busy was 0 ??\n", drive->name); - } - if ((expiry = hwgroup->expiry) != NULL) { - /* continue */ - if ((wait = expiry(drive)) != 0) { - /* reset timer */ - hwgroup->timer.expires = jiffies + wait; - add_timer(&hwgroup->timer); - spin_unlock_irqrestore(&io_request_lock, flags); - return; - } - } - hwgroup->handler = NULL; - /* - * We need to simulate a real interrupt when invoking - * the handler() function, which means we need to globally - * mask the specific IRQ: - */ - spin_unlock(&io_request_lock); - hwif = HWIF(drive); - disable_irq(hwif->irq); /* disable_irq_nosync ?? */ - __cli(); /* local CPU only, as if we were handling an interrupt */ - if (hwgroup->poll_timeout != 0) { - startstop = handler(drive); - } else if (drive_is_ready(drive)) { - if (drive->waiting_for_dma) - (void) hwgroup->hwif->dmaproc(ide_dma_lostirq, drive); - (void)ide_ack_intr(hwif); - printk("%s: lost interrupt\n", drive->name); - startstop = handler(drive); - } else { - if (drive->waiting_for_dma) { - (void) hwgroup->hwif->dmaproc(ide_dma_end, drive); - printk("%s: timeout waiting for DMA\n", drive->name); - (void) hwgroup->hwif->dmaproc(ide_dma_timeout, drive); - } - startstop = ide_error(drive, "irq timeout", GET_STAT()); - } - set_recovery_timer(hwif); - drive->service_time = jiffies - drive->service_start; - enable_irq(hwif->irq); - spin_lock_irq(&io_request_lock); - if (startstop == ide_stopped) - hwgroup->busy = 0; - } - } - ide_do_request(hwgroup, 0); - spin_unlock_irqrestore(&io_request_lock, flags); -} - -/* - * There's nothing really useful we can do with an unexpected interrupt, - * other than reading the status register (to clear it), and logging it. - * There should be no way that an irq can happen before we're ready for it, - * so we needn't worry much about losing an "important" interrupt here. - * - * On laptops (and "green" PCs), an unexpected interrupt occurs whenever the - * drive enters "idle", "standby", or "sleep" mode, so if the status looks - * "good", we just ignore the interrupt completely. - * - * This routine assumes __cli() is in effect when called. - * - * If an unexpected interrupt happens on irq15 while we are handling irq14 - * and if the two interfaces are "serialized" (CMD640), then it looks like - * we could screw up by interfering with a new request being set up for irq15. - * - * In reality, this is a non-issue. The new command is not sent unless the - * drive is ready to accept one, in which case we know the drive is not - * trying to interrupt us. And ide_set_handler() is always invoked before - * completing the issuance of any new drive command, so we will not be - * accidently invoked as a result of any valid command completion interrupt. - * - */ -static void unexpected_intr (int irq, ide_hwgroup_t *hwgroup) -{ - byte stat; - ide_hwif_t *hwif = hwgroup->hwif; - - /* - * handle the unexpected interrupt - */ - do { - if (hwif->irq == irq) { - stat = IN_BYTE(hwif->io_ports[IDE_STATUS_OFFSET]); - if (!OK_STAT(stat, READY_STAT, BAD_STAT)) { - /* Try to not flood the console with msgs */ - static unsigned long last_msgtime = 0, count = 0; - ++count; - if (0 < (signed long)(jiffies - (last_msgtime + HZ))) { - last_msgtime = jiffies; - printk("%s%s: unexpected interrupt, status=0x%02x, count=%ld\n", - hwif->name, (hwif->next == hwgroup->hwif) ? "" : "(?)", stat, count); - } - } - } - } while ((hwif = hwif->next) != hwgroup->hwif); -} - -/* - * entry point for all interrupts, caller does __cli() for us - */ -void ide_intr (int irq, void *dev_id, struct pt_regs *regs) -{ - unsigned long flags; - ide_hwgroup_t *hwgroup = (ide_hwgroup_t *)dev_id; - ide_hwif_t *hwif; - ide_drive_t *drive; - ide_handler_t *handler; - ide_startstop_t startstop; - - spin_lock_irqsave(&io_request_lock, flags); - hwif = hwgroup->hwif; - - if (!ide_ack_intr(hwif)) { - spin_unlock_irqrestore(&io_request_lock, flags); - return; - } - - if ((handler = hwgroup->handler) == NULL || hwgroup->poll_timeout != 0) { - /* - * Not expecting an interrupt from this drive. - * That means this could be: - * (1) an interrupt from another PCI device - * sharing the same PCI INT# as us. - * or (2) a drive just entered sleep or standby mode, - * and is interrupting to let us know. - * or (3) a spurious interrupt of unknown origin. - * - * For PCI, we cannot tell the difference, - * so in that case we just ignore it and hope it goes away. - */ -#ifdef CONFIG_BLK_DEV_IDEPCI - if (IDE_PCI_DEVID_EQ(hwif->pci_devid, IDE_PCI_DEVID_NULL)) -#endif /* CONFIG_BLK_DEV_IDEPCI */ - { - /* - * Probably not a shared PCI interrupt, - * so we can safely try to do something about it: - */ - unexpected_intr(irq, hwgroup); -#ifdef CONFIG_BLK_DEV_IDEPCI - } else { - /* - * Whack the status register, just in case we have a leftover pending IRQ. - */ - (void) IN_BYTE(hwif->io_ports[IDE_STATUS_OFFSET]); -#endif /* CONFIG_BLK_DEV_IDEPCI */ - } - spin_unlock_irqrestore(&io_request_lock, flags); - return; - } - drive = hwgroup->drive; - if (!drive) { - /* - * This should NEVER happen, and there isn't much we could do about it here. - */ - spin_unlock_irqrestore(&io_request_lock, flags); - return; - } - if (!drive_is_ready(drive)) { - /* - * This happens regularly when we share a PCI IRQ with another device. - * Unfortunately, it can also happen with some buggy drives that trigger - * the IRQ before their status register is up to date. Hopefully we have - * enough advance overhead that the latter isn't a problem. - */ - spin_unlock_irqrestore(&io_request_lock, flags); - return; - } - if (!hwgroup->busy) { - hwgroup->busy = 1; /* paranoia */ - printk("%s: ide_intr: hwgroup->busy was 0 ??\n", drive->name); - } - hwgroup->handler = NULL; - del_timer(&hwgroup->timer); - spin_unlock(&io_request_lock); - - if (drive->unmask) - ide__sti(); /* local CPU only */ - startstop = handler(drive); /* service this interrupt, may set handler for next interrupt */ - spin_lock_irq(&io_request_lock); - - /* - * Note that handler() may have set things up for another - * interrupt to occur soon, but it cannot happen until - * we exit from this routine, because it will be the - * same irq as is currently being serviced here, and Linux - * won't allow another of the same (on any CPU) until we return. - */ - set_recovery_timer(HWIF(drive)); - drive->service_time = jiffies - drive->service_start; - if (startstop == ide_stopped) { - if (hwgroup->handler == NULL) { /* paranoia */ - hwgroup->busy = 0; - ide_do_request(hwgroup, hwif->irq); - } else { - printk("%s: ide_intr: huh? expected NULL handler on exit\n", drive->name); - } - } - spin_unlock_irqrestore(&io_request_lock, flags); -} - -/* - * get_info_ptr() returns the (ide_drive_t *) for a given device number. - * It returns NULL if the given device number does not match any present drives. - */ -ide_drive_t *get_info_ptr (kdev_t i_rdev) -{ - int major = MAJOR(i_rdev); -#if 0 - int minor = MINOR(i_rdev) & PARTN_MASK; -#endif - unsigned int h; - - for (h = 0; h < MAX_HWIFS; ++h) { - ide_hwif_t *hwif = &ide_hwifs[h]; - if (hwif->present && major == hwif->major) { - unsigned unit = DEVICE_NR(i_rdev); - if (unit < MAX_DRIVES) { - ide_drive_t *drive = &hwif->drives[unit]; -#if 0 - if ((drive->present) && (drive->part[minor].nr_sects)) -#else - if (drive->present) -#endif - return drive; - } - break; - } - } - return NULL; -} - -/* - * This function is intended to be used prior to invoking ide_do_drive_cmd(). - */ -void ide_init_drive_cmd (struct request *rq) -{ - rq->buffer = NULL; - rq->cmd = IDE_DRIVE_CMD; - rq->sector = 0; - rq->nr_sectors = 0; - rq->current_nr_sectors = 0; - rq->sem = NULL; - rq->bh = NULL; - rq->bhtail = NULL; - rq->q = NULL; -} - -/* - * This function issues a special IDE device request - * onto the request queue. - * - * If action is ide_wait, then the rq is queued at the end of the - * request queue, and the function sleeps until it has been processed. - * This is for use when invoked from an ioctl handler. - * - * If action is ide_preempt, then the rq is queued at the head of - * the request queue, displacing the currently-being-processed - * request and this function returns immediately without waiting - * for the new rq to be completed. This is VERY DANGEROUS, and is - * intended for careful use by the ATAPI tape/cdrom driver code. - * - * If action is ide_next, then the rq is queued immediately after - * the currently-being-processed-request (if any), and the function - * returns without waiting for the new rq to be completed. As above, - * This is VERY DANGEROUS, and is intended for careful use by the - * ATAPI tape/cdrom driver code. - * - * If action is ide_end, then the rq is queued at the end of the - * request queue, and the function returns immediately without waiting - * for the new rq to be completed. This is again intended for careful - * use by the ATAPI tape/cdrom driver code. - */ -int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t action) -{ - unsigned long flags; - ide_hwgroup_t *hwgroup = HWGROUP(drive); - unsigned int major = HWIF(drive)->major; - struct list_head * queue_head; - DECLARE_MUTEX_LOCKED(sem); - -#ifdef CONFIG_BLK_DEV_PDC4030 - if (HWIF(drive)->chipset == ide_pdc4030 && rq->buffer != NULL) - return -ENOSYS; /* special drive cmds not supported */ -#endif - rq->errors = 0; - rq->rq_status = RQ_ACTIVE; - rq->rq_dev = MKDEV(major,(drive->select.b.unit)<<PARTN_BITS); - if (action == ide_wait) - rq->sem = &sem; - spin_lock_irqsave(&io_request_lock, flags); - queue_head = &drive->queue.queue_head; - if (list_empty(queue_head) || action == ide_preempt) { - if (action == ide_preempt) - hwgroup->rq = NULL; - } else { - if (action == ide_wait || action == ide_end) { - queue_head = queue_head->prev; - } else - queue_head = queue_head->next; - } - list_add(&rq->queue, queue_head); - ide_do_request(hwgroup, 0); - spin_unlock_irqrestore(&io_request_lock, flags); - if (action == ide_wait) { - down(&sem); /* wait for it to be serviced */ - return rq->errors ? -EIO : 0; /* return -EIO if errors */ - } - return 0; - -} - -/* - * This routine is called to flush all partitions and partition tables - * for a changed disk, and then re-read the new partition table. - * If we are revalidating a disk because of a media change, then we - * enter with usage == 0. If we are using an ioctl, we automatically have - * usage == 1 (we need an open channel to use an ioctl :-), so this - * is our limit. - */ -int ide_revalidate_disk (kdev_t i_rdev) -{ - ide_drive_t *drive; - ide_hwgroup_t *hwgroup; - unsigned int p, major, minor; - long flags; - - if ((drive = get_info_ptr(i_rdev)) == NULL) - return -ENODEV; - major = MAJOR(i_rdev); - minor = drive->select.b.unit << PARTN_BITS; - hwgroup = HWGROUP(drive); - spin_lock_irqsave(&io_request_lock, flags); - if (drive->busy || (drive->usage > 1)) { - spin_unlock_irqrestore(&io_request_lock, flags); - return -EBUSY; - }; - drive->busy = 1; - MOD_INC_USE_COUNT; - spin_unlock_irqrestore(&io_request_lock, flags); - - for (p = 0; p < (1<<PARTN_BITS); ++p) { - if (drive->part[p].nr_sects > 0) { - kdev_t devp = MKDEV(major, minor+p); - struct super_block * sb = get_super(devp); - fsync_dev (devp); - if (sb) - invalidate_inodes(sb); - invalidate_buffers (devp); - set_blocksize(devp, 1024); - } - drive->part[p].start_sect = 0; - drive->part[p].nr_sects = 0; - }; - - grok_partitions(HWIF(drive)->gd, drive->select.b.unit, - (drive->media != ide_disk && - drive->media != ide_floppy) ? 1 : 1<<PARTN_BITS, - current_capacity(drive)); - - drive->busy = 0; - wake_up(&drive->wqueue); - MOD_DEC_USE_COUNT; - return 0; -} - -static void revalidate_drives (void) -{ - ide_hwif_t *hwif; - ide_drive_t *drive; - int index, unit; - - for (index = 0; index < MAX_HWIFS; ++index) { - hwif = &ide_hwifs[index]; - for (unit = 0; unit < MAX_DRIVES; ++unit) { - drive = &ide_hwifs[index].drives[unit]; - if (drive->revalidate) { - drive->revalidate = 0; - if (!initializing) - (void) ide_revalidate_disk(MKDEV(hwif->major, unit<<PARTN_BITS)); - } - } - } -} - -static void ide_probe_module (void) -{ - if (!ide_probe) { -#ifdef CONFIG_KMOD - (void) request_module("ide-probe-mod"); -#endif /* CONFIG_KMOD */ - } else { - (void) ide_probe->init(); - } - revalidate_drives(); -} - -static void ide_driver_module (void) -{ - int index; - ide_module_t *module = ide_modules; - - for (index = 0; index < MAX_HWIFS; ++index) - if (ide_hwifs[index].present) - goto search; - ide_probe_module(); -search: - while (module) { - (void) module->init(); - module = module->next; - } - revalidate_drives(); -} - -static int ide_open (struct inode * inode, struct file * filp) -{ - ide_drive_t *drive; - int rc; - - if ((drive = get_info_ptr(inode->i_rdev)) == NULL) - return -ENXIO; - MOD_INC_USE_COUNT; - if (drive->driver == NULL) - ide_driver_module(); -#ifdef CONFIG_KMOD - if (drive->driver == NULL) { - if (drive->media == ide_disk) - (void) request_module("ide-disk"); - if (drive->media == ide_cdrom) - (void) request_module("ide-cd"); - if (drive->media == ide_tape) - (void) request_module("ide-tape"); - if (drive->media == ide_floppy) - (void) request_module("ide-floppy"); - } -#endif /* CONFIG_KMOD */ - while (drive->busy) - sleep_on(&drive->wqueue); - drive->usage++; - if (drive->driver != NULL) { - if ((rc = DRIVER(drive)->open(inode, filp, drive))) - MOD_DEC_USE_COUNT; - return rc; - } - printk ("%s: driver not present\n", drive->name); - drive->usage--; - MOD_DEC_USE_COUNT; - return -ENXIO; -} - -/* - * Releasing a block device means we sync() it, so that it can safely - * be forgotten about... - */ -static int ide_release (struct inode * inode, struct file * file) -{ - ide_drive_t *drive; - - if ((drive = get_info_ptr(inode->i_rdev)) != NULL) { - drive->usage--; - if (drive->driver != NULL) - DRIVER(drive)->release(inode, file, drive); - MOD_DEC_USE_COUNT; - } - return 0; -} - -int ide_replace_subdriver (ide_drive_t *drive, const char *driver) -{ - if (!drive->present || drive->busy || drive->usage) - goto abort; - if (drive->driver != NULL && DRIVER(drive)->cleanup(drive)) - goto abort; - strncpy(drive->driver_req, driver, 9); - ide_driver_module(); - drive->driver_req[0] = 0; - ide_driver_module(); - if (DRIVER(drive) && !strcmp(DRIVER(drive)->name, driver)) - return 0; -abort: - return 1; -} - -#ifdef CONFIG_PROC_FS -ide_proc_entry_t generic_subdriver_entries[] = { - { "capacity", S_IFREG|S_IRUGO, proc_ide_read_capacity, NULL }, - { NULL, 0, NULL, NULL } -}; -#endif - -/* - * Note that we only release the standard ports, - * and do not even try to handle any extra ports - * allocated for weird IDE interface chipsets. - */ -void hwif_unregister (ide_hwif_t *hwif) -{ - if (hwif->straight8) { - ide_release_region(hwif->io_ports[IDE_DATA_OFFSET], 8); - goto jump_eight; - } - if (hwif->io_ports[IDE_DATA_OFFSET]) - ide_release_region(hwif->io_ports[IDE_DATA_OFFSET], 1); - if (hwif->io_ports[IDE_ERROR_OFFSET]) - ide_release_region(hwif->io_ports[IDE_ERROR_OFFSET], 1); - if (hwif->io_ports[IDE_NSECTOR_OFFSET]) - ide_release_region(hwif->io_ports[IDE_NSECTOR_OFFSET], 1); - if (hwif->io_ports[IDE_SECTOR_OFFSET]) - ide_release_region(hwif->io_ports[IDE_SECTOR_OFFSET], 1); - if (hwif->io_ports[IDE_LCYL_OFFSET]) - ide_release_region(hwif->io_ports[IDE_LCYL_OFFSET], 1); - if (hwif->io_ports[IDE_HCYL_OFFSET]) - ide_release_region(hwif->io_ports[IDE_HCYL_OFFSET], 1); - if (hwif->io_ports[IDE_SELECT_OFFSET]) - ide_release_region(hwif->io_ports[IDE_SELECT_OFFSET], 1); - if (hwif->io_ports[IDE_STATUS_OFFSET]) - ide_release_region(hwif->io_ports[IDE_STATUS_OFFSET], 1); -jump_eight: - if (hwif->io_ports[IDE_CONTROL_OFFSET]) - ide_release_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1); - if (hwif->io_ports[IDE_IRQ_OFFSET]) - ide_release_region(hwif->io_ports[IDE_IRQ_OFFSET], 1); -} - -void ide_unregister (unsigned int index) -{ - struct gendisk *gd, **gdp; - ide_drive_t *drive, *d; - ide_hwif_t *hwif, *g; - ide_hwgroup_t *hwgroup; - int irq_count = 0, unit, i; - unsigned long flags; - unsigned int p, minor; - ide_hwif_t old_hwif; - - if (index >= MAX_HWIFS) - return; - save_flags(flags); /* all CPUs */ - cli(); /* all CPUs */ - hwif = &ide_hwifs[index]; - if (!hwif->present) - goto abort; - for (unit = 0; unit < MAX_DRIVES; ++unit) { - drive = &hwif->drives[unit]; - if (!drive->present) - continue; - if (drive->busy || drive->usage) - goto abort; - if (drive->driver != NULL && DRIVER(drive)->cleanup(drive)) - goto abort; - } - hwif->present = 0; - - /* - * All clear? Then blow away the buffer cache - */ - sti(); - for (unit = 0; unit < MAX_DRIVES; ++unit) { - drive = &hwif->drives[unit]; - if (!drive->present) - continue; - minor = drive->select.b.unit << PARTN_BITS; - for (p = 0; p < (1<<PARTN_BITS); ++p) { - if (drive->part[p].nr_sects > 0) { - kdev_t devp = MKDEV(hwif->major, minor+p); - struct super_block * sb = get_super(devp); - if (sb) invalidate_inodes(sb); - invalidate_buffers (devp); - } - } -#ifdef CONFIG_PROC_FS - destroy_proc_ide_drives(hwif); -#endif - } - cli(); - hwgroup = hwif->hwgroup; - - /* - * free the irq if we were the only hwif using it - */ - g = hwgroup->hwif; - do { - if (g->irq == hwif->irq) - ++irq_count; - g = g->next; - } while (g != hwgroup->hwif); - if (irq_count == 1) - free_irq(hwif->irq, hwgroup); - - /* - * Note that we only release the standard ports, - * and do not even try to handle any extra ports - * allocated for weird IDE interface chipsets. - */ - hwif_unregister(hwif); - - /* - * Remove us from the hwgroup, and free - * the hwgroup if we were the only member - */ - d = hwgroup->drive; - for (i = 0; i < MAX_DRIVES; ++i) { - drive = &hwif->drives[i]; - if (drive->de) { - devfs_unregister (drive->de); - drive->de = NULL; - } - if (!drive->present) - continue; - while (hwgroup->drive->next != drive) - hwgroup->drive = hwgroup->drive->next; - hwgroup->drive->next = drive->next; - if (hwgroup->drive == drive) - hwgroup->drive = NULL; - if (drive->id != NULL) { - kfree(drive->id); - drive->id = NULL; - } - drive->present = 0; - } - if (d->present) - hwgroup->drive = d; - while (hwgroup->hwif->next != hwif) - hwgroup->hwif = hwgroup->hwif->next; - hwgroup->hwif->next = hwif->next; - if (hwgroup->hwif == hwif) - kfree(hwgroup); - else - hwgroup->hwif = HWIF(hwgroup->drive); - -#ifdef CONFIG_BLK_DEV_IDEDMA - if (hwif->dma_base) - (void) ide_release_dma(hwif); -#endif /* CONFIG_BLK_DEV_IDEDMA */ - - /* - * Remove us from the kernel's knowledge - */ - unregister_blkdev(hwif->major, hwif->name); - kfree(blksize_size[hwif->major]); - kfree(max_sectors[hwif->major]); - kfree(max_readahead[hwif->major]); - blk_cleanup_queue(BLK_DEFAULT_QUEUE(hwif->major)); - blk_dev[hwif->major].data = NULL; - blk_dev[hwif->major].queue = NULL; - blksize_size[hwif->major] = NULL; - for (gdp = &gendisk_head; *gdp; gdp = &((*gdp)->next)) - if (*gdp == hwif->gd) - break; - if (*gdp == NULL) - printk("gd not in disk chain!\n"); - else { - gd = *gdp; *gdp = gd->next; - kfree(gd->sizes); - kfree(gd->part); - if (gd->de_arr) - kfree (gd->de_arr); - if (gd->flags) - kfree (gd->flags); - kfree(gd); - } - old_hwif = *hwif; - init_hwif_data (index); /* restore hwif data to pristine status */ - hwif->hwgroup = old_hwif.hwgroup; - hwif->tuneproc = old_hwif.tuneproc; - hwif->selectproc = old_hwif.selectproc; - hwif->resetproc = old_hwif.resetproc; - hwif->dmaproc = old_hwif.dmaproc; - hwif->dma_base = old_hwif.dma_base; - hwif->dma_extra = old_hwif.dma_extra; - hwif->config_data = old_hwif.config_data; - hwif->select_data = old_hwif.select_data; - hwif->proc = old_hwif.proc; - hwif->irq = old_hwif.irq; - hwif->major = old_hwif.major; - hwif->chipset = old_hwif.chipset; - hwif->autodma = old_hwif.autodma; - hwif->udma_four = old_hwif.udma_four; -#ifdef CONFIG_BLK_DEV_IDEPCI - hwif->pci_dev = old_hwif.pci_dev; - hwif->pci_devid = old_hwif.pci_devid; -#endif /* CONFIG_BLK_DEV_IDEPCI */ - hwif->straight8 = old_hwif.straight8; - -abort: - restore_flags(flags); /* all CPUs */ -} - -/* - * Setup hw_regs_t structure described by parameters. You - * may set up the hw structure yourself OR use this routine to - * do it for you. - */ -void ide_setup_ports ( hw_regs_t *hw, - ide_ioreg_t base, int *offsets, - ide_ioreg_t ctrl, ide_ioreg_t intr, - ide_ack_intr_t *ack_intr, int irq) -{ - int i; - - for (i = 0; i < IDE_NR_PORTS; i++) { - if (offsets[i] == -1) { - switch(i) { - case IDE_CONTROL_OFFSET: - hw->io_ports[i] = ctrl; - break; - case IDE_IRQ_OFFSET: - hw->io_ports[i] = intr; - break; - default: - hw->io_ports[i] = 0; - break; - } - } else { - hw->io_ports[i] = base + offsets[i]; - } - } - hw->irq = irq; - hw->dma = NO_DMA; - hw->ack_intr = ack_intr; -} - -/* - * Register an IDE interface, specifing exactly the registers etc - * Set init=1 iff calling before probes have taken place. - */ -int ide_register_hw (hw_regs_t *hw, ide_hwif_t **hwifp) -{ - int index, retry = 1; - ide_hwif_t *hwif; - - do { - for (index = 0; index < MAX_HWIFS; ++index) { - hwif = &ide_hwifs[index]; - if (hwif->hw.io_ports[IDE_DATA_OFFSET] == hw->io_ports[IDE_DATA_OFFSET]) - goto found; - } - for (index = 0; index < MAX_HWIFS; ++index) { - hwif = &ide_hwifs[index]; - if ((!hwif->present && !hwif->mate && !initializing) || - (!hwif->hw.io_ports[IDE_DATA_OFFSET] && initializing)) - goto found; - } - for (index = 0; index < MAX_HWIFS; index++) - ide_unregister(index); - } while (retry--); - return -1; -found: - if (hwif->present) - ide_unregister(index); - if (hwif->present) - return -1; - memcpy(&hwif->hw, hw, sizeof(*hw)); - memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->hw.io_ports)); - hwif->irq = hw->irq; - hwif->noprobe = 0; - - if (!initializing) { - ide_probe_module(); -#ifdef CONFIG_PROC_FS - create_proc_ide_interfaces(); -#endif - ide_driver_module(); - } - - if (hwifp) - *hwifp = hwif; - - return (initializing || hwif->present) ? index : -1; -} - -/* - * Compatability function with existing drivers. If you want - * something different, use the function above. - */ -int ide_register (int arg1, int arg2, int irq) -{ - hw_regs_t hw; - ide_init_hwif_ports(&hw, (ide_ioreg_t) arg1, (ide_ioreg_t) arg2, NULL); - hw.irq = irq; - return ide_register_hw(&hw, NULL); -} - -void ide_add_setting (ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set) -{ - ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting = NULL; - - while ((*p) && strcmp((*p)->name, name) < 0) - p = &((*p)->next); - if ((setting = kmalloc(sizeof(*setting), GFP_KERNEL)) == NULL) - goto abort; - memset(setting, 0, sizeof(*setting)); - if ((setting->name = kmalloc(strlen(name) + 1, GFP_KERNEL)) == NULL) - goto abort; - strcpy(setting->name, name); setting->rw = rw; - setting->read_ioctl = read_ioctl; setting->write_ioctl = write_ioctl; - setting->data_type = data_type; setting->min = min; - setting->max = max; setting->mul_factor = mul_factor; - setting->div_factor = div_factor; setting->data = data; - setting->set = set; setting->next = *p; - if (drive->driver) - setting->auto_remove = 1; - *p = setting; - return; -abort: - if (setting) - kfree(setting); -} - -void ide_remove_setting (ide_drive_t *drive, char *name) -{ - ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting; - - while ((*p) && strcmp((*p)->name, name)) - p = &((*p)->next); - if ((setting = (*p)) == NULL) - return; - (*p) = setting->next; - kfree(setting->name); - kfree(setting); -} - -static ide_settings_t *ide_find_setting_by_ioctl (ide_drive_t *drive, int cmd) -{ - ide_settings_t *setting = drive->settings; - - while (setting) { - if (setting->read_ioctl == cmd || setting->write_ioctl == cmd) - break; - setting = setting->next; - } - return setting; -} - -ide_settings_t *ide_find_setting_by_name (ide_drive_t *drive, char *name) -{ - ide_settings_t *setting = drive->settings; - - while (setting) { - if (strcmp(setting->name, name) == 0) - break; - setting = setting->next; - } - return setting; -} - -static void auto_remove_settings (ide_drive_t *drive) -{ - ide_settings_t *setting; -repeat: - setting = drive->settings; - while (setting) { - if (setting->auto_remove) { - ide_remove_setting(drive, setting->name); - goto repeat; - } - setting = setting->next; - } -} - -int ide_read_setting (ide_drive_t *drive, ide_settings_t *setting) -{ - int val = -EINVAL; - unsigned long flags; - - if ((setting->rw & SETTING_READ)) { - spin_lock_irqsave(&io_request_lock, flags); - switch(setting->data_type) { - case TYPE_BYTE: - val = *((u8 *) setting->data); - break; - case TYPE_SHORT: - val = *((u16 *) setting->data); - break; - case TYPE_INT: - case TYPE_INTA: - val = *((u32 *) setting->data); - break; - } - spin_unlock_irqrestore(&io_request_lock, flags); - } - return val; -} - -int ide_spin_wait_hwgroup (ide_drive_t *drive, unsigned long *flags) -{ - ide_hwgroup_t *hwgroup = HWGROUP(drive); - unsigned long timeout = jiffies + (3 * HZ); - - spin_lock_irqsave(&io_request_lock, *flags); - while (hwgroup->busy) { - unsigned long lflags; - spin_unlock_irqrestore(&io_request_lock, *flags); - __save_flags(lflags); /* local CPU only */ - __sti(); /* local CPU only; needed for jiffies */ - if (0 < (signed long)(jiffies - timeout)) { - __restore_flags(lflags); /* local CPU only */ - printk("%s: channel busy\n", drive->name); - return -EBUSY; - } - __restore_flags(lflags); /* local CPU only */ - spin_lock_irqsave(&io_request_lock, *flags); - } - return 0; -} - -/* - * FIXME: This should be changed to enqueue a special request - * to the driver to change settings, and then wait on a sema for completion. - * The current scheme of polling is kludgey, though safe enough. - */ -int ide_write_setting (ide_drive_t *drive, ide_settings_t *setting, int val) -{ - unsigned long flags; - int i; - u32 *p; - - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - if (!(setting->rw & SETTING_WRITE)) - return -EPERM; - if (val < setting->min || val > setting->max) - return -EINVAL; - if (setting->set) - return setting->set(drive, val); - if (ide_spin_wait_hwgroup(drive, &flags)) - return -EBUSY; - switch (setting->data_type) { - case TYPE_BYTE: - *((u8 *) setting->data) = val; - break; - case TYPE_SHORT: - *((u16 *) setting->data) = val; - break; - case TYPE_INT: - *((u32 *) setting->data) = val; - break; - case TYPE_INTA: - p = (u32 *) setting->data; - for (i = 0; i < 1 << PARTN_BITS; i++, p++) - *p = val; - break; - } - spin_unlock_irqrestore(&io_request_lock, flags); - return 0; -} - -static int set_io_32bit(ide_drive_t *drive, int arg) -{ - drive->io_32bit = arg; -#ifdef CONFIG_BLK_DEV_DTC2278 - if (HWIF(drive)->chipset == ide_dtc2278) - HWIF(drive)->drives[!drive->select.b.unit].io_32bit = arg; -#endif /* CONFIG_BLK_DEV_DTC2278 */ - return 0; -} - -static int set_using_dma (ide_drive_t *drive, int arg) -{ - if (!drive->driver || !DRIVER(drive)->supports_dma) - return -EPERM; - if (!drive->id || !(drive->id->capability & 1) || !HWIF(drive)->dmaproc) - return -EPERM; - if (HWIF(drive)->dmaproc(arg ? ide_dma_on : ide_dma_off, drive)) - return -EIO; - return 0; -} - -static int set_pio_mode (ide_drive_t *drive, int arg) -{ - struct request rq; - - if (!HWIF(drive)->tuneproc) - return -ENOSYS; - if (drive->special.b.set_tune) - return -EBUSY; - ide_init_drive_cmd(&rq); - drive->tune_req = (byte) arg; - drive->special.b.set_tune = 1; - (void) ide_do_drive_cmd (drive, &rq, ide_wait); - return 0; -} - -void ide_add_generic_settings (ide_drive_t *drive) -{ -/* - * drive setting name read/write access read ioctl write ioctl data type min max mul_factor div_factor data pointer set function - */ - ide_add_setting(drive, "io_32bit", drive->no_io_32bit ? SETTING_READ : SETTING_RW, HDIO_GET_32BIT, HDIO_SET_32BIT, TYPE_BYTE, 0, 1 + (SUPPORT_VLB_SYNC << 1), 1, 1, &drive->io_32bit, set_io_32bit); - ide_add_setting(drive, "keepsettings", SETTING_RW, HDIO_GET_KEEPSETTINGS, HDIO_SET_KEEPSETTINGS, TYPE_BYTE, 0, 1, 1, 1, &drive->keep_settings, NULL); - ide_add_setting(drive, "nice1", SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->nice1, NULL); - ide_add_setting(drive, "pio_mode", SETTING_WRITE, -1, HDIO_SET_PIO_MODE, TYPE_BYTE, 0, 255, 1, 1, NULL, set_pio_mode); - ide_add_setting(drive, "slow", SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->slow, NULL); - ide_add_setting(drive, "unmaskirq", drive->no_unmask ? SETTING_READ : SETTING_RW, HDIO_GET_UNMASKINTR, HDIO_SET_UNMASKINTR, TYPE_BYTE, 0, 1, 1, 1, &drive->unmask, NULL); - ide_add_setting(drive, "using_dma", SETTING_RW, HDIO_GET_DMA, HDIO_SET_DMA, TYPE_BYTE, 0, 1, 1, 1, &drive->using_dma, set_using_dma); - ide_add_setting(drive, "ide_scsi", SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->scsi, NULL); -} - -int ide_wait_cmd (ide_drive_t *drive, int cmd, int nsect, int feature, int sectors, byte *buf) -{ - struct request rq; - byte buffer[4]; - - if (!buf) - buf = buffer; - memset(buf, 0, 4 + SECTOR_WORDS * 4 * sectors); - ide_init_drive_cmd(&rq); - rq.buffer = buf; - *buf++ = cmd; - *buf++ = nsect; - *buf++ = feature; - *buf++ = sectors; - return ide_do_drive_cmd(drive, &rq, ide_wait); -} - -/* - * Delay for *at least* 50ms. As we don't know how much time is left - * until the next tick occurs, we wait an extra tick to be safe. - * This is used only during the probing/polling for drives at boot time. - * - * However, its usefullness may be needed in other places, thus we export it now. - * The future may change this to a millisecond setable delay. - */ -void ide_delay_50ms (void) -{ - unsigned long timeout = jiffies + ((HZ + 19)/20) + 1; - while (0 < (signed long)(timeout - jiffies)); -} - -static int ide_ioctl (struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - int err = 0, major, minor; - ide_drive_t *drive; - struct request rq; - kdev_t dev; - ide_settings_t *setting; - - if (!inode || !(dev = inode->i_rdev)) - return -EINVAL; - major = MAJOR(dev); minor = MINOR(dev); - if ((drive = get_info_ptr(inode->i_rdev)) == NULL) - return -ENODEV; - - if ((setting = ide_find_setting_by_ioctl(drive, cmd)) != NULL) { - if (cmd == setting->read_ioctl) { - err = ide_read_setting(drive, setting); - return err >= 0 ? put_user(err, (long *) arg) : err; - } else { - if ((MINOR(inode->i_rdev) & PARTN_MASK)) - return -EINVAL; - return ide_write_setting(drive, setting, arg); - } - } - - ide_init_drive_cmd (&rq); - switch (cmd) { - case HDIO_GETGEO: - { - struct hd_geometry *loc = (struct hd_geometry *) arg; - unsigned short bios_cyl = drive->bios_cyl; /* truncate */ - if (!loc || (drive->media != ide_disk && drive->media != ide_floppy)) return -EINVAL; - if (put_user(drive->bios_head, (byte *) &loc->heads)) return -EFAULT; - if (put_user(drive->bios_sect, (byte *) &loc->sectors)) return -EFAULT; - if (put_user(bios_cyl, (unsigned short *) &loc->cylinders)) return -EFAULT; - if (put_user((unsigned)drive->part[MINOR(inode->i_rdev)&PARTN_MASK].start_sect, - (unsigned long *) &loc->start)) return -EFAULT; - return 0; - } - - case BLKGETSIZE: /* Return device size */ - return put_user(drive->part[MINOR(inode->i_rdev)&PARTN_MASK].nr_sects, (long *) arg); - - case BLKRRPART: /* Re-read partition tables */ - if (!capable(CAP_SYS_ADMIN)) return -EACCES; - return ide_revalidate_disk(inode->i_rdev); - - case HDIO_OBSOLETE_IDENTITY: - case HDIO_GET_IDENTITY: - if (MINOR(inode->i_rdev) & PARTN_MASK) - return -EINVAL; - if (drive->id == NULL) - return -ENOMSG; - if (copy_to_user((char *)arg, (char *)drive->id, (cmd == HDIO_GET_IDENTITY) ? sizeof(*drive->id) : 142)) - return -EFAULT; - return 0; - - case HDIO_GET_NICE: - return put_user(drive->dsc_overlap << IDE_NICE_DSC_OVERLAP | - drive->atapi_overlap << IDE_NICE_ATAPI_OVERLAP | - drive->nice0 << IDE_NICE_0 | - drive->nice1 << IDE_NICE_1 | - drive->nice2 << IDE_NICE_2, - (long *) arg); - case HDIO_DRIVE_CMD: - { - byte args[4], *argbuf = args; - int argsize = 4; - if (!capable(CAP_SYS_ADMIN)) return -EACCES; - if (NULL == (void *) arg) - return ide_do_drive_cmd(drive, &rq, ide_wait); - if (copy_from_user(args, (void *)arg, 4)) - return -EFAULT; - if (args[3]) { - argsize = 4 + (SECTOR_WORDS * 4 * args[3]); - argbuf = kmalloc(argsize, GFP_KERNEL); - if (argbuf == NULL) - return -ENOMEM; - memcpy(argbuf, args, 4); - } - if (ide_ata66_check(drive, args[0], args[1], args[2])) - goto abort; - - err = ide_wait_cmd(drive, args[0], args[1], args[2], args[3], argbuf); - - if (!err && set_transfer(drive, args[0], args[1], args[2])) { -#if 0 - /* active-retuning-calls future */ - if (HWIF(drive)->tune2proc) - HWIF(drive)->tune2proc(drive, args[1]); -#endif - ide_driveid_update(drive); - } - abort: - if (copy_to_user((void *)arg, argbuf, argsize)) - err = -EFAULT; - if (argsize > 4) - kfree(argbuf); - return err; - } - - case HDIO_SCAN_HWIF: - { - int args[3]; - if (!capable(CAP_SYS_ADMIN)) return -EACCES; - if (copy_from_user(args, (void *)arg, 3 * sizeof(int))) - return -EFAULT; - if (ide_register(args[0], args[1], args[2]) == -1) - return -EIO; - return 0; - } - case HDIO_UNREGISTER_HWIF: - if (!capable(CAP_SYS_ADMIN)) return -EACCES; - /* should I check here for arg > MAX_HWIFS, or - just let ide_unregister fail silently? -- shaver */ - ide_unregister(arg); - return 0; - case HDIO_SET_NICE: - if (!capable(CAP_SYS_ADMIN)) return -EACCES; - if (drive->driver == NULL) - return -EPERM; - if (arg != (arg & ((1 << IDE_NICE_DSC_OVERLAP) | (1 << IDE_NICE_1)))) - return -EPERM; - drive->dsc_overlap = (arg >> IDE_NICE_DSC_OVERLAP) & 1; - if (drive->dsc_overlap && !DRIVER(drive)->supports_dsc_overlap) { - drive->dsc_overlap = 0; - return -EPERM; - } - drive->nice1 = (arg >> IDE_NICE_1) & 1; - return 0; - - case BLKROSET: - case BLKROGET: - case BLKFLSBUF: - case BLKSSZGET: - case BLKPG: - return blk_ioctl(inode->i_rdev, cmd, arg); - - default: - if (drive->driver != NULL) - return DRIVER(drive)->ioctl(drive, inode, file, cmd, arg); - return -EPERM; - } -} - -static int ide_check_media_change (kdev_t i_rdev) -{ - ide_drive_t *drive; - - if ((drive = get_info_ptr(i_rdev)) == NULL) - return -ENODEV; - if (drive->driver != NULL) - return DRIVER(drive)->media_change(drive); - return 0; -} - -void ide_fixstring (byte *s, const int bytecount, const int byteswap) -{ - byte *p = s, *end = &s[bytecount & ~1]; /* bytecount must be even */ - - if (byteswap) { - /* convert from big-endian to host byte order */ - for (p = end ; p != s;) { - unsigned short *pp = (unsigned short *) (p -= 2); - *pp = ntohs(*pp); - } - } - - /* strip leading blanks */ - while (s != end && *s == ' ') - ++s; - - /* compress internal blanks and strip trailing blanks */ - while (s != end && *s) { - if (*s++ != ' ' || (s != end && *s && *s != ' ')) - *p++ = *(s-1); - } - - /* wipe out trailing garbage */ - while (p != end) - *p++ = '\0'; -} - -/* - * stridx() returns the offset of c within s, - * or -1 if c is '\0' or not found within s. - */ -static int __init stridx (const char *s, char c) -{ - char *i = strchr(s, c); - return (i && c) ? i - s : -1; -} - -/* - * match_parm() does parsing for ide_setup(): - * - * 1. the first char of s must be '='. - * 2. if the remainder matches one of the supplied keywords, - * the index (1 based) of the keyword is negated and returned. - * 3. if the remainder is a series of no more than max_vals numbers - * separated by commas, the numbers are saved in vals[] and a - * count of how many were saved is returned. Base10 is assumed, - * and base16 is allowed when prefixed with "0x". - * 4. otherwise, zero is returned. - */ -static int __init match_parm (char *s, const char *keywords[], int vals[], int max_vals) -{ - static const char *decimal = "0123456789"; - static const char *hex = "0123456789abcdef"; - int i, n; - - if (*s++ == '=') { - /* - * Try matching against the supplied keywords, - * and return -(index+1) if we match one - */ - if (keywords != NULL) { - for (i = 0; *keywords != NULL; ++i) { - if (!strcmp(s, *keywords++)) - return -(i+1); - } - } - /* - * Look for a series of no more than "max_vals" - * numeric values separated by commas, in base10, - * or base16 when prefixed with "0x". - * Return a count of how many were found. - */ - for (n = 0; (i = stridx(decimal, *s)) >= 0;) { - vals[n] = i; - while ((i = stridx(decimal, *++s)) >= 0) - vals[n] = (vals[n] * 10) + i; - if (*s == 'x' && !vals[n]) { - while ((i = stridx(hex, *++s)) >= 0) - vals[n] = (vals[n] * 0x10) + i; - } - if (++n == max_vals) - break; - if (*s == ',' || *s == ';') - ++s; - } - if (!*s) - return n; - } - return 0; /* zero = nothing matched */ -} - -/* - * ide_setup() gets called VERY EARLY during initialization, - * to handle kernel "command line" strings beginning with "hdx=" - * or "ide". Here is the complete set currently supported: - * - * "hdx=" is recognized for all "x" from "a" to "h", such as "hdc". - * "idex=" is recognized for all "x" from "0" to "3", such as "ide1". - * - * "hdx=noprobe" : drive may be present, but do not probe for it - * "hdx=none" : drive is NOT present, ignore cmos and do not probe - * "hdx=nowerr" : ignore the WRERR_STAT bit on this drive - * "hdx=cdrom" : drive is present, and is a cdrom drive - * "hdx=cyl,head,sect" : disk drive is present, with specified geometry - * "hdx=noremap" : do not remap 0->1 even though EZD was detected - * "hdx=autotune" : driver will attempt to tune interface speed - * to the fastest PIO mode supported, - * if possible for this drive only. - * Not fully supported by all chipset types, - * and quite likely to cause trouble with - * older/odd IDE drives. - * - * "hdx=slow" : insert a huge pause after each access to the data - * port. Should be used only as a last resort. - * - * "hdx=swapdata" : when the drive is a disk, byte swap all data - * "hdx=bswap" : same as above.......... - * "hdxlun=xx" : set the drive last logical unit. - * "hdx=flash" : allows for more than one ata_flash disk to be - * registered. In most cases, only one device - * will be present. - * "hdx=scsi" : the return of the ide-scsi flag, this is useful for - * allowwing ide-floppy, ide-tape, and ide-cdrom|writers - * to use ide-scsi emulation on a device specific option. - * "idebus=xx" : inform IDE driver of VESA/PCI bus speed in MHz, - * where "xx" is between 20 and 66 inclusive, - * used when tuning chipset PIO modes. - * For PCI bus, 25 is correct for a P75 system, - * 30 is correct for P90,P120,P180 systems, - * and 33 is used for P100,P133,P166 systems. - * If in doubt, use idebus=33 for PCI. - * As for VLB, it is safest to not specify it. - * - * "idex=noprobe" : do not attempt to access/use this interface - * "idex=base" : probe for an interface at the addr specified, - * where "base" is usually 0x1f0 or 0x170 - * and "ctl" is assumed to be "base"+0x206 - * "idex=base,ctl" : specify both base and ctl - * "idex=base,ctl,irq" : specify base, ctl, and irq number - * "idex=autotune" : driver will attempt to tune interface speed - * to the fastest PIO mode supported, - * for all drives on this interface. - * Not fully supported by all chipset types, - * and quite likely to cause trouble with - * older/odd IDE drives. - * "idex=noautotune" : driver will NOT attempt to tune interface speed - * This is the default for most chipsets, - * except the cmd640. - * "idex=serialize" : do not overlap operations on idex and ide(x^1) - * "idex=four" : four drives on idex and ide(x^1) share same ports - * "idex=reset" : reset interface before first use - * "idex=dma" : enable DMA by default on both drives if possible - * "idex=ata66" : informs the interface that it has an 80c cable - * for chipsets that are ATA-66 capable, but - * the ablity to bit test for detection is - * currently unknown. - * "ide=reverse" : Formerly called to pci sub-system, but now local. - * - * "splitfifo=betweenChan" - * : FIFO Configuration of VIA 82c586(<nothing>,"A"or"B"). - * --see what follows... - * "splitfifo=betweenChan,thresholdprim,thresholdsec" - * : FIFO Configuration of VIA 82c586(<nothing>,"A" or "B"). - * betweenChan = 1(all FIFO's to primary channel) - * , 2(all FIFO's to secondary channel) - * , 3 or 4(evenly shared between them). - * note: without FIFO, a channel is (u)dma disabled! - * thresholdprim = 4, 3, 2 or 1 - * (standing for 1, 3/4, 1/2, 1/4). - * Sets the threshold of FIFO to begin dma - * transfer on the primary channel. - * thresholdsec = cf upper, but for secondary channel. - * - * The following are valid ONLY on ide0, (except dc4030) - * and the defaults for the base,ctl ports must not be altered. - * - * "ide0=dtc2278" : probe/support DTC2278 interface - * "ide0=ht6560b" : probe/support HT6560B interface - * "ide0=cmd640_vlb" : *REQUIRED* for VLB cards with the CMD640 chip - * (not for PCI -- automatically detected) - * "ide0=qd6580" : probe/support qd6580 interface - * "ide0=ali14xx" : probe/support ali14xx chipsets (ALI M1439, M1443, M1445) - * "ide0=umc8672" : probe/support umc8672 chipsets - * "idex=dc4030" : probe/support Promise DC4030VL interface - * "ide=doubler" : probe/support IDE doublers on Amiga - */ -int __init ide_setup (char *s) -{ - int i, vals[3]; - ide_hwif_t *hwif; - ide_drive_t *drive; - unsigned int hw, unit; - const char max_drive = 'a' + ((MAX_HWIFS * MAX_DRIVES) - 1); - const char max_hwif = '0' + (MAX_HWIFS - 1); - - printk("ide_setup: %s", s); - init_ide_data (); - -#ifdef CONFIG_BLK_DEV_IDEDOUBLER - if (!strcmp(s, "ide=doubler")) { - extern int ide_doubler; - - printk(" : Enabled support for IDE doublers\n"); - ide_doubler = 1; - return 0; - } -#endif /* CONFIG_BLK_DEV_IDEDOUBLER */ - -#ifdef CONFIG_BLK_DEV_IDEPCI - if (!strcmp(s, "ide=reverse")) { - ide_scan_direction = 1; - printk(" : Enabled support for IDE inverse scan order.\n"); - return 0; - } -#endif /* CONFIG_BLK_DEV_IDEPCI */ - - /* - * Look for drive options: "hdx=" - */ - if (s[0] == 'h' && s[1] == 'd' && s[2] >= 'a' && s[2] <= max_drive) { - const char *hd_words[] = {"none", "noprobe", "nowerr", "cdrom", - "serialize", "autotune", "noautotune", - "slow", "swapdata", "bswap", "flash", - "remap", "noremap", "scsi", NULL}; - unit = s[2] - 'a'; - hw = unit / MAX_DRIVES; - unit = unit % MAX_DRIVES; - hwif = &ide_hwifs[hw]; - drive = &hwif->drives[unit]; - if (strncmp(s + 4, "ide-", 4) == 0) { - strncpy(drive->driver_req, s + 4, 9); - goto done; - } - /* - * Look for last lun option: "hdxlun=" - */ - if (s[3] == 'l' && s[4] == 'u' && s[5] == 'n') { - if (match_parm(&s[6], NULL, vals, 1) != 1) - goto bad_option; - if (vals[0] >= 0 && vals[0] <= 7) { - drive->last_lun = vals[0]; - drive->forced_lun = 1; - } else - printk(" -- BAD LAST LUN! Expected value from 0 to 7"); - goto done; - } - switch (match_parm(&s[3], hd_words, vals, 3)) { - case -1: /* "none" */ - drive->nobios = 1; /* drop into "noprobe" */ - case -2: /* "noprobe" */ - drive->noprobe = 1; - goto done; - case -3: /* "nowerr" */ - drive->bad_wstat = BAD_R_STAT; - hwif->noprobe = 0; - goto done; - case -4: /* "cdrom" */ - drive->present = 1; - drive->media = ide_cdrom; - hwif->noprobe = 0; - goto done; - case -5: /* "serialize" */ - printk(" -- USE \"ide%d=serialize\" INSTEAD", hw); - goto do_serialize; - case -6: /* "autotune" */ - drive->autotune = 1; - goto done; - case -7: /* "noautotune" */ - drive->autotune = 2; - goto done; - case -8: /* "slow" */ - drive->slow = 1; - goto done; - case -9: /* "swapdata" or "bswap" */ - case -10: - drive->bswap = 1; - goto done; - case -11: /* "flash" */ - drive->ata_flash = 1; - goto done; - case -12: /* "remap" */ - drive->remap_0_to_1 = 1; - goto done; - case -13: /* "noremap" */ - drive->remap_0_to_1 = 2; - goto done; - case -14: /* "scsi" */ -#if defined(CONFIG_BLK_DEV_IDESCSI) && defined(CONFIG_SCSI) - drive->scsi = 1; - goto done; -#else - drive->scsi = 0; - goto bad_option; -#endif /* defined(CONFIG_BLK_DEV_IDESCSI) && defined(CONFIG_SCSI) */ - case 3: /* cyl,head,sect */ - drive->media = ide_disk; - drive->cyl = drive->bios_cyl = vals[0]; - drive->head = drive->bios_head = vals[1]; - drive->sect = drive->bios_sect = vals[2]; - drive->present = 1; - drive->forced_geom = 1; - hwif->noprobe = 0; - goto done; - default: - goto bad_option; - } - } - -#if defined(CONFIG_BLK_DEV_VIA82CXXX) - /* - * Look for drive option "splitfifo=..." - */ - - if (s[0] == 's' && s[1] == 'p' && s[2] == 'l' && - s[3] == 'i' && s[4] == 't' && s[5] == 'f' && - s[6] == 'i' && s[7] == 'f' && s[8] == 'o') { - byte tmp = 0x3a; /* default config byte */ - - i = match_parm(&s[9], NULL, vals, 3); - switch(i) { - case 3: - tmp &= 0xf0; - if ((vals[1] > 0) && (vals[1] < 5)) { - /* sets threshold for primary Channel: */ - byte x = 4 - vals[1]; - tmp |= (x << 2); - } - else - goto bad_option; - if ((vals[2] > 0) && (vals[2] < 5)) { - /* sets threshold for secondary Channel: */ - byte x = 4 - vals[2]; - tmp |= x; - } - else - goto bad_option; - case 1: - /* set the FIFO config between channels to 0: */ - tmp &= 0x9f; - /* set the needed FIFO config between channels: */ - if (vals[0] == 1) /* primary fifo only */ - tmp |= 0x10; - else if (vals[0] == 2) /* secondary fifo only */ - tmp |= 0x70; - else if (vals[0] == 4) /* other shared fifo config */ - tmp |= 0x50; - else if (vals[0] == 3) /* default config */ - tmp |= 0x30; - else - goto bad_option; - break; - default: - goto bad_option; - } - /* set the found option in fifoconfig */ - fifoconfig = tmp; - goto done; - } -#endif /* defined(CONFIG_BLK_DEV_VIA82CXXX) */ - - if (s[0] != 'i' || s[1] != 'd' || s[2] != 'e') - goto bad_option; - /* - * Look for bus speed option: "idebus=" - */ - if (s[3] == 'b' && s[4] == 'u' && s[5] == 's') { - if (match_parm(&s[6], NULL, vals, 1) != 1) - goto bad_option; - if (vals[0] >= 20 && vals[0] <= 66) { - idebus_parameter = vals[0]; - } else - printk(" -- BAD BUS SPEED! Expected value from 20 to 66"); - goto done; - } - /* - * Look for interface options: "idex=" - */ - if (s[3] >= '0' && s[3] <= max_hwif) { - /* - * Be VERY CAREFUL changing this: note hardcoded indexes below - * -8,-9,-10 : are reserved for future idex calls to ease the hardcoding. - */ - const char *ide_words[] = { - "noprobe", "serialize", "autotune", "noautotune", "reset", "dma", "ata66", - "minus8", "minus9", "minus10", - "four", "qd6580", "ht6560b", "cmd640_vlb", "dtc2278", "umc8672", "ali14xx", "dc4030", NULL }; - hw = s[3] - '0'; - hwif = &ide_hwifs[hw]; - i = match_parm(&s[4], ide_words, vals, 3); - - /* - * Cryptic check to ensure chipset not already set for hwif: - */ - if (i > 0 || i <= -11) { /* is parameter a chipset name? */ - if (hwif->chipset != ide_unknown) - goto bad_option; /* chipset already specified */ - if (i <= -11 && i != -18 && hw != 0) - goto bad_hwif; /* chipset drivers are for "ide0=" only */ - if (i <= -11 && i != -18 && ide_hwifs[hw+1].chipset != ide_unknown) - goto bad_option; /* chipset for 2nd port already specified */ - printk("\n"); - } - - switch (i) { -#ifdef CONFIG_BLK_DEV_PDC4030 - case -18: /* "dc4030" */ - { - extern void init_pdc4030(void); - init_pdc4030(); - goto done; - } -#endif /* CONFIG_BLK_DEV_PDC4030 */ -#ifdef CONFIG_BLK_DEV_ALI14XX - case -17: /* "ali14xx" */ - { - extern void init_ali14xx (void); - init_ali14xx(); - goto done; - } -#endif /* CONFIG_BLK_DEV_ALI14XX */ -#ifdef CONFIG_BLK_DEV_UMC8672 - case -16: /* "umc8672" */ - { - extern void init_umc8672 (void); - init_umc8672(); - goto done; - } -#endif /* CONFIG_BLK_DEV_UMC8672 */ -#ifdef CONFIG_BLK_DEV_DTC2278 - case -15: /* "dtc2278" */ - { - extern void init_dtc2278 (void); - init_dtc2278(); - goto done; - } -#endif /* CONFIG_BLK_DEV_DTC2278 */ -#ifdef CONFIG_BLK_DEV_CMD640 - case -14: /* "cmd640_vlb" */ - { - extern int cmd640_vlb; /* flag for cmd640.c */ - cmd640_vlb = 1; - goto done; - } -#endif /* CONFIG_BLK_DEV_CMD640 */ -#ifdef CONFIG_BLK_DEV_HT6560B - case -13: /* "ht6560b" */ - { - extern void init_ht6560b (void); - init_ht6560b(); - goto done; - } -#endif /* CONFIG_BLK_DEV_HT6560B */ -#if CONFIG_BLK_DEV_QD6580 - case -12: /* "qd6580" */ - { - extern void init_qd6580 (void); - init_qd6580(); - goto done; - } -#endif /* CONFIG_BLK_DEV_QD6580 */ -#ifdef CONFIG_BLK_DEV_4DRIVES - case -11: /* "four" drives on one set of ports */ - { - ide_hwif_t *mate = &ide_hwifs[hw^1]; - mate->drives[0].select.all ^= 0x20; - mate->drives[1].select.all ^= 0x20; - hwif->chipset = mate->chipset = ide_4drives; - mate->irq = hwif->irq; - memcpy(mate->io_ports, hwif->io_ports, sizeof(hwif->io_ports)); - goto do_serialize; - } -#endif /* CONFIG_BLK_DEV_4DRIVES */ - case -10: /* minus10 */ - case -9: /* minus9 */ - case -8: /* minus8 */ - goto bad_option; - case -7: /* ata66 */ -#ifdef CONFIG_BLK_DEV_IDEPCI - hwif->udma_four = 1; - goto done; -#else /* !CONFIG_BLK_DEV_IDEPCI */ - hwif->udma_four = 0; - goto bad_hwif; -#endif /* CONFIG_BLK_DEV_IDEPCI */ - case -6: /* dma */ - hwif->autodma = 1; - goto done; - case -5: /* "reset" */ - hwif->reset = 1; - goto done; - case -4: /* "noautotune" */ - hwif->drives[0].autotune = 2; - hwif->drives[1].autotune = 2; - goto done; - case -3: /* "autotune" */ - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - goto done; - case -2: /* "serialize" */ - do_serialize: - hwif->mate = &ide_hwifs[hw^1]; - hwif->mate->mate = hwif; - hwif->serialized = hwif->mate->serialized = 1; - goto done; - - case -1: /* "noprobe" */ - hwif->noprobe = 1; - goto done; - - case 1: /* base */ - vals[1] = vals[0] + 0x206; /* default ctl */ - case 2: /* base,ctl */ - vals[2] = 0; /* default irq = probe for it */ - case 3: /* base,ctl,irq */ - hwif->hw.irq = vals[2]; - ide_init_hwif_ports(&hwif->hw, (ide_ioreg_t) vals[0], (ide_ioreg_t) vals[1], &hwif->irq); - memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports)); - hwif->irq = vals[2]; - hwif->noprobe = 0; - hwif->chipset = ide_generic; - goto done; - - case 0: goto bad_option; - default: - printk(" -- SUPPORT NOT CONFIGURED IN THIS KERNEL\n"); - return 0; - } - } -bad_option: - printk(" -- BAD OPTION\n"); - return 0; -bad_hwif: - printk("-- NOT SUPPORTED ON ide%d", hw); -done: - printk("\n"); - return 0; -} - -/* - * probe_for_hwifs() finds/initializes "known" IDE interfaces - */ -static void __init probe_for_hwifs (void) -{ -#ifdef CONFIG_PCI - if (pci_present()) - { -#ifdef CONFIG_BLK_DEV_IDEPCI - ide_scan_pcibus(ide_scan_direction); -#else -#ifdef CONFIG_BLK_DEV_RZ1000 - { - extern void ide_probe_for_rz100x(void); - ide_probe_for_rz100x(); - } -#endif /* CONFIG_BLK_DEV_RZ1000 */ -#endif /* CONFIG_BLK_DEV_IDEPCI */ - } -#endif /* CONFIG_PCI */ - -#ifdef CONFIG_BLK_DEV_CMD640 - { - extern void ide_probe_for_cmd640x(void); - ide_probe_for_cmd640x(); - } -#endif /* CONFIG_BLK_DEV_CMD640 */ -#ifdef CONFIG_BLK_DEV_PDC4030 - { - extern int ide_probe_for_pdc4030(void); - (void) ide_probe_for_pdc4030(); - } -#endif /* CONFIG_BLK_DEV_PDC4030 */ -#ifdef CONFIG_BLK_DEV_IDE_PMAC - { - extern void pmac_ide_probe(void); - pmac_ide_probe(); - } -#endif /* CONFIG_BLK_DEV_IDE_PMAC */ -#ifdef CONFIG_BLK_DEV_IDE_ICSIDE - { - extern void icside_init(void); - icside_init(); - } -#endif /* CONFIG_BLK_DEV_IDE_ICSIDE */ -#ifdef CONFIG_BLK_DEV_IDE_RAPIDE - { - extern void rapide_init(void); - rapide_init(); - } -#endif /* CONFIG_BLK_DEV_IDE_RAPIDE */ -#ifdef CONFIG_BLK_DEV_GAYLE - { - extern void gayle_init(void); - gayle_init(); - } -#endif /* CONFIG_BLK_DEV_GAYLE */ -#ifdef CONFIG_BLK_DEV_FALCON_IDE - { - extern void falconide_init(void); - falconide_init(); - } -#endif /* CONFIG_BLK_DEV_FALCON_IDE */ -#ifdef CONFIG_BLK_DEV_MAC_IDE - { - extern void macide_init(void); - macide_init(); - } -#endif /* CONFIG_BLK_DEV_MAC_IDE */ -#ifdef CONFIG_BLK_DEV_BUDDHA - { - extern void buddha_init(void); - buddha_init(); - } -#endif /* CONFIG_BLK_DEV_BUDDHA */ -#if defined(CONFIG_BLK_DEV_ISAPNP) && defined(CONFIG_ISAPNP) - { - extern void pnpide_init(int enable); - pnpide_init(1); - } -#endif /* CONFIG_BLK_DEV_ISAPNP */ -} - -void __init ide_init_builtin_drivers (void) -{ - /* - * Probe for special PCI and other "known" interface chipsets - */ - probe_for_hwifs (); - -#ifdef CONFIG_BLK_DEV_IDE -#if defined(__mc68000__) || defined(CONFIG_APUS) - if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET]) { - ide_get_lock(&ide_lock, NULL, NULL); /* for atari only */ - disable_irq(ide_hwifs[0].irq); /* disable_irq_nosync ?? */ - } -#endif /* __mc68000__ || CONFIG_APUS */ - - (void) ideprobe_init(); - -#if defined(__mc68000__) || defined(CONFIG_APUS) - if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET]) { - enable_irq(ide_hwifs[0].irq); - ide_release_lock(&ide_lock); /* for atari only */ - } -#endif /* __mc68000__ || CONFIG_APUS */ -#endif /* CONFIG_BLK_DEV_IDE */ - -#ifdef CONFIG_PROC_FS - proc_ide_create(); -#endif - - /* - * Attempt to match drivers for the available drives - */ -#ifdef CONFIG_BLK_DEV_IDEDISK - (void) idedisk_init(); -#endif /* CONFIG_BLK_DEV_IDEDISK */ -#ifdef CONFIG_BLK_DEV_IDECD - (void) ide_cdrom_init(); -#endif /* CONFIG_BLK_DEV_IDECD */ -#ifdef CONFIG_BLK_DEV_IDETAPE - (void) idetape_init(); -#endif /* CONFIG_BLK_DEV_IDETAPE */ -#ifdef CONFIG_BLK_DEV_IDEFLOPPY - (void) idefloppy_init(); -#endif /* CONFIG_BLK_DEV_IDEFLOPPY */ -#ifdef CONFIG_BLK_DEV_IDESCSI - #ifdef CONFIG_SCSI - (void) idescsi_init(); - #else - #warning ide scsi-emulation selected but no SCSI-subsystem in kernel - #endif -#endif /* CONFIG_BLK_DEV_IDESCSI */ -} - -static int default_cleanup (ide_drive_t *drive) -{ - return ide_unregister_subdriver(drive); -} - -static ide_startstop_t default_do_request(ide_drive_t *drive, struct request *rq, unsigned long block) -{ - ide_end_request(0, HWGROUP(drive)); - return ide_stopped; -} - -static void default_end_request (byte uptodate, ide_hwgroup_t *hwgroup) -{ - ide_end_request(uptodate, hwgroup); -} - -static int default_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - return -EIO; -} - -static int default_open (struct inode *inode, struct file *filp, ide_drive_t *drive) -{ - drive->usage--; - return -EIO; -} - -static void default_release (struct inode *inode, struct file *filp, ide_drive_t *drive) -{ -} - -static int default_check_media_change (ide_drive_t *drive) -{ - return 1; -} - -static void default_pre_reset (ide_drive_t *drive) -{ -} - -static unsigned long default_capacity (ide_drive_t *drive) -{ - return 0x7fffffff; /* cdrom or tape */ -} - -static ide_startstop_t default_special (ide_drive_t *drive) -{ - special_t *s = &drive->special; - - s->all = 0; - drive->mult_req = 0; - return ide_stopped; -} - -static void setup_driver_defaults (ide_drive_t *drive) -{ - ide_driver_t *d = drive->driver; - - if (d->cleanup == NULL) d->cleanup = default_cleanup; - if (d->do_request == NULL) d->do_request = default_do_request; - if (d->end_request == NULL) d->end_request = default_end_request; - if (d->ioctl == NULL) d->ioctl = default_ioctl; - if (d->open == NULL) d->open = default_open; - if (d->release == NULL) d->release = default_release; - if (d->media_change == NULL) d->media_change = default_check_media_change; - if (d->pre_reset == NULL) d->pre_reset = default_pre_reset; - if (d->capacity == NULL) d->capacity = default_capacity; - if (d->special == NULL) d->special = default_special; -} - -ide_drive_t *ide_scan_devices (byte media, const char *name, ide_driver_t *driver, int n) -{ - unsigned int unit, index, i; - - for (index = 0, i = 0; index < MAX_HWIFS; ++index) { - ide_hwif_t *hwif = &ide_hwifs[index]; - if (!hwif->present) - continue; - for (unit = 0; unit < MAX_DRIVES; ++unit) { - ide_drive_t *drive = &hwif->drives[unit]; - char *req = drive->driver_req; - if (*req && !strstr(name, req)) - continue; - if (drive->present && drive->media == media && drive->driver == driver && ++i > n) - return drive; - } - } - return NULL; -} - -int ide_register_subdriver (ide_drive_t *drive, ide_driver_t *driver, int version) -{ - unsigned long flags; - - save_flags(flags); /* all CPUs */ - cli(); /* all CPUs */ - if (version != IDE_SUBDRIVER_VERSION || !drive->present || drive->driver != NULL || drive->busy || drive->usage) { - restore_flags(flags); /* all CPUs */ - return 1; - } - drive->driver = driver; - setup_driver_defaults(drive); - restore_flags(flags); /* all CPUs */ - if (drive->autotune != 2) { - if (driver->supports_dma && HWIF(drive)->dmaproc != NULL) { - /* - * Force DMAing for the beginning of the check. - * Some chipsets appear to do interesting things, - * if not checked and cleared. - * PARANOIA!!! - */ - (void) (HWIF(drive)->dmaproc(ide_dma_off_quietly, drive)); - (void) (HWIF(drive)->dmaproc(ide_dma_check, drive)); - } - drive->dsc_overlap = (drive->next != drive && driver->supports_dsc_overlap); - drive->nice1 = 1; - } - drive->revalidate = 1; -#ifdef CONFIG_PROC_FS - ide_add_proc_entries(drive->proc, generic_subdriver_entries, drive); - ide_add_proc_entries(drive->proc, driver->proc, drive); -#endif - return 0; -} - -int ide_unregister_subdriver (ide_drive_t *drive) -{ - unsigned long flags; - - save_flags(flags); /* all CPUs */ - cli(); /* all CPUs */ - if (drive->usage || drive->busy || drive->driver == NULL || DRIVER(drive)->busy) { - restore_flags(flags); /* all CPUs */ - return 1; - } -#if defined(CONFIG_BLK_DEV_ISAPNP) && defined(CONFIG_ISAPNP) && defined(MODULE) - pnpide_init(0); -#endif /* CONFIG_BLK_DEV_ISAPNP */ -#ifdef CONFIG_PROC_FS - ide_remove_proc_entries(drive->proc, DRIVER(drive)->proc); - ide_remove_proc_entries(drive->proc, generic_subdriver_entries); -#endif - auto_remove_settings(drive); - drive->driver = NULL; - restore_flags(flags); /* all CPUs */ - return 0; -} - -int ide_register_module (ide_module_t *module) -{ - ide_module_t *p = ide_modules; - - while (p) { - if (p == module) - return 1; - p = p->next; - } - module->next = ide_modules; - ide_modules = module; - revalidate_drives(); - return 0; -} - -void ide_unregister_module (ide_module_t *module) -{ - ide_module_t **p; - - for (p = &ide_modules; (*p) && (*p) != module; p = &((*p)->next)); - if (*p) - *p = (*p)->next; -} - -struct block_device_operations ide_fops[] = {{ - open: ide_open, - release: ide_release, - ioctl: ide_ioctl, - check_media_change: ide_check_media_change, - revalidate: ide_revalidate_disk -}}; - -EXPORT_SYMBOL(ide_hwifs); -EXPORT_SYMBOL(ide_register_module); -EXPORT_SYMBOL(ide_unregister_module); -EXPORT_SYMBOL(ide_spin_wait_hwgroup); - -/* - * Probe module - */ -devfs_handle_t ide_devfs_handle = NULL; - -EXPORT_SYMBOL(ide_probe); -EXPORT_SYMBOL(drive_is_flashcard); -EXPORT_SYMBOL(ide_timer_expiry); -EXPORT_SYMBOL(ide_intr); -EXPORT_SYMBOL(ide_fops); -EXPORT_SYMBOL(ide_get_queue); -EXPORT_SYMBOL(do_ide0_request); -EXPORT_SYMBOL(ide_add_generic_settings); -EXPORT_SYMBOL(ide_devfs_handle); -#if MAX_HWIFS > 1 -EXPORT_SYMBOL(do_ide1_request); -#endif /* MAX_HWIFS > 1 */ -#if MAX_HWIFS > 2 -EXPORT_SYMBOL(do_ide2_request); -#endif /* MAX_HWIFS > 2 */ -#if MAX_HWIFS > 3 -EXPORT_SYMBOL(do_ide3_request); -#endif /* MAX_HWIFS > 3 */ -#if MAX_HWIFS > 4 -EXPORT_SYMBOL(do_ide4_request); -#endif /* MAX_HWIFS > 4 */ -#if MAX_HWIFS > 5 -EXPORT_SYMBOL(do_ide5_request); -#endif /* MAX_HWIFS > 5 */ -#if MAX_HWIFS > 6 -EXPORT_SYMBOL(do_ide6_request); -#endif /* MAX_HWIFS > 6 */ -#if MAX_HWIFS > 7 -EXPORT_SYMBOL(do_ide7_request); -#endif /* MAX_HWIFS > 7 */ -#if MAX_HWIFS > 8 -EXPORT_SYMBOL(do_ide8_request); -#endif /* MAX_HWIFS > 8 */ -#if MAX_HWIFS > 9 -EXPORT_SYMBOL(do_ide9_request); -#endif /* MAX_HWIFS > 9 */ - -/* - * Driver module - */ -EXPORT_SYMBOL(ide_scan_devices); -EXPORT_SYMBOL(ide_register_subdriver); -EXPORT_SYMBOL(ide_unregister_subdriver); -EXPORT_SYMBOL(ide_replace_subdriver); -EXPORT_SYMBOL(ide_input_data); -EXPORT_SYMBOL(ide_output_data); -EXPORT_SYMBOL(atapi_input_bytes); -EXPORT_SYMBOL(atapi_output_bytes); -EXPORT_SYMBOL(ide_set_handler); -EXPORT_SYMBOL(ide_dump_status); -EXPORT_SYMBOL(ide_error); -EXPORT_SYMBOL(ide_fixstring); -EXPORT_SYMBOL(ide_wait_stat); -EXPORT_SYMBOL(ide_do_reset); -EXPORT_SYMBOL(ide_init_drive_cmd); -EXPORT_SYMBOL(ide_do_drive_cmd); -EXPORT_SYMBOL(ide_end_drive_cmd); -EXPORT_SYMBOL(ide_end_request); -EXPORT_SYMBOL(ide_revalidate_disk); -EXPORT_SYMBOL(ide_cmd); -EXPORT_SYMBOL(ide_wait_cmd); -EXPORT_SYMBOL(ide_delay_50ms); -EXPORT_SYMBOL(ide_stall_queue); -#ifdef CONFIG_PROC_FS -EXPORT_SYMBOL(ide_add_proc_entries); -EXPORT_SYMBOL(ide_remove_proc_entries); -EXPORT_SYMBOL(proc_ide_read_geometry); -EXPORT_SYMBOL(create_proc_ide_interfaces); -#endif -EXPORT_SYMBOL(ide_add_setting); -EXPORT_SYMBOL(ide_remove_setting); - -EXPORT_SYMBOL(ide_register_hw); -EXPORT_SYMBOL(ide_register); -EXPORT_SYMBOL(ide_unregister); -EXPORT_SYMBOL(ide_setup_ports); -EXPORT_SYMBOL(hwif_unregister); -EXPORT_SYMBOL(get_info_ptr); -EXPORT_SYMBOL(current_capacity); - -/* - * This is gets invoked once during initialization, to set *everything* up - */ -int __init ide_init (void) -{ - static char banner_printed = 0; - int i; - - if (!banner_printed) { - printk(KERN_INFO "Uniform Multi-Platform E-IDE driver " REVISION "\n"); - ide_devfs_handle = devfs_mk_dir (NULL, "ide", 3, NULL); - (void) ide_system_bus_speed(); - banner_printed = 1; - } - - init_ide_data (); - - initializing = 1; - ide_init_builtin_drivers(); - initializing = 0; - - for (i = 0; i < MAX_HWIFS; ++i) { - ide_hwif_t *hwif = &ide_hwifs[i]; - if (hwif->present) - ide_geninit(hwif); - } - - return 0; -} - -static void __init parse_options (char *line) -{ - char *next = line; - - if (line == NULL || !*line) - return; - while ((line = next) != NULL) { - if ((next = strchr(line,' ')) != NULL) - *next++ = 0; - if (!strncmp(line,"ide",3) || - !strncmp(line,"idebus",6) || -#ifdef CONFIG_BLK_DEV_VIA82CXXX - !strncmp(line,"splitfifo",9) || -#endif /* CONFIG_BLK_DEV_VIA82CXXX */ - !strncmp(line,"hdxlun",6) || - (!strncmp(line,"hd",2) && line[2] != '=')) - (void) ide_setup(line); - } -} - -#ifdef MODULE -char *options = NULL; -MODULE_PARM(options,"s"); - -int init_module (void) -{ - parse_options(options); - return ide_init(); -} - -void cleanup_module (void) -{ - int index; - - for (index = 0; index < MAX_HWIFS; ++index) - ide_unregister(index); - -#ifdef CONFIG_PROC_FS - proc_ide_destroy(); -#endif - devfs_unregister (ide_devfs_handle); -} - -#else /* !MODULE */ - -static int parse_ide_setup (char *line) -{ - parse_options(line); - return 0; -} -__setup("", parse_ide_setup); - -#endif /* MODULE */ diff --git a/drivers/block/ide_modes.h b/drivers/block/ide_modes.h deleted file mode 100644 index f94d91313..000000000 --- a/drivers/block/ide_modes.h +++ /dev/null @@ -1,233 +0,0 @@ -/* - * linux/drivers/block/ide_modes.h - * - * Copyright (C) 1996 Linus Torvalds, Igor Abramov, and Mark Lord - */ - -#ifndef _IDE_MODES_H -#define _IDE_MODES_H - -#include <linux/config.h> - -/* - * Shared data/functions for determining best PIO mode for an IDE drive. - * Most of this stuff originally lived in cmd640.c, and changes to the - * ide_pio_blacklist[] table should be made with EXTREME CAUTION to avoid - * breaking the fragile cmd640.c support. - */ - -#ifdef CONFIG_BLK_DEV_IDE_MODES - -/* - * Standard (generic) timings for PIO modes, from ATA2 specification. - * These timings are for access to the IDE data port register *only*. - * Some drives may specify a mode, while also specifying a different - * value for cycle_time (from drive identification data). - */ -typedef struct ide_pio_timings_s { - int setup_time; /* Address setup (ns) minimum */ - int active_time; /* Active pulse (ns) minimum */ - int cycle_time; /* Cycle time (ns) minimum = (setup + active + recovery) */ -} ide_pio_timings_t; - -typedef struct ide_pio_data_s { - byte pio_mode; - byte use_iordy; - byte overridden; - byte blacklisted; - unsigned int cycle_time; -} ide_pio_data_t; - -#ifndef _IDE_C - -int ide_scan_pio_blacklist (char *model); -byte ide_get_best_pio_mode (ide_drive_t *drive, byte mode_wanted, byte max_mode, ide_pio_data_t *d); -extern const ide_pio_timings_t ide_pio_timings[6]; - -#else /* _IDE_C */ - -const ide_pio_timings_t ide_pio_timings[6] = { - { 70, 165, 600 }, /* PIO Mode 0 */ - { 50, 125, 383 }, /* PIO Mode 1 */ - { 30, 100, 240 }, /* PIO Mode 2 */ - { 30, 80, 180 }, /* PIO Mode 3 with IORDY */ - { 25, 70, 120 }, /* PIO Mode 4 with IORDY */ - { 20, 50, 100 } /* PIO Mode 5 with IORDY (nonstandard) */ -}; - -/* - * Black list. Some drives incorrectly report their maximal PIO mode, - * at least in respect to CMD640. Here we keep info on some known drives. - */ -static struct ide_pio_info { - const char *name; - int pio; -} ide_pio_blacklist [] = { -/* { "Conner Peripherals 1275MB - CFS1275A", 4 }, */ - { "Conner Peripherals 540MB - CFS540A", 3 }, - - { "WDC AC2700", 3 }, - { "WDC AC2540", 3 }, - { "WDC AC2420", 3 }, - { "WDC AC2340", 3 }, - { "WDC AC2250", 0 }, - { "WDC AC2200", 0 }, - { "WDC AC21200", 4 }, - { "WDC AC2120", 0 }, - { "WDC AC2850", 3 }, - { "WDC AC1270", 3 }, - { "WDC AC1170", 1 }, - { "WDC AC1210", 1 }, - { "WDC AC280", 0 }, -/* { "WDC AC21000", 4 }, */ - { "WDC AC31000", 3 }, - { "WDC AC31200", 3 }, -/* { "WDC AC31600", 4 }, */ - - { "Maxtor 7131 AT", 1 }, - { "Maxtor 7171 AT", 1 }, - { "Maxtor 7213 AT", 1 }, - { "Maxtor 7245 AT", 1 }, - { "Maxtor 7345 AT", 1 }, - { "Maxtor 7546 AT", 3 }, - { "Maxtor 7540 AV", 3 }, - - { "SAMSUNG SHD-3121A", 1 }, - { "SAMSUNG SHD-3122A", 1 }, - { "SAMSUNG SHD-3172A", 1 }, - -/* { "ST51080A", 4 }, - * { "ST51270A", 4 }, - * { "ST31220A", 4 }, - * { "ST31640A", 4 }, - * { "ST32140A", 4 }, - * { "ST3780A", 4 }, - */ - { "ST5660A", 3 }, - { "ST3660A", 3 }, - { "ST3630A", 3 }, - { "ST3655A", 3 }, - { "ST3391A", 3 }, - { "ST3390A", 1 }, - { "ST3600A", 1 }, - { "ST3290A", 0 }, - { "ST3144A", 0 }, - { "ST3491A", 1 }, /* reports 3, should be 1 or 2 (depending on */ - /* drive) according to Seagates FIND-ATA program */ - - { "QUANTUM ELS127A", 0 }, - { "QUANTUM ELS170A", 0 }, - { "QUANTUM LPS240A", 0 }, - { "QUANTUM LPS210A", 3 }, - { "QUANTUM LPS270A", 3 }, - { "QUANTUM LPS365A", 3 }, - { "QUANTUM LPS540A", 3 }, - { "QUANTUM LIGHTNING 540A", 3 }, - { "QUANTUM LIGHTNING 730A", 3 }, - { "QUANTUM FIREBALL", 3 }, /* For models 540/640/1080/1280 */ - /* 1080A works fine in mode4 with triton */ - { NULL, 0 } -}; - -/* - * This routine searches the ide_pio_blacklist for an entry - * matching the start/whole of the supplied model name. - * - * Returns -1 if no match found. - * Otherwise returns the recommended PIO mode from ide_pio_blacklist[]. - */ -int ide_scan_pio_blacklist (char *model) -{ - struct ide_pio_info *p; - - for (p = ide_pio_blacklist; p->name != NULL; p++) { - if (strncmp(p->name, model, strlen(p->name)) == 0) - return p->pio; - } - return -1; -} - -/* - * This routine returns the recommended PIO settings for a given drive, - * based on the drive->id information and the ide_pio_blacklist[]. - * This is used by most chipset support modules when "auto-tuning". - */ - -/* - * Drive PIO mode auto selection - */ -byte ide_get_best_pio_mode (ide_drive_t *drive, byte mode_wanted, byte max_mode, ide_pio_data_t *d) -{ - int pio_mode; - int cycle_time = 0; - int use_iordy = 0; - struct hd_driveid* id = drive->id; - int overridden = 0; - int blacklisted = 0; - - if (mode_wanted != 255) { - pio_mode = mode_wanted; - } else if (!drive->id) { - pio_mode = 0; - } else if ((pio_mode = ide_scan_pio_blacklist(id->model)) != -1) { - overridden = 1; - blacklisted = 1; - use_iordy = (pio_mode > 2); - } else { - pio_mode = id->tPIO; - if (pio_mode > 2) { /* 2 is maximum allowed tPIO value */ - pio_mode = 2; - overridden = 1; - } - if (id->field_valid & 2) { /* drive implements ATA2? */ - if (id->capability & 8) { /* drive supports use_iordy? */ - use_iordy = 1; - cycle_time = id->eide_pio_iordy; - if (id->eide_pio_modes & 7) { - overridden = 0; - if (id->eide_pio_modes & 4) - pio_mode = 5; - else if (id->eide_pio_modes & 2) - pio_mode = 4; - else - pio_mode = 3; - } - } else { - cycle_time = id->eide_pio; - } - } - -#if 0 - if (drive->id->major_rev_num & 0x0004) printf("ATA-2 "); -#endif - - /* - * Conservative "downgrade" for all pre-ATA2 drives - */ - if (pio_mode && pio_mode < 4) { - pio_mode--; - overridden = 1; -#if 0 - use_iordy = (pio_mode > 2); -#endif - if (cycle_time && cycle_time < ide_pio_timings[pio_mode].cycle_time) - cycle_time = 0; /* use standard timing */ - } - } - if (pio_mode > max_mode) { - pio_mode = max_mode; - cycle_time = 0; - } - if (d) { - d->pio_mode = pio_mode; - d->cycle_time = cycle_time ? cycle_time : ide_pio_timings[pio_mode].cycle_time; - d->use_iordy = use_iordy; - d->overridden = overridden; - d->blacklisted = blacklisted; - } - return pio_mode; -} - -#endif /* _IDE_C */ -#endif /* CONFIG_BLK_DEV_IDE_MODES */ -#endif /* _IDE_MODES_H */ diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c index c14591b92..63c5e4b85 100644 --- a/drivers/block/ll_rw_blk.c +++ b/drivers/block/ll_rw_blk.c @@ -28,8 +28,6 @@ #include <linux/module.h> -#define DEBUG_ELEVATOR - /* * MAC Floppy IWM hooks */ @@ -150,18 +148,6 @@ request_queue_t * blk_get_queue (kdev_t dev) return ret; } -static inline int get_request_latency(elevator_t * elevator, int rw) -{ - int latency; - - if (rw != READ) - latency = elevator->write_latency; - else - latency = elevator->read_latency; - - return latency; -} - void blk_cleanup_queue(request_queue_t * q) { memset(q, 0, sizeof(*q)); @@ -186,7 +172,7 @@ static inline int ll_new_segment(request_queue_t *q, struct request *req, int ma { if (req->nr_segments < max_segments) { req->nr_segments++; - q->nr_segments++; + q->elevator.nr_segments++; return 1; } return 0; @@ -212,18 +198,18 @@ static int ll_merge_requests_fn(request_queue_t *q, struct request *req, struct request *next, int max_segments) { int total_segments = req->nr_segments + next->nr_segments; - int same_segment; + int same_segment; - same_segment = 0; + same_segment = 0; if (req->bhtail->b_data + req->bhtail->b_size == next->bh->b_data) { total_segments--; - same_segment = 1; + same_segment = 1; } if (total_segments > max_segments) return 0; - q->nr_segments -= same_segment; + q->elevator.nr_segments -= same_segment; req->nr_segments = total_segments; return 1; } @@ -254,7 +240,7 @@ static void generic_plug_device (request_queue_t *q, kdev_t dev) void blk_init_queue(request_queue_t * q, request_fn_proc * rfn) { INIT_LIST_HEAD(&q->queue_head); - q->elevator = ELEVATOR_DEFAULTS; + elevator_init(&q->elevator); q->request_fn = rfn; q->back_merge_fn = ll_back_merge_fn; q->front_merge_fn = ll_front_merge_fn; @@ -425,113 +411,6 @@ static inline void drive_stat_acct(struct request *req, printk(KERN_ERR "drive_stat_acct: cmd not R/W?\n"); } -/* elevator */ - -#define elevator_sequence_after(a,b) ((int)((b)-(a)) < 0) -#define elevator_sequence_before(a,b) elevator_sequence_after(b,a) -#define elevator_sequence_after_eq(a,b) ((int)((b)-(a)) <= 0) -#define elevator_sequence_before_eq(a,b) elevator_sequence_after_eq(b,a) - -static inline struct list_head * seek_to_not_starving_chunk(request_queue_t * q, - int * lat, int * starving) -{ - int sequence = q->elevator.sequence; - struct list_head * entry = q->queue_head.prev; - int pos = 0; - - do { - struct request * req = blkdev_entry_to_request(entry); - if (elevator_sequence_before(req->elevator_sequence, sequence)) { - *lat -= q->nr_segments - pos; - *starving = 1; - return entry; - } - pos += req->nr_segments; - } while ((entry = entry->prev) != &q->queue_head); - - *starving = 0; - - return entry->next; -} - -static inline void elevator_merge_requests(elevator_t * e, struct request * req, struct request * next) -{ - if (elevator_sequence_before(next->elevator_sequence, req->elevator_sequence)) - req->elevator_sequence = next->elevator_sequence; - if (req->cmd == READ) - e->read_pendings--; - -} - -static inline int elevator_sequence(elevator_t * e, int latency) -{ - return latency + e->sequence; -} - -#define elevator_merge_before(q, req, lat) __elevator_merge((q), (req), (lat), 0) -#define elevator_merge_after(q, req, lat) __elevator_merge((q), (req), (lat), 1) -static inline void __elevator_merge(request_queue_t * q, struct request * req, int latency, int after) -{ - int sequence = elevator_sequence(&q->elevator, latency); - if (after) - sequence -= req->nr_segments; - if (elevator_sequence_before(sequence, req->elevator_sequence)) - req->elevator_sequence = sequence; -} - -static inline void elevator_queue(request_queue_t * q, - struct request * req, - struct list_head * entry, - int latency, int starving) -{ - struct request * tmp, * __tmp; - int __latency = latency; - - __tmp = tmp = blkdev_entry_to_request(entry); - - for (;; tmp = blkdev_next_request(tmp)) - { - if ((latency -= tmp->nr_segments) <= 0) - { - tmp = __tmp; - latency = __latency; - - if (starving) - break; - - if (q->head_active && !q->plugged) - { - latency -= tmp->nr_segments; - break; - } - - list_add(&req->queue, &q->queue_head); - goto after_link; - } - - if (tmp->queue.next == &q->queue_head) - break; - - { - const int after_current = IN_ORDER(tmp,req); - const int before_next = IN_ORDER(req,blkdev_next_request(tmp)); - - if (!IN_ORDER(tmp,blkdev_next_request(tmp))) { - if (after_current || before_next) - break; - } else { - if (after_current && before_next) - break; - } - } - } - - list_add(&req->queue, &tmp->queue); - - after_link: - req->elevator_sequence = elevator_sequence(&q->elevator, latency); -} - /* * add-request adds a request to the linked list. * It disables interrupts (aquires the request spinlock) so that it can muck @@ -542,20 +421,19 @@ static inline void elevator_queue(request_queue_t * q, * which is important for drive_stat_acct() above. */ -static inline void __add_request(request_queue_t * q, struct request * req, - int empty, struct list_head * entry, - int latency, int starving) +static inline void add_request(request_queue_t * q, struct request * req, + struct list_head * head, int latency) { int major; drive_stat_acct(req, req->nr_sectors, 1); - if (empty) { + if (list_empty(head)) { req->elevator_sequence = elevator_sequence(&q->elevator, latency); list_add(&req->queue, &q->queue_head); return; } - elevator_queue(q, req, entry, latency, starving); + q->elevator.elevator_fn(req, &q->elevator, &q->queue_head, head, latency); /* * FIXME(eric) I don't understand why there is a need for this @@ -579,19 +457,17 @@ static inline void __add_request(request_queue_t * q, struct request * req, /* * Has to be called with the request spinlock aquired */ -static inline void attempt_merge (request_queue_t * q, - struct request *req, - int max_sectors, - int max_segments) +static void attempt_merge(request_queue_t * q, + struct request *req, + int max_sectors, + int max_segments) { struct request *next; - if (req->queue.next == &q->queue_head) - return; next = blkdev_next_request(req); if (req->sector + req->nr_sectors != next->sector) return; - if (next->sem || req->cmd != next->cmd || req->rq_dev != next->rq_dev || req->nr_sectors + next->nr_sectors > max_sectors) + if (req->cmd != next->cmd || req->rq_dev != next->rq_dev || req->nr_sectors + next->nr_sectors > max_sectors || next->sem) return; /* * If we are not allowed to merge these requests, then @@ -611,54 +487,28 @@ static inline void attempt_merge (request_queue_t * q, wake_up (&wait_for_request); } -static inline void elevator_debug(request_queue_t * q, kdev_t dev) +static inline void attempt_back_merge(request_queue_t * q, + struct request *req, + int max_sectors, + int max_segments) { -#ifdef DEBUG_ELEVATOR - int read_pendings = 0, nr_segments = 0; - elevator_t * elevator = &q->elevator; - struct list_head * entry = &q->queue_head; - static int counter; - - if (counter++ % 100) + if (&req->queue == q->queue_head.prev) return; - - while ((entry = entry->next) != &q->queue_head) - { - struct request * req; - - req = blkdev_entry_to_request(entry); - if (!req->q) - continue; - if (req->cmd == READ) - read_pendings++; - nr_segments += req->nr_segments; - } - - if (read_pendings != elevator->read_pendings) - { - printk(KERN_WARNING - "%s: elevator read_pendings %d should be %d\n", - kdevname(dev), elevator->read_pendings, - read_pendings); - elevator->read_pendings = read_pendings; - } - if (nr_segments != q->nr_segments) - { - printk(KERN_WARNING - "%s: elevator nr_segments %d should be %d\n", - kdevname(dev), q->nr_segments, - nr_segments); - q->nr_segments = nr_segments; - } -#endif + attempt_merge(q, req, max_sectors, max_segments); } -static inline void elevator_account_request(request_queue_t * q, struct request * req) +static inline void attempt_front_merge(request_queue_t * q, + struct list_head * head, + struct request *req, + int max_sectors, + int max_segments) { - q->elevator.sequence++; - if (req->cmd == READ) - q->elevator.read_pendings++; - q->nr_segments++; + struct list_head * prev; + + prev = req->queue.prev; + if (head == prev) + return; + attempt_merge(q, blkdev_entry_to_request(prev), max_sectors, max_segments); } static inline void __make_request(request_queue_t * q, int rw, @@ -667,11 +517,13 @@ static inline void __make_request(request_queue_t * q, int rw, int major = MAJOR(bh->b_rdev); unsigned int sector, count; int max_segments = MAX_SEGMENTS; - struct request * req, * prev; + struct request * req; int rw_ahead, max_req, max_sectors; unsigned long flags; - int orig_latency, latency, __latency, starving, __starving, empty; - struct list_head * entry, * __entry = NULL; + + int orig_latency, latency, starving, sequence; + struct list_head * entry, * head = &q->queue_head; + elevator_t * elevator; count = bh->b_size >> 9; sector = bh->b_rsector; @@ -758,7 +610,8 @@ static inline void __make_request(request_queue_t * q, int rw, */ max_sectors = get_max_sectors(bh->b_rdev); - __latency = orig_latency = get_request_latency(&q->elevator, rw); + elevator = &q->elevator; + orig_latency = elevator_request_latency(elevator, rw); /* * Now we acquire the request spinlock, we have to be mega careful @@ -767,46 +620,42 @@ static inline void __make_request(request_queue_t * q, int rw, spin_lock_irqsave(&io_request_lock,flags); elevator_debug(q, bh->b_rdev); - empty = 0; - if (list_empty(&q->queue_head)) { - empty = 1; + if (list_empty(head)) { q->plug_device_fn(q, bh->b_rdev); /* is atomic */ goto get_rq; } /* avoid write-bombs to not hurt iteractiveness of reads */ - if (rw != READ && q->elevator.read_pendings) - max_segments = q->elevator.max_bomb_segments; - - entry = seek_to_not_starving_chunk(q, &__latency, &starving); + if (rw != READ && elevator->read_pendings) + max_segments = elevator->max_bomb_segments; - __entry = entry; - __starving = starving; + sequence = elevator->sequence; + latency = orig_latency - elevator->nr_segments; + starving = 0; + entry = head; - latency = __latency; - - if (q->head_active && !q->plugged) { - /* - * The scsi disk and cdrom drivers completely remove the request - * from the queue when they start processing an entry. For this - * reason it is safe to continue to add links to the top entry - * for those devices. - * - * All other drivers need to jump over the first entry, as that - * entry may be busy being processed and we thus can't change - * it. - */ - if (entry == q->queue_head.next) { - latency -= blkdev_entry_to_request(entry)->nr_segments; - if ((entry = entry->next) == &q->queue_head) - goto get_rq; - starving = 0; - } - } + /* + * The scsi disk and cdrom drivers completely remove the request + * from the queue when they start processing an entry. For this + * reason it is safe to continue to add links to the top entry + * for those devices. + * + * All other drivers need to jump over the first entry, as that + * entry may be busy being processed and we thus can't change + * it. + */ + if (q->head_active && !q->plugged) + head = head->next; - prev = NULL; - do { + while ((entry = entry->prev) != head && !starving) { req = blkdev_entry_to_request(entry); + if (!req->q) + break; + latency += req->nr_segments; + if (elevator_sequence_before(req->elevator_sequence, sequence)) + starving = 1; + if (latency < 0) + continue; if (req->sem) continue; @@ -833,20 +682,20 @@ static inline void __make_request(request_queue_t * q, int rw, * this */ if(!(q->back_merge_fn)(q, req, bh, max_segments)) - continue; + break; req->bhtail->b_reqnext = bh; req->bhtail = bh; req->nr_sectors += count; drive_stat_acct(req, count, 0); - elevator_merge_after(q, req, latency); + elevator_merge_after(elevator, req, latency); /* Can we now merge this req with the next? */ - attempt_merge(q, req, max_sectors, max_segments); + attempt_back_merge(q, req, max_sectors, max_segments); /* or to the beginning? */ } else if (req->sector - count == sector) { - if (!prev && starving) - continue; + if (starving) + break; /* * The merge_fn is a more advanced way * of accomplishing the same task. Instead @@ -860,7 +709,7 @@ static inline void __make_request(request_queue_t * q, int rw, * this */ if(!(q->front_merge_fn)(q, req, bh, max_segments)) - continue; + break; bh->b_reqnext = req->bh; req->bh = bh; req->buffer = bh->b_data; @@ -869,10 +718,9 @@ static inline void __make_request(request_queue_t * q, int rw, req->nr_sectors += count; drive_stat_acct(req, count, 0); - elevator_merge_before(q, req, latency); + elevator_merge_before(elevator, req, latency); - if (prev) - attempt_merge(q, prev, max_sectors, max_segments); + attempt_front_merge(q, head, req, max_sectors, max_segments); } else continue; @@ -880,9 +728,7 @@ static inline void __make_request(request_queue_t * q, int rw, spin_unlock_irqrestore(&io_request_lock,flags); return; - } while (prev = req, - (latency -= req->nr_segments) >= 0 && - (entry = entry->next) != &q->queue_head); + } /* find an unused request. */ get_rq: @@ -899,31 +745,10 @@ get_rq: req = __get_request_wait(max_req, bh->b_rdev); spin_lock_irqsave(&io_request_lock,flags); - /* lock got dropped so revalidate elevator */ - empty = 1; - if (!list_empty(&q->queue_head)) { - empty = 0; - __latency = orig_latency; - __entry = seek_to_not_starving_chunk(q, &__latency, &__starving); - } - } - /* - * Dont start the IO if the buffer has been - * invalidated meanwhile. (we have to do this - * within the io request lock and atomically - * before adding the request, see buffer.c's - * insert_into_queues_exclusive() function. - */ - if (!test_bit(BH_Req, &bh->b_state)) { - req->rq_status = RQ_INACTIVE; - spin_unlock_irqrestore(&io_request_lock,flags); - /* - * A fake 'everything went ok' completion event. - * The bh doesnt matter anymore, but we should not - * signal errors to RAID levels. - */ - bh->b_end_io(bh, 1); - return; + /* revalidate elevator */ + head = &q->queue_head; + if (q->head_active && !q->plugged) + head = head->next; } /* fill up the request-info, and add it to the queue */ @@ -939,8 +764,8 @@ get_rq: req->bh = bh; req->bhtail = bh; req->q = q; - __add_request(q, req, empty, __entry, __latency, __starving); - elevator_account_request(q, req); + add_request(q, req, head, orig_latency); + elevator_account_request(elevator, req); spin_unlock_irqrestore(&io_request_lock, flags); return; @@ -1166,10 +991,10 @@ int __init blk_dev_init(void) #ifdef CONFIG_ISP16_CDI isp16_init(); #endif CONFIG_ISP16_CDI -#ifdef CONFIG_BLK_DEV_IDE +#if defined(CONFIG_IDE) && defined(CONFIG_BLK_DEV_IDE) ide_init(); /* this MUST precede hd_init */ #endif -#ifdef CONFIG_BLK_DEV_HD +#if defined(CONFIG_IDE) && defined(CONFIG_BLK_DEV_HD) hd_init(); #endif #ifdef CONFIG_BLK_DEV_PS2 diff --git a/drivers/block/macide.c b/drivers/block/macide.c deleted file mode 100644 index 46a14ba19..000000000 --- a/drivers/block/macide.c +++ /dev/null @@ -1,116 +0,0 @@ -/* - * linux/drivers/ide/macide.c -- Macintosh IDE Driver - * - * Copyright (C) 1998 by Michael Schmitz - * - * This driver was written based on information obtained from the MacOS IDE - * driver binary by Mikael Forselius - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive for - * more details. - */ - -#include <linux/types.h> -#include <linux/mm.h> -#include <linux/interrupt.h> -#include <linux/blkdev.h> -#include <linux/hdreg.h> -#include <linux/delay.h> -#include <linux/ide.h> - -#include <asm/machw.h> -#include <asm/macintosh.h> -#include <asm/macints.h> - - /* - * Base of the IDE interface (see ATAManager ROM code) - */ - -#define MAC_HD_BASE 0x50f1a000 - - /* - * Offsets from the above base (scaling 4) - */ - -#define MAC_HD_DATA 0x00 -#define MAC_HD_ERROR 0x04 /* see err-bits */ -#define MAC_HD_NSECTOR 0x08 /* nr of sectors to read/write */ -#define MAC_HD_SECTOR 0x0c /* starting sector */ -#define MAC_HD_LCYL 0x10 /* starting cylinder */ -#define MAC_HD_HCYL 0x14 /* high byte of starting cyl */ -#define MAC_HD_SELECT 0x18 /* 101dhhhh , d=drive, hhhh=head */ -#define MAC_HD_STATUS 0x1c /* see status-bits */ -#define MAC_HD_CONTROL 0x38 /* control/altstatus */ - -static int __init macide_offsets[IDE_NR_PORTS] = { - MAC_HD_DATA, MAC_HD_ERROR, MAC_HD_NSECTOR, MAC_HD_SECTOR, MAC_HD_LCYL, - MAC_HD_HCYL, MAC_HD_SELECT, MAC_HD_STATUS, MAC_HD_CONTROL -}; - - /* - * Other registers - */ - - /* - * IDE interrupt status register for both (?) hwifs on Quadra - * Initial setting: 0xc - * Guessing again: - * Bit 0+1: some interrupt flags - * Bit 2+3: some interrupt enable - * Bit 4: ?? - * Bit 5: IDE interrupt flag (any hwif) - * Bit 6: maybe IDE interrupt enable (any hwif) ?? - * Bit 7: Any interrupt condition - * - * Only relevant item: bit 5, to be checked by mac_ack_intr - */ - -#define MAC_HD_ISR 0x101 - -static int mac_ack_intr(ide_hwif_t* hwif) -{ - unsigned char isr; - isr = readb(MAC_HD_BASE + MAC_HD_ISR); - if (isr & (1<<5)) { - writeb(isr & ~(1<<5), MAC_HD_BASE + MAC_HD_ISR); - return 1; - } - - return 0; -} - - /* - * Probe for a Macintosh IDE interface - */ - -void __init macide_init(void) -{ - hw_regs_t hw; - int index = -1; - - if (!MACH_IS_MAC || macintosh_config->ide_type == 0) - return; - - switch (macintosh_config->ide_type) { - case MAC_IDE_QUADRA: - ide_setup_ports(&hw, (ide_ioreg_t)MAC_HD_BASE, macide_offsets, - 0, (ide_ioreg_t)(MAC_HD_BASE+MAC_HD_ISR), - mac_ack_intr, IRQ_NUBUS_F); - index = ide_register_hw(&hw, NULL); - break; - - default: - ide_setup_ports(&hw, (ide_ioreg_t)MAC_HD_BASE, macide_offsets, - 0, 0, NULL, IRQ_NUBUS_C); - index = ide_register_hw(&hw, NULL); - break; - } - - if (index != -1) { - if (macintosh_config->ide_type == MAC_IDE_QUADRA) - printk("ide%d: Macintosh Quadra IDE interface\n", index); - else - printk("ide%d: Macintosh Powerbook IDE interface\n", index); - } -} diff --git a/drivers/block/ns87415.c b/drivers/block/ns87415.c deleted file mode 100644 index 0e5675fde..000000000 --- a/drivers/block/ns87415.c +++ /dev/null @@ -1,185 +0,0 @@ -/* - * linux/drivers/block/ns87415.c Version 1.00 December 7, 1997 - * - * Copyright (C) 1997-1998 Mark Lord - * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) - * - * Inspired by an earlier effort from David S. Miller (davem@caipfs.rutgers.edu) - */ - -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/timer.h> -#include <linux/mm.h> -#include <linux/ioport.h> -#include <linux/interrupt.h> -#include <linux/blkdev.h> -#include <linux/hdreg.h> -#include <linux/pci.h> -#include <linux/delay.h> -#include <linux/ide.h> - -#include <asm/io.h> - -static unsigned int ns87415_count = 0, ns87415_control[MAX_HWIFS] = { 0 }; - -/* - * This routine either enables/disables (according to drive->present) - * the IRQ associated with the port (HWIF(drive)), - * and selects either PIO or DMA handshaking for the next I/O operation. - */ -static void ns87415_prepare_drive (ide_drive_t *drive, unsigned int use_dma) -{ - ide_hwif_t *hwif = HWIF(drive); - unsigned int bit, other, new, *old = (unsigned int *) hwif->select_data; - struct pci_dev *dev = hwif->pci_dev; - unsigned long flags; - - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ - new = *old; - - /* Adjust IRQ enable bit */ - bit = 1 << (8 + hwif->channel); - new = drive->present ? (new & ~bit) : (new | bit); - - /* Select PIO or DMA, DMA may only be selected for one drive/channel. */ - bit = 1 << (20 + drive->select.b.unit + (hwif->channel << 1)); - other = 1 << (20 + (1 - drive->select.b.unit) + (hwif->channel << 1)); - new = use_dma ? ((new & ~other) | bit) : (new & ~bit); - - if (new != *old) { - unsigned char stat; - - /* - * Don't change DMA engine settings while Write Buffers - * are busy. - */ - (void) pci_read_config_byte(dev, 0x43, &stat); - while (stat & 0x03) { - udelay(1); - (void) pci_read_config_byte(dev, 0x43, &stat); - } - - *old = new; - (void) pci_write_config_dword(dev, 0x40, new); - - /* - * And let things settle... - */ - udelay(10); - } - - __restore_flags(flags); /* local CPU only */ -} - -static void ns87415_selectproc (ide_drive_t *drive) -{ - ns87415_prepare_drive (drive, drive->using_dma); -} - -static int ns87415_dmaproc(ide_dma_action_t func, ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - byte dma_stat; - - switch (func) { - case ide_dma_end: /* returns 1 on error, 0 otherwise */ - drive->waiting_for_dma = 0; - dma_stat = inb(hwif->dma_base+2); - outb(inb(hwif->dma_base)&~1, hwif->dma_base); /* stop DMA */ - outb(inb(hwif->dma_base)|6, hwif->dma_base); /* from ERRATA: clear the INTR & ERROR bits */ - ide_destroy_dmatable(drive); /* and free any DMA resources */ - return (dma_stat & 7) != 4; /* verify good DMA status */ - case ide_dma_write: - case ide_dma_read: - ns87415_prepare_drive(drive, 1); /* select DMA xfer */ - if (!ide_dmaproc(func, drive)) /* use standard DMA stuff */ - return 0; - ns87415_prepare_drive(drive, 0); /* DMA failed: select PIO xfer */ - return 1; - case ide_dma_check: - if (drive->media != ide_disk) - return ide_dmaproc(ide_dma_off_quietly, drive); - /* Fallthrough... */ - default: - return ide_dmaproc(func, drive); /* use standard DMA stuff */ - } -} - -void __init ide_init_ns87415 (ide_hwif_t *hwif) -{ - struct pci_dev *dev = hwif->pci_dev; - unsigned int ctrl, using_inta; - byte progif; -#ifdef __sparc_v9__ - int timeout; - byte stat; -#endif - - /* Set a good latency timer and cache line size value. */ - (void) pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64); -#ifdef __sparc_v9__ - (void) pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 0x10); -#endif - - /* - * We cannot probe for IRQ: both ports share common IRQ on INTA. - * Also, leave IRQ masked during drive probing, to prevent infinite - * interrupts from a potentially floating INTA.. - * - * IRQs get unmasked in selectproc when drive is first used. - */ - (void) pci_read_config_dword(dev, 0x40, &ctrl); - (void) pci_read_config_byte(dev, 0x09, &progif); - /* is irq in "native" mode? */ - using_inta = progif & (1 << (hwif->channel << 1)); - if (!using_inta) - using_inta = ctrl & (1 << (4 + hwif->channel)); - if (hwif->mate) { - hwif->select_data = hwif->mate->select_data; - } else { - hwif->select_data = (unsigned long) - &ns87415_control[ns87415_count++]; - ctrl |= (1 << 8) | (1 << 9); /* mask both IRQs */ - if (using_inta) - ctrl &= ~(1 << 6); /* unmask INTA */ - *((unsigned int *)hwif->select_data) = ctrl; - (void) pci_write_config_dword(dev, 0x40, ctrl); - - /* - * Set prefetch size to 512 bytes for both ports, - * but don't turn on/off prefetching here. - */ - pci_write_config_byte(dev, 0x55, 0xee); - -#ifdef __sparc_v9__ - /* - * XXX: Reset the device, if we don't it will not respond - * to SELECT_DRIVE() properly during first probe_hwif(). - */ - timeout = 10000; - outb(12, hwif->io_ports[IDE_CONTROL_OFFSET]); - udelay(10); - outb(8, hwif->io_ports[IDE_CONTROL_OFFSET]); - do { - udelay(50); - stat = inb(hwif->io_ports[IDE_STATUS_OFFSET]); - if (stat == 0xff) - break; - } while ((stat & BUSY_STAT) && --timeout); -#endif - } - - if (hwif->dma_base) - outb(0x60, hwif->dma_base + 2); - - if (!using_inta) - hwif->irq = hwif->channel ? 15 : 14; /* legacy mode */ - else if (!hwif->irq && hwif->mate && hwif->mate->irq) - hwif->irq = hwif->mate->irq; /* share IRQ with mate */ - - if (hwif->dma_base) - hwif->dmaproc = &ns87415_dmaproc; - hwif->selectproc = &ns87415_selectproc; -} diff --git a/drivers/block/opti621.c b/drivers/block/opti621.c deleted file mode 100644 index cc2aa567c..000000000 --- a/drivers/block/opti621.c +++ /dev/null @@ -1,315 +0,0 @@ -/* - * linux/drivers/block/opti621.c Version 0.6 Jan 02, 1999 - * - * Copyright (C) 1996-1998 Linus Torvalds & authors (see below) - */ - -/* - * Authors: - * Jaromir Koutek <miri@punknet.cz>, - * Jan Harkes <jaharkes@cwi.nl>, - * Mark Lord <mlord@pobox.com> - * Some parts of code are from ali14xx.c and from rz1000.c. - * - * OPTi is trademark of OPTi, Octek is trademark of Octek. - * - * I used docs from OPTi databook, from ftp.opti.com, file 9123-0002.ps - * and disassembled/traced setupvic.exe (DOS program). - * It increases kernel code about 2 kB. - * I don't have this card no more, but I hope I can get some in case - * of needed development. - * My card is Octek PIDE 1.01 (on card) or OPTiViC (program). - * It has a place for a secondary connector in circuit, but nothing - * is there. Also BIOS says no address for - * secondary controller (see bellow in ide_init_opti621). - * I've only tested this on my system, which only has one disk. - * It's Western Digital WDAC2850, with PIO mode 3. The PCI bus - * is at 20 MHz (I have DX2/80, I tried PCI at 40, but I got random - * lockups). I tried the OCTEK double speed CD-ROM and - * it does not work! But I can't boot DOS also, so it's probably - * hardware fault. I have connected Conner 80MB, the Seagate 850MB (no - * problems) and Seagate 1GB (as slave, WD as master). My experiences - * with the third, 1GB drive: I got 3MB/s (hdparm), but sometimes - * it slows to about 100kB/s! I don't know why and I have - * not this drive now, so I can't try it again. - * I write this driver because I lost the paper ("manual") with - * settings of jumpers on the card and I have to boot Linux with - * Loadlin except LILO, cause I have to run the setupvic.exe program - * already or I get disk errors (my test: rpm -Vf - * /usr/X11R6/bin/XF86_SVGA - or any big file). - * Some numbers from hdparm -t /dev/hda: - * Timing buffer-cache reads: 32 MB in 3.02 seconds =10.60 MB/sec - * Timing buffered disk reads: 16 MB in 5.52 seconds = 2.90 MB/sec - * I have 4 Megs/s before, but I don't know why (maybe changes - * in hdparm test). - * After release of 0.1, I got some successful reports, so it might work. - * - * The main problem with OPTi is that some timings for master - * and slave must be the same. For example, if you have master - * PIO 3 and slave PIO 0, driver have to set some timings of - * master for PIO 0. Second problem is that opti621_tune_drive - * got only one drive to set, but have to set both drives. - * This is solved in compute_pios. If you don't set - * the second drive, compute_pios use ide_get_best_pio_mode - * for autoselect mode (you can change it to PIO 0, if you want). - * If you then set the second drive to another PIO, the old value - * (automatically selected) will be overrided by yours. - * There is a 25/33MHz switch in configuration - * register, but driver is written for use at any frequency which get - * (use idebus=xx to select PCI bus speed). - * Use ide0=autotune for automatical tune of the PIO modes. - * If you get strange results, do not use this and set PIO manually - * by hdparm. - * - * Version 0.1, Nov 8, 1996 - * by Jaromir Koutek, for 2.1.8. - * Initial version of driver. - * - * Version 0.2 - * Number 0.2 skipped. - * - * Version 0.3, Nov 29, 1997 - * by Mark Lord (probably), for 2.1.68 - * Updates for use with new IDE block driver. - * - * Version 0.4, Dec 14, 1997 - * by Jan Harkes - * Fixed some errors and cleaned the code. - * - * Version 0.5, Jan 2, 1998 - * by Jaromir Koutek - * Updates for use with (again) new IDE block driver. - * Update of documentation. - * - * Version 0.6, Jan 2, 1999 - * by Jaromir Koutek - * Reversed to version 0.3 of the driver, because - * 0.5 doesn't work. - */ - -#undef REALLY_SLOW_IO /* most systems can safely undef this */ -#define OPTI621_DEBUG /* define for debug messages */ - -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/delay.h> -#include <linux/timer.h> -#include <linux/mm.h> -#include <linux/ioport.h> -#include <linux/blkdev.h> -#include <linux/hdreg.h> -#include <linux/ide.h> - -#include <asm/io.h> - -#include "ide_modes.h" - -#define OPTI621_MAX_PIO 3 -/* In fact, I do not have any PIO 4 drive - * (address: 25 ns, data: 70 ns, recovery: 35 ns), - * but OPTi 82C621 is programmable and it can do (minimal values): - * on 40MHz PCI bus (pulse 25 ns): - * address: 25 ns, data: 25 ns, recovery: 50 ns; - * on 20MHz PCI bus (pulse 50 ns): - * address: 50 ns, data: 50 ns, recovery: 100 ns. - */ - -/* #define READ_PREFETCH 0 */ -/* Uncommnent for disable read prefetch. - * There is some readprefetch capatibility in hdparm, - * but when I type hdparm -P 1 /dev/hda, I got errors - * and till reset drive is inacessible. - * This (hw) read prefetch is safe on my drive. - */ - -#ifndef READ_PREFETCH -#define READ_PREFETCH 0x40 /* read prefetch is enabled */ -#endif /* else read prefetch is disabled */ - -#define READ_REG 0 /* index of Read cycle timing register */ -#define WRITE_REG 1 /* index of Write cycle timing register */ -#define CNTRL_REG 3 /* index of Control register */ -#define STRAP_REG 5 /* index of Strap register */ -#define MISC_REG 6 /* index of Miscellaneous register */ - -int reg_base; - -#define PIO_NOT_EXIST 254 -#define PIO_DONT_KNOW 255 - -/* there are stored pio numbers from other calls of opti621_tune_drive */ - -static void compute_pios(ide_drive_t *drive, byte pio) -/* Store values into drive->drive_data - * second_contr - 0 for primary controller, 1 for secondary - * slave_drive - 0 -> pio is for master, 1 -> pio is for slave - * pio - PIO mode for selected drive (for other we don't know) - */ -{ - int d; - ide_hwif_t *hwif = HWIF(drive); - - drive->drive_data = ide_get_best_pio_mode(drive, pio, OPTI621_MAX_PIO, NULL); - for (d = 0; d < 2; ++d) { - drive = &hwif->drives[d]; - if (drive->present) { - if (drive->drive_data == PIO_DONT_KNOW) - drive->drive_data = ide_get_best_pio_mode(drive, 255, OPTI621_MAX_PIO, NULL); -#ifdef OPTI621_DEBUG - printk("%s: Selected PIO mode %d\n", drive->name, drive->drive_data); -#endif - } else { - drive->drive_data = PIO_NOT_EXIST; - } - } -} - -int cmpt_clk(int time, int bus_speed) -/* Returns (rounded up) time in clocks for time in ns, - * with bus_speed in MHz. - * Example: bus_speed = 40 MHz, time = 80 ns - * 1000/40 = 25 ns (clk value), - * 80/25 = 3.2, rounded up to 4 (I hope ;-)). - * Use idebus=xx to select right frequency. - */ -{ - return ((time*bus_speed+999)/1000); -} - -static void write_reg(byte value, int reg) -/* Write value to register reg, base of register - * is at reg_base (0x1f0 primary, 0x170 secondary, - * if not changed by PCI configuration). - * This is from setupvic.exe program. - */ -{ - inw(reg_base+1); - inw(reg_base+1); - outb(3, reg_base+2); - outb(value, reg_base+reg); - outb(0x83, reg_base+2); -} - -static byte read_reg(int reg) -/* Read value from register reg, base of register - * is at reg_base (0x1f0 primary, 0x170 secondary, - * if not changed by PCI configuration). - * This is from setupvic.exe program. - */ -{ - byte ret; - inw(reg_base+1); - inw(reg_base+1); - outb(3, reg_base+2); - ret=inb(reg_base+reg); - outb(0x83, reg_base+2); - return ret; -} - -typedef struct pio_clocks_s { - int address_time; /* Address setup (clocks) */ - int data_time; /* Active/data pulse (clocks) */ - int recovery_time; /* Recovery time (clocks) */ -} pio_clocks_t; - -static void compute_clocks(int pio, pio_clocks_t *clks) -{ - if (pio != PIO_NOT_EXIST) { - int adr_setup, data_pls, bus_speed; - bus_speed = ide_system_bus_speed(); - adr_setup = ide_pio_timings[pio].setup_time; - data_pls = ide_pio_timings[pio].active_time; - clks->address_time = cmpt_clk(adr_setup, bus_speed); - clks->data_time = cmpt_clk(data_pls, bus_speed); - clks->recovery_time = cmpt_clk(ide_pio_timings[pio].cycle_time - - adr_setup-data_pls, bus_speed); - if (clks->address_time<1) clks->address_time = 1; - if (clks->address_time>4) clks->address_time = 4; - if (clks->data_time<1) clks->data_time = 1; - if (clks->data_time>16) clks->data_time = 16; - if (clks->recovery_time<2) clks->recovery_time = 2; - if (clks->recovery_time>17) clks->recovery_time = 17; - } else { - clks->address_time = 1; - clks->data_time = 1; - clks->recovery_time = 2; - /* minimal values */ - } - -} - -/* Main tune procedure, called from tuneproc. */ -static void opti621_tune_drive (ide_drive_t *drive, byte pio) -{ - /* primary and secondary drives share some registers, - * so we have to program both drives - */ - unsigned long flags; - byte pio1, pio2; - pio_clocks_t first, second; - int ax, drdy; - byte cycle1, cycle2, misc; - ide_hwif_t *hwif = HWIF(drive); - - /* sets drive->drive_data for both drives */ - compute_pios(drive, pio); - pio1 = hwif->drives[0].drive_data; - pio2 = hwif->drives[1].drive_data; - - compute_clocks(pio1, &first); - compute_clocks(pio2, &second); - - /* ax = max(a1,a2) */ - ax = (first.address_time < second.address_time) ? second.address_time : first.address_time; - - drdy = 2; /* DRDY is default 2 (by OPTi Databook) */ - - cycle1 = ((first.data_time-1)<<4) | (first.recovery_time-2); - cycle2 = ((second.data_time-1)<<4) | (second.recovery_time-2); - misc = READ_PREFETCH | ((ax-1)<<4) | ((drdy-2)<<1); - -#ifdef OPTI621_DEBUG - printk("%s: master: address: %d, data: %d, recovery: %d, drdy: %d [clk]\n", - hwif->name, ax, first.data_time, first.recovery_time, drdy); - printk("%s: slave: address: %d, data: %d, recovery: %d, drdy: %d [clk]\n", - hwif->name, ax, second.data_time, second.recovery_time, drdy); -#endif - - save_flags(flags); /* all CPUs */ - cli(); /* all CPUs */ - - reg_base = hwif->io_ports[IDE_DATA_OFFSET]; - outb(0xc0, reg_base+CNTRL_REG); /* allow Register-B */ - outb(0xff, reg_base+5); /* hmm, setupvic.exe does this ;-) */ - inb(reg_base+CNTRL_REG); /* if reads 0xff, adapter not exist? */ - read_reg(CNTRL_REG); /* if reads 0xc0, no interface exist? */ - read_reg(STRAP_REG); /* read version, probably 0 */ - - /* program primary drive */ - write_reg(0, MISC_REG); /* select Index-0 for Register-A */ - write_reg(cycle1, READ_REG); /* set read cycle timings */ - write_reg(cycle1, WRITE_REG); /* set write cycle timings */ - - /* program secondary drive */ - write_reg(1, MISC_REG); /* select Index-1 for Register-B */ - write_reg(cycle2, READ_REG); /* set read cycle timings */ - write_reg(cycle2, WRITE_REG); /* set write cycle timings */ - - write_reg(0x85, CNTRL_REG); /* use Register-A for drive 0 */ - /* use Register-B for drive 1 */ - - write_reg(misc, MISC_REG); /* set address setup, DRDY timings, */ - /* and read prefetch for both drives */ - - restore_flags(flags); /* all CPUs */ -} - -/* - * ide_init_opti621() is called once for each hwif found at boot. - */ -void ide_init_opti621 (ide_hwif_t *hwif) -{ - hwif->drives[0].drive_data = PIO_DONT_KNOW; - hwif->drives[1].drive_data = PIO_DONT_KNOW; - hwif->tuneproc = &opti621_tune_drive; -} diff --git a/drivers/block/pdc202xx.c b/drivers/block/pdc202xx.c deleted file mode 100644 index 9ec7c8997..000000000 --- a/drivers/block/pdc202xx.c +++ /dev/null @@ -1,731 +0,0 @@ -/* - * linux/drivers/block/pdc202xx.c Version 0.29 Feb. 10, 2000 - * - * Copyright (C) 1998-2000 Andre Hedrick (andre@suse.com) - * May be copied or modified under the terms of the GNU General Public License - * - * Promise Ultra33 cards with BIOS v1.20 through 1.28 will need this - * compiled into the kernel if you have more than one card installed. - * Note that BIOS v1.29 is reported to fix the problem. Since this is - * safe chipset tuning, including this support is harmless - * - * The latest chipset code will support the following :: - * Three Ultra33 controllers and 12 drives. - * 8 are UDMA supported and 4 are limited to DMA mode 2 multi-word. - * The 8/4 ratio is a BIOS code limit by promise. - * - * UNLESS you enable "CONFIG_PDC202XX_BURST" - * - * There is only one BIOS in the three contollers. - * - * May 8 20:56:17 Orion kernel: - * Uniform Multi-Platform E-IDE driver Revision: 6.19 - * PDC20246: IDE controller on PCI bus 00 dev a0 - * PDC20246: not 100% native mode: will probe irqs later - * PDC20246: ROM enabled at 0xfebd0000 - * PDC20246: (U)DMA Burst Bit ENABLED Primary PCI Mode Secondary PCI Mode. - * ide0: BM-DMA at 0xef80-0xef87, BIOS settings: hda:DMA, hdb:DMA - * ide1: BM-DMA at 0xef88-0xef8f, BIOS settings: hdc:pio, hdd:pio - * PDC20246: IDE controller on PCI bus 00 dev 98 - * PDC20246: not 100% native mode: will probe irqs later - * PDC20246: ROM enabled at 0xfebc0000 - * PDC20246: (U)DMA Burst Bit ENABLED Primary PCI Mode Secondary PCI Mode. - * ide2: BM-DMA at 0xef40-0xef47, BIOS settings: hde:DMA, hdf:DMA - * ide3: BM-DMA at 0xef48-0xef4f, BIOS settings: hdg:DMA, hdh:DMA - * PDC20246: IDE controller on PCI bus 00 dev 90 - * PDC20246: not 100% native mode: will probe irqs later - * PDC20246: ROM enabled at 0xfebb0000 - * PDC20246: (U)DMA Burst Bit DISABLED Primary PCI Mode Secondary PCI Mode. - * PDC20246: FORCING BURST BIT 0x00 -> 0x01 ACTIVE - * ide4: BM-DMA at 0xef00-0xef07, BIOS settings: hdi:DMA, hdj:pio - * ide5: BM-DMA at 0xef08-0xef0f, BIOS settings: hdk:pio, hdl:pio - * PIIX3: IDE controller on PCI bus 00 dev 39 - * PIIX3: device not capable of full native PCI mode - * - * ide0 at 0xeff0-0xeff7,0xefe6 on irq 19 - * ide1 at 0xefa8-0xefaf,0xebe6 on irq 19 - * ide2 at 0xefa0-0xefa7,0xef7e on irq 18 - * ide3 at 0xef68-0xef6f,0xef66 on irq 18 - * ide4 at 0xef38-0xef3f,0xef62 on irq 17 - * hda: QUANTUM FIREBALL ST6.4A, 6149MB w/81kB Cache, CHS=13328/15/63, UDMA(33) - * hdb: QUANTUM FIREBALL ST3.2A, 3079MB w/81kB Cache, CHS=6256/16/63, UDMA(33) - * hde: Maxtor 72004 AP, 1916MB w/128kB Cache, CHS=3893/16/63, DMA - * hdf: Maxtor 71626 A, 1554MB w/64kB Cache, CHS=3158/16/63, DMA - * hdi: Maxtor 90680D4, 6485MB w/256kB Cache, CHS=13176/16/63, UDMA(33) - * hdj: Maxtor 90680D4, 6485MB w/256kB Cache, CHS=13176/16/63, UDMA(33) - * - * Promise Ultra66 cards with BIOS v1.11 this - * compiled into the kernel if you have more than one card installed. - * - * PDC20262: IDE controller on PCI bus 00 dev a0 - * PDC20262: not 100% native mode: will probe irqs later - * PDC20262: ROM enabled at 0xfebb0000 - * PDC20262: (U)DMA Burst Bit ENABLED Primary PCI Mode Secondary PCI Mode. - * ide0: BM-DMA at 0xef00-0xef07, BIOS settings: hda:pio, hdb:pio - * ide1: BM-DMA at 0xef08-0xef0f, BIOS settings: hdc:pio, hdd:pio - * - * UDMA 4/2 and UDMA 3/1 only differ by the testing bit 13 in word93. - * Chipset timing speeds must be identical - * - * drive_number - * = ((HWIF(drive)->channel ? 2 : 0) + (drive->select.b.unit & 0x01)); - * = ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01)); - */ - -/* - * Portions Copyright (C) 1999 Promise Technology, Inc. - * Author: Frank Tiernan (frankt@promise.com) - * Released under terms of General Public License - */ - -#include <linux/config.h> -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/delay.h> -#include <linux/timer.h> -#include <linux/mm.h> -#include <linux/ioport.h> -#include <linux/blkdev.h> -#include <linux/hdreg.h> -#include <linux/interrupt.h> -#include <linux/pci.h> -#include <linux/init.h> -#include <linux/ide.h> - -#include <asm/io.h> -#include <asm/irq.h> - -#include "ide_modes.h" - -#define PDC202XX_DEBUG_DRIVE_INFO 0 -#define PDC202XX_DECODE_REGISTER_INFO 0 - -#undef DISPLAY_PDC202XX_TIMINGS - -#if defined(DISPLAY_PDC202XX_TIMINGS) && defined(CONFIG_PROC_FS) -#include <linux/stat.h> -#include <linux/proc_fs.h> - -static int pdc202xx_get_info(char *, char **, off_t, int); -extern int (*pdc202xx_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -extern char *ide_media_verbose(ide_drive_t *); -static struct pci_dev *bmide_dev; - -static int pdc202xx_get_info (char *buffer, char **addr, off_t offset, int count) -{ - char *p = buffer; - - u32 bibma = bmide_dev->resource[4].start; - u8 c0 = 0, c1 = 0; - - /* - * at that point bibma+0x2 et bibma+0xa are byte registers - * to investigate: - */ - c0 = inb_p((unsigned short)bibma + 0x02); - c1 = inb_p((unsigned short)bibma + 0x0a); - - switch(bmide_dev->device) { - case PCI_DEVICE_ID_PROMISE_20262: - p += sprintf(p, "\n PDC20262 Chipset.\n"); - break; - case PCI_DEVICE_ID_PROMISE_20246: - p += sprintf(p, "\n PDC20246 Chipset.\n"); - break; - default: - p += sprintf(p, "\n PDC202XX Chipset.\n"); - break; - } - - p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n"); - p += sprintf(p, " %sabled %sabled\n", - (c0&0x80) ? "dis" : " en", - (c1&0x80) ? "dis" : " en"); - p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n"); - p += sprintf(p, "DMA enabled: %s %s %s %s\n", - (c0&0x20) ? "yes" : "no ", (c0&0x40) ? "yes" : "no ", - (c1&0x20) ? "yes" : "no ", (c1&0x40) ? "yes" : "no " ); - - p += sprintf(p, "UDMA\n"); - p += sprintf(p, "DMA\n"); - p += sprintf(p, "PIO\n"); - - return p-buffer; /* => must be less than 4k! */ -} -#endif /* defined(DISPLAY_PDC202XX_TIMINGS) && defined(CONFIG_PROC_FS) */ - -byte pdc202xx_proc = 0; - -extern char *ide_xfer_verbose (byte xfer_rate); - -/* A Register */ -#define SYNC_ERRDY_EN 0xC0 - -#define SYNC_IN 0x80 /* control bit, different for master vs. slave drives */ -#define ERRDY_EN 0x40 /* control bit, different for master vs. slave drives */ -#define IORDY_EN 0x20 /* PIO: IOREADY */ -#define PREFETCH_EN 0x10 /* PIO: PREFETCH */ - -#define PA3 0x08 /* PIO"A" timing */ -#define PA2 0x04 /* PIO"A" timing */ -#define PA1 0x02 /* PIO"A" timing */ -#define PA0 0x01 /* PIO"A" timing */ - -/* B Register */ - -#define MB2 0x80 /* DMA"B" timing */ -#define MB1 0x40 /* DMA"B" timing */ -#define MB0 0x20 /* DMA"B" timing */ - -#define PB4 0x10 /* PIO_FORCE 1:0 */ - -#define PB3 0x08 /* PIO"B" timing */ /* PIO flow Control mode */ -#define PB2 0x04 /* PIO"B" timing */ /* PIO 4 */ -#define PB1 0x02 /* PIO"B" timing */ /* PIO 3 half */ -#define PB0 0x01 /* PIO"B" timing */ /* PIO 3 other half */ - -/* C Register */ -#define IORDYp_NO_SPEED 0x4F -#define SPEED_DIS 0x0F - -#define DMARQp 0x80 -#define IORDYp 0x40 -#define DMAR_EN 0x20 -#define DMAW_EN 0x10 - -#define MC3 0x08 /* DMA"C" timing */ -#define MC2 0x04 /* DMA"C" timing */ -#define MC1 0x02 /* DMA"C" timing */ -#define MC0 0x01 /* DMA"C" timing */ - -#if PDC202XX_DECODE_REGISTER_INFO - -#define REG_A 0x01 -#define REG_B 0x02 -#define REG_C 0x04 -#define REG_D 0x08 - -static void decode_registers (byte registers, byte value) -{ - byte bit = 0, bit1 = 0, bit2 = 0; - - switch(registers) { - case REG_A: - bit2 = 0; - printk("A Register "); - if (value & 0x80) printk("SYNC_IN "); - if (value & 0x40) printk("ERRDY_EN "); - if (value & 0x20) printk("IORDY_EN "); - if (value & 0x10) printk("PREFETCH_EN "); - if (value & 0x08) { printk("PA3 ");bit2 |= 0x08; } - if (value & 0x04) { printk("PA2 ");bit2 |= 0x04; } - if (value & 0x02) { printk("PA1 ");bit2 |= 0x02; } - if (value & 0x01) { printk("PA0 ");bit2 |= 0x01; } - printk("PIO(A) = %d ", bit2); - break; - case REG_B: - bit1 = 0;bit2 = 0; - printk("B Register "); - if (value & 0x80) { printk("MB2 ");bit1 |= 0x80; } - if (value & 0x40) { printk("MB1 ");bit1 |= 0x40; } - if (value & 0x20) { printk("MB0 ");bit1 |= 0x20; } - printk("DMA(B) = %d ", bit1 >> 5); - if (value & 0x10) printk("PIO_FORCED/PB4 "); - if (value & 0x08) { printk("PB3 ");bit2 |= 0x08; } - if (value & 0x04) { printk("PB2 ");bit2 |= 0x04; } - if (value & 0x02) { printk("PB1 ");bit2 |= 0x02; } - if (value & 0x01) { printk("PB0 ");bit2 |= 0x01; } - printk("PIO(B) = %d ", bit2); - break; - case REG_C: - bit2 = 0; - printk("C Register "); - if (value & 0x80) printk("DMARQp "); - if (value & 0x40) printk("IORDYp "); - if (value & 0x20) printk("DMAR_EN "); - if (value & 0x10) printk("DMAW_EN "); - - if (value & 0x08) { printk("MC3 ");bit2 |= 0x08; } - if (value & 0x04) { printk("MC2 ");bit2 |= 0x04; } - if (value & 0x02) { printk("MC1 ");bit2 |= 0x02; } - if (value & 0x01) { printk("MC0 ");bit2 |= 0x01; } - printk("DMA(C) = %d ", bit2); - break; - case REG_D: - printk("D Register "); - break; - default: - return; - } - printk("\n %s ", (registers & REG_D) ? "DP" : - (registers & REG_C) ? "CP" : - (registers & REG_B) ? "BP" : - (registers & REG_A) ? "AP" : "ERROR"); - for (bit=128;bit>0;bit/=2) - printk("%s", (value & bit) ? "1" : "0"); - printk("\n"); -} - -#endif /* PDC202XX_DECODE_REGISTER_INFO */ - -static int config_chipset_for_dma (ide_drive_t *drive, byte ultra) -{ - struct hd_driveid *id = drive->id; - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - unsigned long high_16 = dev->resource[4].start & PCI_BASE_ADDRESS_IO_MASK; - - int err; - unsigned int drive_conf; - byte drive_pci; - byte test1, test2, speed = -1; - byte AP, BP, CP, DP, TB, TC; - unsigned short EP; - byte CLKSPD = IN_BYTE(high_16 + 0x11); - int drive_number = ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01)); - byte udma_66 = ((id->hw_config & 0x2000) && (hwif->udma_four)) ? 1 : 0; - byte udma_33 = ultra ? (inb(high_16 + 0x001f) & 1) : 0; - - /* - * Set the control register to use the 66Mhz system - * clock for UDMA 3/4 mode operation. If one drive on - * a channel is U66 capable but the other isn't we - * fall back to U33 mode. The BIOS INT 13 hooks turn - * the clock on then off for each read/write issued. I don't - * do that here because it would require modifying the - * kernel, seperating the fop routines from the kernel or - * somehow hooking the fops calls. It may also be possible to - * leave the 66Mhz clock on and readjust the timing - * parameters. - */ - - byte mask = hwif->channel ? 0x08 : 0x02; - unsigned short c_mask = hwif->channel ? (1<<11) : (1<<10); - byte ultra_66 = ((id->dma_ultra & 0x0010) || (id->dma_ultra & 0x0008)) ? 1 : 0; - - pci_read_config_word(dev, 0x50, &EP); - - if ((ultra_66) && (EP & c_mask)) { -#ifdef DEBUG - printk("ULTRA66: %s channel of Ultra 66 requires an 80-pin cable for Ultra66 operation.\n", hwif->channel ? "Secondary", "Primary"); - printk(" Switching to Ultra33 mode.\n"); -#endif /* DEBUG */ - /* Primary : zero out second bit */ - /* Secondary : zero out fourth bit */ - OUT_BYTE(CLKSPD & ~mask, (high_16 + 0x11)); - } else { - if (ultra_66) { - /* - * check to make sure drive on same channel - * is u66 capable - */ - if (hwif->drives[!(drive_number%2)].id) { - if ((hwif->drives[!(drive_number%2)].id->dma_ultra & 0x0010) || - (hwif->drives[!(drive_number%2)].id->dma_ultra & 0x0008)) { - OUT_BYTE(CLKSPD | mask, (high_16 + 0x11)); - } else { - OUT_BYTE(CLKSPD & ~mask, (high_16 + 0x11)); - } - } else { /* udma4 drive by itself */ - OUT_BYTE(CLKSPD | mask, (high_16 + 0x11)); - } - } - } - - switch(drive_number) { - case 0: drive_pci = 0x60; - pci_read_config_dword(dev, drive_pci, &drive_conf); - if ((drive_conf != 0x004ff304) && (drive_conf != 0x004ff3c4)) - goto chipset_is_set; - pci_read_config_byte(dev, (drive_pci), &test1); - if (!(test1 & SYNC_ERRDY_EN)) - pci_write_config_byte(dev, (drive_pci), test1|SYNC_ERRDY_EN); - break; - case 1: drive_pci = 0x64; - pci_read_config_dword(dev, drive_pci, &drive_conf); - if ((drive_conf != 0x004ff304) && (drive_conf != 0x004ff3c4)) - goto chipset_is_set; - pci_read_config_byte(dev, 0x60, &test1); - pci_read_config_byte(dev, (drive_pci), &test2); - if ((test1 & SYNC_ERRDY_EN) && !(test2 & SYNC_ERRDY_EN)) - pci_write_config_byte(dev, (drive_pci), test2|SYNC_ERRDY_EN); - break; - case 2: drive_pci = 0x68; - pci_read_config_dword(dev, drive_pci, &drive_conf); - if ((drive_conf != 0x004ff304) && (drive_conf != 0x004ff3c4)) - goto chipset_is_set; - pci_read_config_byte(dev, (drive_pci), &test1); - if (!(test1 & SYNC_ERRDY_EN)) - pci_write_config_byte(dev, (drive_pci), test1|SYNC_ERRDY_EN); - break; - case 3: drive_pci = 0x6c; - pci_read_config_dword(dev, drive_pci, &drive_conf); - if ((drive_conf != 0x004ff304) && (drive_conf != 0x004ff3c4)) - goto chipset_is_set; - pci_read_config_byte(dev, 0x68, &test1); - pci_read_config_byte(dev, (drive_pci), &test2); - if ((test1 & SYNC_ERRDY_EN) && !(test2 & SYNC_ERRDY_EN)) - pci_write_config_byte(dev, (drive_pci), test2|SYNC_ERRDY_EN); - break; - default: - return ide_dma_off; - } - -chipset_is_set: - - if (drive->media != ide_disk) - return ide_dma_off_quietly; - - pci_read_config_byte(dev, (drive_pci), &AP); - pci_read_config_byte(dev, (drive_pci)|0x01, &BP); - pci_read_config_byte(dev, (drive_pci)|0x02, &CP); - pci_read_config_byte(dev, (drive_pci)|0x03, &DP); - - if (id->capability & 4) { /* IORDY_EN */ - pci_write_config_byte(dev, (drive_pci), AP|IORDY_EN); - pci_read_config_byte(dev, (drive_pci), &AP); - } - - if (drive->media == ide_disk) { /* PREFETCH_EN */ - pci_write_config_byte(dev, (drive_pci), AP|PREFETCH_EN); - pci_read_config_byte(dev, (drive_pci), &AP); - } - - if ((BP & 0xF0) && (CP & 0x0F)) { - /* clear DMA modes of upper 842 bits of B Register */ - /* clear PIO forced mode upper 1 bit of B Register */ - pci_write_config_byte(dev, (drive_pci)|0x01, BP & ~0xF0); - pci_read_config_byte(dev, (drive_pci)|0x01, &BP); - - /* clear DMA modes of lower 8421 bits of C Register */ - pci_write_config_byte(dev, (drive_pci)|0x02, CP & ~0x0F); - pci_read_config_byte(dev, (drive_pci)|0x02, &CP); - } - - pci_read_config_byte(dev, (drive_pci), &AP); - pci_read_config_byte(dev, (drive_pci)|0x01, &BP); - pci_read_config_byte(dev, (drive_pci)|0x02, &CP); - - if ((id->dma_ultra & 0x0010) && (udma_66) && (udma_33)) { - /* speed 8 == UDMA mode 4 == speed 6 plus cable */ - speed = XFER_UDMA_4; TB = 0x20; TC = 0x01; - } else if ((id->dma_ultra & 0x0008) && (udma_66) && (udma_33)) { - /* speed 7 == UDMA mode 3 == speed 5 plus cable */ - speed = XFER_UDMA_3; TB = 0x40; TC = 0x02; - } else if ((id->dma_ultra & 0x0004) && (udma_33)) { - /* speed 6 == UDMA mode 2 */ - speed = XFER_UDMA_2; TB = 0x20; TC = 0x01; - } else if ((id->dma_ultra & 0x0002) && (udma_33)) { - /* speed 5 == UDMA mode 1 */ - speed = XFER_UDMA_1; TB = 0x40; TC = 0x02; - } else if ((id->dma_ultra & 0x0001) && (udma_33)) { - /* speed 4 == UDMA mode 0 */ - speed = XFER_UDMA_0; TB = 0x60; TC = 0x03; - } else if (id->dma_mword & 0x0004) { - /* speed 4 == DMA mode 2 multi-word */ - speed = XFER_MW_DMA_2; TB = 0x60; TC = 0x03; - } else if (id->dma_mword & 0x0002) { - /* speed 3 == DMA mode 1 multi-word */ - speed = XFER_MW_DMA_1; TB = 0x60; TC = 0x04; - } else if (id->dma_mword & 0x0001) { - /* speed 2 == DMA mode 0 multi-word */ - speed = XFER_MW_DMA_0; TB = 0x60; TC = 0x05; - } else if (id->dma_1word & 0x0004) { - /* speed 2 == DMA mode 2 single-word */ - speed = XFER_SW_DMA_2; TB = 0x60; TC = 0x05; - } else if (id->dma_1word & 0x0002) { - /* speed 1 == DMA mode 1 single-word */ - speed = XFER_SW_DMA_1; TB = 0x80; TC = 0x06; - } else if (id->dma_1word & 0x0001) { - /* speed 0 == DMA mode 0 single-word */ - speed = XFER_SW_DMA_0; TB = 0xC0; TC = 0x0B; - } else { - /* restore original pci-config space */ - pci_write_config_dword(dev, drive_pci, drive_conf); - return ide_dma_off_quietly; - } - - pci_write_config_byte(dev, (drive_pci)|0x01, BP|TB); - pci_write_config_byte(dev, (drive_pci)|0x02, CP|TC); - -#if PDC202XX_DECODE_REGISTER_INFO - pci_read_config_byte(dev, (drive_pci), &AP); - pci_read_config_byte(dev, (drive_pci)|0x01, &BP); - pci_read_config_byte(dev, (drive_pci)|0x02, &CP); - - decode_registers(REG_A, AP); - decode_registers(REG_B, BP); - decode_registers(REG_C, CP); - decode_registers(REG_D, DP); -#endif /* PDC202XX_DECODE_REGISTER_INFO */ - - err = ide_config_drive_speed(drive, speed); - -#if PDC202XX_DEBUG_DRIVE_INFO - printk("%s: %s drive%d 0x%08x ", - drive->name, ide_xfer_verbose(speed), - drive_number, drive_conf); - pci_read_config_dword(dev, drive_pci, &drive_conf); - printk("0x%08x\n", drive_conf); -#endif /* PDC202XX_DEBUG_DRIVE_INFO */ - - return ((int) ((id->dma_ultra >> 11) & 3) ? ide_dma_on : - ((id->dma_ultra >> 8) & 7) ? ide_dma_on : - ((id->dma_mword >> 8) & 7) ? ide_dma_on : - ((id->dma_1word >> 8) & 7) ? ide_dma_on : - ide_dma_off_quietly); -} - -/* 0 1 2 3 4 5 6 7 8 - * 960, 480, 390, 300, 240, 180, 120, 90, 60 - * 180, 150, 120, 90, 60 - * DMA_Speed - * 180, 120, 90, 90, 90, 60, 30 - * 11, 5, 4, 3, 2, 1, 0 - */ - -static int config_chipset_for_pio (ide_drive_t *drive, byte pio) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - byte drive_pci, speed; - byte AP, BP, TA, TB; - - int drive_number = ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01)); - int err; - - switch (drive_number) { - case 0: drive_pci = 0x60; break; - case 1: drive_pci = 0x64; break; - case 2: drive_pci = 0x68; break; - case 3: drive_pci = 0x6c; break; - default: return 1; - } - - pci_read_config_byte(dev, (drive_pci), &AP); - pci_read_config_byte(dev, (drive_pci)|0x01, &BP); - - - if ((AP & 0x0F) || (BP & 0x07)) { - /* clear PIO modes of lower 8421 bits of A Register */ - pci_write_config_byte(dev, (drive_pci), AP & ~0x0F); - pci_read_config_byte(dev, (drive_pci), &AP); - - /* clear PIO modes of lower 421 bits of B Register */ - pci_write_config_byte(dev, (drive_pci)|0x01, BP & ~0x07); - pci_read_config_byte(dev, (drive_pci)|0x01, &BP); - - pci_read_config_byte(dev, (drive_pci), &AP); - pci_read_config_byte(dev, (drive_pci)|0x01, &BP); - } - - pio = (pio == 5) ? 4 : pio; - switch (ide_get_best_pio_mode(drive, 255, pio, NULL)) { - case 4: speed = XFER_PIO_4; TA=0x01; TB=0x04; break; - case 3: speed = XFER_PIO_3; TA=0x02; TB=0x06; break; - case 2: speed = XFER_PIO_2; TA=0x03; TB=0x08; break; - case 1: speed = XFER_PIO_1; TA=0x05; TB=0x0C; break; - case 0: - default: speed = XFER_PIO_0; TA=0x09; TB=0x13; break; - } - pci_write_config_byte(dev, (drive_pci), AP|TA); - pci_write_config_byte(dev, (drive_pci)|0x01, BP|TB); - -#if PDC202XX_DECODE_REGISTER_INFO - pci_read_config_byte(dev, (drive_pci), &AP); - pci_read_config_byte(dev, (drive_pci)|0x01, &BP); - pci_read_config_byte(dev, (drive_pci)|0x02, &CP); - pci_read_config_byte(dev, (drive_pci)|0x03, &DP); - - decode_registers(REG_A, AP); - decode_registers(REG_B, BP); - decode_registers(REG_C, CP); - decode_registers(REG_D, DP); -#endif /* PDC202XX_DECODE_REGISTER_INFO */ - - err = ide_config_drive_speed(drive, speed); - -#if PDC202XX_DEBUG_DRIVE_INFO - printk("%s: %s drive%d 0x%08x ", - drive->name, ide_xfer_verbose(speed), - drive_number, drive_conf); - pci_read_config_dword(dev, drive_pci, &drive_conf); - printk("0x%08x\n", drive_conf); -#endif /* PDC202XX_DEBUG_DRIVE_INFO */ - - return err; -} - -static void pdc202xx_tune_drive (ide_drive_t *drive, byte pio) -{ - (void) config_chipset_for_pio(drive, pio); -} - -static int config_drive_xfer_rate (ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - ide_hwif_t *hwif = HWIF(drive); - ide_dma_action_t dma_func = ide_dma_off_quietly; - - if (id && (id->capability & 1) && hwif->autodma) { - /* Consult the list of known "bad" drives */ - if (ide_dmaproc(ide_dma_bad_drive, drive)) { - dma_func = ide_dma_off; - goto fast_ata_pio; - } - dma_func = ide_dma_off_quietly; - if (id->field_valid & 4) { - if (id->dma_ultra & 0x001F) { - /* Force if Capable UltraDMA */ - dma_func = config_chipset_for_dma(drive, 1); - if ((id->field_valid & 2) && - (dma_func != ide_dma_on)) - goto try_dma_modes; - } - } else if (id->field_valid & 2) { -try_dma_modes: - if ((id->dma_mword & 0x0007) || - (id->dma_1word & 0x0007)) { - /* Force if Capable regular DMA modes */ - dma_func = config_chipset_for_dma(drive, 0); - if (dma_func != ide_dma_on) - goto no_dma_set; - } - } else if (ide_dmaproc(ide_dma_good_drive, drive)) { - if (id->eide_dma_time > 150) { - goto no_dma_set; - } - /* Consult the list of known "good" drives */ - dma_func = config_chipset_for_dma(drive, 0); - if (dma_func != ide_dma_on) - goto no_dma_set; - } else { - goto fast_ata_pio; - } - } else if ((id->capability & 8) || (id->field_valid & 2)) { -fast_ata_pio: - dma_func = ide_dma_off_quietly; -no_dma_set: - (void) config_chipset_for_pio(drive, 5); - } - - return HWIF(drive)->dmaproc(dma_func, drive); -} - -/* - * pdc202xx_dmaproc() initiates/aborts (U)DMA read/write operations on a drive. - */ -int pdc202xx_dmaproc (ide_dma_action_t func, ide_drive_t *drive) -{ - switch (func) { - case ide_dma_check: - return config_drive_xfer_rate(drive); - default: - break; - } - return ide_dmaproc(func, drive); /* use standard DMA stuff */ -} - -unsigned int __init pci_init_pdc202xx (struct pci_dev *dev, const char *name) -{ - unsigned long high_16 = dev->resource[4].start & PCI_BASE_ADDRESS_IO_MASK; - byte udma_speed_flag = inb(high_16 + 0x001f); - byte primary_mode = inb(high_16 + 0x001a); - byte secondary_mode = inb(high_16 + 0x001b); - - if (dev->device == PCI_DEVICE_ID_PROMISE_20262) { - int i = 0; - /* - * software reset - this is required because the bios - * will set UDMA timing on if the hdd supports it. The - * user may want to turn udma off. A bug in the pdc20262 - * is that it cannot handle a downgrade in timing from UDMA - * to DMA. Disk accesses after issuing a set feature command - * will result in errors. A software reset leaves the timing - * registers intact, but resets the drives. - */ - - OUT_BYTE(udma_speed_flag | 0x10, high_16 + 0x001f); - ide_delay_50ms(); - ide_delay_50ms(); - OUT_BYTE(udma_speed_flag & ~0x10, high_16 + 0x001f); - for (i=0; i<40; i++) - ide_delay_50ms(); - } - - if (dev->resource[PCI_ROM_RESOURCE].start) { - pci_write_config_dword(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); - printk("%s: ROM enabled at 0x%08lx\n", name, dev->resource[PCI_ROM_RESOURCE].start); - } - - if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE) { - byte irq = 0, irq2 = 0; - pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); - pci_read_config_byte(dev, (PCI_INTERRUPT_LINE)|0x80, &irq2); /* 0xbc */ - if (irq != irq2) { - pci_write_config_byte(dev, (PCI_INTERRUPT_LINE)|0x80, irq); /* 0xbc */ - printk("%s: pci-config space interrupt mirror fixed.\n", name); - } - } - - printk("%s: (U)DMA Burst Bit %sABLED " \ - "Primary %s Mode " \ - "Secondary %s Mode.\n", - name, - (udma_speed_flag & 1) ? "EN" : "DIS", - (primary_mode & 1) ? "MASTER" : "PCI", - (secondary_mode & 1) ? "MASTER" : "PCI" ); - -#ifdef CONFIG_PDC202XX_BURST - if (!(udma_speed_flag & 1)) { - printk("%s: FORCING BURST BIT 0x%02x -> 0x%02x ", name, udma_speed_flag, (udma_speed_flag|1)); - outb(udma_speed_flag|1, high_16 + 0x001f); - printk("%sCTIVE\n", (inb(high_16 + 0x001f) & 1) ? "A" : "INA"); - } -#endif /* CONFIG_PDC202XX_BURST */ - -#ifdef CONFIG_PDC202XX_MASTER - if (!(primary_mode & 1)) { - printk("%s: FORCING PRIMARY MODE BIT 0x%02x -> 0x%02x ", - name, primary_mode, (primary_mode|1)); - outb(primary_mode|1, high_16 + 0x001a); - printk("%s\n", (inb(high_16 + 0x001a) & 1) ? "MASTER" : "PCI"); - } - - if (!(secondary_mode & 1)) { - printk("%s: FORCING SECONDARY MODE BIT 0x%02x -> 0x%02x ", - name, secondary_mode, (secondary_mode|1)); - outb(secondary_mode|1, high_16 + 0x001b); - printk("%s\n", (inb(high_16 + 0x001b) & 1) ? "MASTER" : "PCI"); - } -#endif /* CONFIG_PDC202XX_MASTER */ - -#if defined(DISPLAY_PDC202XX_TIMINGS) && defined(CONFIG_PROC_FS) - pdc202xx_proc = 1; - bmide_dev = dev; - pdc202xx_display_info = &pdc202xx_get_info; -#endif /* DISPLAY_PDC202XX_TIMINGS && CONFIG_PROC_FS */ - - return dev->irq; -} - -unsigned int __init ata66_pdc202xx (ide_hwif_t *hwif) -{ - unsigned short mask = (hwif->channel) ? (1<<11) : (1<<10); - unsigned short CIS; - - pci_read_config_word(hwif->pci_dev, 0x50, &CIS); - return ((CIS & mask) ? 0 : 1); -} - -void __init ide_init_pdc202xx (ide_hwif_t *hwif) -{ - hwif->tuneproc = &pdc202xx_tune_drive; - - if (hwif->dma_base) { - hwif->dmaproc = &pdc202xx_dmaproc; - } else { - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - } -} diff --git a/drivers/block/pdc4030.c b/drivers/block/pdc4030.c deleted file mode 100644 index f42c4946f..000000000 --- a/drivers/block/pdc4030.c +++ /dev/null @@ -1,552 +0,0 @@ -/* -*- linux-c -*- - * linux/drivers/ide/pdc4030.c Version 0.90 May 27, 1999 - * - * Copyright (C) 1995-1999 Linus Torvalds & authors (see below) - */ - -/* - * Principal Author/Maintainer: peterd@pnd-pc.demon.co.uk - * - * This file provides support for the second port and cache of Promise - * IDE interfaces, e.g. DC4030VL, DC4030VL-1 and DC4030VL-2. - * - * Thanks are due to Mark Lord for advice and patiently answering stupid - * questions, and all those mugs^H^H^H^Hbrave souls who've tested this, - * especially Andre Hedrick. - * - * Version 0.01 Initial version, #include'd in ide.c rather than - * compiled separately. - * Reads use Promise commands, writes as before. Drives - * on second channel are read-only. - * Version 0.02 Writes working on second channel, reads on both - * channels. Writes fail under high load. Suspect - * transfers of >127 sectors don't work. - * Version 0.03 Brought into line with ide.c version 5.27. - * Other minor changes. - * Version 0.04 Updated for ide.c version 5.30 - * Changed initialization strategy - * Version 0.05 Kernel integration. -ml - * Version 0.06 Ooops. Add hwgroup to direct call of ide_intr() -ml - * Version 0.07 Added support for DC4030 variants - * Secondary interface autodetection - * Version 0.08 Renamed to pdc4030.c - * Version 0.09 Obsolete - never released - did manual write request - * splitting before max_sectors[major][minor] available. - * Version 0.10 Updated for 2.1 series of kernels - * Version 0.11 Updated for 2.3 series of kernels - * Autodetection code added. - * - * Version 0.90 Transition to BETA code. No lost/unexpected interrupts - */ - -/* - * Once you've compiled it in, you'll have to also enable the interface - * setup routine from the kernel command line, as in - * - * 'linux ide0=dc4030' or 'linux ide1=dc4030' - * - * It should now work as a second controller also ('ide1=dc4030') but only - * if you DON'T have BIOS V4.44, which has a bug. If you have this version - * and EPROM programming facilities, you need to fix 4 bytes: - * 2496: 81 81 - * 2497: 3E 3E - * 2498: 22 98 * - * 2499: 06 05 * - * 249A: F0 F0 - * 249B: 01 01 - * ... - * 24A7: 81 81 - * 24A8: 3E 3E - * 24A9: 22 98 * - * 24AA: 06 05 * - * 24AB: 70 70 - * 24AC: 01 01 - * - * As of January 1999, Promise Technology Inc. have finally supplied me with - * some technical information which has shed a glimmer of light on some of the - * problems I was having, especially with writes. - * - * There are still problems with the robustness and efficiency of this driver - * because I still don't understand what the card is doing with interrupts. - */ - -#define DEBUG_READ -#define DEBUG_WRITE - -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/delay.h> -#include <linux/timer.h> -#include <linux/mm.h> -#include <linux/ioport.h> -#include <linux/blkdev.h> -#include <linux/hdreg.h> -#include <linux/ide.h> - -#include <asm/io.h> -#include <asm/irq.h> - -#include "pdc4030.h" - -/* - * promise_selectproc() is invoked by ide.c - * in preparation for access to the specified drive. - */ -static void promise_selectproc (ide_drive_t *drive) -{ - unsigned int number; - - number = (HWIF(drive)->channel << 1) + drive->select.b.unit; - OUT_BYTE(number,IDE_FEATURE_REG); -} - -/* - * pdc4030_cmd handles the set of vendor specific commands that are initiated - * by command F0. They all have the same success/failure notification - - * 'P' (=0x50) on success, 'p' (=0x70) on failure. - */ -int pdc4030_cmd(ide_drive_t *drive, byte cmd) -{ - unsigned long timeout, timer; - byte status_val; - - promise_selectproc(drive); /* redundant? */ - OUT_BYTE(0xF3,IDE_SECTOR_REG); - OUT_BYTE(cmd,IDE_SELECT_REG); - OUT_BYTE(PROMISE_EXTENDED_COMMAND,IDE_COMMAND_REG); - timeout = HZ * 10; - timeout += jiffies; - do { - if(time_after(jiffies, timeout)) { - return 2; /* device timed out */ - } - /* This is out of delay_10ms() */ - /* Delays at least 10ms to give interface a chance */ - timer = jiffies + (HZ + 99)/100 + 1; - while (time_after(timer, jiffies)); - status_val = IN_BYTE(IDE_SECTOR_REG); - } while (status_val != 0x50 && status_val != 0x70); - - if(status_val == 0x50) - return 0; /* device returned success */ - else - return 1; /* device returned failure */ -} - -/* - * pdc4030_identify sends a vendor-specific IDENTIFY command to the drive - */ -int pdc4030_identify(ide_drive_t *drive) -{ - return pdc4030_cmd(drive, PROMISE_IDENTIFY); -} - -int enable_promise_support = 0; - -void __init init_pdc4030 (void) -{ - enable_promise_support = 1; -} - -/* - * setup_pdc4030() - * Completes the setup of a Promise DC4030 controller card, once found. - */ -int __init setup_pdc4030 (ide_hwif_t *hwif) -{ - ide_drive_t *drive; - ide_hwif_t *hwif2; - struct dc_ident ident; - int i; - ide_startstop_t startstop; - - if (!hwif) return 0; - - drive = &hwif->drives[0]; - hwif2 = &ide_hwifs[hwif->index+1]; - if (hwif->chipset == ide_pdc4030) /* we've already been found ! */ - return 1; - - if (IN_BYTE(IDE_NSECTOR_REG) == 0xFF || IN_BYTE(IDE_SECTOR_REG) == 0xFF) { - return 0; - } - if (IDE_CONTROL_REG) - OUT_BYTE(0x08,IDE_CONTROL_REG); - if (pdc4030_cmd(drive,PROMISE_GET_CONFIG)) { - return 0; - } - if (ide_wait_stat(&startstop, drive,DATA_READY,BAD_W_STAT,WAIT_DRQ)) { - printk(KERN_INFO - "%s: Failed Promise read config!\n",hwif->name); - return 0; - } - ide_input_data(drive,&ident,SECTOR_WORDS); - if (ident.id[1] != 'P' || ident.id[0] != 'T') { - return 0; - } - printk(KERN_INFO "%s: Promise caching controller, ",hwif->name); - switch(ident.type) { - case 0x43: printk("DC4030VL-2, "); break; - case 0x41: printk("DC4030VL-1, "); break; - case 0x40: printk("DC4030VL, "); break; - default: - printk("unknown - type 0x%02x - please report!\n" - ,ident.type); - printk("Please e-mail the following data to " - "promise@pnd-pc.demon.co.uk along with\n" - "a description of your card and drives:\n"); - for (i=0; i < 0x90; i++) { - printk("%02x ", ((unsigned char *)&ident)[i]); - if ((i & 0x0f) == 0x0f) printk("\n"); - } - return 0; - } - printk("%dKB cache, ",(int)ident.cache_mem); - switch(ident.irq) { - case 0x00: hwif->irq = 14; break; - case 0x01: hwif->irq = 12; break; - default: hwif->irq = 15; break; - } - printk("on IRQ %d\n",hwif->irq); - - /* - * Once found and identified, we set up the next hwif in the array - * (hwif2 = ide_hwifs[hwif->index+1]) with the same io ports, irq - * and other settings as the main hwif. This gives us two "mated" - * hwifs pointing to the Promise card. - * - * We also have to shift the default values for the remaining - * interfaces "up by one" to make room for the second interface on the - * same set of values. - */ - - hwif->chipset = hwif2->chipset = ide_pdc4030; - hwif->mate = hwif2; - hwif2->mate = hwif; - hwif2->channel = 1; - hwif->selectproc = hwif2->selectproc = &promise_selectproc; - hwif->serialized = hwif2->serialized = 1; - -/* Shift the remaining interfaces down by one */ - for (i=MAX_HWIFS-1 ; i > hwif->index+1 ; i--) { - ide_hwif_t *h = &ide_hwifs[i]; - -#ifdef DEBUG - printk(KERN_DEBUG "Shifting i/f %d values to i/f %d\n",i-1,i); -#endif - ide_init_hwif_ports(&h->hw, (h-1)->io_ports[IDE_DATA_OFFSET], 0, NULL); - memcpy(h->io_ports, h->hw.io_ports, sizeof(h->io_ports)); - h->noprobe = (h-1)->noprobe; - } - ide_init_hwif_ports(&hwif2->hw, hwif->io_ports[IDE_DATA_OFFSET], 0, NULL); - memcpy(hwif2->io_ports, hwif->hw.io_ports, sizeof(hwif2->io_ports)); - hwif2->irq = hwif->irq; - hwif2->hw.irq = hwif->hw.irq = hwif->irq; - for (i=0; i<2 ; i++) { - hwif->drives[i].io_32bit = 3; - hwif2->drives[i].io_32bit = 3; - hwif->drives[i].keep_settings = 1; - hwif2->drives[i].keep_settings = 1; - if (!ident.current_tm[i].cyl) - hwif->drives[i].noprobe = 1; - if (!ident.current_tm[i+2].cyl) - hwif2->drives[i].noprobe = 1; - } - return 1; -} - -/* - * detect_pdc4030() - * Tests for the presence of a DC4030 Promise card on this interface - * Returns: 1 if found, 0 if not found - */ -int __init detect_pdc4030(ide_hwif_t *hwif) -{ - ide_drive_t *drive = &hwif->drives[0]; - - if (IDE_DATA_REG == 0) { /* Skip test for non-existent interface */ - return 0; - } - OUT_BYTE(0xF3, IDE_SECTOR_REG); - OUT_BYTE(0x14, IDE_SELECT_REG); - OUT_BYTE(PROMISE_EXTENDED_COMMAND, IDE_COMMAND_REG); - - ide_delay_50ms(); - - if (IN_BYTE(IDE_ERROR_REG) == 'P' && - IN_BYTE(IDE_NSECTOR_REG) == 'T' && - IN_BYTE(IDE_SECTOR_REG) == 'I') { - return 1; - } else { - return 0; - } -} - -void __init ide_probe_for_pdc4030(void) -{ - unsigned int index; - ide_hwif_t *hwif; - - if (enable_promise_support == 0) - return; - for (index = 0; index < MAX_HWIFS; index++) { - hwif = &ide_hwifs[index]; - if (hwif->chipset == ide_unknown && detect_pdc4030(hwif)) { - setup_pdc4030(hwif); - } - } -} - - - -/* - * promise_read_intr() is the handler for disk read/multread interrupts - */ -static ide_startstop_t promise_read_intr (ide_drive_t *drive) -{ - byte stat; - int total_remaining; - unsigned int sectors_left, sectors_avail, nsect; - struct request *rq; - - if (!OK_STAT(stat=GET_STAT(),DATA_READY,BAD_R_STAT)) { - return ide_error(drive, "promise_read_intr", stat); - } - -read_again: - do { - sectors_left = IN_BYTE(IDE_NSECTOR_REG); - IN_BYTE(IDE_SECTOR_REG); - } while (IN_BYTE(IDE_NSECTOR_REG) != sectors_left); - rq = HWGROUP(drive)->rq; - sectors_avail = rq->nr_sectors - sectors_left; - if (!sectors_avail) - goto read_again; - -read_next: - rq = HWGROUP(drive)->rq; - nsect = rq->current_nr_sectors; - if (nsect > sectors_avail) - nsect = sectors_avail; - sectors_avail -= nsect; - ide_input_data(drive, rq->buffer, nsect * SECTOR_WORDS); -#ifdef DEBUG_READ - printk(KERN_DEBUG "%s: promise_read: sectors(%ld-%ld), " - "buf=0x%08lx, rem=%ld\n", drive->name, rq->sector, - rq->sector+nsect-1, (unsigned long) rq->buffer, - rq->nr_sectors-nsect); -#endif - rq->sector += nsect; - rq->buffer += nsect<<9; - rq->errors = 0; - rq->nr_sectors -= nsect; - total_remaining = rq->nr_sectors; - if ((rq->current_nr_sectors -= nsect) <= 0) { - ide_end_request(1, HWGROUP(drive)); - } -/* - * Now the data has been read in, do the following: - * - * if there are still sectors left in the request, - * if we know there are still sectors available from the interface, - * go back and read the next bit of the request. - * else if DRQ is asserted, there are more sectors available, so - * go back and find out how many, then read them in. - * else if BUSY is asserted, we are going to get an interrupt, so - * set the handler for the interrupt and just return - */ - if (total_remaining > 0) { - if (sectors_avail) - goto read_next; - stat = GET_STAT(); - if (stat & DRQ_STAT) - goto read_again; - if (stat & BUSY_STAT) { - ide_set_handler (drive, &promise_read_intr, WAIT_CMD, NULL); -#ifdef DEBUG_READ - printk(KERN_DEBUG "%s: promise_read: waiting for" - "interrupt\n", drive->name); -#endif - return ide_started; - } - printk(KERN_ERR "%s: Eeek! promise_read_intr: sectors left " - "!DRQ !BUSY\n", drive->name); - return ide_error(drive, "promise read intr", stat); - } - return ide_stopped; -} - -/* - * promise_complete_pollfunc() - * This is the polling function for waiting (nicely!) until drive stops - * being busy. It is invoked at the end of a write, after the previous poll - * has finished. - * - * Once not busy, the end request is called. - */ -static ide_startstop_t promise_complete_pollfunc(ide_drive_t *drive) -{ - ide_hwgroup_t *hwgroup = HWGROUP(drive); - struct request *rq = hwgroup->rq; - int i; - - if (GET_STAT() & BUSY_STAT) { - if (time_before(jiffies, hwgroup->poll_timeout)) { - ide_set_handler(drive, &promise_complete_pollfunc, HZ/100, NULL); - return ide_started; /* continue polling... */ - } - hwgroup->poll_timeout = 0; - printk(KERN_ERR "%s: completion timeout - still busy!\n", - drive->name); - return ide_error(drive, "busy timeout", GET_STAT()); - } - - hwgroup->poll_timeout = 0; -#ifdef DEBUG_WRITE - printk(KERN_DEBUG "%s: Write complete - end_request\n", drive->name); -#endif - for (i = rq->nr_sectors; i > 0; ) { - i -= rq->current_nr_sectors; - ide_end_request(1, hwgroup); - } - return ide_stopped; -} - -/* - * promise_write_pollfunc() is the handler for disk write completion polling. - */ -static ide_startstop_t promise_write_pollfunc (ide_drive_t *drive) -{ - ide_hwgroup_t *hwgroup = HWGROUP(drive); - - if (IN_BYTE(IDE_NSECTOR_REG) != 0) { - if (time_before(jiffies, hwgroup->poll_timeout)) { - ide_set_handler (drive, &promise_write_pollfunc, HZ/100, NULL); - return ide_started; /* continue polling... */ - } - hwgroup->poll_timeout = 0; - printk(KERN_ERR "%s: write timed-out!\n",drive->name); - return ide_error (drive, "write timeout", GET_STAT()); - } - - /* - * Now write out last 4 sectors and poll for not BUSY - */ - ide_multwrite(drive, 4); - hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; - ide_set_handler(drive, &promise_complete_pollfunc, HZ/100, NULL); -#ifdef DEBUG_WRITE - printk(KERN_DEBUG "%s: Done last 4 sectors - status = %02x\n", - drive->name, GET_STAT()); -#endif - return ide_started; -} - -/* - * promise_write() transfers a block of one or more sectors of data to a - * drive as part of a disk write operation. All but 4 sectors are transfered - * in the first attempt, then the interface is polled (nicely!) for completion - * before the final 4 sectors are transfered. There is no interrupt generated - * on writes (at least on the DC4030VL-2), we just have to poll for NOT BUSY. - */ -static ide_startstop_t promise_write (ide_drive_t *drive) -{ - ide_hwgroup_t *hwgroup = HWGROUP(drive); - struct request *rq = &hwgroup->wrq; - -#ifdef DEBUG_WRITE - printk(KERN_DEBUG "%s: promise_write: sectors(%ld-%ld), " - "buffer=0x%08x\n", drive->name, rq->sector, - rq->sector + rq->nr_sectors - 1, (unsigned int)rq->buffer); -#endif - - /* - * If there are more than 4 sectors to transfer, do n-4 then go into - * the polling strategy as defined above. - */ - if (rq->nr_sectors > 4) { - if (ide_multwrite(drive, rq->nr_sectors - 4)) - return ide_stopped; - hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; - ide_set_handler (drive, &promise_write_pollfunc, HZ/100, NULL); - return ide_started; - } else { - /* - * There are 4 or fewer sectors to transfer, do them all in one go - * and wait for NOT BUSY. - */ - if (ide_multwrite(drive, rq->nr_sectors)) - return ide_stopped; - hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; - ide_set_handler(drive, &promise_complete_pollfunc, HZ/100, NULL); -#ifdef DEBUG_WRITE - printk(KERN_DEBUG "%s: promise_write: <= 4 sectors, " - "status = %02x\n", drive->name, GET_STAT()); -#endif - return ide_started; - } -} - -/* - * do_pdc4030_io() is called from do_rw_disk, having had the block number - * already set up. It issues a READ or WRITE command to the Promise - * controller, assuming LBA has been used to set up the block number. - */ -ide_startstop_t do_pdc4030_io (ide_drive_t *drive, struct request *rq) -{ - unsigned long timeout; - byte stat; - - if (rq->cmd == READ) { - OUT_BYTE(PROMISE_READ, IDE_COMMAND_REG); -/* - * The card's behaviour is odd at this point. If the data is - * available, DRQ will be true, and no interrupt will be - * generated by the card. If this is the case, we need to call the - * "interrupt" handler (promise_read_intr) directly. Otherwise, if - * an interrupt is going to occur, bit0 of the SELECT register will - * be high, so we can set the handler the just return and be interrupted. - * If neither of these is the case, we wait for up to 50ms (badly I'm - * afraid!) until one of them is. - */ - timeout = jiffies + HZ/20; /* 50ms wait */ - do { - stat=GET_STAT(); - if (stat & DRQ_STAT) { - udelay(1); - return promise_read_intr(drive); - } - if (IN_BYTE(IDE_SELECT_REG) & 0x01) { -#ifdef DEBUG_READ - printk(KERN_DEBUG "%s: read: waiting for " - "interrupt\n", drive->name); -#endif - ide_set_handler(drive, &promise_read_intr, WAIT_CMD, NULL); - return ide_started; - } - udelay(1); - } while (time_before(jiffies, timeout)); - - printk(KERN_ERR "%s: reading: No DRQ and not waiting - Odd!\n", - drive->name); - return ide_stopped; - } else if (rq->cmd == WRITE) { - ide_startstop_t startstop; - OUT_BYTE(PROMISE_WRITE, IDE_COMMAND_REG); - if (ide_wait_stat(&startstop, drive, DATA_READY, drive->bad_wstat, WAIT_DRQ)) { - printk(KERN_ERR "%s: no DRQ after issuing " - "PROMISE_WRITE\n", drive->name); - return startstop; - } - if (!drive->unmask) - __cli(); /* local CPU only */ - HWGROUP(drive)->wrq = *rq; /* scratchpad */ - return promise_write(drive); - - } else { - printk("KERN_WARNING %s: bad command: %d\n", - drive->name, rq->cmd); - ide_end_request(0, HWGROUP(drive)); - return ide_stopped; - } -} diff --git a/drivers/block/pdc4030.h b/drivers/block/pdc4030.h deleted file mode 100644 index 551785c36..000000000 --- a/drivers/block/pdc4030.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * linux/drivers/ide/pdc4030.h - * - * Copyright (C) 1995-1998 Linus Torvalds & authors - */ - -/* - * Principal author: Peter Denison <peterd@pnd-pc.demon.co.uk> - */ - -#ifndef IDE_PROMISE_H -#define IDE_PROMISE_H - -#define PROMISE_EXTENDED_COMMAND 0xF0 -#define PROMISE_READ 0xF2 -#define PROMISE_WRITE 0xF3 -/* Extended commands - main command code = 0xf0 */ -#define PROMISE_GET_CONFIG 0x10 -#define PROMISE_IDENTIFY 0x20 - -struct translation_mode { - u16 cyl; - u8 head; - u8 sect; -}; - -struct dc_ident { - u8 type; - u8 unknown1; - u8 hw_revision; - u8 firmware_major; - u8 firmware_minor; - u8 bios_address; - u8 irq; - u8 unknown2; - u16 cache_mem; - u16 unknown3; - u8 id[2]; - u16 info; - struct translation_mode current_tm[4]; - u8 pad[SECTOR_WORDS*4 - 32]; -}; - -#endif IDE_PROMISE_H diff --git a/drivers/block/piix.c b/drivers/block/piix.c deleted file mode 100644 index 97e57fa55..000000000 --- a/drivers/block/piix.c +++ /dev/null @@ -1,434 +0,0 @@ -/* - * linux/drivers/block/piix.c Version 0.30 Feb. 26, 2000 - * - * Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer - * Copyright (C) 1998-2000 Andre Hedrick (andre@suse.com) - * May be copied or modified under the terms of the GNU General Public License - * - * PIO mode setting function for Intel chipsets. - * For use instead of BIOS settings. - * - * 40-41 - * 42-43 - * - * 41 - * 43 - * - * | PIO 0 | c0 | 80 | 0 | piix_tune_drive(drive, 0); - * | PIO 2 | SW2 | d0 | 90 | 4 | piix_tune_drive(drive, 2); - * | PIO 3 | MW1 | e1 | a1 | 9 | piix_tune_drive(drive, 3); - * | PIO 4 | MW2 | e3 | a3 | b | piix_tune_drive(drive, 4); - * - * sitre = word40 & 0x4000; primary - * sitre = word42 & 0x4000; secondary - * - * 44 8421|8421 hdd|hdb - * - * 48 8421 hdd|hdc|hdb|hda udma enabled - * - * 0001 hda - * 0010 hdb - * 0100 hdc - * 1000 hdd - * - * 4a 84|21 hdb|hda - * 4b 84|21 hdd|hdc - * - * ata-33/82371AB - * ata-33/82371EB - * ata-33/82801AB ata-66/82801AA - * 00|00 udma 0 00|00 reserved - * 01|01 udma 1 01|01 udma 3 - * 10|10 udma 2 10|10 udma 4 - * 11|11 reserved 11|11 reserved - * - * 54 8421|8421 ata66 drive|ata66 enable - * - * pci_read_config_word(HWIF(drive)->pci_dev, 0x40, ®40); - * pci_read_config_word(HWIF(drive)->pci_dev, 0x42, ®42); - * pci_read_config_word(HWIF(drive)->pci_dev, 0x44, ®44); - * pci_read_config_word(HWIF(drive)->pci_dev, 0x48, ®48); - * pci_read_config_word(HWIF(drive)->pci_dev, 0x4a, ®4a); - * pci_read_config_word(HWIF(drive)->pci_dev, 0x54, ®54); - * - * 00:1f.1 IDE interface: Intel Corporation: - * Unknown device 2411 (rev 01) (prog-if 80 [Master]) - * Control: I/O+ Mem- BusMaster+ SpecCycle- MemWINV- VGASnoop- - * ParErr- Stepping- SERR- FastB2B- - * Status: Cap- 66Mhz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- - * <TAbort- <MAbort- >SERR- <PERR- - * Latency: 0 set - * Region 4: I/O ports at ffa0 - * 00: 86 80 11 24 05 00 80 02 01 80 01 01 00 00 00 00 - * 10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - * 20: a1 ff 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - * 30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - * 40: 07 a3 03 a3 00 00 00 00 05 00 02 02 00 00 00 00 - * 50: 00 00 00 00 11 04 00 00 00 00 00 00 00 00 00 00 - * 60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - * 70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - * 80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - * 90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - * a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - * b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - * c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - * d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - * e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - * f0: 00 00 00 00 00 00 00 00 3a 0f 00 00 00 00 00 00 - * - */ - -#include <linux/config.h> -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/ioport.h> -#include <linux/pci.h> -#include <linux/hdreg.h> -#include <linux/ide.h> -#include <linux/delay.h> - -#include <asm/io.h> - -#include "ide_modes.h" - -#define PIIX_DEBUG_DRIVE_INFO 0 - -#define DISPLAY_PIIX_TIMINGS - -#if defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS) -#include <linux/stat.h> -#include <linux/proc_fs.h> - -static int piix_get_info(char *, char **, off_t, int); -extern int (*piix_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -extern char *ide_media_verbose(ide_drive_t *); -static struct pci_dev *bmide_dev; - -static int piix_get_info (char *buffer, char **addr, off_t offset, int count) -{ - char *p = buffer; - u32 bibma = bmide_dev->resource[4].start; - u16 reg40 = 0, psitre = 0, reg42 = 0, ssitre = 0; - u8 c0 = 0, c1 = 0; - u8 reg44 = 0, reg48 = 0, reg4a = 0, reg4b = 0, reg54 = 0; - - pci_read_config_word(bmide_dev, 0x40, ®40); - pci_read_config_word(bmide_dev, 0x42, ®42); - pci_read_config_byte(bmide_dev, 0x44, ®44); - pci_read_config_byte(bmide_dev, 0x48, ®48); - pci_read_config_byte(bmide_dev, 0x4a, ®4a); - pci_read_config_byte(bmide_dev, 0x4b, ®4b); - pci_read_config_byte(bmide_dev, 0x54, ®54); - - psitre = (reg40 & 0x4000) ? 1 : 0; - ssitre = (reg42 & 0x4000) ? 1 : 0; - - /* - * at that point bibma+0x2 et bibma+0xa are byte registers - * to investigate: - */ - c0 = inb_p((unsigned short)bibma + 0x02); - c1 = inb_p((unsigned short)bibma + 0x0a); - - switch(bmide_dev->device) { - case PCI_DEVICE_ID_INTEL_82372FB_1: - case PCI_DEVICE_ID_INTEL_82801AA_1: - p += sprintf(p, "\n Intel PIIX4 Ultra 66 Chipset.\n"); - break; - case PCI_DEVICE_ID_INTEL_82801AB_1: - case PCI_DEVICE_ID_INTEL_82371AB: - p += sprintf(p, "\n Intel PIIX4 Ultra 33 Chipset.\n"); - break; - case PCI_DEVICE_ID_INTEL_82371SB_1: - p += sprintf(p, "\n Intel PIIX3 Chipset.\n"); - break; - case PCI_DEVICE_ID_INTEL_82371FB_1: - case PCI_DEVICE_ID_INTEL_82371FB_0: - default: - p += sprintf(p, "\n Intel PIIX Chipset.\n"); - break; - } - p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n"); - p += sprintf(p, " %sabled %sabled\n", - (c0&0x80) ? "dis" : " en", - (c1&0x80) ? "dis" : " en"); - p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n"); - p += sprintf(p, "DMA enabled: %s %s %s %s\n", - (c0&0x20) ? "yes" : "no ", - (c0&0x40) ? "yes" : "no ", - (c1&0x20) ? "yes" : "no ", - (c1&0x40) ? "yes" : "no " ); - p += sprintf(p, "UDMA enabled: %s %s %s %s\n", - (reg48&0x01) ? "yes" : "no ", - (reg48&0x02) ? "yes" : "no ", - (reg48&0x04) ? "yes" : "no ", - (reg48&0x08) ? "yes" : "no " ); - p += sprintf(p, "UDMA enabled: %s %s %s %s\n", - ((reg54&0x11) && (reg4a&0x02)) ? "4" : - ((reg54&0x11) && (reg4a&0x01)) ? "3" : - (reg4a&0x02) ? "2" : - (reg4a&0x01) ? "1" : - (reg4a&0x00) ? "0" : "X", - ((reg54&0x22) && (reg4a&0x20)) ? "4" : - ((reg54&0x22) && (reg4a&0x10)) ? "3" : - (reg4a&0x20) ? "2" : - (reg4a&0x10) ? "1" : - (reg4a&0x00) ? "0" : "X", - ((reg54&0x44) && (reg4b&0x02)) ? "4" : - ((reg54&0x44) && (reg4b&0x01)) ? "3" : - (reg4b&0x02) ? "2" : - (reg4b&0x01) ? "1" : - (reg4b&0x00) ? "0" : "X", - ((reg54&0x88) && (reg4b&0x20)) ? "4" : - ((reg54&0x88) && (reg4b&0x10)) ? "3" : - (reg4b&0x20) ? "2" : - (reg4b&0x10) ? "1" : - (reg4b&0x00) ? "0" : "X"); - - p += sprintf(p, "UDMA\n"); - p += sprintf(p, "DMA\n"); - p += sprintf(p, "PIO\n"); - -/* - * FIXME.... Add configuration junk data....blah blah...... - */ - - return p-buffer; /* => must be less than 4k! */ -} -#endif /* defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS) */ - -/* - * Used to set Fifo configuration via kernel command line: - */ - -byte piix_proc = 0; - -extern char *ide_xfer_verbose (byte xfer_rate); - -/* - * - */ -static byte piix_dma_2_pio (byte xfer_rate) { - switch(xfer_rate) { - case XFER_UDMA_4: - case XFER_UDMA_3: - case XFER_UDMA_2: - case XFER_UDMA_1: - case XFER_UDMA_0: - case XFER_MW_DMA_2: - case XFER_PIO_4: - return 4; - case XFER_MW_DMA_1: - case XFER_PIO_3: - return 3; - case XFER_SW_DMA_2: - case XFER_PIO_2: - return 2; - case XFER_MW_DMA_0: - case XFER_SW_DMA_1: - case XFER_SW_DMA_0: - case XFER_PIO_1: - case XFER_PIO_0: - case XFER_PIO_SLOW: - default: - return 0; - } -} - -/* - * Based on settings done by AMI BIOS - * (might be usefull if drive is not registered in CMOS for any reason). - */ -static void piix_tune_drive (ide_drive_t *drive, byte pio) -{ - unsigned long flags; - u16 master_data; - byte slave_data; - int is_slave = (&HWIF(drive)->drives[1] == drive); - int master_port = HWIF(drive)->index ? 0x42 : 0x40; - int slave_port = 0x44; - /* ISP RTC */ - byte timings[][2] = { { 0, 0 }, - { 0, 0 }, - { 1, 0 }, - { 2, 1 }, - { 2, 3 }, }; - - pio = ide_get_best_pio_mode(drive, pio, 5, NULL); - pci_read_config_word(HWIF(drive)->pci_dev, master_port, &master_data); - if (is_slave) { - master_data = master_data | 0x4000; - if (pio > 1) - /* enable PPE, IE and TIME */ - master_data = master_data | 0x0070; - pci_read_config_byte(HWIF(drive)->pci_dev, slave_port, &slave_data); - slave_data = slave_data & (HWIF(drive)->index ? 0x0f : 0xf0); - slave_data = slave_data | ((timings[pio][0] << 2) | (timings[pio][1] - << (HWIF(drive)->index ? 4 : 0))); - } else { - master_data = master_data & 0xccf8; - if (pio > 1) - /* enable PPE, IE and TIME */ - master_data = master_data | 0x0007; - master_data = master_data | (timings[pio][0] << 12) | - (timings[pio][1] << 8); - } - save_flags(flags); - cli(); - pci_write_config_word(HWIF(drive)->pci_dev, master_port, master_data); - if (is_slave) - pci_write_config_byte(HWIF(drive)->pci_dev, slave_port, slave_data); - restore_flags(flags); -} - -static int piix_config_drive_for_dma (ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - - int sitre; - short reg4042, reg44, reg48, reg4a, reg54; - byte speed; - - byte maslave = hwif->channel ? 0x42 : 0x40; - byte udma_66 = ((id->hw_config & 0x2000) && (hwif->udma_four)) ? 1 : 0; - int ultra66 = ((dev->device == PCI_DEVICE_ID_INTEL_82801AA_1) || - (dev->device == PCI_DEVICE_ID_INTEL_82372FB_1)) ? 1 : 0; - int ultra = ((ultra66) || - (dev->device == PCI_DEVICE_ID_INTEL_82371AB) || - (dev->device == PCI_DEVICE_ID_INTEL_82801AB_1)) ? 1 : 0; - int drive_number = ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01)); - int a_speed = 2 << (drive_number * 4); - int u_flag = 1 << drive_number; - int v_flag = 0x10 << drive_number; - int u_speed = 0; - - pci_read_config_word(dev, maslave, ®4042); - sitre = (reg4042 & 0x4000) ? 1 : 0; - pci_read_config_word(dev, 0x44, ®44); - pci_read_config_word(dev, 0x48, ®48); - pci_read_config_word(dev, 0x4a, ®4a); - pci_read_config_word(dev, 0x54, ®54); - - if ((id->dma_ultra & 0x0010) && (ultra)) { - u_speed = 2 << (drive_number * 4); - speed = ((udma_66) && (ultra66)) ? XFER_UDMA_4 : XFER_UDMA_2; - } else if ((id->dma_ultra & 0x0008) && (ultra)) { - u_speed = 1 << (drive_number * 4); - speed = ((udma_66) && (ultra66)) ? XFER_UDMA_3 : XFER_UDMA_1; - } else if ((id->dma_ultra & 0x0004) && (ultra)) { - u_speed = 2 << (drive_number * 4); - speed = XFER_UDMA_2; - } else if ((id->dma_ultra & 0x0002) && (ultra)) { - u_speed = 1 << (drive_number * 4); - speed = XFER_UDMA_1; - } else if ((id->dma_ultra & 0x0001) && (ultra)) { - u_speed = 0 << (drive_number * 4); - speed = XFER_UDMA_0; - } else if (id->dma_mword & 0x0004) { - speed = XFER_MW_DMA_2; - } else if (id->dma_mword & 0x0002) { - speed = XFER_MW_DMA_1; - } else if (id->dma_1word & 0x0004) { - speed = XFER_SW_DMA_2; - } else { - speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, 5, NULL); - } - - if (speed >= XFER_UDMA_0) { - if (!(reg48 & u_flag)) - pci_write_config_word(dev, 0x48, reg48|u_flag); - if (!(reg4a & u_speed)) { - pci_write_config_word(dev, 0x4a, reg4a & ~a_speed); - pci_write_config_word(dev, 0x4a, reg4a|u_speed); - } - if (speed > XFER_UDMA_2) { - if (!(reg54 & v_flag)) { - pci_write_config_word(dev, 0x54, reg54|v_flag); - } - } else { - pci_write_config_word(dev, 0x54, reg54 & ~v_flag); - } - } - - if (speed < XFER_UDMA_0) { - if (reg48 & u_flag) - pci_write_config_word(dev, 0x48, reg48 & ~u_flag); - if (reg4a & a_speed) - pci_write_config_word(dev, 0x4a, reg4a & ~a_speed); - if (reg54 & v_flag) - pci_write_config_word(dev, 0x54, reg54 & ~v_flag); - } - - piix_tune_drive(drive, piix_dma_2_pio(speed)); - - (void) ide_config_drive_speed(drive, speed); - -#if PIIX_DEBUG_DRIVE_INFO - printk("%s: %s drive%d\n", drive->name, ide_xfer_verbose(speed), drive_number); -#endif /* PIIX_DEBUG_DRIVE_INFO */ - - return ((int) ((id->dma_ultra >> 11) & 3) ? ide_dma_on : - ((id->dma_ultra >> 8) & 7) ? ide_dma_on : - ((id->dma_mword >> 8) & 7) ? ide_dma_on : - ((id->dma_1word >> 8) & 7) ? ide_dma_on : - ide_dma_off_quietly); -} - -static int piix_dmaproc(ide_dma_action_t func, ide_drive_t *drive) -{ - switch (func) { - case ide_dma_check: - return ide_dmaproc((ide_dma_action_t) piix_config_drive_for_dma(drive), drive); - default : - break; - } - /* Other cases are done by generic IDE-DMA code. */ - return ide_dmaproc(func, drive); -} - -unsigned int __init pci_init_piix (struct pci_dev *dev, const char *name) -{ -#if defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS) - piix_proc = 1; - bmide_dev = dev; - piix_display_info = &piix_get_info; -#endif /* DISPLAY_PIIX_TIMINGS && CONFIG_PROC_FS */ - return 0; -} - -/* - * Sheesh, someone at Intel needs to go read the ATA-4/5 T13 standards. - * It does not specify device detection, but channel!!! - * You determine later if bit 13 of word93 is set... - */ -unsigned int __init ata66_piix (ide_hwif_t *hwif) -{ - byte reg54h = 0, reg55h = 0, ata66 = 0; - byte mask = hwif->channel ? 0x0c : 0x03; - - pci_read_config_byte(hwif->pci_dev, 0x54, ®54h); - pci_read_config_byte(hwif->pci_dev, 0x55, ®55h); - ata66 = (reg54h & mask) ? 1 : 0; - - return ata66; -} - -void __init ide_init_piix (ide_hwif_t *hwif) -{ - hwif->tuneproc = &piix_tune_drive; - - if (hwif->dma_base) { -#ifdef CONFIG_PIIX_TUNING - hwif->dmaproc = &piix_dmaproc; -#endif /* CONFIG_PIIX_TUNING */ - hwif->drives[0].autotune = 0; - hwif->drives[1].autotune = 0; - } else { - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - } - if (!hwif->irq) - hwif->irq = hwif->channel ? 15 : 14; -} diff --git a/drivers/block/q40ide.c b/drivers/block/q40ide.c deleted file mode 100644 index 0f2330370..000000000 --- a/drivers/block/q40ide.c +++ /dev/null @@ -1,109 +0,0 @@ -/* - * linux/drivers/block/q40ide.c -- Q40 I/O port IDE Driver - * - * original file created 12 Jul 1997 by Geert Uytterhoeven - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive for - * more details. - * - * RZ: - * almost identical with pcide.c, maybe we can merge it later. - * Differences: - * max 2 HWIFS for now - * translate portaddresses to q40 native addresses (not yet...) instead rely on in/out[bw] - * address translation - * - */ - -#include <linux/types.h> -#include <linux/mm.h> -#include <linux/interrupt.h> -#include <linux/blkdev.h> -#include <linux/hdreg.h> - -#include <linux/ide.h> - - /* - * Bases of the IDE interfaces - */ - -#define PCIDE_NUM_HWIFS 2 - -#define PCIDE_BASE1 0x1f0 -#define PCIDE_BASE2 0x170 -#define PCIDE_BASE3 0x1e8 -#define PCIDE_BASE4 0x168 -#define PCIDE_BASE5 0x1e0 -#define PCIDE_BASE6 0x160 - -static const q40ide_ioreg_t pcide_bases[PCIDE_NUM_HWIFS] = { - PCIDE_BASE1, PCIDE_BASE2, /* PCIDE_BASE3, PCIDE_BASE4 , PCIDE_BASE5, - PCIDE_BASE6 */ -}; - - - /* - * Offsets from one of the above bases - */ - -#undef HD_DATA -#define HD_DATA 0x1f0 - -#define PCIDE_REG(x) ((q40ide_ioreg_t)(HD_##x-PCIDE_BASE1)) - -static const int pcide_offsets[IDE_NR_PORTS] = { - PCIDE_REG(DATA), PCIDE_REG(ERROR), PCIDE_REG(NSECTOR), PCIDE_REG(SECTOR), - PCIDE_REG(LCYL), PCIDE_REG(HCYL), PCIDE_REG(CURRENT), PCIDE_REG(STATUS), - PCIDE_REG(CMD) -}; - -int q40ide_default_irq(q40ide_ioreg_t base) -{ - switch (base) { - case 0x1f0: return 14; - case 0x170: return 15; - case 0x1e8: return 11; - default: - return 0; - } -} - -void q40_ide_init_hwif_ports (q40ide_ioreg_t *p, q40ide_ioreg_t base, int *irq) -{ - q40ide_ioreg_t port = base; - int i = 8; - - while (i--) - *p++ = port++; - *p++ = base + 0x206; - if (irq != NULL) - *irq = 0; -} - - - /* - * Probe for PC IDE interfaces - */ - -int q40ide_probe_hwif(int index, ide_hwif_t *hwif) -{ - static int pcide_index[PCIDE_NUM_HWIFS] = { 0, }; - int i; - - if (!MACH_IS_Q40) - return 0; - - for (i = 0; i < PCIDE_NUM_HWIFS; i++) { - if (!pcide_index[i]) { - /*printk("ide%d: Q40 IDE interface\n", index);*/ - pcide_index[i] = index+1; - } - if (pcide_index[i] == index+1) { - ide_setup_ports(hwif,(ide_ioreg_t) pcide_bases[i], pcide_offsets, 0, /*q40_ack_intr???*/ NULL); - hwif->irq = ide_default_irq((ide_ioreg_t)pcide_bases[i]); /*q40_ide_irq[i]; */ /* 14 */ - return 1; - } - } - return 0; -} diff --git a/drivers/block/qd6580.c b/drivers/block/qd6580.c deleted file mode 100644 index 31781a9f0..000000000 --- a/drivers/block/qd6580.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * linux/drivers/block/qd6580.c Version 0.02 Feb 09, 1996 - * - * Copyright (C) 1996 Linus Torvalds & author (see below) - */ - -/* - * QDI QD6580 EIDE controller fast support by Colten Edwards. - * No net access, but (maybe) can be reached at pje120@cs.usask.ca - */ - -#undef REALLY_SLOW_IO /* most systems can safely undef this */ - -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/delay.h> -#include <linux/timer.h> -#include <linux/mm.h> -#include <linux/ioport.h> -#include <linux/blkdev.h> -#include <linux/hdreg.h> -#include <linux/ide.h> - -#include <asm/io.h> - -#include "ide_modes.h" - -/* - * Register 0xb3 looks like: - * 0x4f is fast mode3 ? - * 0x3f is medium mode2 ? - * 0x2f is slower mode1 ? - * 0x1f is slower yet mode0 ? - * 0x0f ??? ??? - * - * Don't know whether this sets BOTH drives, or just the first drive. - * Don't know if there is a separate setting for the second drive. - * - * Feel free to patch this if you have one of these beasts - * and can work out the answers! - * - * I/O ports are 0xb0 0xb2 and 0xb3 - * - * More research on qd6580 being done by willmore@cig.mot.com (David) - * -- this is apparently a *dual* IDE interface - */ - -static void tune_qd6580 (ide_drive_t *drive, byte pio) -{ - unsigned long flags; - - pio = ide_get_best_pio_mode(drive, pio, 3, NULL); - - save_flags(flags); /* all CPUs */ - cli(); /* all CPUs */ - outb_p(0x8d,0xb0); - outb_p(0x0 ,0xb2); - outb_p(((pio+1)<<4)|0x0f,0xb3); - inb(0x3f6); - restore_flags(flags); /* all CPUs */ -} - -void __init init_qd6580 (void) -{ - ide_hwifs[0].chipset = ide_qd6580; - ide_hwifs[1].chipset = ide_qd6580; - ide_hwifs[0].tuneproc = &tune_qd6580; - ide_hwifs[0].mate = &ide_hwifs[1]; - ide_hwifs[1].mate = &ide_hwifs[0]; - ide_hwifs[1].channel = 1; -} diff --git a/drivers/block/rapide.c b/drivers/block/rapide.c deleted file mode 100644 index 5905aca41..000000000 --- a/drivers/block/rapide.c +++ /dev/null @@ -1,92 +0,0 @@ -/* - * linux/drivers/block/rapide.c - * - * Copyright (c) 1996-1998 Russell King. - * - * Changelog: - * 08-06-1996 RMK Created - * 13-04-1998 RMK Added manufacturer and product IDs - */ - -#include <linux/module.h> -#include <linux/malloc.h> -#include <linux/blkdev.h> -#include <linux/errno.h> -#include <linux/ide.h> - -#include <asm/ecard.h> - -static const card_ids __init rapide_cids[] = { - { MANU_YELLOWSTONE, PROD_YELLOWSTONE_RAPIDE32 }, - { 0xffff, 0xffff } -}; - -static struct expansion_card *ec[MAX_ECARDS]; -static int result[MAX_ECARDS]; - -static inline int rapide_register(struct expansion_card *ec) -{ - unsigned long port = ecard_address (ec, ECARD_MEMC, 0); - hw_regs_t hw; - - int i; - - memset(&hw, 0, sizeof(hw)); - - for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { - hw.io_ports[i] = (ide_ioreg_t)port; - port += 1 << 4; - } - hw.io_ports[IDE_CONTROL_OFFSET] = port + 0x206; - hw.irq = ec->irq; - - return ide_register_hw(&hw, NULL); -} - -int __init rapide_init(void) -{ - int i; - - for (i = 0; i < MAX_ECARDS; i++) - ec[i] = NULL; - - ecard_startfind(); - - for (i = 0; ; i++) { - if ((ec[i] = ecard_find(0, rapide_cids)) == NULL) - break; - - ecard_claim(ec[i]); - result[i] = rapide_register(ec[i]); - } - for (i = 0; i < MAX_ECARDS; i++) - if (ec[i] && result[i] < 0) { - ecard_release(ec[i]); - ec[i] = NULL; - } - return 0; -} - -#ifdef MODULE - -int init_module (void) -{ - return rapide_init(); -} - -void cleanup_module (void) -{ - int i; - - for (i = 0; i < MAX_ECARDS; i++) - if (ec[i]) { - unsigned long port; - port = ecard_address(ec[i], ECARD_MEMC, 0); - - ide_unregister_port(port, ec[i]->irq, 16); - ecard_release(ec[i]); - ec[i] = NULL; - } -} -#endif - diff --git a/drivers/block/rz1000.c b/drivers/block/rz1000.c deleted file mode 100644 index 455641c1d..000000000 --- a/drivers/block/rz1000.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * linux/drivers/block/rz1000.c Version 0.05 December 8, 1997 - * - * Copyright (C) 1995-1998 Linus Torvalds & author (see below) - */ - -/* - * Principal Author: mlord@pobox.com (Mark Lord) - * - * See linux/MAINTAINERS for address of current maintainer. - * - * This file provides support for disabling the buggy read-ahead - * mode of the RZ1000 IDE chipset, commonly used on Intel motherboards. - * - * Dunno if this fixes both ports, or only the primary port (?). - */ - -#undef REALLY_SLOW_IO /* most systems can safely undef this */ - -#include <linux/config.h> /* for CONFIG_BLK_DEV_IDEPCI */ -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/delay.h> -#include <linux/timer.h> -#include <linux/mm.h> -#include <linux/ioport.h> -#include <linux/blkdev.h> -#include <linux/hdreg.h> -#include <linux/pci.h> -#include <linux/ide.h> - -#include <asm/io.h> - -#ifdef CONFIG_BLK_DEV_IDEPCI - -void __init ide_init_rz1000 (ide_hwif_t *hwif) /* called from ide-pci.c */ -{ - unsigned short reg; - struct pci_dev *dev = hwif->pci_dev; - - hwif->chipset = ide_rz1000; - if (!pci_read_config_word (dev, 0x40, ®) - && !pci_write_config_word(dev, 0x40, reg & 0xdfff)) - { - printk("%s: disabled chipset read-ahead (buggy RZ1000/RZ1001)\n", hwif->name); - } else { - hwif->serialized = 1; - hwif->drives[0].no_unmask = 1; - hwif->drives[1].no_unmask = 1; - printk("%s: serialized, disabled unmasking (buggy RZ1000/RZ1001)\n", hwif->name); - } -} - -#else - -static void __init init_rz1000 (struct pci_dev *dev, const char *name) -{ - unsigned short reg, h; - - if (!pci_read_config_word (dev, PCI_COMMAND, ®) && !(reg & PCI_COMMAND_IO)) { - printk("%s: buggy IDE controller disabled (BIOS)\n", name); - return; - } - if (!pci_read_config_word (dev, 0x40, ®) - && !pci_write_config_word(dev, 0x40, reg & 0xdfff)) - { - printk("IDE: disabled chipset read-ahead (buggy %s)\n", name); - } else { - for (h = 0; h < MAX_HWIFS; ++h) { - ide_hwif_t *hwif = &ide_hwifs[h]; - if ((hwif->io_ports[IDE_DATA_OFFSET] == 0x1f0 || hwif->io_ports[IDE_DATA_OFFSET] == 0x170) - && (hwif->chipset == ide_unknown || hwif->chipset == ide_generic)) - { - hwif->chipset = ide_rz1000; - hwif->serialized = 1; - hwif->drives[0].no_unmask = 1; - hwif->drives[1].no_unmask = 1; - if (hwif->io_ports[IDE_DATA_OFFSET] == 0x170) - hwif->channel = 1; - printk("%s: serialized, disabled unmasking (buggy %s)\n", hwif->name, name); - } - } - } -} - -void __init ide_probe_for_rz100x (void) /* called from ide.c */ -{ - struct pci_dev *dev = NULL; - - while ((dev = pci_find_device(PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1000, dev))!=NULL) - init_rz1000 (dev, "RZ1000"); - while ((dev = pci_find_device(PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1001, dev))!=NULL) - init_rz1000 (dev, "RZ1001"); -} - -#endif CONFIG_BLK_DEV_IDEPCI diff --git a/drivers/block/sis5513.c b/drivers/block/sis5513.c deleted file mode 100644 index 942187900..000000000 --- a/drivers/block/sis5513.c +++ /dev/null @@ -1,549 +0,0 @@ -/* - * linux/drivers/block/sis5513.c Version 0.09 Feb. 10, 2000 - * - * Copyright (C) 1999-2000 Andre Hedrick (andre@suse.com) - * May be copied or modified under the terms of the GNU General Public License - * - * Thanks to SIS Taiwan for direct support and hardware. - * Tested and designed on the SiS620/5513 chipset. - */ - -#include <linux/config.h> -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/delay.h> -#include <linux/timer.h> -#include <linux/mm.h> -#include <linux/ioport.h> -#include <linux/blkdev.h> -#include <linux/hdreg.h> - -#include <linux/interrupt.h> -#include <linux/pci.h> -#include <linux/init.h> -#include <linux/ide.h> - -#include <asm/io.h> -#include <asm/irq.h> - -#include "ide_modes.h" - -#define DISPLAY_SIS_TIMINGS -#define SIS5513_DEBUG_DRIVE_INFO 0 - -static struct pci_dev *host_dev = NULL; - -#define arraysize(x) (sizeof(x)/sizeof(*(x))) - -#define SIS5513_FLAG_ATA_00 0x00000000 -#define SIS5513_FLAG_ATA_16 0x00000001 -#define SIS5513_FLAG_ATA_33 0x00000002 -#define SIS5513_FLAG_ATA_66 0x00000004 -#define SIS5513_FLAG_LATENCY 0x00000010 - -static const struct { - const char *name; - unsigned short host_id; - unsigned int flags; -} SiSHostChipInfo[] = { - { "SiS530", PCI_DEVICE_ID_SI_530, SIS5513_FLAG_ATA_66, }, - { "SiS540", PCI_DEVICE_ID_SI_540, SIS5513_FLAG_ATA_66, }, - { "SiS620", PCI_DEVICE_ID_SI_620, SIS5513_FLAG_ATA_66|SIS5513_FLAG_LATENCY, }, - { "SiS630", PCI_DEVICE_ID_SI_630, SIS5513_FLAG_ATA_66|SIS5513_FLAG_LATENCY, }, - { "SiS5591", PCI_DEVICE_ID_SI_5591, SIS5513_FLAG_ATA_33, }, - { "SiS5597", PCI_DEVICE_ID_SI_5597, SIS5513_FLAG_ATA_33, }, - { "SiS5600", PCI_DEVICE_ID_SI_5600, SIS5513_FLAG_ATA_33, }, - { "SiS5511", PCI_DEVICE_ID_SI_5511, SIS5513_FLAG_ATA_16, }, -}; - -#if 0 - -static struct _pio_mode_mapping { - byte data_active; - byte recovery; - byte pio_mode; -} pio_mode_mapping[] = { - { 8, 12, 0 }, - { 6, 7, 1 }, - { 4, 4, 2 }, - { 3, 3, 3 }, - { 3, 1, 4 } -}; - -static struct _dma_mode_mapping { - byte data_active; - byte recovery; - byte dma_mode; -} dma_mode_mapping[] = { - { 8, 8, 0 }, - { 3, 2, 1 }, - { 3, 1, 2 } -}; - -static struct _udma_mode_mapping { - byte cycle_time; - char * udma_mode; -} udma_mode_mapping[] = { - { 8, "Mode 0" }, - { 6, "Mode 1" }, - { 4, "Mode 2" }, - { 3, "Mode 3" }, - { 2, "Mode 4" }, - { 0, "Undefined" } -}; - -static __inline__ char * find_udma_mode (byte cycle_time) -{ - int n; - - for (n = 0; n <= 4; n++) - if (udma_mode_mapping[n].cycle_time <= cycle_time) - return udma_mode_mapping[n].udma_mode; - return udma_mode_mapping[4].udma_mode; -} -#endif - -#if defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS) -#include <linux/stat.h> -#include <linux/proc_fs.h> - -static int sis_get_info(char *, char **, off_t, int); -extern int (*sis_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -struct pci_dev *bmide_dev; - -static char *cable_type[] = { - "80 pins", - "40 pins" -}; - -static char *recovery_time [] ={ - "12 PCICLK", "1 PCICLK", - "2 PCICLK", "3 PCICLK", - "4 PCICLK", "5 PCICLCK", - "6 PCICLK", "7 PCICLCK", - "8 PCICLK", "9 PCICLCK", - "10 PCICLK", "11 PCICLK", - "13 PCICLK", "14 PCICLK", - "15 PCICLK", "15 PCICLK" -}; - -static char *cycle_time [] = { - "Undefined", "2 CLCK", - "3 CLK", "4 CLK", - "5 CLK", "6 CLK", - "7 CLK", "8 CLK" -}; - -static char *active_time [] = { - "8 PCICLK", "1 PCICLCK", - "2 PCICLK", "2 PCICLK", - "4 PCICLK", "5 PCICLK", - "6 PCICLK", "12 PCICLK" -}; - -static int sis_get_info (char *buffer, char **addr, off_t offset, int count) -{ - int rc; - char *p = buffer; - byte reg,reg1; - u16 reg2, reg3; - - p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n"); - rc = pci_read_config_byte(bmide_dev, 0x4a, ®); - p += sprintf(p, "Channel Status: %s \t \t \t \t %s \n", - (reg & 0x02) ? "On" : "Off", - (reg & 0x04) ? "On" : "Off"); - - rc = pci_read_config_byte(bmide_dev, 0x09, ®); - p += sprintf(p, "Operation Mode: %s \t \t \t %s \n", - (reg & 0x01) ? "Native" : "Compatible", - (reg & 0x04) ? "Native" : "Compatible"); - - rc = pci_read_config_byte(bmide_dev, 0x48, ®); - p += sprintf(p, "Cable Type: %s \t \t \t %s\n", - (reg & 0x10) ? cable_type[1] : cable_type[0], - (reg & 0x20) ? cable_type[1] : cable_type[0]); - - rc = pci_read_config_word(bmide_dev, 0x4c, ®2); - rc = pci_read_config_word(bmide_dev, 0x4e, ®3); - p += sprintf(p, "Prefetch Count: %d \t \t \t \t %d\n", - reg2, reg3); - - rc = pci_read_config_byte(bmide_dev, 0x4b, ®); - p += sprintf(p, "Drvie 0: Postwrite %s \t \t Postwrite %s\n", - (reg & 0x10) ? "Enabled" : "Disabled", - (reg & 0x40) ? "Enabled" : "Disabled"); - p += sprintf(p, " Prefetch %s \t \t Prefetch %s\n", - (reg & 0x01) ? "Enabled" : "Disabled", - (reg & 0x04) ? "Enabled" : "Disabled"); - - rc = pci_read_config_byte(bmide_dev, 0x41, ®); - rc = pci_read_config_byte(bmide_dev, 0x45, ®1); - p += sprintf(p, " UDMA %s \t \t \t UDMA %s\n", - (reg & 0x80) ? "Enabled" : "Disabled", - (reg1 & 0x80) ? "Enabled" : "Disabled"); - p += sprintf(p, " UDMA Cycle Time %s \t UDMA Cycle Time %s\n", - cycle_time[(reg & 0x70) >> 4], cycle_time[(reg1 & 0x70) >> 4]); - p += sprintf(p, " Data Active Time %s \t Data Active Time %s\n", - active_time[(reg & 0x07)], active_time[(reg &0x07)] ); - - rc = pci_read_config_byte(bmide_dev, 0x40, ®); - rc = pci_read_config_byte(bmide_dev, 0x44, ®1); - p += sprintf(p, " Data Recovery Time %s \t Data Recovery Time %s\n", - recovery_time[(reg & 0x0f)], recovery_time[(reg1 & 0x0f)]); - - - rc = pci_read_config_byte(bmide_dev, 0x4b, ®); - p += sprintf(p, "Drvie 1: Postwrite %s \t \t Postwrite %s\n", - (reg & 0x20) ? "Enabled" : "Disabled", - (reg & 0x80) ? "Enabled" : "Disabled"); - p += sprintf(p, " Prefetch %s \t \t Prefetch %s\n", - (reg & 0x02) ? "Enabled" : "Disabled", - (reg & 0x08) ? "Enabled" : "Disabled"); - - rc = pci_read_config_byte(bmide_dev, 0x43, ®); - rc = pci_read_config_byte(bmide_dev, 0x47, ®1); - p += sprintf(p, " UDMA %s \t \t \t UDMA %s\n", - (reg & 0x80) ? "Enabled" : "Disabled", - (reg1 & 0x80) ? "Enabled" : "Disabled"); - p += sprintf(p, " UDMA Cycle Time %s \t UDMA Cycle Time %s\n", - cycle_time[(reg & 0x70) >> 4], cycle_time[(reg1 & 0x70) >> 4]); - p += sprintf(p, " Data Active Time %s \t Data Active Time %s\n", - active_time[(reg & 0x07)], active_time[(reg &0x07)] ); - - rc = pci_read_config_byte(bmide_dev, 0x42, ®); - rc = pci_read_config_byte(bmide_dev, 0x46, ®1); - p += sprintf(p, " Data Recovery Time %s \t Data Recovery Time %s\n", - recovery_time[(reg & 0x0f)], recovery_time[(reg1 & 0x0f)]); - return p-buffer; -} -#endif /* defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS) */ - -byte sis_proc = 0; -extern char *ide_xfer_verbose (byte xfer_rate); - -/* - * ((id->hw_config & 0x2000) && (HWIF(drive)->udma_four)) - */ -static int config_chipset_for_dma (ide_drive_t *drive, byte ultra) -{ - struct hd_driveid *id = drive->id; - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - - byte drive_pci, test1, test2, mask; - int err; - - unsigned long dma_base = hwif->dma_base; - byte unit = (drive->select.b.unit & 0x01); - byte speed = 0x00, unmask = 0xE0, four_two = 0x00; - int drive_number = ((hwif->channel ? 2 : 0) + unit); - byte udma_66 = ((id->hw_config & 0x2000) && (hwif->udma_four)) ? 1 : 0; - - if (host_dev) { - switch(host_dev->device) { - case PCI_DEVICE_ID_SI_530: - case PCI_DEVICE_ID_SI_540: - case PCI_DEVICE_ID_SI_620: - case PCI_DEVICE_ID_SI_630: - unmask = 0xF0; - four_two = 0x01; - default: - break; - } - } - - switch(drive_number) { - case 0: drive_pci = 0x40;break; - case 1: drive_pci = 0x42;break; - case 2: drive_pci = 0x44;break; - case 3: drive_pci = 0x46;break; - default: return ide_dma_off; - } - - pci_read_config_byte(dev, drive_pci, &test1); - pci_read_config_byte(dev, drive_pci|0x01, &test2); - - if ((!ultra) && (test2 & 0x80)) { - pci_write_config_byte(dev, drive_pci|0x01, test2 & ~0x80); - pci_read_config_byte(dev, drive_pci|0x01, &test2); - } - - if ((id->dma_ultra & 0x0010) && (ultra) && (udma_66) && (four_two)) { - if (!(test2 & 0x90)) { - pci_write_config_byte(dev, drive_pci|0x01, test2 & ~unmask); - pci_write_config_byte(dev, drive_pci|0x01, test2|0x90); - } - speed = XFER_UDMA_4; - } else if ((id->dma_ultra & 0x0008) && (ultra) && (udma_66) && (four_two)) { - if (!(test2 & 0xA0)) { - pci_write_config_byte(dev, drive_pci|0x01, test2 & ~unmask); - pci_write_config_byte(dev, drive_pci|0x01, test2|0xA0); - } - speed = XFER_UDMA_3; - } else if ((id->dma_ultra & 0x0004) && (ultra)) { - mask = (four_two) ? 0xB0 : 0xA0; - if (!(test2 & mask)) { - pci_write_config_byte(dev, drive_pci|0x01, test2 & ~unmask); - pci_write_config_byte(dev, drive_pci|0x01, test2|mask); - } - speed = XFER_UDMA_2; - } else if ((id->dma_ultra & 0x0002) && (ultra)) { - mask = (four_two) ? 0xD0 : 0xC0; - if (!(test2 & mask)) { - pci_write_config_byte(dev, drive_pci|0x01, test2 & ~unmask); - pci_write_config_byte(dev, drive_pci|0x01, test2|mask); - } - speed = XFER_UDMA_1; - } else if ((id->dma_ultra & 0x0001) && (ultra)) { - if (!(test2 & unmask)) { - pci_write_config_byte(dev, drive_pci|0x01, test2 & ~unmask); - pci_write_config_byte(dev, drive_pci|0x01, test2|unmask); - } - speed = XFER_UDMA_0; - } else if (id->dma_mword & 0x0004) { - speed = XFER_MW_DMA_2; - } else if (id->dma_mword & 0x0002) { - speed = XFER_MW_DMA_1; - } else if (id->dma_mword & 0x0001) { - speed = XFER_MW_DMA_0; - } else if (id->dma_1word & 0x0004) { - speed = XFER_SW_DMA_2; - } else if (id->dma_1word & 0x0002) { - speed = XFER_SW_DMA_1; - } else if (id->dma_1word & 0x0001) { - speed = XFER_SW_DMA_0; - } else { - return ((int) ide_dma_off_quietly); - } - - outb(inb(dma_base+2)|(1<<(5+unit)), dma_base+2); - err = ide_config_drive_speed(drive, speed); - -#if SIS5513_DEBUG_DRIVE_INFO - printk("%s: %s drive%d\n", drive->name, ide_xfer_verbose(speed), drive_number); -#endif /* SIS5513_DEBUG_DRIVE_INFO */ - - return ((int) ((id->dma_ultra >> 11) & 3) ? ide_dma_on : - ((id->dma_ultra >> 8) & 7) ? ide_dma_on : - ((id->dma_mword >> 8) & 7) ? ide_dma_on : - ((id->dma_1word >> 8) & 7) ? ide_dma_on : - ide_dma_off_quietly); -} - -static void config_drive_art_rwp (ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - - byte timing, pio, drive_pci, test1, test2; - - unsigned short eide_pio_timing[6] = {600, 390, 240, 180, 120, 90}; - unsigned short xfer_pio = drive->id->eide_pio_modes; - int drive_number = ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01)); - - if (drive->media == ide_disk) { - struct pci_dev *dev = hwif->pci_dev; - byte reg4bh = 0; - byte rw_prefetch = (0x11 << drive_number); - - pci_read_config_byte(dev, 0x4b, ®4bh); - if ((reg4bh & rw_prefetch) != rw_prefetch) - pci_write_config_byte(dev, 0x4b, reg4bh|rw_prefetch); - } - - pio = ide_get_best_pio_mode(drive, 255, 5, NULL); - - if (xfer_pio> 4) - xfer_pio = 0; - - if (drive->id->eide_pio_iordy > 0) { - for (xfer_pio = 5; - xfer_pio>0 && - drive->id->eide_pio_iordy>eide_pio_timing[xfer_pio]; - xfer_pio--); - } else { - xfer_pio = (drive->id->eide_pio_modes & 4) ? 0x05 : - (drive->id->eide_pio_modes & 2) ? 0x04 : - (drive->id->eide_pio_modes & 1) ? 0x03 : xfer_pio; - } - - timing = (xfer_pio >= pio) ? xfer_pio : pio; - -/* - * Mode 0 Mode 1 Mode 2 Mode 3 Mode 4 - * Active time 8T (240ns) 6T (180ns) 4T (120ns) 3T (90ns) 3T (90ns) - * 0x41 2:0 bits 000 110 100 011 011 - * Recovery time 12T (360ns) 7T (210ns) 4T (120ns) 3T (90ns) 1T (30ns) - * 0x40 3:0 bits 0000 0111 0100 0011 0001 - * Cycle time 20T (600ns) 13T (390ns) 8T (240ns) 6T (180ns) 4T (120ns) - */ - - switch(drive_number) { - case 0: drive_pci = 0x40;break; - case 1: drive_pci = 0x42;break; - case 2: drive_pci = 0x44;break; - case 3: drive_pci = 0x46;break; - default: return; - } - - pci_read_config_byte(dev, drive_pci, &test1); - pci_read_config_byte(dev, drive_pci|0x01, &test2); - - /* - * Do a blanket clear of active and recovery timings. - */ - - test1 &= ~0x07; - test2 &= ~0x0F; - - switch(timing) { - case 4: test1 |= 0x01;test2 |= 0x03;break; - case 3: test1 |= 0x03;test2 |= 0x03;break; - case 2: test1 |= 0x04;test2 |= 0x04;break; - case 1: test1 |= 0x07;test2 |= 0x06;break; - default: break; - } - - pci_write_config_byte(dev, drive_pci, test1); - pci_write_config_byte(dev, drive_pci|0x01, test2); -} - -static int config_drive_xfer_rate (ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - ide_dma_action_t dma_func = ide_dma_off_quietly; - - if (id && (id->capability & 1) && HWIF(drive)->autodma) { - /* Consult the list of known "bad" drives */ - if (ide_dmaproc(ide_dma_bad_drive, drive)) { - return HWIF(drive)->dmaproc(ide_dma_off, drive); - } - - if (id->field_valid & 4) { - if (id->dma_ultra & 0x001F) { - /* Force if Capable UltraDMA */ - dma_func = config_chipset_for_dma(drive, 1); - if ((id->field_valid & 2) && - (dma_func != ide_dma_on)) - goto try_dma_modes; - } - } else if (id->field_valid & 2) { -try_dma_modes: - if ((id->dma_mword & 0x0007) || - (id->dma_1word & 0x0007)) { - /* Force if Capable regular DMA modes */ - dma_func = config_chipset_for_dma(drive, 0); - } - } else if ((ide_dmaproc(ide_dma_good_drive, drive)) && - (id->eide_dma_time > 150)) { - /* Consult the list of known "good" drives */ - dma_func = config_chipset_for_dma(drive, 0); - } - } - return HWIF(drive)->dmaproc(dma_func, drive); -} - -/* - * sis5513_dmaproc() initiates/aborts (U)DMA read/write operations on a drive. - */ -int sis5513_dmaproc (ide_dma_action_t func, ide_drive_t *drive) -{ - switch (func) { - case ide_dma_check: - config_drive_art_rwp(drive); - return config_drive_xfer_rate(drive); - default: - break; - } - return ide_dmaproc(func, drive); /* use standard DMA stuff */ -} - -unsigned int __init pci_init_sis5513 (struct pci_dev *dev, const char *name) -{ - struct pci_dev *host; - int i = 0; - byte latency = 0; - - pci_read_config_byte(dev, PCI_LATENCY_TIMER, &latency); - - for (i = 0; i < arraysize (SiSHostChipInfo) && !host_dev; i++) { - host = pci_find_device (PCI_VENDOR_ID_SI, - SiSHostChipInfo[i].host_id, - NULL); - if (!host) - continue; - - host_dev = host; - printk(SiSHostChipInfo[i].name); - printk("\n"); - if (SiSHostChipInfo[i].flags & SIS5513_FLAG_LATENCY) { - if (latency != 0x10) - pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x10); - } - } - - if (host_dev) { - byte reg52h = 0; - - pci_read_config_byte(dev, 0x52, ®52h); - if (!(reg52h & 0x04)) { - /* set IDE controller to operate in Compabitility mode obly */ - pci_write_config_byte(dev, 0x52, reg52h|0x04); - } -#if defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS) - sis_proc = 1; - bmide_dev = dev; - sis_display_info = &sis_get_info; -#endif /* defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS) */ - } - return 0; -} - -unsigned int __init ata66_sis5513 (ide_hwif_t *hwif) -{ - byte reg48h = 0, ata66 = 0; - byte mask = hwif->channel ? 0x20 : 0x10; - pci_read_config_byte(hwif->pci_dev, 0x48, ®48h); - - if (host_dev) { - switch(host_dev->device) { - case PCI_DEVICE_ID_SI_530: - case PCI_DEVICE_ID_SI_540: - case PCI_DEVICE_ID_SI_620: - case PCI_DEVICE_ID_SI_630: - ata66 = (reg48h & mask) ? 0 : 1; - default: - break; - } - } - return (ata66); -} - -void __init ide_init_sis5513 (ide_hwif_t *hwif) -{ - - hwif->irq = hwif->channel ? 15 : 14; - - if (!(hwif->dma_base)) - return; - - if (host_dev) { - switch(host_dev->device) { - case PCI_DEVICE_ID_SI_530: - case PCI_DEVICE_ID_SI_540: - case PCI_DEVICE_ID_SI_620: - case PCI_DEVICE_ID_SI_630: - case PCI_DEVICE_ID_SI_5600: - case PCI_DEVICE_ID_SI_5597: - case PCI_DEVICE_ID_SI_5591: - hwif->autodma = 1; - hwif->dmaproc = &sis5513_dmaproc; - break; - default: - hwif->autodma = 0; - break; - } - } - return; -} diff --git a/drivers/block/sl82c105.c b/drivers/block/sl82c105.c deleted file mode 100644 index 483a98fde..000000000 --- a/drivers/block/sl82c105.c +++ /dev/null @@ -1,138 +0,0 @@ -/* - * linux/drivers/block/sl82c105.c - * - * SL82C105/Winbond 553 IDE driver - * - * Maintainer unknown. - * - * Drive tuning added from Rebel.com's kernel sources - * -- Russell King (15/11/98) linux@arm.linux.org.uk - */ - -#include <linux/config.h> -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/timer.h> -#include <linux/mm.h> -#include <linux/ioport.h> -#include <linux/interrupt.h> -#include <linux/blkdev.h> -#include <linux/hdreg.h> -#include <linux/pci.h> -#include <linux/ide.h> - -#include <asm/io.h> -#include <asm/dma.h> - -#include "ide_modes.h" - -extern char *ide_xfer_verbose (byte xfer_rate); - -#ifdef CONFIG_ARCH_NETWINDER -/* - * Convert a PIO mode and cycle time to the required on/off - * times for the interface. This has protection against run-away - * timings. - */ -static unsigned int get_timing_sl82c105(ide_pio_data_t *p) -{ - unsigned int cmd_on; - unsigned int cmd_off; - - cmd_on = (ide_pio_timings[p->pio_mode].active_time + 29) / 30; - cmd_off = (p->cycle_time - 30 * cmd_on + 29) / 30; - - if (cmd_on > 32) - cmd_on = 32; - if (cmd_on == 0) - cmd_on = 1; - - if (cmd_off > 32) - cmd_off = 32; - if (cmd_off == 0) - cmd_off = 1; - - return (cmd_on - 1) << 8 | (cmd_off - 1) | (p->use_iordy ? 0x40 : 0x00); -} - -/* - * We only deal with PIO mode here - DMA mode 'using_dma' is not - * initialised at the point that this function is called. - */ -static void tune_sl82c105(ide_drive_t *drive, byte pio) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - ide_pio_data_t p; - unsigned short drv_ctrl = 0x909; - unsigned int xfer_mode, reg; - - reg = (hwif->channel ? 0x4c : 0x44) + (drive->select.b.unit ? 4 : 0); - - pio = ide_get_best_pio_mode(drive, pio, 5, &p); - - switch (pio) { - default: - case 0: xfer_mode = XFER_PIO_0; break; - case 1: xfer_mode = XFER_PIO_1; break; - case 2: xfer_mode = XFER_PIO_2; break; - case 3: xfer_mode = XFER_PIO_3; break; - case 4: xfer_mode = XFER_PIO_4; break; - } - - if (ide_config_drive_speed(drive, xfer_mode) == 0) - drv_ctrl = get_timing_sl82c105(&p); - - pci_write_config_word(dev, reg, drv_ctrl); - pci_read_config_word(dev, reg, &drv_ctrl); - - printk("%s: selected %s (%dns) (%04X)\n", drive->name, - ide_xfer_verbose(xfer_mode), p.cycle_time, drv_ctrl); -} -#endif - -void ide_dmacapable_sl82c105(ide_hwif_t *hwif, unsigned long dmabase) -{ - unsigned char rev; - - pci_read_config_byte(hwif->pci_dev, PCI_REVISION_ID, &rev); - - if (rev <= 5) { - hwif->autodma = 0; - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - printk(" %s: revision %d, Bus-Master DMA disabled\n", - hwif->name, rev); - } - ide_setup_dma(hwif, dmabase, 8); -} - -void ide_init_sl82c105(ide_hwif_t *hwif) -{ - struct pci_dev *dev = hwif->pci_dev; - -#ifdef CONFIG_ARCH_NETWINDER - unsigned char ctrl_stat; - - pci_read_config_byte(dev, 0x40, &ctrl_stat); - pci_write_config_byte(dev, 0x40, ctrl_stat | 0x33); - - hwif->tuneproc = tune_sl82c105; -#else - unsigned short t16; - unsigned int t32; - pci_read_config_word(dev, PCI_COMMAND, &t16); - printk("SL82C105 command word: %x\n",t16); - t16 |= PCI_COMMAND_IO; - pci_write_config_word(dev, PCI_COMMAND, t16); - /* IDE timing */ - pci_read_config_dword(dev, 0x44, &t32); - printk("IDE timing: %08x, resetting to PIO0 timing\n",t32); - pci_write_config_dword(dev, 0x44, 0x03e4); -#ifndef CONFIG_MBX - pci_read_config_dword(dev, 0x40, &t32); - printk("IDE control/status register: %08x\n",t32); - pci_write_config_dword(dev, 0x40, 0x10ff08a1); -#endif /* CONFIG_MBX */ -#endif -} diff --git a/drivers/block/trm290.c b/drivers/block/trm290.c deleted file mode 100644 index fb5e8d1af..000000000 --- a/drivers/block/trm290.c +++ /dev/null @@ -1,282 +0,0 @@ -/* - * linux/drivers/block/trm290.c Version 1.01 December 5, 1997 - * - * Copyright (c) 1997-1998 Mark Lord - * May be copied or modified under the terms of the GNU General Public License - */ - -/* - * This module provides support for the bus-master IDE DMA function - * of the Tekram TRM290 chip, used on a variety of PCI IDE add-on boards, - * including a "Precision Instruments" board. The TRM290 pre-dates - * the sff-8038 standard (ide-dma.c) by a few months, and differs - * significantly enough to warrant separate routines for some functions, - * while re-using others from ide-dma.c. - * - * EXPERIMENTAL! It works for me (a sample of one). - * - * Works reliably for me in DMA mode (READs only), - * DMA WRITEs are disabled by default (see #define below); - * - * DMA is not enabled automatically for this chipset, - * but can be turned on manually (with "hdparm -d1") at run time. - * - * I need volunteers with "spare" drives for further testing - * and development, and maybe to help figure out the peculiarities. - * Even knowing the registers (below), some things behave strangely. - */ - -#define TRM290_NO_DMA_WRITES /* DMA writes seem unreliable sometimes */ - -/* - * TRM-290 PCI-IDE2 Bus Master Chip - * ================================ - * The configuration registers are addressed in normal I/O port space - * and are used as follows: - * - * trm290_base depends on jumper settings, and is probed for by ide-dma.c - * - * trm290_base+2 when WRITTEN: chiptest register (byte, write-only) - * bit7 must always be written as "1" - * bits6-2 undefined - * bit1 1=legacy_compatible_mode, 0=native_pci_mode - * bit0 1=test_mode, 0=normal(default) - * - * trm290_base+2 when READ: status register (byte, read-only) - * bits7-2 undefined - * bit1 channel0 busmaster interrupt status 0=none, 1=asserted - * bit0 channel0 interrupt status 0=none, 1=asserted - * - * trm290_base+3 Interrupt mask register - * bits7-5 undefined - * bit4 legacy_header: 1=present, 0=absent - * bit3 channel1 busmaster interrupt status 0=none, 1=asserted (read only) - * bit2 channel1 interrupt status 0=none, 1=asserted (read only) - * bit1 channel1 interrupt mask: 1=masked, 0=unmasked(default) - * bit0 channel0 interrupt mask: 1=masked, 0=unmasked(default) - * - * trm290_base+1 "CPR" Config Pointer Register (byte) - * bit7 1=autoincrement CPR bits 2-0 after each access of CDR - * bit6 1=min. 1 wait-state posted write cycle (default), 0=0 wait-state - * bit5 0=enabled master burst access (default), 1=disable (write only) - * bit4 PCI DEVSEL# timing select: 1=medium(default), 0=fast - * bit3 0=primary IDE channel, 1=secondary IDE channel - * bits2-0 register index for accesses through CDR port - * - * trm290_base+0 "CDR" Config Data Register (word) - * two sets of seven config registers, - * selected by CPR bit 3 (channel) and CPR bits 2-0 (index 0 to 6), - * each index defined below: - * - * Index-0 Base address register for command block (word) - * defaults: 0x1f0 for primary, 0x170 for secondary - * - * Index-1 general config register (byte) - * bit7 1=DMA enable, 0=DMA disable - * bit6 1=activate IDE_RESET, 0=no action (default) - * bit5 1=enable IORDY, 0=disable IORDY (default) - * bit4 0=16-bit data port(default), 1=8-bit (XT) data port - * bit3 interrupt polarity: 1=active_low, 0=active_high(default) - * bit2 power-saving-mode(?): 1=enable, 0=disable(default) (write only) - * bit1 bus_master_mode(?): 1=enable, 0=disable(default) - * bit0 enable_io_ports: 1=enable(default), 0=disable - * - * Index-2 read-ahead counter preload bits 0-7 (byte, write only) - * bits7-0 bits7-0 of readahead count - * - * Index-3 read-ahead config register (byte, write only) - * bit7 1=enable_readahead, 0=disable_readahead(default) - * bit6 1=clear_FIFO, 0=no_action - * bit5 undefined - * bit4 mode4 timing control: 1=enable, 0=disable(default) - * bit3 undefined - * bit2 undefined - * bits1-0 bits9-8 of read-ahead count - * - * Index-4 base address register for control block (word) - * defaults: 0x3f6 for primary, 0x376 for secondary - * - * Index-5 data port timings (shared by both drives) (byte) - * standard PCI "clk" (clock) counts, default value = 0xf5 - * - * bits7-6 setup time: 00=1clk, 01=2clk, 10=3clk, 11=4clk - * bits5-3 hold time: 000=1clk, 001=2clk, 010=3clk, - * 011=4clk, 100=5clk, 101=6clk, - * 110=8clk, 111=12clk - * bits2-0 active time: 000=2clk, 001=3clk, 010=4clk, - * 011=5clk, 100=6clk, 101=8clk, - * 110=12clk, 111=16clk - * - * Index-6 command/control port timings (shared by both drives) (byte) - * same layout as Index-5, default value = 0xde - * - * Suggested CDR programming for PIO mode0 (600ns): - * 0x01f0,0x21,0xff,0x80,0x03f6,0xf5,0xde ; primary - * 0x0170,0x21,0xff,0x80,0x0376,0xf5,0xde ; secondary - * - * Suggested CDR programming for PIO mode3 (180ns): - * 0x01f0,0x21,0xff,0x80,0x03f6,0x09,0xde ; primary - * 0x0170,0x21,0xff,0x80,0x0376,0x09,0xde ; secondary - * - * Suggested CDR programming for PIO mode4 (120ns): - * 0x01f0,0x21,0xff,0x80,0x03f6,0x00,0xde ; primary - * 0x0170,0x21,0xff,0x80,0x0376,0x00,0xde ; secondary - * - */ - -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/mm.h> -#include <linux/ioport.h> -#include <linux/interrupt.h> -#include <linux/blkdev.h> -#include <linux/init.h> -#include <linux/hdreg.h> -#include <linux/pci.h> -#include <linux/delay.h> -#include <linux/ide.h> - -#include <asm/io.h> - -static void trm290_prepare_drive (ide_drive_t *drive, unsigned int use_dma) -{ - ide_hwif_t *hwif = HWIF(drive); - unsigned int reg; - unsigned long flags; - - /* select PIO or DMA */ - reg = use_dma ? (0x21 | 0x82) : (0x21 & ~0x82); - - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ - - if (reg != hwif->select_data) { - hwif->select_data = reg; - outb(0x51|(hwif->channel<<3), hwif->config_data+1); /* set PIO/DMA */ - outw(reg & 0xff, hwif->config_data); - } - - /* enable IRQ if not probing */ - if (drive->present) { - reg = inw(hwif->config_data+3) & 0x13; - reg &= ~(1 << hwif->channel); - outw(reg, hwif->config_data+3); - } - - __restore_flags(flags); /* local CPU only */ -} - -static void trm290_selectproc (ide_drive_t *drive) -{ - trm290_prepare_drive(drive, drive->using_dma); -} - -static int trm290_dmaproc (ide_dma_action_t func, ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - unsigned int count, reading = 2, writing = 0; - - switch (func) { - case ide_dma_write: - reading = 0; - writing = 1; -#ifdef TRM290_NO_DMA_WRITES - break; /* always use PIO for writes */ -#endif - case ide_dma_read: - if (!(count = ide_build_dmatable(drive, func))) - break; /* try PIO instead of DMA */ - trm290_prepare_drive(drive, 1); /* select DMA xfer */ - outl(hwif->dmatable_dma|reading|writing, hwif->dma_base); - drive->waiting_for_dma = 1; - outw((count * 2) - 1, hwif->dma_base+2); /* start DMA */ - if (drive->media != ide_disk) - return 0; - ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL); - OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); - return 0; - case ide_dma_begin: - return 0; - case ide_dma_end: - drive->waiting_for_dma = 0; - ide_destroy_dmatable(drive); /* purge DMA mappings */ - return (inw(hwif->dma_base+2) != 0x00ff); - case ide_dma_test_irq: - return (inw(hwif->dma_base+2) == 0x00ff); - default: - return ide_dmaproc(func, drive); - } - trm290_prepare_drive(drive, 0); /* select PIO xfer */ - return 1; -} - -/* - * Invoked from ide-dma.c at boot time. - */ -void __init ide_init_trm290 (ide_hwif_t *hwif) -{ - unsigned int cfgbase = 0; - unsigned long flags; - byte reg; - struct pci_dev *dev = hwif->pci_dev; - - hwif->chipset = ide_trm290; - cfgbase = dev->resource[4].start; - if ((dev->class & 5) && cfgbase) - { - hwif->config_data = cfgbase & PCI_BASE_ADDRESS_IO_MASK; - printk("TRM290: chip config base at 0x%04lx\n", hwif->config_data); - } else { - hwif->config_data = 0x3df0; - printk("TRM290: using default config base at 0x%04lx\n", hwif->config_data); - } - - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ - /* put config reg into first byte of hwif->select_data */ - outb(0x51|(hwif->channel<<3), hwif->config_data+1); - hwif->select_data = 0x21; /* select PIO as default */ - outb(hwif->select_data, hwif->config_data); - reg = inb(hwif->config_data+3); /* get IRQ info */ - reg = (reg & 0x10) | 0x03; /* mask IRQs for both ports */ - outb(reg, hwif->config_data+3); - __restore_flags(flags); /* local CPU only */ - - if ((reg & 0x10)) - hwif->irq = hwif->channel ? 15 : 14; /* legacy mode */ - else if (!hwif->irq && hwif->mate && hwif->mate->irq) - hwif->irq = hwif->mate->irq; /* sharing IRQ with mate */ - ide_setup_dma(hwif, (hwif->config_data + 4) ^ (hwif->channel ? 0x0080 : 0x0000), 3); - hwif->dmaproc = &trm290_dmaproc; - hwif->selectproc = &trm290_selectproc; - hwif->autodma = 0; /* play it safe for now */ -#if 1 - { - /* - * My trm290-based card doesn't seem to work with all possible values - * for the control basereg, so this kludge ensures that we use only - * values that are known to work. Ugh. -ml - */ - unsigned short old, compat = hwif->channel ? 0x374 : 0x3f4; - static unsigned short next_offset = 0; - - outb(0x54|(hwif->channel<<3), hwif->config_data+1); - old = inw(hwif->config_data) & ~1; - if (old != compat && inb(old+2) == 0xff) { - compat += (next_offset += 0x400); /* leave lower 10 bits untouched */ -#if 1 - if (ide_check_region(compat + 2, 1)) - printk("Aieee %s: ide_check_region failure at 0x%04x\n", hwif->name, (compat + 2)); - /* - * The region check is not needed; however......... - * Since this is the checked in ide-probe.c, - * this is only an assignment. - */ -#endif - hwif->io_ports[IDE_CONTROL_OFFSET] = compat + 2; - outw(compat|1, hwif->config_data); - printk("%s: control basereg workaround: old=0x%04x, new=0x%04x\n", hwif->name, old, inw(hwif->config_data) & ~1); - } - } -#endif -} diff --git a/drivers/block/umc8672.c b/drivers/block/umc8672.c deleted file mode 100644 index 02b581a28..000000000 --- a/drivers/block/umc8672.c +++ /dev/null @@ -1,159 +0,0 @@ -/* - * linux/drivers/block/umc8672.c Version 0.05 Jul 31, 1996 - * - * Copyright (C) 1995-1996 Linus Torvalds & author (see below) - */ - -/* - * Principal Author/Maintainer: PODIEN@hml2.atlas.de (Wolfram Podien) - * - * This file provides support for the advanced features - * of the UMC 8672 IDE interface. - * - * Version 0.01 Initial version, hacked out of ide.c, - * and #include'd rather than compiled separately. - * This will get cleaned up in a subsequent release. - * - * Version 0.02 now configs/compiles separate from ide.c -ml - * Version 0.03 enhanced auto-tune, fix display bug - * Version 0.05 replace sti() with restore_flags() -ml - * add detection of possible race condition -ml - */ - -/* - * VLB Controller Support from - * Wolfram Podien - * Rohoefe 3 - * D28832 Achim - * Germany - * - * To enable UMC8672 support there must a lilo line like - * append="ide0=umc8672"... - * To set the speed according to the abilities of the hardware there must be a - * line like - * #define UMC_DRIVE0 11 - * in the beginning of the driver, which sets the speed of drive 0 to 11 (there - * are some lines present). 0 - 11 are allowed speed values. These values are - * the results from the DOS speed test program supplied from UMC. 11 is the - * highest speed (about PIO mode 3) - */ -#define REALLY_SLOW_IO /* some systems can safely undef this */ - -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/delay.h> -#include <linux/timer.h> -#include <linux/mm.h> -#include <linux/ioport.h> -#include <linux/blkdev.h> -#include <linux/hdreg.h> -#include <linux/ide.h> - -#include <asm/io.h> - -#include "ide_modes.h" - -/* - * Default speeds. These can be changed with "auto-tune" and/or hdparm. - */ -#define UMC_DRIVE0 1 /* DOS measured drive speeds */ -#define UMC_DRIVE1 1 /* 0 to 11 allowed */ -#define UMC_DRIVE2 1 /* 11 = Fastest Speed */ -#define UMC_DRIVE3 1 /* In case of crash reduce speed */ - -static byte current_speeds[4] = {UMC_DRIVE0, UMC_DRIVE1, UMC_DRIVE2, UMC_DRIVE3}; -static const byte pio_to_umc [5] = {0,3,7,10,11}; /* rough guesses */ - -/* 0 1 2 3 4 5 6 7 8 9 10 11 */ -static const byte speedtab [3][12] = { - {0xf, 0xb, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 }, - {0x3, 0x2, 0x2, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 }, - {0xff,0xcb,0xc0,0x58,0x36,0x33,0x23,0x22,0x21,0x11,0x10,0x0}}; - -static void out_umc (char port,char wert) -{ - outb_p (port,0x108); - outb_p (wert,0x109); -} - -static inline byte in_umc (char port) -{ - outb_p (port,0x108); - return inb_p (0x109); -} - -static void umc_set_speeds (byte speeds[]) -{ - int i, tmp; - - outb_p (0x5A,0x108); /* enable umc */ - - out_umc (0xd7,(speedtab[0][speeds[2]] | (speedtab[0][speeds[3]]<<4))); - out_umc (0xd6,(speedtab[0][speeds[0]] | (speedtab[0][speeds[1]]<<4))); - tmp = 0; - for (i = 3; i >= 0; i--) - { - tmp = (tmp << 2) | speedtab[1][speeds[i]]; - } - out_umc (0xdc,tmp); - for (i = 0;i < 4; i++) - { - out_umc (0xd0+i,speedtab[2][speeds[i]]); - out_umc (0xd8+i,speedtab[2][speeds[i]]); - } - outb_p (0xa5,0x108); /* disable umc */ - - printk ("umc8672: drive speeds [0 to 11]: %d %d %d %d\n", - speeds[0], speeds[1], speeds[2], speeds[3]); -} - -static void tune_umc (ide_drive_t *drive, byte pio) -{ - unsigned long flags; - ide_hwgroup_t *hwgroup = ide_hwifs[HWIF(drive)->index^1].hwgroup; - - pio = ide_get_best_pio_mode(drive, pio, 4, NULL); - printk("%s: setting umc8672 to PIO mode%d (speed %d)\n", drive->name, pio, pio_to_umc[pio]); - save_flags(flags); /* all CPUs */ - cli(); /* all CPUs */ - if (hwgroup && hwgroup->handler != NULL) { - printk("umc8672: other interface is busy: exiting tune_umc()\n"); - } else { - current_speeds[drive->name[2] - 'a'] = pio_to_umc[pio]; - umc_set_speeds (current_speeds); - } - restore_flags(flags); /* all CPUs */ -} - -void __init init_umc8672 (void) /* called from ide.c */ -{ - unsigned long flags; - - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ - if (check_region(0x108, 2)) { - __restore_flags(flags); - printk("\numc8672: PORTS 0x108-0x109 ALREADY IN USE\n"); - return; - } - outb_p (0x5A,0x108); /* enable umc */ - if (in_umc (0xd5) != 0xa0) - { - __restore_flags(flags); /* local CPU only */ - printk ("umc8672: not found\n"); - return; - } - outb_p (0xa5,0x108); /* disable umc */ - - umc_set_speeds (current_speeds); - __restore_flags(flags); /* local CPU only */ - - request_region(0x108, 2, "umc8672"); - ide_hwifs[0].chipset = ide_umc8672; - ide_hwifs[1].chipset = ide_umc8672; - ide_hwifs[0].tuneproc = &tune_umc; - ide_hwifs[1].tuneproc = &tune_umc; - ide_hwifs[0].mate = &ide_hwifs[1]; - ide_hwifs[1].mate = &ide_hwifs[0]; - ide_hwifs[1].channel = 1; -} diff --git a/drivers/block/via82cxxx.c b/drivers/block/via82cxxx.c deleted file mode 100644 index c2ec24d39..000000000 --- a/drivers/block/via82cxxx.c +++ /dev/null @@ -1,834 +0,0 @@ -/* - * linux/drivers/block/via82cxxx.c Version 0.07 Feb. 10, 2000 - * - * Copyright (C) 1998-99 Michel Aubry, Maintainer - * Copyright (C) 1999 Jeff Garzik, MVP4 Support - * (jgarzik@mandrakesoft.com) - * Copyright (C) 1998-2000 Andre Hedrick (andre@suse.com) - * May be copied or modified under the terms of the GNU General Public License - * - * The VIA MVP-4 is reported OK with UDMA. - * The VIA MVP-3 is reported OK with UDMA. - * The TX Pro III is also reported OK with UDMA. - * - * VIA chips also have a single FIFO, with the same 64 bytes deep - * buffer (16 levels of 4 bytes each). - * - * However, VIA chips can have the buffer split either 8:8 levels, - * 16:0 levels or 0:16 levels between both channels. One could think - * of using this feature, as even if no level of FIFO is given to a - * given channel, one can for instance always reach ATAPI drives through - * it, or, if one channel is unused, configuration defaults to - * an even split FIFO levels. - * - * This feature is available only through a kernel command line : - * "splitfifo=Chan,Thr0,Thr1" or "splitfifo=Chan". - * where: Chan =1,2,3 or 4 and Thrx = 1,2,3,or 4. - * - * If Chan == 1: - * gives all the fifo to channel 0, - * sets its threshold to Thr0/4, - * and disables any dma access to channel 1. - * - * If chan == 2: - * gives all the fifo to channel 1, - * sets its threshold to Thr1/4, - * and disables any dma access to channel 0. - * - * If chan == 3 or 4: - * shares evenly fifo between channels, - * gives channel 0 a threshold of Thr0/4, - * and channel 1 a threshold of Thr1/4. - * - * Note that by default (if no command line is provided) and if a channel - * has been disabled in Bios, all the fifo is given to the active channel, - * and its threshold is set to 3/4. - * - * VT82c586B - * - * Offset 4B-48 - Drive Timing Control - * | pio0 | pio1 | pio2 | pio3 | pio4 - * 25.0 MHz | 0xA8 | 0x65 | 0x65 | 0x31 | 0x20 - * 33.0 MHz | 0xA8 | 0x65 | 0x65 | 0x31 | 0x20 - * 37.5 MHz | 0xA9 | 0x76 | 0x76 | 0x32 | 0x21 - * - * Offset 53-50 - UltraDMA Extended Timing Control - * UDMA | NO | 0 | 1 | 2 - * | 0x03 | 0x62 | 0x61 | 0x60 - * - * VT82c596B & VT82c686A - * - * Offset 4B-48 - Drive Timing Control - * | pio0 | pio1 | pio2 | pio3 | pio4 - * 25.0 MHz | 0xA8 | 0x65 | 0x65 | 0x31 | 0x20 - * 33.0 MHz | 0xA8 | 0x65 | 0x65 | 0x31 | 0x20 - * 37.5 MHz | 0xDB | 0x87 | 0x87 | 0x42 | 0x31 - * 41.5 MHz | 0xFE | 0xA8 | 0xA8 | 0x53 | 0x32 - * - * Offset 53-50 - UltraDMA Extended Timing Control - * UDMA | NO | 0 | 1 | 2 - * 33.0 MHz | 0x03 | 0xE2 | 0xE1 | 0xE0 - * 37.5 MHz | 0x03 | 0xE2 | 0xE2 | 0xE1 (1) - * - * Offset 53-50 - UltraDMA Extended Timing Control - * UDMA | NO | 0 | 1 | 2 | 3 | 4 - * 33.0 MHz | (2) | 0xE6 | 0xE4 | 0xE2 | 0xE1 | 0xE0 - * 37.5 MHz | (2) | 0xE6 | 0xE6 | 0xE4 | 0xE2 | 0xE1 (1) - * - */ - -#include <linux/config.h> -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/timer.h> -#include <linux/mm.h> -#include <linux/ioport.h> -#include <linux/interrupt.h> -#include <linux/blkdev.h> -#include <linux/hdreg.h> -#include <linux/pci.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/ide.h> - -#include <asm/io.h> - -static struct pci_dev *host_dev = NULL; -static struct pci_dev *isa_dev = NULL; - -static const struct { - const char *name; - unsigned short host_id; -} ApolloHostChipInfo[] = { - { "VT 82C585 Apollo VP1/VPX", PCI_DEVICE_ID_VIA_82C585, }, - { "VT 82C595 Apollo VP2", PCI_DEVICE_ID_VIA_82C595, }, - { "VT 82C597 Apollo VP3", PCI_DEVICE_ID_VIA_82C597_0, }, - { "VT 82C598 Apollo MVP3", PCI_DEVICE_ID_VIA_82C598_0, }, - { "VT 82C680 Apollo P6", PCI_DEVICE_ID_VIA_82C680, }, - { "VT 82C691 Apollo Pro", PCI_DEVICE_ID_VIA_82C691, }, - { "VT 82C693 Apollo Pro Plus", PCI_DEVICE_ID_VIA_82C693, }, - { "Apollo MVP4", PCI_DEVICE_ID_VIA_8501_0, }, - { "VT 8371", PCI_DEVICE_ID_VIA_8371_0, }, - { "VT 8601", PCI_DEVICE_ID_VIA_8601_0, }, -}; - -#define NUM_APOLLO_ISA_CHIP_DEVICES 2 -#define VIA_FLAG_CHECK_REV 0x00000001 -#define VIA_FLAG_ATA_66 0x00000002 - -static const struct { - unsigned short host_id; - unsigned short isa_id; - unsigned int flags; -} ApolloISAChipInfo[] = { - { PCI_DEVICE_ID_VIA_82C585, PCI_DEVICE_ID_VIA_82C586_1, VIA_FLAG_CHECK_REV }, - { PCI_DEVICE_ID_VIA_82C595, PCI_DEVICE_ID_VIA_82C586_1, VIA_FLAG_CHECK_REV }, - { PCI_DEVICE_ID_VIA_82C597_0, PCI_DEVICE_ID_VIA_82C586_1, VIA_FLAG_CHECK_REV }, - { PCI_DEVICE_ID_VIA_82C598_0, PCI_DEVICE_ID_VIA_82C586_1, VIA_FLAG_CHECK_REV }, - { PCI_DEVICE_ID_VIA_82C598_0, PCI_DEVICE_ID_VIA_82C596, 0 }, - { PCI_DEVICE_ID_VIA_82C680, PCI_DEVICE_ID_VIA_82C586_1, VIA_FLAG_CHECK_REV }, - { PCI_DEVICE_ID_VIA_82C691, PCI_DEVICE_ID_VIA_82C596, 0 }, - { PCI_DEVICE_ID_VIA_82C693, PCI_DEVICE_ID_VIA_82C596, 0 }, - { PCI_DEVICE_ID_VIA_8501_0, PCI_DEVICE_ID_VIA_82C686, VIA_FLAG_ATA_66 }, - { PCI_DEVICE_ID_VIA_8371_0, PCI_DEVICE_ID_VIA_82C686, VIA_FLAG_ATA_66 }, - { PCI_DEVICE_ID_VIA_8601_0, PCI_DEVICE_ID_VIA_8231, VIA_FLAG_ATA_66 }, -}; - -#define arraysize(x) (sizeof(x)/sizeof(*(x))) - -#define DISPLAY_VIA_TIMINGS - -#if defined(DISPLAY_VIA_TIMINGS) && defined(CONFIG_PROC_FS) -#include <linux/stat.h> -#include <linux/proc_fs.h> - -static char *FIFO_str[] = { - " 1 ", - "3/4", - "1/2", - "1/4" -}; - -static char *control3_str[] = { - "No limitation", - "64", - "128", - "192" -}; - -static int via_get_info(char *, char **, off_t, int); -extern int (*via_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -static struct pci_dev *bmide_dev; - -static char * print_apollo_drive_config (char *buf, struct pci_dev *dev) -{ - int rc; - unsigned int time; - byte tm; - char *p = buf; - - /* Drive Timing Control */ - rc = pci_read_config_dword(dev, 0x48, &time); - p += sprintf(p, "Act Pls Width: %02d %02d %02d %02d\n", - ((time & 0xf0000000)>>28) + 1, - ((time & 0xf00000)>>20) + 1, - ((time & 0xf000)>>12) + 1, - ((time & 0xf0)>>4) + 1 ); - p += sprintf(p, "Recovery Time: %02d %02d %02d %02d\n", - ((time & 0x0f000000)>>24) + 1, - ((time & 0x0f0000)>>16) + 1, - ((time & 0x0f00)>>8) + 1, - (time & 0x0f) + 1 ); - - /* Address Setup Time */ - rc = pci_read_config_byte(dev, 0x4C, &tm); - p += sprintf(p, "Add. Setup T.: %01dT %01dT %01dT %01dT\n", - ((tm & 0xc0)>>6) + 1, - ((tm & 0x30)>>4) + 1, - ((tm & 0x0c)>>2) + 1, - (tm & 0x03) + 1 ); - - /* UltraDMA33 Extended Timing Control */ - rc = pci_read_config_dword(dev, 0x50, &time); - p += sprintf(p, "------------------UDMA-Timing-Control------------------------\n"); - p += sprintf(p, "Enable Meth.: %01d %01d %01d %01d\n", - (time & 0x80000000) ? 1 : 0, - (time & 0x800000) ? 1 : 0, - (time & 0x8000) ? 1 : 0, - (time & 0x80) ? 1 : 0 ); - p += sprintf(p, "Enable: %s %s %s %s\n", - (time & 0x40000000) ? "yes" : "no ", - (time & 0x400000) ? "yes" : "no ", - (time & 0x4000) ? "yes" : "no ", - (time & 0x40) ? "yes" : "no " ); - p += sprintf(p, "Transfer Mode: %s %s %s %s\n", - (time & 0x20000000) ? "PIO" : "DMA", - (time & 0x200000) ? "PIO" : "DMA", - (time & 0x2000) ? "PIO" : "DMA", - (time & 0x20) ? "PIO" : "DMA" ); - p += sprintf(p, "Cycle Time: %01dT %01dT %01dT %01dT\n", - ((time & 0x03000000)>>24) + 2, - ((time & 0x030000)>>16) + 2, - ((time & 0x0300)>>8) + 2, - (time & 0x03) + 2 ); - - return (char *)p; -} - -static char * print_apollo_ide_config (char *buf, struct pci_dev *dev) -{ - byte time, tmp; - unsigned short size0, size1; - int rc; - char *p = buf; - - rc = pci_read_config_byte(dev, 0x41, &time); - p += sprintf(p, "Prefetch Buffer : %s %s\n", - (time & 128) ? "on " : "off", - (time & 32) ? "on " : "off" ); - p += sprintf(p, "Post Write Buffer: %s %s\n", - (time & 64) ? "on " : "off", - (time & 16) ? "on " : "off" ); - - /* FIFO configuration */ - rc = pci_read_config_byte(dev, 0x43, &time); - tmp = ((time & 0x20)>>2) + ((time & 0x40)>>3); - p += sprintf(p, "FIFO Conf/Chan. : %02d %02d\n", - 16 - tmp, tmp); - tmp = (time & 0x0F)>>2; - p += sprintf(p, "Threshold Prim. : %s %s\n", - FIFO_str[tmp], - FIFO_str[time & 0x03] ); - - /* chipset Control3 */ - rc = pci_read_config_byte(dev, 0x46, &time); - p += sprintf(p, "Read DMA FIFO flush: %s %s\n", - (time & 0x80) ? "on " : "off", - (time & 0x40) ? "on " : "off" ); - p += sprintf(p, "End Sect. FIFO flush: %s %s\n", - (time & 0x20) ? "on " : "off", - (time & 0x10) ? "on " : "off" ); - p += sprintf(p, "Max DRDY Pulse Width: %s %s\n", - control3_str[(time & 0x03)], - (time & 0x03) ? "PCI clocks" : "" ); - - /* Primary and Secondary sector sizes */ - rc = pci_read_config_word(dev, 0x60, &size0); - rc = pci_read_config_word(dev, 0x68, &size1); - p += sprintf(p, "Bytes Per Sector: %03d %03d\n", - size0 & 0xfff, - size1 & 0xfff ); - - return (char *)p; -} - -static char * print_apollo_chipset_control1 (char *buf, struct pci_dev *dev) -{ - byte t; - int rc; - char *p = buf; - unsigned short c; - byte l, l_max; - - rc = pci_read_config_word(dev, 0x04, &c); - rc = pci_read_config_byte(dev, 0x44, &t); - rc = pci_read_config_byte(dev, 0x0d, &l); - rc = pci_read_config_byte(dev, 0x3f, &l_max); - - p += sprintf(p, "Command register = 0x%x\n", c); - p += sprintf(p, "Master Read Cycle IRDY %d Wait State\n", - (t & 64) >>6 ); - p += sprintf(p, "Master Write Cycle IRDY %d Wait State\n", - (t & 32) >> 5 ); - p += sprintf(p, "FIFO Output Data 1/2 Clock Advance: %s\n", - (t & 16) ? "on " : "off" ); - p += sprintf(p, "Bus Master IDE Status Register Read Retry: %s\n", - (t & 8) ? "on " : "off" ); - p += sprintf(p, "Latency timer = %d (max. = %d)\n", - l, l_max); - - return (char *)p; -} - -static char * print_apollo_chipset_control2 (char *buf, struct pci_dev *dev) -{ - byte t; - int rc; - char *p = buf; - rc = pci_read_config_byte(dev, 0x45, &t); - p += sprintf(p, "Interrupt Steering Swap: %s\n", - (t & 64) ? "on ":"off" ); - - return (char *)p; -} - -static char * print_apollo_chipset_control3 (char *buf, struct pci_dev *dev, - unsigned short n) -{ - /* - * at that point we can be sure that register 0x20 of the - * chipset contains the right address... - */ - unsigned int bibma; - int rc; - byte c0, c1; - char *p = buf; - - rc = pci_read_config_dword(dev, 0x20, &bibma); - bibma = (bibma & 0xfff0) ; - - /* - * at that point bibma+0x2 et bibma+0xa are byte registers - * to investigate: - */ - c0 = inb((unsigned short)bibma + 0x02); - c1 = inb((unsigned short)bibma + 0x0a); - - if (n == 0) { - /*p = sprintf(p,"--------------------Primary IDE------------Secondary IDE-----");*/ - p += sprintf(p, "both channels togth: %s %s\n", - (c0&0x80) ? "no" : "yes", - (c1&0x80) ? "no" : "yes" ); - } else { - /*p = sprintf(p,"--------------drive0------drive1-------drive0------drive1----");*/ - p += sprintf(p, "DMA enabled: %s %s %s %s\n", - (c0&0x20) ? "yes" : "no ", - (c0&0x40) ? "yes" : "no ", - (c1&0x20) ? "yes" : "no ", - (c1&0x40) ? "yes" : "no " ); - } - - return (char *)p; -} - -static int via_get_info (char *buffer, char **addr, off_t offset, int count) -{ - /* - * print what /proc/via displays, - * if required from DISPLAY_APOLLO_TIMINGS - */ - char *p = buffer; - /* Parameter of chipset : */ - - /* Miscellaneous control 1 */ - p = print_apollo_chipset_control1(buffer, bmide_dev); - - /* Miscellaneous control 2 */ - p = print_apollo_chipset_control2(p, bmide_dev); - /* Parameters of drives: */ - - /* Header */ - p += sprintf(p, "------------------Primary IDE------------Secondary IDE-----\n"); - p = print_apollo_chipset_control3(p, bmide_dev, 0); - p = print_apollo_ide_config(p, bmide_dev); - p += sprintf(p, "--------------drive0------drive1-------drive0------drive1----\n"); - p = print_apollo_chipset_control3(p, bmide_dev, 1); - p = print_apollo_drive_config(p, bmide_dev); - - return p-buffer; /* hoping it is less than 4K... */ -} - -#endif /* defined(DISPLAY_VIA_TIMINGS) && defined(CONFIG_PROC_FS) */ - -/* - * Used to set Fifo configuration via kernel command line: - */ - -byte via_proc = 0; -byte fifoconfig = 0; -static byte newfifo = 0; - -/* Used to just intialize once Fifo configuration */ -static short int done = 0; - -/* - * Set VIA Chipset Timings for (U)DMA modes enabled. - * - * VIA Apollo chipset has complete support for - * setting up the timing parameters. - */ -static void set_via_timings (ide_hwif_t *hwif) -{ - struct pci_dev *dev = hwif->pci_dev; - byte post = hwif->channel ? 0x30 : 0xc0; - byte flush = hwif->channel ? 0x50 : 0xa0; - int mask = hwif->channel ? ((newfifo & 0x60) ? 0 : 1) : - (((newfifo & 0x60) == 0x60) ? 1 : 0); - byte via_config = 0; - int rc = 0, errors = 0; - - printk("%s: VIA Bus-Master ", hwif->name); - - /* - * setting IDE read prefetch buffer and IDE post write buffer. - * (This feature allows prefetched reads and post writes). - */ - if ((rc = pci_read_config_byte(dev, 0x41, &via_config))) - errors++; - - if (mask) { - if ((rc = pci_write_config_byte(dev, 0x41, via_config & ~post))) - errors++; - } else { - if ((rc = pci_write_config_byte(dev, 0x41, via_config | post))) - errors++; - } - - /* - * setting Channel read and End-of-sector FIFO flush. - * (This feature ensures that FIFO flush is enabled: - * - for read DMA when interrupt asserts the given channel. - * - at the end of each sector for the given channel.) - */ - if ((rc = pci_read_config_byte(dev, 0x46, &via_config))) - errors++; - - if (mask) { - if ((rc = pci_write_config_byte(dev, 0x46, via_config & ~flush))) - errors++; - } else { - if ((rc = pci_write_config_byte(dev, 0x46, via_config | flush))) - errors++; - } - - if (!hwif->dma_base) - printk("Config %s. No DMA Enabled\n", - errors ? "ERROR":"Success"); - else - printk("(U)DMA Timing Config %s\n", - errors ? "ERROR" : "Success"); -} - -/* - * Sets VIA 82cxxx FIFO configuration: - * This chipsets gets a splitable fifo. This can be driven either by command - * line option (eg "splitfifo=2,2,3" which asks this driver to switch all the - * 16 fifo levels to the second drive, and give it a threshold of 3 for (u)dma - * triggering. - */ - -static int via_set_fifoconfig(ide_hwif_t *hwif) -{ - byte fifo; - unsigned int timings; - struct pci_dev *dev = hwif->pci_dev; - - /* read port configuration */ - if (pci_read_config_dword(dev, 0x40, &timings)) - return 1; - - /* first read actual fifo config: */ - if (pci_read_config_byte(dev, 0x43, &fifo)) - return 1; - - /* keep 4 and 7 bit as they seem to differ between chipsets flavors... */ - newfifo = fifo & 0x90; - - if (fifoconfig) { - /* we received a config request from kernel command line: */ - newfifo |= fifoconfig & 0x6f; - } else { - /* If ever just one channel is unused, allocate all fifo levels to it - * and give it a 3/4 threshold for (u)dma transfers. - * Otherwise, share it evenly between channels: - */ - if ((timings & 3) == 2) { - /* only primary channel is enabled - * 16 buf. to prim. chan. thresh=3/4 - */ - newfifo |= 0x06; - } else if ((timings & 3) == 1) { - /* only secondary channel is enabled! - * 16 buffers to sec. ch. thresh=3/4 - */ - newfifo |= 0x69; - } else { - /* fifo evenly distributed: */ - newfifo |= 0x2a; - } - } - - /* write resulting configuration to chipset: */ - if (pci_write_config_byte(dev, 0x43, newfifo)) - return 1; - - /* and then reread it to get the actual one */ - if (pci_read_config_byte(dev, 0x43, &newfifo)) - return 1; - - /* print a kernel report: */ - printk("Split FIFO Configuration: %s Primary buffers, threshold = %s\n", - ((newfifo & 0x60) == 0x60) ? " 0" : - ((newfifo & 0x60) ? " 8" : "16"), - !(newfifo & 0x0c) ? "1" : - (!(newfifo & 0x08) ? "3/4" : - (newfifo & 0x04) ? "1/4" : "1/2")); - - printk(" %s Second. buffers, threshold = %s\n", - ((newfifo & 0x60) == 0x60) ? "16" : - ((newfifo & 0x60) ? " 8" : " 0"), - !(newfifo & 0x03) ? "1" : - (!(newfifo & 0x02) ? "3/4" : - (newfifo & 0x01) ? "1/4" : "1/2")); - return 0; -} - -#ifdef CONFIG_VIA82CXXX_TUNING - -static int via82cxxx_tune_chipset (ide_drive_t *drive, byte speed) -{ - struct hd_driveid *id = drive->id; - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - unsigned long dma_base = hwif->dma_base; - byte unit = (drive->select.b.unit & 0x01); - int drive_number = ((hwif->channel ? 2 : 0) + unit); - - byte ata2_pci = 0x00; - byte ata3_pci = 0x00; - byte timing = 0x00; - byte ultra = 0x00; - int err; - - int bus_speed = ide_system_bus_speed(); - - switch(drive_number) { - case 0: ata2_pci = 0x48; ata3_pci = 0x50; break; - case 1: ata2_pci = 0x49; ata3_pci = 0x51; break; - case 2: ata2_pci = 0x4a; ata3_pci = 0x52; break; - case 3: ata2_pci = 0x4b; ata3_pci = 0x53; break; - default: - return err; - } - - pci_read_config_byte(dev, ata2_pci, &timing); - pci_read_config_byte(dev, ata3_pci, &ultra); - - switch(speed) { - case XFER_UDMA_4: - case XFER_UDMA_3: - case XFER_UDMA_2: - case XFER_UDMA_1: - case XFER_UDMA_0: - case XFER_MW_DMA_2: - case XFER_MW_DMA_1: - case XFER_MW_DMA_0: - case XFER_SW_DMA_2: - case XFER_SW_DMA_1: - case XFER_SW_DMA_0: - case XFER_PIO_4: - case XFER_PIO_3: - case XFER_PIO_2: - case XFER_PIO_1: - case XFER_PIO_0: - case XFER_PIO_SLOW: - default: - break; - } - - pci_write_config_byte(dev, ata2_pci, timing); - pci_write_config_byte(dev, ata3_pci, ultra); - - err = ide_config_drive_speed(drive, speed); - - return(err); -} - -static int config_chipset_for_dma (ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - byte speed = 0x00; - int rval; - - if ((id->dma_ultra & 0x0010) && (HWIF(drive)->udma_four)) { - speed = XFER_UDMA_4; - } else if ((id->dma_ultra & 0x0008) && (HWIF(drive)->udma_four)) { - speed = XFER_UDMA_3; - } else if (id->dma_ultra & 0x0004) { - speed = XFER_UDMA_2; - } else if (id->dma_ultra & 0x0002) { - speed = XFER_UDMA_1; - } else if (id->dma_ultra & 0x0001) { - speed = XFER_UDMA_0; - } else if (id->dma_mword & 0x0004) { - speed = XFER_MW_DMA_2; - } else if (id->dma_mword & 0x0002) { - speed = XFER_MW_DMA_1; - } else if (id->dma_mword & 0x0001) { - speed = XFER_MW_DMA_0; - } else if (id->dma_1word & 0x0004) { - speed = XFER_SW_DMA_2; - } else if (id->dma_1word & 0x0002) { - speed = XFER_SW_DMA_1; - } else if (id->dma_1word & 0x0001) { - speed = XFER_SW_DMA_0; - } else { - return ((int) ide_dma_off_quietly); - } - - (void) via82cxxx_tune_chipset(drive, speed); - - rval = (int)( ((id->dma_ultra >> 11) & 3) ? ide_dma_on : - ((id->dma_ultra >> 8) & 7) ? ide_dma_on : - ((id->dma_mword >> 8) & 7) ? ide_dma_on : - ((id->dma_1word >> 8) & 7) ? ide_dma_on : - ide_dma_off_quietly); - return rval; -} - -static void config_chipset_for_pio (ide_drive_t *drive) -{ - unsigned short eide_pio_timing[6] = {960, 480, 240, 180, 120, 90}; - unsigned short xfer_pio = drive->id->eide_pio_modes; - byte timing, speed, pio; - - pio = ide_get_best_pio_mode(drive, 255, 5, NULL); - - if (xfer_pio> 4) - xfer_pio = 0; - - if (drive->id->eide_pio_iordy > 0) { - for (xfer_pio = 5; - xfer_pio>0 && - drive->id->eide_pio_iordy>eide_pio_timing[xfer_pio]; - xfer_pio--); - } else { - xfer_pio = (drive->id->eide_pio_modes & 4) ? 0x05 : - (drive->id->eide_pio_modes & 2) ? 0x04 : - (drive->id->eide_pio_modes & 1) ? 0x03 : - (drive->id->tPIO & 2) ? 0x02 : - (drive->id->tPIO & 1) ? 0x01 : xfer_pio; - } - - timing = (xfer_pio >= pio) ? xfer_pio : pio; - - switch(timing) { - case 4: speed = XFER_PIO_4;break; - case 3: speed = XFER_PIO_3;break; - case 2: speed = XFER_PIO_2;break; - case 1: speed = XFER_PIO_1;break; - default: - speed = (!drive->id->tPIO) ? XFER_PIO_0 : XFER_PIO_SLOW; break; - } - (void) via82cxxx_tune_chipset(drive, speed); -} - -static void via82cxxx_tune_drive (ide_drive_t *drive, byte pio) -{ - byte speed; - switch(pio) { - case 4: speed = XFER_PIO_4;break; - case 3: speed = XFER_PIO_3;break; - case 2: speed = XFER_PIO_2;break; - case 1: speed = XFER_PIO_1;break; - default: speed = XFER_PIO_0;break; - } - (void) via82cxxx_tune_chipset(drive, speed); -} - -static int config_drive_xfer_rate (ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - ide_dma_action_t dma_func = ide_dma_on; - - if (id && (id->capability & 1) && HWIF(drive)->autodma) { - /* Consult the list of known "bad" drives */ - if (ide_dmaproc(ide_dma_bad_drive, drive)) { - dma_func = ide_dma_off; - goto fast_ata_pio; - } - dma_func = ide_dma_off_quietly; - if (id->field_valid & 4) { - if (id->dma_ultra & 0x001F) { - /* Force if Capable UltraDMA */ - dma_func = config_chipset_for_dma(drive); - if ((id->field_valid & 2) && - (dma_func != ide_dma_on)) - goto try_dma_modes; - } - } else if (id->field_valid & 2) { -try_dma_modes: - if ((id->dma_mword & 0x0007) || - (id->dma_1word & 0x0007)) { - /* Force if Capable regular DMA modes */ - dma_func = config_chipset_for_dma(drive); - if (dma_func != ide_dma_on) - goto no_dma_set; - } - } else if (ide_dmaproc(ide_dma_good_drive, drive)) { - if (id->eide_dma_time > 150) { - goto no_dma_set; - } - /* Consult the list of known "good" drives */ - dma_func = config_chipset_for_dma(drive); - if (dma_func != ide_dma_on) - goto no_dma_set; - } else { - goto fast_ata_pio; - } - } else if ((id->capability & 8) || (id->field_valid & 2)) { -fast_ata_pio: - dma_func = ide_dma_off_quietly; -no_dma_set: - config_chipset_for_pio(drive); - } - return HWIF(drive)->dmaproc(dma_func, drive); -} - -int via82cxxx_dmaproc (ide_dma_action_t func, ide_drive_t *drive) -{ - switch (func) { - case ide_dma_check: - return config_drive_xfer_rate(drive); - default: - break; - } - return ide_dmaproc(func, drive); /* use standard DMA stuff */ -} -#endif /* CONFIG_VIA82CXXX_TUNING */ - -unsigned int __init pci_init_via82cxxx (struct pci_dev *dev, const char *name) -{ - struct pci_dev *host; - struct pci_dev *isa; - int i, j, ata33, ata66; - - byte revision = 0; - - for (i = 0; i < arraysize (ApolloHostChipInfo) && !host_dev; i++) { - host = pci_find_device (PCI_VENDOR_ID_VIA, - ApolloHostChipInfo[i].host_id, - NULL); - if (!host) - continue; - - host_dev = host; - printk(ApolloHostChipInfo[i].name); - - for (j = 0; j < arraysize (ApolloISAChipInfo) && !isa_dev; j++) { - if (ApolloISAChipInfo[j].host_id != - ApolloHostChipInfo[i].host_id) - continue; - - isa = pci_find_device (PCI_VENDOR_ID_VIA, - ApolloISAChipInfo[j].isa_id, - NULL); - if (!isa) - continue; - - isa_dev = isa; - - ata33 = 1; - ata66 = 0; - - if (ApolloISAChipInfo[j].flags & VIA_FLAG_CHECK_REV) { - pci_read_config_byte(isa_dev, 0x0d, &revision); - ata33 = (revision >= 0x20) ? 1 : 0; - } else if (ApolloISAChipInfo[j].flags & VIA_FLAG_ATA_66) { - ata33 = 0; - ata66 = 1; - } - - if (ata33 | ata66) - printk(" Chipset Core ATA-%s", ata66 ? "66" : "33"); - } - printk("\n"); - } - -#if defined(DISPLAY_VIA_TIMINGS) && defined(CONFIG_PROC_FS) - via_proc = 1; - bmide_dev = dev; - via_display_info = &via_get_info; -#endif /* DISPLAY_VIA_TIMINGS && CONFIG_PROC_FS*/ - - return 0; -} - -unsigned int __init ata66_via82cxxx (ide_hwif_t *hwif) -{ - /* (Jeff Garzik) FIXME!!! for MVP4 */ - return 0; -} - -void __init ide_init_via82cxxx (ide_hwif_t *hwif) -{ - set_via_timings(hwif); - -#ifdef CONFIG_VIA82CXXX_TUNING - hwif->tuneproc = &via82cxxx_tune_drive; - if (hwif->dma_base) { - hwif->dmaproc = &via82cxxx_dmaproc; - } else { - hwif->autodma = 0; - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - } -#endif /* CONFIG_VIA82CXXX_TUNING */ -} - -/* - * ide_dmacapable_via82cxxx(ide_hwif_t *, unsigned long) - * checks if channel "channel" of if hwif is dma - * capable or not, according to kernel command line, - * and the new fifo settings. - * It calls "ide_setup_dma" on capable mainboards, and - * bypasses the setup if not capable. - */ - -void ide_dmacapable_via82cxxx (ide_hwif_t *hwif, unsigned long dmabase) -{ - if (!done) { - via_set_fifoconfig(hwif); - done = 1; - } - - /* - * check if any fifo is available for requested port: - */ - if (((hwif->channel == 0) && ((newfifo & 0x60) == 0x60)) || - ((hwif->channel == 1) && ((newfifo & 0x60) == 0x00))) { - printk(" %s: VP_IDE Bus-Master DMA disabled (FIFO setting)\n", hwif->name); - } else { - ide_setup_dma(hwif, dmabase, 8); - } -} |