summaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-03-19 01:28:40 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-03-19 01:28:40 +0000
commit8abb719409c9060a7c0676f76e9182c1e0b8ca46 (patch)
treeb88cc5a6cd513a04a512b7e6215c873c90a1c5dd /drivers/block
parentf01bd7aeafd95a08aafc9e3636bb26974df69d82 (diff)
Merge with 2.3.99-pre1.
Diffstat (limited to 'drivers/block')
-rw-r--r--drivers/block/Config.in209
-rw-r--r--drivers/block/DAC960.c10
-rw-r--r--drivers/block/Makefile216
-rw-r--r--drivers/block/aec6210.c372
-rw-r--r--drivers/block/ali14xx.c225
-rw-r--r--drivers/block/alim15x3.c689
-rw-r--r--drivers/block/amd7409.c411
-rw-r--r--drivers/block/blkpg.c7
-rw-r--r--drivers/block/buddha.c165
-rw-r--r--drivers/block/cmd640.c855
-rw-r--r--drivers/block/cmd64x.c721
-rw-r--r--drivers/block/cs5530.c361
-rw-r--r--drivers/block/cy82c693.c441
-rw-r--r--drivers/block/dtc2278.c133
-rw-r--r--drivers/block/elevator.c150
-rw-r--r--drivers/block/falconide.c66
-rw-r--r--drivers/block/gayle.c169
-rw-r--r--drivers/block/hd.c883
-rw-r--r--drivers/block/hpt34x.c419
-rw-r--r--drivers/block/hpt366.c564
-rw-r--r--drivers/block/ht6560b.c342
-rw-r--r--drivers/block/icside.c643
-rw-r--r--drivers/block/ide-cd.c2729
-rw-r--r--drivers/block/ide-cd.h736
-rw-r--r--drivers/block/ide-cs.c481
-rw-r--r--drivers/block/ide-disk.c906
-rw-r--r--drivers/block/ide-dma.c580
-rw-r--r--drivers/block/ide-features.c312
-rw-r--r--drivers/block/ide-floppy.c1680
-rw-r--r--drivers/block/ide-geometry.c214
-rw-r--r--drivers/block/ide-pci.c728
-rw-r--r--drivers/block/ide-pmac.c969
-rw-r--r--drivers/block/ide-pnp.c158
-rw-r--r--drivers/block/ide-probe.c929
-rw-r--r--drivers/block/ide-proc.c904
-rw-r--r--drivers/block/ide-tape.c6031
-rw-r--r--drivers/block/ide.c3637
-rw-r--r--drivers/block/ide_modes.h233
-rw-r--r--drivers/block/ll_rw_blk.c341
-rw-r--r--drivers/block/macide.c116
-rw-r--r--drivers/block/ns87415.c185
-rw-r--r--drivers/block/opti621.c315
-rw-r--r--drivers/block/pdc202xx.c731
-rw-r--r--drivers/block/pdc4030.c552
-rw-r--r--drivers/block/pdc4030.h44
-rw-r--r--drivers/block/piix.c434
-rw-r--r--drivers/block/q40ide.c109
-rw-r--r--drivers/block/qd6580.c71
-rw-r--r--drivers/block/rapide.c92
-rw-r--r--drivers/block/rz1000.c96
-rw-r--r--drivers/block/sis5513.c549
-rw-r--r--drivers/block/sl82c105.c138
-rw-r--r--drivers/block/trm290.c282
-rw-r--r--drivers/block/umc8672.c159
-rw-r--r--drivers/block/via82cxxx.c834
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, &reg54h);
-
- 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, &reg53h);
- p += sprintf(p, "PCI Clock: %d.\n", reg53h);
-
- pci_read_config_byte(bmide_dev, 0x53, &reg53h);
- 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, &reg53h);
- 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, &reg53h);
- 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, &reg53h);
- p += sprintf(p,
- "Channel state: %s %s\n",
- channel_status[reg53h & 0x07],
- channel_status[(reg53h & 0x70) >> 4] );
-
- pci_read_config_byte(bmide_dev, 0x58, &reg5xh);
- pci_read_config_byte(bmide_dev, 0x5c, &reg5yh);
- 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, &reg5xh);
- pci_read_config_byte(bmide_dev, 0x5d, &reg5yh);
- 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, &reg5xh);
- pci_read_config_byte(bmide_dev, 0x55, &reg5yh);
- 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, &reg5xh);
- pci_read_config_byte(bmide_dev, 0x5b, &reg5xh1);
- pci_read_config_byte(bmide_dev, 0x5e, &reg5yh);
- pci_read_config_byte(bmide_dev, 0x5f, &reg5yh1);
-
- 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, &reg5xh);
- pci_read_config_byte(bmide_dev, 0x57, &reg5yh);
- 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, &reg53);
- (void) pci_read_config_byte(bmide_dev, DRWTIM0, &reg54);
- (void) pci_read_config_byte(bmide_dev, ARTTIM1, &reg55);
- (void) pci_read_config_byte(bmide_dev, DRWTIM1, &reg56);
- (void) pci_read_config_byte(bmide_dev, ARTTIM2, &reg57);
- (void) pci_read_config_byte(bmide_dev, DRWTIM2, &reg58);
- (void) pci_read_config_byte(bmide_dev, DRWTIM3, &reg5b);
- (void) pci_read_config_byte(bmide_dev, BMIDESR0, &reg72);
- (void) pci_read_config_byte(bmide_dev, UDIDETCR0, &reg73);
- (void) pci_read_config_byte(bmide_dev, BMIDESR1, &reg7a);
- (void) pci_read_config_byte(bmide_dev, UDIDETCR1, &reg7b);
-
- 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, &reg72);
- (void) pci_read_config_byte(dev, UDIDETCR0, &reg73);
- (void) pci_read_config_byte(dev, BMIDESR1, &reg7a);
- (void) pci_read_config_byte(dev, UDIDETCR1, &reg7b);
-
- 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, &reg1);
- pci_read_config_dword(HWIF(drive)->pci_dev, 0x48, &reg2);
- 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, &reg1);
- pci_read_config_dword(HWIF(drive)->pci_dev, 0x48, &reg2);
- 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, &reg1);
- /* 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, &reg51h);
-
-#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, &reg50h);
- pci_write_config_byte(HWIF(drive)->pci_dev, 0x50, reg50h|0x03);
- pci_read_config_byte(HWIF(drive)->pci_dev, 0x50, &reg50h);
- /* 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, &reg40);
- * pci_read_config_word(HWIF(drive)->pci_dev, 0x42, &reg42);
- * pci_read_config_word(HWIF(drive)->pci_dev, 0x44, &reg44);
- * pci_read_config_word(HWIF(drive)->pci_dev, 0x48, &reg48);
- * pci_read_config_word(HWIF(drive)->pci_dev, 0x4a, &reg4a);
- * pci_read_config_word(HWIF(drive)->pci_dev, 0x54, &reg54);
- *
- * 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, &reg40);
- pci_read_config_word(bmide_dev, 0x42, &reg42);
- pci_read_config_byte(bmide_dev, 0x44, &reg44);
- pci_read_config_byte(bmide_dev, 0x48, &reg48);
- pci_read_config_byte(bmide_dev, 0x4a, &reg4a);
- pci_read_config_byte(bmide_dev, 0x4b, &reg4b);
- pci_read_config_byte(bmide_dev, 0x54, &reg54);
-
- 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, &reg4042);
- sitre = (reg4042 & 0x4000) ? 1 : 0;
- pci_read_config_word(dev, 0x44, &reg44);
- pci_read_config_word(dev, 0x48, &reg48);
- pci_read_config_word(dev, 0x4a, &reg4a);
- pci_read_config_word(dev, 0x54, &reg54);
-
- 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, &reg54h);
- pci_read_config_byte(hwif->pci_dev, 0x55, &reg55h);
- 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, &reg)
- && !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) && !(reg & PCI_COMMAND_IO)) {
- printk("%s: buggy IDE controller disabled (BIOS)\n", name);
- return;
- }
- if (!pci_read_config_word (dev, 0x40, &reg)
- && !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, &reg);
- 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, &reg);
- 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, &reg);
- 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, &reg2);
- rc = pci_read_config_word(bmide_dev, 0x4e, &reg3);
- p += sprintf(p, "Prefetch Count: %d \t \t \t \t %d\n",
- reg2, reg3);
-
- rc = pci_read_config_byte(bmide_dev, 0x4b, &reg);
- 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, &reg);
- rc = pci_read_config_byte(bmide_dev, 0x45, &reg1);
- 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, &reg);
- rc = pci_read_config_byte(bmide_dev, 0x44, &reg1);
- 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, &reg);
- 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, &reg);
- rc = pci_read_config_byte(bmide_dev, 0x47, &reg1);
- 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, &reg);
- rc = pci_read_config_byte(bmide_dev, 0x46, &reg1);
- 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, &reg4bh);
- 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, &reg52h);
- 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, &reg48h);
-
- 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);
- }
-}