summaryrefslogtreecommitdiff
path: root/i386/i386at/gpl/linux/block
diff options
context:
space:
mode:
Diffstat (limited to 'i386/i386at/gpl/linux/block')
-rw-r--r--i386/i386at/gpl/linux/block/cmd640.c738
-rw-r--r--i386/i386at/gpl/linux/block/floppy.c4100
-rw-r--r--i386/i386at/gpl/linux/block/genhd.c610
-rw-r--r--i386/i386at/gpl/linux/block/ide-cd.c2770
-rw-r--r--i386/i386at/gpl/linux/block/ide.c3087
-rw-r--r--i386/i386at/gpl/linux/block/ide.h655
-rw-r--r--i386/i386at/gpl/linux/block/ide_modes.h142
-rw-r--r--i386/i386at/gpl/linux/block/rz1000.c56
-rw-r--r--i386/i386at/gpl/linux/block/triton.c467
9 files changed, 0 insertions, 12625 deletions
diff --git a/i386/i386at/gpl/linux/block/cmd640.c b/i386/i386at/gpl/linux/block/cmd640.c
deleted file mode 100644
index 99a139d..0000000
--- a/i386/i386at/gpl/linux/block/cmd640.c
+++ /dev/null
@@ -1,738 +0,0 @@
-/*
- * linux/drivers/block/cmd640.c Version 0.07 Jan 27, 1996
- *
- * Copyright (C) 1995-1996 Linus Torvalds & author (see below)
- */
-
-/*
- * Principal Author/Maintainer: abramov@cecmow.enet.dec.com (Igor Abramov)
- *
- * This file provides support for the advanced features and bugs
- * of IDE interfaces using the CMD Technologies 0640 IDE interface chip.
- *
- * 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
- * read-ahead 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 read ahead mode. Separate function for setting
- * readahead is added, possibly it will be called some
- * day from ioctl processing code.
- *
- * Version 0.04 Now configs/compiles separate from ide.c -ml
- *
- * 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. Readahead is enabled only for
- * detected hard drives, not included in readahed
- * 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. -ml
- *
- */
-
-#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 <asm/io.h>
-#include "ide.h"
-#include "ide_modes.h"
-
-int cmd640_vlb = 0;
-
-/*
- * CMD640 specific registers definition.
- */
-
-#define VID 0x00
-#define DID 0x02
-#define PCMD 0x04
-#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 DIS_RA2 0x04
-#define DIS_RA3 0x08
-#define DRWTIM23 0x58
-#define BRST 0x59
-
-static ide_tuneproc_t cmd640_tune_drive;
-
-/* Interface to access cmd640x registers */
-static void (*put_cmd640_reg)(int reg_no, int val);
-static byte (*get_cmd640_reg)(int reg_no);
-
-enum { none, vlb, pci1, pci2 };
-static int bus_type = none;
-static int cmd640_chip_version;
-static int cmd640_key;
-static int bus_speed; /* MHz */
-
-/*
- * For some unknown reasons pcibios functions which read and write registers
- * do not always work with cmd640. We use direct IO instead.
- */
-
-/* PCI method 1 access */
-
-static void put_cmd640_reg_pci1(int reg_no, int val)
-{
- unsigned long flags;
-
- save_flags(flags);
- cli();
- outl_p((reg_no & 0xfc) | cmd640_key, 0xcf8);
- outb_p(val, (reg_no & 3) + 0xcfc);
- restore_flags(flags);
-}
-
-static byte get_cmd640_reg_pci1(int reg_no)
-{
- byte b;
- unsigned long flags;
-
- save_flags(flags);
- cli();
- outl_p((reg_no & 0xfc) | cmd640_key, 0xcf8);
- b = inb_p(0xcfc + (reg_no & 3));
- restore_flags(flags);
- return b;
-}
-
-/* PCI method 2 access (from CMD datasheet) */
-
-static void put_cmd640_reg_pci2(int reg_no, int val)
-{
- unsigned long flags;
-
- save_flags(flags);
- cli();
- outb_p(0x10, 0xcf8);
- outb_p(val, cmd640_key + reg_no);
- outb_p(0, 0xcf8);
- restore_flags(flags);
-}
-
-static byte get_cmd640_reg_pci2(int reg_no)
-{
- byte b;
- unsigned long flags;
-
- save_flags(flags);
- cli();
- outb_p(0x10, 0xcf8);
- b = inb_p(cmd640_key + reg_no);
- outb_p(0, 0xcf8);
- restore_flags(flags);
- return b;
-}
-
-/* VLB access */
-
-static void put_cmd640_reg_vlb(int reg_no, int val)
-{
- unsigned long flags;
-
- save_flags(flags);
- cli();
- outb_p(reg_no, cmd640_key + 8);
- outb_p(val, cmd640_key + 0xc);
- restore_flags(flags);
-}
-
-static byte get_cmd640_reg_vlb(int reg_no)
-{
- byte b;
- unsigned long flags;
-
- save_flags(flags);
- cli();
- outb_p(reg_no, cmd640_key + 8);
- b = inb_p(cmd640_key + 0xc);
- restore_flags(flags);
- return b;
-}
-
-/*
- * Probe for CMD640x -- pci method 1
- */
-
-static int probe_for_cmd640_pci1(void)
-{
- long id;
- int k;
-
- for (k = 0x80000000; k <= 0x8000f800; k += 0x800) {
- outl(k, 0xcf8);
- id = inl(0xcfc);
- if (id != 0x06401095)
- continue;
- put_cmd640_reg = put_cmd640_reg_pci1;
- get_cmd640_reg = get_cmd640_reg_pci1;
- cmd640_key = k;
- return 1;
- }
- return 0;
-}
-
-/*
- * Probe for CMD640x -- pci method 2
- */
-
-static int probe_for_cmd640_pci2(void)
-{
- int i;
- int v_id;
- int d_id;
-
- for (i = 0xc000; i <= 0xcf00; i += 0x100) {
- outb(0x10, 0xcf8);
- v_id = inw(i);
- d_id = inw(i + 2);
- outb(0, 0xcf8);
- if (v_id != 0x1095 || d_id != 0x640)
- continue;
- put_cmd640_reg = put_cmd640_reg_pci2;
- get_cmd640_reg = get_cmd640_reg_pci2;
- cmd640_key = i;
- return 1;
- }
- return 0;
-}
-
-/*
- * Probe for CMD640x -- vlb
- */
-
-static int probe_for_cmd640_vlb(void) {
- byte b;
-
- outb(CFR, 0x178);
- b = inb(0x17c);
- if (b == 0xff || b == 0 || (b & CFR_AT_VESA_078h)) {
- outb(CFR, 0x78);
- b = inb(0x7c);
- if (b == 0xff || b == 0 || !(b & CFR_AT_VESA_078h))
- return 0;
- cmd640_key = 0x70;
- } else {
- cmd640_key = 0x170;
- }
- put_cmd640_reg = put_cmd640_reg_vlb;
- get_cmd640_reg = get_cmd640_reg_vlb;
- return 1;
-}
-
-/*
- * Low level reset for controller, actually it has nothing specific for
- * CMD640, but I don't know how to use standard reset routine before
- * we recognized any drives.
- */
-
-static void cmd640_reset_controller(int iface_no)
-{
- int retry_count = 600;
- int base_port = iface_no ? 0x170 : 0x1f0;
-
- outb_p(4, base_port + 7);
- udelay(5);
- outb_p(0, base_port + 7);
-
- do {
- udelay(5);
- retry_count -= 1;
- } while ((inb_p(base_port + 7) & 0x80) && retry_count);
-
- if (retry_count == 0)
- printk("cmd640: failed to reset controller %d\n", iface_no);
-#if 0
- else
- printk("cmd640: controller %d reset [%d]\n",
- iface_no, retry_count);
-#endif
-}
-
-/*
- * Probe for Cmd640x and initialize it if found
- */
-
-int ide_probe_for_cmd640x(void)
-{
- int second_port;
- byte b;
-
- if (probe_for_cmd640_pci1()) {
- bus_type = pci1;
- } else if (probe_for_cmd640_pci2()) {
- bus_type = pci2;
- } else if (cmd640_vlb && probe_for_cmd640_vlb()) {
- /* May be remove cmd640_vlb at all, and probe in any case */
- bus_type = vlb;
- } else {
- return 0;
- }
-
- ide_hwifs[0].serialized = 1; /* ensure this *always* gets set */
-
-#if 0
- /* Dump initial state of chip registers */
- for (b = 0; b != 0xff; b++) {
- printk(" %2x%c", get_cmd640_reg(b),
- ((b&0xf) == 0xf) ? '\n' : ',');
- }
-
-#endif
-
- /*
- * Undocumented magic. (There is no 0x5b port in specs)
- */
-
- put_cmd640_reg(0x5b, 0xbd);
- if (get_cmd640_reg(0x5b) != 0xbd) {
- printk("ide: can't initialize cmd640 -- wrong value in 0x5b\n");
- return 0;
- }
- put_cmd640_reg(0x5b, 0);
-
- /*
- * Documented magic.
- */
-
- cmd640_chip_version = get_cmd640_reg(CFR) & CFR_DEVREV;
- if (cmd640_chip_version == 0) {
- printk ("ide: wrong CMD640 version -- 0\n");
- return 0;
- }
-
- /*
- * Setup the most conservative timings for all drives,
- */
- put_cmd640_reg(ARTTIM0, 0xc0);
- put_cmd640_reg(ARTTIM1, 0xc0);
- put_cmd640_reg(ARTTIM23, 0xcc); /* 0xc0? */
-
- /*
- * Do not initialize secondary controller for vlbus
- */
- second_port = (bus_type != vlb);
-
- /*
- * Set the maximum allowed bus speed (it is safest until we
- * find how to detect bus speed)
- * Normally PCI bus runs at 33MHz, but often works overclocked to 40
- */
- bus_speed = (bus_type == vlb) ? 50 : 40;
-
- /*
- * Setup Control Register
- */
- b = get_cmd640_reg(CNTRL);
-
- if (second_port)
- b |= CNTRL_ENA_2ND;
- else
- b &= ~CNTRL_ENA_2ND;
-
- /*
- * Disable readahead for drives at primary interface
- */
- b |= (CNTRL_DIS_RA0 | CNTRL_DIS_RA1);
-
- put_cmd640_reg(CNTRL, b);
-
- /*
- * Note that we assume that the first interface is at 0x1f0,
- * and that the second interface, if enabled, is at 0x170.
- */
- ide_hwifs[0].chipset = ide_cmd640;
- ide_hwifs[0].tuneproc = &cmd640_tune_drive;
- if (ide_hwifs[0].drives[0].autotune == 0)
- ide_hwifs[0].drives[0].autotune = 1;
- if (ide_hwifs[0].drives[1].autotune == 0)
- ide_hwifs[0].drives[1].autotune = 1;
-
- /*
- * Initialize 2nd IDE port, if required
- */
- if (second_port) {
- ide_hwifs[1].chipset = ide_cmd640;
- ide_hwifs[1].tuneproc = &cmd640_tune_drive;
- if (ide_hwifs[1].drives[0].autotune == 0)
- ide_hwifs[1].drives[0].autotune = 1;
- if (ide_hwifs[1].drives[1].autotune == 0)
- ide_hwifs[1].drives[1].autotune = 1;
- /* We reset timings, and disable read-ahead */
- put_cmd640_reg(ARTTIM23, (DIS_RA2 | DIS_RA3));
- put_cmd640_reg(DRWTIM23, 0);
-
- cmd640_reset_controller(1);
- }
-
- printk("ide: buggy CMD640%c interface at ",
- 'A' - 1 + cmd640_chip_version);
- switch (bus_type) {
- case vlb :
- printk("local bus, port 0x%x", cmd640_key);
- break;
- case pci1:
- printk("pci, (0x%x)", cmd640_key);
- break;
- case pci2:
- printk("pci,(access method 2) (0x%x)", cmd640_key);
- break;
- }
-
- /*
- * Reset interface timings
- */
- put_cmd640_reg(CMDTIM, 0);
-
- printk("\n ... serialized, secondary interface %s\n",
- second_port ? "enabled" : "disabled");
-
- return 1;
-}
-
-int cmd640_off(void) {
- static int a = 0;
- byte b;
-
- if (bus_type == none || a == 1)
- return 0;
- a = 1;
- b = get_cmd640_reg(CNTRL);
- b &= ~CNTRL_ENA_2ND;
- put_cmd640_reg(CNTRL, b);
- return 1;
-}
-
-/*
- * Sets readahead mode for specific drive
- * in the future it could be called from ioctl
- */
-
-static void set_readahead_mode(int mode, int if_num, int dr_num)
-{
- static int masks[2][2] =
- {
- {CNTRL_DIS_RA0, CNTRL_DIS_RA1},
- {DIS_RA2, DIS_RA3}
- };
-
- int port = (if_num == 0) ? CNTRL : ARTTIM23;
- int mask = masks[if_num][dr_num];
- byte b;
-
- b = get_cmd640_reg(port);
- if (mode)
- b &= ~mask; /* Enable readahead for specific drive */
- else
- b |= mask; /* Disable readahed for specific drive */
- put_cmd640_reg(port, b);
-}
-
-static struct readahead_black_list {
- const char* name;
- int mode;
-} drives_ra[] = {
- { "ST3655A", 0 },
- { "SAMSUNG", 0 }, /* Be conservative */
- { NULL, 0 }
-};
-
-static int strmatch(const char* pattern, const char* name) {
- char c1, c2;
-
- while (1) {
- c1 = *pattern++;
- c2 = *name++;
- if (c1 == 0) {
- return 0;
- }
- if (c1 != c2)
- return 1;
- }
-}
-
-static int known_drive_readahead(char* name) {
- int i;
-
- for (i = 0; drives_ra[i].name != NULL; i++) {
- if (strmatch(drives_ra[i].name, name) == 0) {
- return drives_ra[i].mode;
- }
- }
- return -1;
-}
-
-static int arttim[4] = {2, 2, 2, 2}; /* Address setup count (in clocks) */
-static int a_count[4] = {1, 1, 1, 1}; /* Active count (encoded) */
-static int r_count[4] = {1, 1, 1, 1}; /* Recovery count (encoded) */
-
-/*
- * Convert address setup count from number of clocks
- * to representation used by controller
- */
-
-inline static int pack_arttim(int clocks)
-{
- if (clocks <= 2) return 0x40;
- else if (clocks == 3) return 0x80;
- else if (clocks == 4) return 0x00;
- else return 0xc0;
-}
-
-/*
- * Pack active and recovery counts into single byte representation
- * used by controller
- */
-
-inline static int pack_counts(int act_count, int rec_count)
-{
- return ((act_count & 0x0f)<<4) | (rec_count & 0x0f);
-}
-
-inline int max(int a, int b) { return a > b ? a : b; }
-inline int max4(int *p) { return max(p[0], max(p[1], max(p[2], p[3]))); }
-
-/*
- * Set timing parameters
- */
-
-static void cmd640_set_timing(int if_num, int dr_num)
-{
- int b_reg;
- int ac, rc, at;
-
- /*
- * Set address setup count and drive read/write timing registers.
- * Primary interface has individual count/timing registers for
- * each drive. Secondary interface has common set of registers, and
- * we should set timings for the slowest drive.
- */
-
- if (if_num == 0) {
- b_reg = dr_num ? ARTTIM1 : ARTTIM0;
- at = arttim[dr_num];
- ac = a_count[dr_num];
- rc = r_count[dr_num];
- } else {
- b_reg = ARTTIM23;
- at = max(arttim[2], arttim[3]);
- ac = max(a_count[2], a_count[3]);
- rc = max(r_count[2], r_count[3]);
- }
-
- put_cmd640_reg(b_reg, pack_arttim(at));
- put_cmd640_reg(b_reg + 1, pack_counts(ac, rc));
-
- /*
- * Update CMDTIM (IDE Command Block Timing Register)
- */
-
- ac = max4(r_count);
- rc = max4(a_count);
- put_cmd640_reg(CMDTIM, pack_counts(ac, rc));
-}
-
-/*
- * Standard timings for PIO modes
- */
-
-static struct pio_timing {
- int mc_time; /* Minimal cycle time (ns) */
- int av_time; /* Address valid to DIOR-/DIOW- setup (ns) */
- int ds_time; /* DIOR data setup (ns) */
-} 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 */
- { 25, 70, 125 }, /* PIO Mode 4 -- should be 120, not 125 */
- { 20, 50, 100 } /* PIO Mode ? (nonstandard) */
-};
-
-static void cmd640_timings_to_clocks(int mc_time, int av_time, int ds_time,
- int clock_time, int drv_idx)
-{
- int a, b;
-
- arttim[drv_idx] = (mc_time + clock_time - 1)/clock_time;
-
- a = (av_time + clock_time - 1)/clock_time;
- if (a < 2)
- a = 2;
- b = (ds_time + clock_time - 1)/clock_time - a;
- if (b < 2)
- b = 2;
- if (b > 0x11) {
- a += b - 0x11;
- b = 0x11;
- }
- if (a > 0x10)
- a = 0x10;
- if (cmd640_chip_version > 1)
- b -= 1;
- if (b > 0x10)
- b = 0x10;
-
- a_count[drv_idx] = a;
- r_count[drv_idx] = b;
-}
-
-static void set_pio_mode(int if_num, int drv_num, int mode_num) {
- int p_base;
- int i;
-
- p_base = if_num ? 0x170 : 0x1f0;
- outb_p(3, p_base + 1);
- outb_p(mode_num | 8, p_base + 2);
- outb_p((drv_num | 0xa) << 4, p_base + 6);
- outb_p(0xef, p_base + 7);
- for (i = 0; (i < 100) && (inb (p_base + 7) & 0x80); i++)
- udelay(10000);
-}
-
-/*
- * Set a specific pio_mode for a drive
- */
-
-static void cmd640_set_mode(ide_drive_t* drive, int pio_mode) {
- int interface_number;
- int drive_number;
- int clock_time; /* ns */
- int mc_time, av_time, ds_time;
-
- interface_number = HWIF(drive)->index;
- drive_number = drive->select.b.unit;
- clock_time = 1000/bus_speed;
-
- mc_time = pio_timings[pio_mode].mc_time;
- av_time = pio_timings[pio_mode].av_time;
- ds_time = pio_timings[pio_mode].ds_time;
-
- cmd640_timings_to_clocks(mc_time, av_time, ds_time, clock_time,
- interface_number*2 + drive_number);
- set_pio_mode(interface_number, drive_number, pio_mode);
- cmd640_set_timing(interface_number, drive_number);
-}
-
-/*
- * Drive PIO mode "autoconfiguration".
- * Ideally, this code should *always* call cmd640_set_mode(), but it doesn't.
- */
-
-static void cmd640_tune_drive(ide_drive_t *drive, byte pio_mode) {
- int interface_number;
- int drive_number;
- int clock_time; /* ns */
- int max_pio;
- int mc_time, av_time, ds_time;
- struct hd_driveid* id;
- int readahead; /* there is a global named read_ahead */
-
- if (pio_mode != 255) {
- cmd640_set_mode(drive, pio_mode);
- return;
- }
-
- interface_number = HWIF(drive)->index;
- drive_number = drive->select.b.unit;
- clock_time = 1000/bus_speed;
- id = drive->id;
- if ((max_pio = ide_scan_pio_blacklist(id->model)) != -1) {
- ds_time = pio_timings[max_pio].ds_time;
- } else {
- max_pio = id->tPIO;
- ds_time = pio_timings[max_pio].ds_time;
- if (id->field_valid & 2) {
- if ((id->capability & 8) && (id->eide_pio_modes & 7)) {
- if (id->eide_pio_modes & 4) max_pio = 5;
- else if (id->eide_pio_modes & 2) max_pio = 4;
- else max_pio = 3;
- ds_time = id->eide_pio_iordy;
- } else {
- ds_time = id->eide_pio;
- }
- if (ds_time == 0)
- ds_time = pio_timings[max_pio].ds_time;
- }
-
- /*
- * Conservative "downgrade"
- */
- if (max_pio < 4 && max_pio != 0) {
- max_pio -= 1;
- ds_time = pio_timings[max_pio].ds_time;
- }
- }
- mc_time = pio_timings[max_pio].mc_time;
- av_time = pio_timings[max_pio].av_time;
- cmd640_timings_to_clocks(mc_time, av_time, ds_time, clock_time,
- interface_number*2 + drive_number);
- set_pio_mode(interface_number, drive_number, max_pio);
- cmd640_set_timing(interface_number, drive_number);
-
- /*
- * Disable (or set) readahead mode
- */
-
- readahead = 0;
- if (cmd640_chip_version > 1) { /* Mmmm.. probably should be > 2 ?? */
- readahead = known_drive_readahead(id->model);
- if (readahead == -1)
- readahead = 1; /* Mmmm.. probably be 0 ?? */
- set_readahead_mode(readahead, interface_number, drive_number);
- }
-
- printk ("Mode and Timing set to PIO%d, Readahead is %s\n",
- max_pio, readahead ? "enabled" : "disabled");
-}
-
diff --git a/i386/i386at/gpl/linux/block/floppy.c b/i386/i386at/gpl/linux/block/floppy.c
deleted file mode 100644
index ee4a898..0000000
--- a/i386/i386at/gpl/linux/block/floppy.c
+++ /dev/null
@@ -1,4100 +0,0 @@
-/*
- * linux/kernel/floppy.c
- *
- * Copyright (C) 1991, 1992 Linus Torvalds
- * Copyright (C) 1993, 1994 Alain Knaff
- */
-/*
- * 02.12.91 - Changed to static variables to indicate need for reset
- * and recalibrate. This makes some things easier (output_byte reset
- * checking etc), and means less interrupt jumping in case of errors,
- * so the code is hopefully easier to understand.
- */
-
-/*
- * This file is certainly a mess. I've tried my best to get it working,
- * but I don't like programming floppies, and I have only one anyway.
- * Urgel. I should check for more errors, and do more graceful error
- * recovery. Seems there are problems with several drives. I've tried to
- * correct them. No promises.
- */
-
-/*
- * As with hd.c, all routines within this file can (and will) be called
- * by interrupts, so extreme caution is needed. A hardware interrupt
- * handler may not sleep, or a kernel panic will happen. Thus I cannot
- * call "floppy-on" directly, but have to set a special timer interrupt
- * etc.
- */
-
-/*
- * 28.02.92 - made track-buffering routines, based on the routines written
- * by entropy@wintermute.wpi.edu (Lawrence Foard). Linus.
- */
-
-/*
- * Automatic floppy-detection and formatting written by Werner Almesberger
- * (almesber@nessie.cs.id.ethz.ch), who also corrected some problems with
- * the floppy-change signal detection.
- */
-
-/*
- * 1992/7/22 -- Hennus Bergman: Added better error reporting, fixed
- * FDC data overrun bug, added some preliminary stuff for vertical
- * recording support.
- *
- * 1992/9/17: Added DMA allocation & DMA functions. -- hhb.
- *
- * TODO: Errors are still not counted properly.
- */
-
-/* 1992/9/20
- * Modifications for ``Sector Shifting'' by Rob Hooft (hooft@chem.ruu.nl)
- * modelled after the freeware MS/DOS program fdformat/88 V1.8 by
- * Christoph H. Hochst\"atter.
- * I have fixed the shift values to the ones I always use. Maybe a new
- * ioctl() should be created to be able to modify them.
- * There is a bug in the driver that makes it impossible to format a
- * floppy as the first thing after bootup.
- */
-
-/*
- * 1993/4/29 -- Linus -- cleaned up the timer handling in the kernel, and
- * this helped the floppy driver as well. Much cleaner, and still seems to
- * work.
- */
-
-/* 1994/6/24 --bbroad-- added the floppy table entries and made
- * minor modifications to allow 2.88 floppies to be run.
- */
-
-/* 1994/7/13 -- Paul Vojta -- modified the probing code to allow three or more
- * disk types.
- */
-
-/*
- * 1994/8/8 -- Alain Knaff -- Switched to fdpatch driver: Support for bigger
- * format bug fixes, but unfortunately some new bugs too...
- */
-
-/* 1994/9/17 -- Koen Holtman -- added logging of physical floppy write
- * errors to allow safe writing by specialized programs.
- */
-
-/* 1995/4/24 -- Dan Fandrich -- added support for Commodore 1581 3.5" disks
- * by defining bit 1 of the "stretch" parameter to mean put sectors on the
- * opposite side of the disk, leaving the sector IDs alone (i.e. Commodore's
- * drives are "upside-down").
- */
-
-/*
- * 1995/8/26 -- Andreas Busse -- added Mips support.
- */
-
-/*
- * 1995/10/18 -- Ralf Baechle -- Portability cleanup; move machine dependend
- * features to asm/floppy.h.
- */
-
-
-#define FLOPPY_SANITY_CHECK
-#undef FLOPPY_SILENT_DCL_CLEAR
-
-#define REALLY_SLOW_IO
-
-#define DEBUGT 2
-#define DCL_DEBUG /* debug disk change line */
-
-/* do print messages for unexpected interrupts */
-static int print_unex=1;
-#include <linux/utsname.h>
-#include <linux/module.h>
-
-/* the following is the mask of allowed drives. By default units 2 and
- * 3 of both floppy controllers are disabled, because switching on the
- * motor of these drives causes system hangs on some PCI computers. drive
- * 0 is the low bit (0x1), and drive 7 is the high bit (0x80). Bits are on if
- * a drive is allowed. */
-static int FLOPPY_IRQ=6;
-static int FLOPPY_DMA=2;
-static int allowed_drive_mask = 0x33;
-
-
-#include <linux/sched.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/timer.h>
-#include <linux/tqueue.h>
-#define FDPATCHES
-#include <linux/fdreg.h>
-
-
-#include <linux/fd.h>
-
-
-#define OLDFDRAWCMD 0x020d /* send a raw command to the fdc */
-
-struct old_floppy_raw_cmd {
- void *data;
- long length;
-
- unsigned char rate;
- unsigned char flags;
- unsigned char cmd_count;
- unsigned char cmd[9];
- unsigned char reply_count;
- unsigned char reply[7];
- int track;
-};
-
-#include <linux/errno.h>
-#include <linux/malloc.h>
-#include <linux/mm.h>
-#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/delay.h>
-#include <linux/mc146818rtc.h> /* CMOS defines */
-#include <linux/ioport.h>
-
-#include <asm/dma.h>
-#include <asm/floppy.h>
-#include <asm/irq.h>
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/segment.h>
-
-#define MAJOR_NR FLOPPY_MAJOR
-
-#include <linux/blk.h>
-
-
-/* Dma Memory related stuff */
-
-/* Pure 2^n version of get_order */
-static inline int __get_order (int size)
-{
- int order;
-
-#ifdef _ASM_IO_H2
- __asm__ __volatile__("bsr %1,%0"
- : "=r" (order)
- : "r" (size / PAGE_SIZE));
-#else
- for (order = 0; order < NR_MEM_LISTS; ++order)
- if (size <= (PAGE_SIZE << order))
- return order;
-#endif
- return NR_MEM_LISTS;
-}
-
-static unsigned long dma_mem_alloc(int size)
-{
- int order = __get_order(size);
-
- if (order >= NR_MEM_LISTS)
- return(0);
- return __get_dma_pages(GFP_KERNEL,order);
-}
-
-/* End dma memory related stuff */
-
-static unsigned int fake_change = 0;
-static int initialising=1;
-
-static inline int TYPE(kdev_t x) {
- return (MINOR(x)>>2) & 0x1f;
-}
-static inline int DRIVE(kdev_t x) {
- return (MINOR(x)&0x03) | ((MINOR(x)&0x80) >> 5);
-}
-#define ITYPE(x) (((x)>>2) & 0x1f)
-#define TOMINOR(x) ((x & 3) | ((x & 4) << 5))
-#define UNIT(x) ((x) & 0x03) /* drive on fdc */
-#define FDC(x) (((x) & 0x04) >> 2) /* fdc of drive */
-#define REVDRIVE(fdc, unit) ((unit) + ((fdc) << 2))
- /* reverse mapping from unit and fdc to drive */
-#define DP (&drive_params[current_drive])
-#define DRS (&drive_state[current_drive])
-#define DRWE (&write_errors[current_drive])
-#define FDCS (&fdc_state[fdc])
-#define CLEARF(x) (clear_bit(x##_BIT, &DRS->flags))
-#define SETF(x) (set_bit(x##_BIT, &DRS->flags))
-#define TESTF(x) (test_bit(x##_BIT, &DRS->flags))
-
-#define UDP (&drive_params[drive])
-#define UDRS (&drive_state[drive])
-#define UDRWE (&write_errors[drive])
-#define UFDCS (&fdc_state[FDC(drive)])
-#define UCLEARF(x) (clear_bit(x##_BIT, &UDRS->flags))
-#define USETF(x) (set_bit(x##_BIT, &UDRS->flags))
-#define UTESTF(x) (test_bit(x##_BIT, &UDRS->flags))
-
-#define DPRINT(x) printk(DEVICE_NAME "%d: " x,current_drive)
-
-#define DPRINT1(x,x1) printk(DEVICE_NAME "%d: " x,current_drive,(x1))
-
-#define DPRINT2(x,x1,x2) printk(DEVICE_NAME "%d: " x,current_drive,(x1),(x2))
-
-#define DPRINT3(x,x1,x2,x3) printk(DEVICE_NAME "%d: " x,current_drive,(x1),(x2),(x3))
-
-#define PH_HEAD(floppy,head) (((((floppy)->stretch & 2) >>1) ^ head) << 2)
-#define STRETCH(floppy) ((floppy)->stretch & FD_STRETCH)
-
-#define CLEARSTRUCT(x) memset((x), 0, sizeof(*(x)))
-
-/* read/write */
-#define COMMAND raw_cmd->cmd[0]
-#define DR_SELECT raw_cmd->cmd[1]
-#define TRACK raw_cmd->cmd[2]
-#define HEAD raw_cmd->cmd[3]
-#define SECTOR raw_cmd->cmd[4]
-#define SIZECODE raw_cmd->cmd[5]
-#define SECT_PER_TRACK raw_cmd->cmd[6]
-#define GAP raw_cmd->cmd[7]
-#define SIZECODE2 raw_cmd->cmd[8]
-#define NR_RW 9
-
-/* format */
-#define F_SIZECODE raw_cmd->cmd[2]
-#define F_SECT_PER_TRACK raw_cmd->cmd[3]
-#define F_GAP raw_cmd->cmd[4]
-#define F_FILL raw_cmd->cmd[5]
-#define NR_F 6
-
-/*
- * Maximum disk size (in kilobytes). This default is used whenever the
- * current disk size is unknown.
- * [Now it is rather a minimum]
- */
-#define MAX_DISK_SIZE 2 /* 3984*/
-
-#define K_64 0x10000 /* 64KB */
-
-/*
- * globals used by 'result()'
- */
-#define MAX_REPLIES 17
-static unsigned char reply_buffer[MAX_REPLIES];
-static int inr; /* size of reply buffer, when called from interrupt */
-#define ST0 (reply_buffer[0])
-#define ST1 (reply_buffer[1])
-#define ST2 (reply_buffer[2])
-#define ST3 (reply_buffer[0]) /* result of GETSTATUS */
-#define R_TRACK (reply_buffer[3])
-#define R_HEAD (reply_buffer[4])
-#define R_SECTOR (reply_buffer[5])
-#define R_SIZECODE (reply_buffer[6])
-
-#define SEL_DLY (2*HZ/100)
-
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
-/*
- * this struct defines the different floppy drive types.
- */
-static struct {
- struct floppy_drive_params params;
- const char *name; /* name printed while booting */
-} default_drive_params[]= {
-/* NOTE: the time values in jiffies should be in msec!
- CMOS drive type
- | Maximum data rate supported by drive type
- | | Head load time, msec
- | | | Head unload time, msec (not used)
- | | | | Step rate interval, usec
- | | | | | Time needed for spinup time (jiffies)
- | | | | | | Timeout for spinning down (jiffies)
- | | | | | | | Spindown offset (where disk stops)
- | | | | | | | | Select delay
- | | | | | | | | | RPS
- | | | | | | | | | | Max number of tracks
- | | | | | | | | | | | Interrupt timeout
- | | | | | | | | | | | | Max nonintlv. sectors
- | | | | | | | | | | | | | -Max Errors- flags */
-{{0, 500, 16, 16, 8000, 1*HZ, 3*HZ, 0, SEL_DLY, 5, 80, 3*HZ, 20, {3,1,2,0,2}, 0,
- 0, { 7, 4, 8, 2, 1, 5, 3,10}, 3*HZ/2, 0 }, "unknown" },
-
-{{1, 300, 16, 16, 8000, 1*HZ, 3*HZ, 0, SEL_DLY, 5, 40, 3*HZ, 17, {3,1,2,0,2}, 0,
- 0, { 1, 0, 0, 0, 0, 0, 0, 0}, 3*HZ/2, 1 }, "360K PC" }, /*5 1/4 360 KB PC*/
-
-{{2, 500, 16, 16, 6000, 4*HZ/10, 3*HZ, 14, SEL_DLY, 6, 83, 3*HZ, 17, {3,1,2,0,2}, 0,
- 0, { 2, 5, 6,23,10,20,11, 0}, 3*HZ/2, 2 }, "1.2M" }, /*5 1/4 HD AT*/
-
-{{3, 250, 16, 16, 3000, 1*HZ, 3*HZ, 0, SEL_DLY, 5, 83, 3*HZ, 20, {3,1,2,0,2}, 0,
- 0, { 4,22,21,30, 3, 0, 0, 0}, 3*HZ/2, 4 }, "720k" }, /*3 1/2 DD*/
-
-{{4, 500, 16, 16, 4000, 4*HZ/10, 3*HZ, 10, SEL_DLY, 5, 83, 3*HZ, 20, {3,1,2,0,2}, 0,
- 0, { 7, 4,25,22,31,21,29,11}, 3*HZ/2, 7 }, "1.44M" }, /*3 1/2 HD*/
-
-{{5, 1000, 15, 8, 3000, 4*HZ/10, 3*HZ, 10, SEL_DLY, 5, 83, 3*HZ, 40, {3,1,2,0,2}, 0,
- 0, { 7, 8, 4,25,28,22,31,21}, 3*HZ/2, 8 }, "2.88M AMI BIOS" }, /*3 1/2 ED*/
-
-{{6, 1000, 15, 8, 3000, 4*HZ/10, 3*HZ, 10, SEL_DLY, 5, 83, 3*HZ, 40, {3,1,2,0,2}, 0,
- 0, { 7, 8, 4,25,28,22,31,21}, 3*HZ/2, 8 }, "2.88M" } /*3 1/2 ED*/
-/* | --autodetected formats--- | | |
- * read_track | | Name printed when booting
- * | Native format
- * Frequency of disk change checks */
-};
-
-static struct floppy_drive_params drive_params[N_DRIVE];
-static struct floppy_drive_struct drive_state[N_DRIVE];
-static struct floppy_write_errors write_errors[N_DRIVE];
-static struct floppy_raw_cmd *raw_cmd, default_raw_cmd;
-
-/*
- * This struct defines the different floppy types.
- *
- * Bit 0 of 'stretch' tells if the tracks need to be doubled for some
- * types (e.g. 360kB diskette in 1.2MB drive, etc.). Bit 1 of 'stretch'
- * tells if the disk is in Commodore 1581 format, which means side 0 sectors
- * are located on side 1 of the disk but with a side 0 ID, and vice-versa.
- * This is the same as the Sharp MZ-80 5.25" CP/M disk format, except that the
- * 1581's logical side 0 is on physical side 1, whereas the Sharp's logical
- * side 0 is on physical side 0 (but with the misnamed sector IDs).
- * 'stretch' should probably be renamed to something more general, like
- * 'options'. Other parameters should be self-explanatory (see also
- * setfdprm(8)).
- */
-static struct floppy_struct floppy_type[32] = {
- { 0, 0,0, 0,0,0x00,0x00,0x00,0x00,NULL }, /* 0 no testing */
- { 720, 9,2,40,0,0x2A,0x02,0xDF,0x50,"d360" }, /* 1 360KB PC */
- { 2400,15,2,80,0,0x1B,0x00,0xDF,0x54,"h1200" }, /* 2 1.2MB AT */
- { 720, 9,1,80,0,0x2A,0x02,0xDF,0x50,"D360" }, /* 3 360KB SS 3.5" */
- { 1440, 9,2,80,0,0x2A,0x02,0xDF,0x50,"D720" }, /* 4 720KB 3.5" */
- { 720, 9,2,40,1,0x23,0x01,0xDF,0x50,"h360" }, /* 5 360KB AT */
- { 1440, 9,2,80,0,0x23,0x01,0xDF,0x50,"h720" }, /* 6 720KB AT */
- { 2880,18,2,80,0,0x1B,0x00,0xCF,0x6C,"H1440" }, /* 7 1.44MB 3.5" */
- { 5760,36,2,80,0,0x1B,0x43,0xAF,0x54,"E2880" }, /* 8 2.88MB 3.5" */
- { 5760,36,2,80,0,0x1B,0x43,0xAF,0x54,"CompaQ"}, /* 9 2.88MB 3.5" */
-
- { 2880,18,2,80,0,0x25,0x00,0xDF,0x02,"h1440" }, /* 10 1.44MB 5.25" */
- { 3360,21,2,80,0,0x1C,0x00,0xCF,0x0C,"H1680" }, /* 11 1.68MB 3.5" */
- { 820,10,2,41,1,0x25,0x01,0xDF,0x2E,"h410" }, /* 12 410KB 5.25" */
- { 1640,10,2,82,0,0x25,0x02,0xDF,0x2E,"H820" }, /* 13 820KB 3.5" */
- { 2952,18,2,82,0,0x25,0x00,0xDF,0x02,"h1476" }, /* 14 1.48MB 5.25" */
- { 3444,21,2,82,0,0x25,0x00,0xDF,0x0C,"H1722" }, /* 15 1.72MB 3.5" */
- { 840,10,2,42,1,0x25,0x01,0xDF,0x2E,"h420" }, /* 16 420KB 5.25" */
- { 1660,10,2,83,0,0x25,0x02,0xDF,0x2E,"H830" }, /* 17 830KB 3.5" */
- { 2988,18,2,83,0,0x25,0x00,0xDF,0x02,"h1494" }, /* 18 1.49MB 5.25" */
- { 3486,21,2,83,0,0x25,0x00,0xDF,0x0C,"H1743" }, /* 19 1.74 MB 3.5" */
-
- { 1760,11,2,80,0,0x1C,0x09,0xCF,0x00,"h880" }, /* 20 880KB 5.25" */
- { 2080,13,2,80,0,0x1C,0x01,0xCF,0x00,"D1040" }, /* 21 1.04MB 3.5" */
- { 2240,14,2,80,0,0x1C,0x19,0xCF,0x00,"D1120" }, /* 22 1.12MB 3.5" */
- { 3200,20,2,80,0,0x1C,0x20,0xCF,0x2C,"h1600" }, /* 23 1.6MB 5.25" */
- { 3520,22,2,80,0,0x1C,0x08,0xCF,0x2e,"H1760" }, /* 24 1.76MB 3.5" */
- { 3840,24,2,80,0,0x1C,0x20,0xCF,0x00,"H1920" }, /* 25 1.92MB 3.5" */
- { 6400,40,2,80,0,0x25,0x5B,0xCF,0x00,"E3200" }, /* 26 3.20MB 3.5" */
- { 7040,44,2,80,0,0x25,0x5B,0xCF,0x00,"E3520" }, /* 27 3.52MB 3.5" */
- { 7680,48,2,80,0,0x25,0x63,0xCF,0x00,"E3840" }, /* 28 3.84MB 3.5" */
-
- { 3680,23,2,80,0,0x1C,0x10,0xCF,0x00,"H1840" }, /* 29 1.84MB 3.5" */
- { 1600,10,2,80,0,0x25,0x02,0xDF,0x2E,"D800" }, /* 30 800KB 3.5" */
- { 3200,20,2,80,0,0x1C,0x00,0xCF,0x2C,"H1600" }, /* 31 1.6MB 3.5" */
-};
-
-#define NUMBER(x) (sizeof(x) / sizeof(*(x)))
-#define SECTSIZE (_FD_SECTSIZE(*floppy))
-
-/* Auto-detection: Disk type used until the next media change occurs. */
-static struct floppy_struct *current_type[N_DRIVE] = {
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL
-};
-
-/*
- * User-provided type information. current_type points to
- * the respective entry of this array.
- */
-static struct floppy_struct user_params[N_DRIVE];
-
-static int floppy_sizes[256];
-static int floppy_blocksizes[256] = { 0, };
-
-/*
- * The driver is trying to determine the correct media format
- * while probing is set. rw_interrupt() clears it after a
- * successful access.
- */
-static int probing = 0;
-
-/* Synchronization of FDC access. */
-#define FD_COMMAND_NONE -1
-#define FD_COMMAND_ERROR 2
-#define FD_COMMAND_OKAY 3
-
-static volatile int command_status = FD_COMMAND_NONE, fdc_busy = 0;
-static struct wait_queue *fdc_wait = NULL, *command_done = NULL;
-#ifdef MACH
-extern int issig (void);
-#define NO_SIGNAL (! issig () || ! interruptible)
-#else
-#define NO_SIGNAL (!(current->signal & ~current->blocked) || !interruptible)
-#endif
-#define CALL(x) if ((x) == -EINTR) return -EINTR
-#define ECALL(x) if ((ret = (x))) return ret;
-#define _WAIT(x,i) CALL(ret=wait_til_done((x),i))
-#define WAIT(x) _WAIT((x),interruptible)
-#define IWAIT(x) _WAIT((x),1)
-
-/* Errors during formatting are counted here. */
-static int format_errors;
-
-/* Format request descriptor. */
-static struct format_descr format_req;
-
-/*
- * Rate is 0 for 500kb/s, 1 for 300kbps, 2 for 250kbps
- * Spec1 is 0xSH, where S is stepping rate (F=1ms, E=2ms, D=3ms etc),
- * H is head unload time (1=16ms, 2=32ms, etc)
- */
-
-/*
- * Track buffer
- * Because these are written to by the DMA controller, they must
- * not contain a 64k byte boundary crossing, or data will be
- * corrupted/lost. Alignment of these is enforced in boot/head.S.
- * Note that you must not change the sizes below without updating head.S.
- */
-static char *floppy_track_buffer=0;
-static int max_buffer_sectors=0;
-
-static int *errors;
-typedef void (*done_f)(int);
-static struct cont_t {
- void (*interrupt)(void); /* this is called after the interrupt of the
- * main command */
- void (*redo)(void); /* this is called to retry the operation */
- void (*error)(void); /* this is called to tally an error */
- done_f done; /* this is called to say if the operation has
- * succeeded/failed */
-} *cont=NULL;
-
-static void floppy_ready(void);
-static void floppy_start(void);
-static void process_fd_request(void);
-static void recalibrate_floppy(void);
-static void floppy_shutdown(void);
-
-static int floppy_grab_irq_and_dma(void);
-static void floppy_release_irq_and_dma(void);
-
-/*
- * The "reset" variable should be tested whenever an interrupt is scheduled,
- * after the commands have been sent. This is to ensure that the driver doesn't
- * get wedged when the interrupt doesn't come because of a failed command.
- * reset doesn't need to be tested before sending commands, because
- * output_byte is automatically disabled when reset is set.
- */
-#define CHECK_RESET { if (FDCS->reset){ reset_fdc(); return; } }
-static void reset_fdc(void);
-
-/*
- * These are global variables, as that's the easiest way to give
- * information to interrupts. They are the data used for the current
- * request.
- */
-#define NO_TRACK -1
-#define NEED_1_RECAL -2
-#define NEED_2_RECAL -3
-
-/* */
-static int usage_count = 0;
-
-
-/* buffer related variables */
-static int buffer_track = -1;
-static int buffer_drive = -1;
-static int buffer_min = -1;
-static int buffer_max = -1;
-
-/* fdc related variables, should end up in a struct */
-static struct floppy_fdc_state fdc_state[N_FDC];
-static int fdc; /* current fdc */
-
-static struct floppy_struct * floppy = floppy_type;
-static unsigned char current_drive = 0;
-static long current_count_sectors = 0;
-static unsigned char sector_t; /* sector in track */
-
-#ifdef DEBUGT
-static long unsigned debugtimer;
-#endif
-
-/*
- * Debugging
- * =========
- */
-static inline void set_debugt(void)
-{
-#ifdef DEBUGT
- debugtimer = jiffies;
-#endif
-}
-
-static inline void debugt(const char *message)
-{
-#ifdef DEBUGT
- if (DP->flags & DEBUGT)
- printk("%s dtime=%lu\n", message, jiffies-debugtimer);
-#endif
-}
-
-typedef void (*timeout_fn)(unsigned long);
-static struct timer_list fd_timeout ={ NULL, NULL, 0, 0,
- (timeout_fn) floppy_shutdown };
-
-static const char *timeout_message;
-
-#ifdef FLOPPY_SANITY_CHECK
-static void is_alive(const char *message)
-{
- /* this routine checks whether the floppy driver is "alive" */
- if (fdc_busy && command_status < 2 && !fd_timeout.prev){
- DPRINT1("timeout handler died: %s\n",message);
- }
-}
-#endif
-
-#ifdef FLOPPY_SANITY_CHECK
-
-#define OLOGSIZE 20
-
-static void (*lasthandler)(void) = NULL;
-static int interruptjiffies=0;
-static int resultjiffies=0;
-static int resultsize=0;
-static int lastredo=0;
-
-static struct output_log {
- unsigned char data;
- unsigned char status;
- unsigned long jiffies;
-} output_log[OLOGSIZE];
-
-static int output_log_pos=0;
-#endif
-
-#define CURRENTD -1
-#define MAXTIMEOUT -2
-
-static void reschedule_timeout(int drive, const char *message, int marg)
-{
- if (drive == CURRENTD)
- drive = current_drive;
- del_timer(&fd_timeout);
- if (drive < 0 || drive > N_DRIVE) {
- fd_timeout.expires = jiffies + 20*HZ;
- drive=0;
- } else
- fd_timeout.expires = jiffies + UDP->timeout;
- add_timer(&fd_timeout);
- if (UDP->flags & FD_DEBUG){
- DPRINT("reschedule timeout ");
- printk(message, marg);
- printk("\n");
- }
- timeout_message = message;
-}
-
-static int maximum(int a, int b)
-{
- if(a > b)
- return a;
- else
- return b;
-}
-#define INFBOUND(a,b) (a)=maximum((a),(b));
-
-static int minimum(int a, int b)
-{
- if(a < b)
- return a;
- else
- return b;
-}
-#define SUPBOUND(a,b) (a)=minimum((a),(b));
-
-
-/*
- * Bottom half floppy driver.
- * ==========================
- *
- * This part of the file contains the code talking directly to the hardware,
- * and also the main service loop (seek-configure-spinup-command)
- */
-
-/*
- * disk change.
- * This routine is responsible for maintaining the FD_DISK_CHANGE flag,
- * and the last_checked date.
- *
- * last_checked is the date of the last check which showed 'no disk change'
- * FD_DISK_CHANGE is set under two conditions:
- * 1. The floppy has been changed after some i/o to that floppy already
- * took place.
- * 2. No floppy disk is in the drive. This is done in order to ensure that
- * requests are quickly flushed in case there is no disk in the drive. It
- * follows that FD_DISK_CHANGE can only be cleared if there is a disk in
- * the drive.
- *
- * For 1., maxblock is observed. Maxblock is 0 if no i/o has taken place yet.
- * For 2., FD_DISK_NEWCHANGE is watched. FD_DISK_NEWCHANGE is cleared on
- * each seek. If a disk is present, the disk change line should also be
- * cleared on each seek. Thus, if FD_DISK_NEWCHANGE is clear, but the disk
- * change line is set, this means either that no disk is in the drive, or
- * that it has been removed since the last seek.
- *
- * This means that we really have a third possibility too:
- * The floppy has been changed after the last seek.
- */
-
-static int disk_change(int drive)
-{
- int fdc=FDC(drive);
-#ifdef FLOPPY_SANITY_CHECK
- if (jiffies < UDP->select_delay + UDRS->select_date)
- DPRINT("WARNING disk change called early\n");
- if (!(FDCS->dor & (0x10 << UNIT(drive))) ||
- (FDCS->dor & 3) != UNIT(drive) ||
- fdc != FDC(drive)){
- DPRINT("probing disk change on unselected drive\n");
- DPRINT3("drive=%d fdc=%d dor=%x\n",drive, FDC(drive),
- FDCS->dor);
- }
-#endif
-
-#ifdef DCL_DEBUG
- if (UDP->flags & FD_DEBUG){
- DPRINT1("checking disk change line for drive %d\n",drive);
- DPRINT1("jiffies=%ld\n", jiffies);
- DPRINT1("disk change line=%x\n",fd_inb(FD_DIR)&0x80);
- DPRINT1("flags=%x\n",UDRS->flags);
- }
-#endif
- if (UDP->flags & FD_BROKEN_DCL)
- return UTESTF(FD_DISK_CHANGED);
- if ((fd_inb(FD_DIR) ^ UDP->flags) & 0x80){
- USETF(FD_VERIFY); /* verify write protection */
- if (UDRS->maxblock){
- /* mark it changed */
- USETF(FD_DISK_CHANGED);
-
- /* invalidate its geometry */
- if (UDRS->keep_data >= 0) {
- if ((UDP->flags & FTD_MSG) &&
- current_type[drive] != NULL)
- DPRINT("Disk type is undefined after "
- "disk change\n");
- current_type[drive] = NULL;
- floppy_sizes[TOMINOR(current_drive)] = MAX_DISK_SIZE;
- }
- }
- /*USETF(FD_DISK_NEWCHANGE);*/
- return 1;
- } else {
- UDRS->last_checked=jiffies;
- UCLEARF(FD_DISK_NEWCHANGE);
- }
- return 0;
-}
-
-static inline int is_selected(int dor, int unit)
-{
- return ((dor & (0x10 << unit)) && (dor &3) == unit);
-}
-
-static int set_dor(int fdc, char mask, char data)
-{
- register unsigned char drive, unit, newdor,olddor;
-
- if (FDCS->address == -1)
- return -1;
-
- olddor = FDCS->dor;
- newdor = (olddor & mask) | data;
- if (newdor != olddor){
- unit = olddor & 0x3;
- if (is_selected(olddor, unit) && !is_selected(newdor,unit)){
- drive = REVDRIVE(fdc,unit);
-#ifdef DCL_DEBUG
- if (UDP->flags & FD_DEBUG){
- DPRINT("calling disk change from set_dor\n");
- }
-#endif
- disk_change(drive);
- }
- FDCS->dor = newdor;
- fd_outb(newdor, FD_DOR);
-
- unit = newdor & 0x3;
- if (!is_selected(olddor, unit) && is_selected(newdor,unit)){
- drive = REVDRIVE(fdc,unit);
- UDRS->select_date = jiffies;
- }
- }
- if (newdor & 0xf0)
- floppy_grab_irq_and_dma();
- if (olddor & 0xf0)
- floppy_release_irq_and_dma();
- return olddor;
-}
-
-static void twaddle(void)
-{
- if (DP->select_delay)
- return;
- fd_outb(FDCS->dor & ~(0x10<<UNIT(current_drive)),FD_DOR);
- fd_outb(FDCS->dor, FD_DOR);
- DRS->select_date = jiffies;
-}
-
-/* reset all driver information about the current fdc. This is needed after
- * a reset, and after a raw command. */
-static void reset_fdc_info(int mode)
-{
- int drive;
-
- FDCS->spec1 = FDCS->spec2 = -1;
- FDCS->need_configure = 1;
- FDCS->perp_mode = 1;
- FDCS->rawcmd = 0;
- for (drive = 0; drive < N_DRIVE; drive++)
- if (FDC(drive) == fdc &&
- (mode || UDRS->track != NEED_1_RECAL))
- UDRS->track = NEED_2_RECAL;
-}
-
-/* selects the fdc and drive, and enables the fdc's input/dma. */
-static void set_fdc(int drive)
-{
- if (drive >= 0 && drive < N_DRIVE){
- fdc = FDC(drive);
- current_drive = drive;
- }
- if (fdc != 1 && fdc != 0) {
- printk("bad fdc value\n");
- return;
- }
- set_dor(fdc,~0,8);
- set_dor(1-fdc, ~8, 0);
- if (FDCS->rawcmd == 2)
- reset_fdc_info(1);
- if (fd_inb(FD_STATUS) != STATUS_READY)
- FDCS->reset = 1;
-}
-
-/* locks the driver */
-static int lock_fdc(int drive, int interruptible)
-{
- if (!usage_count){
- printk("trying to lock fdc while usage count=0\n");
- return -1;
- }
- floppy_grab_irq_and_dma();
- cli();
- while (fdc_busy && NO_SIGNAL)
- interruptible_sleep_on(&fdc_wait);
- if (fdc_busy){
- sti();
- return -EINTR;
- }
- fdc_busy = 1;
- sti();
- command_status = FD_COMMAND_NONE;
- reschedule_timeout(drive, "lock fdc", 0);
- set_fdc(drive);
- return 0;
-}
-
-#define LOCK_FDC(drive,interruptible) \
-if (lock_fdc(drive,interruptible)) return -EINTR;
-
-
-/* unlocks the driver */
-static inline void unlock_fdc(void)
-{
- raw_cmd = 0;
- if (!fdc_busy)
- DPRINT("FDC access conflict!\n");
-
- if (DEVICE_INTR)
- DPRINT1("device interrupt still active at FDC release: %p!\n",
- DEVICE_INTR);
- command_status = FD_COMMAND_NONE;
- del_timer(&fd_timeout);
- cont = NULL;
- fdc_busy = 0;
- floppy_release_irq_and_dma();
- wake_up(&fdc_wait);
-}
-
-/* switches the motor off after a given timeout */
-static void motor_off_callback(unsigned long nr)
-{
- unsigned char mask = ~(0x10 << UNIT(nr));
-
- set_dor(FDC(nr), mask, 0);
-}
-
-static struct timer_list motor_off_timer[N_DRIVE] = {
- { NULL, NULL, 0, 0, motor_off_callback },
- { NULL, NULL, 0, 1, motor_off_callback },
- { NULL, NULL, 0, 2, motor_off_callback },
- { NULL, NULL, 0, 3, motor_off_callback },
- { NULL, NULL, 0, 4, motor_off_callback },
- { NULL, NULL, 0, 5, motor_off_callback },
- { NULL, NULL, 0, 6, motor_off_callback },
- { NULL, NULL, 0, 7, motor_off_callback }
-};
-
-/* schedules motor off */
-static void floppy_off(unsigned int drive)
-{
- unsigned long volatile delta;
- register int fdc=FDC(drive);
-
- if (!(FDCS->dor & (0x10 << UNIT(drive))))
- return;
-
- del_timer(motor_off_timer+drive);
-
- /* make spindle stop in a position which minimizes spinup time
- * next time */
- if (UDP->rps){
- delta = jiffies - UDRS->first_read_date + HZ -
- UDP->spindown_offset;
- delta = ((delta * UDP->rps) % HZ) / UDP->rps;
- motor_off_timer[drive].expires = jiffies + UDP->spindown - delta;
- }
- add_timer(motor_off_timer+drive);
-}
-
-/*
- * cycle through all N_DRIVE floppy drives, for disk change testing.
- * stopping at current drive. This is done before any long operation, to
- * be sure to have up to date disk change information.
- */
-static void scandrives(void)
-{
- int i, drive, saved_drive;
-
- if (DP->select_delay)
- return;
-
- saved_drive = current_drive;
- for (i=0; i < N_DRIVE; i++){
- drive = (saved_drive + i + 1) % N_DRIVE;
- if (UDRS->fd_ref == 0 || UDP->select_delay != 0)
- continue; /* skip closed drives */
- set_fdc(drive);
- if (!(set_dor(fdc, ~3, UNIT(drive) | (0x10 << UNIT(drive))) &
- (0x10 << UNIT(drive))))
- /* switch the motor off again, if it was off to
- * begin with */
- set_dor(fdc, ~(0x10 << UNIT(drive)), 0);
- }
- set_fdc(saved_drive);
-}
-
-static struct timer_list fd_timer ={ NULL, NULL, 0, 0, 0 };
-
-/* this function makes sure that the disk stays in the drive during the
- * transfer */
-static void fd_watchdog(void)
-{
-#ifdef DCL_DEBUG
- if (DP->flags & FD_DEBUG){
- DPRINT("calling disk change from watchdog\n");
- }
-#endif
-
- if (disk_change(current_drive)){
- DPRINT("disk removed during i/o\n");
- floppy_shutdown();
- } else {
- del_timer(&fd_timer);
- fd_timer.function = (timeout_fn) fd_watchdog;
- fd_timer.expires = jiffies + HZ / 10;
- add_timer(&fd_timer);
- }
-}
-
-static void main_command_interrupt(void)
-{
- del_timer(&fd_timer);
- cont->interrupt();
-}
-
-/* waits for a delay (spinup or select) to pass */
-static int wait_for_completion(int delay, timeout_fn function)
-{
- if (FDCS->reset){
- reset_fdc(); /* do the reset during sleep to win time
- * if we don't need to sleep, it's a good
- * occasion anyways */
- return 1;
- }
-
- if (jiffies < delay){
- del_timer(&fd_timer);
- fd_timer.function = function;
- fd_timer.expires = delay;
- add_timer(&fd_timer);
- return 1;
- }
- return 0;
-}
-
-static int hlt_disabled=0;
-static void floppy_disable_hlt(void)
-{
- unsigned long flags;
- save_flags(flags);
- cli();
- if (!hlt_disabled){
- hlt_disabled=1;
-#ifdef HAVE_DISABLE_HLT
- disable_hlt();
-#endif
- }
- restore_flags(flags);
-}
-
-static void floppy_enable_hlt(void)
-{
- unsigned long flags;
- save_flags(flags);
- cli();
- if (hlt_disabled){
- hlt_disabled=0;
-#ifdef HAVE_DISABLE_HLT
- enable_hlt();
-#endif
- }
- restore_flags(flags);
-}
-
-
-static void setup_DMA(void)
-{
-#ifdef FLOPPY_SANITY_CHECK
- if (raw_cmd->length == 0){
- int i;
-
- printk("zero dma transfer size:");
- for (i=0; i < raw_cmd->cmd_count; i++)
- printk("%x,", raw_cmd->cmd[i]);
- printk("\n");
- cont->done(0);
- FDCS->reset = 1;
- return;
- }
- if ((long) raw_cmd->kernel_data % 512){
- printk("non aligned address: %p\n", raw_cmd->kernel_data);
- cont->done(0);
- FDCS->reset=1;
- return;
- }
- if (CROSS_64KB(raw_cmd->kernel_data, raw_cmd->length)) {
- printk("DMA crossing 64-K boundary %p-%p\n",
- raw_cmd->kernel_data,
- raw_cmd->kernel_data + raw_cmd->length);
- cont->done(0);
- FDCS->reset=1;
- return;
- }
-#endif
- cli();
- fd_disable_dma();
- fd_clear_dma_ff();
- fd_set_dma_mode((raw_cmd->flags & FD_RAW_READ)?
- DMA_MODE_READ : DMA_MODE_WRITE);
- fd_set_dma_addr(virt_to_bus(raw_cmd->kernel_data));
- fd_set_dma_count(raw_cmd->length);
- fd_enable_dma();
- sti();
- floppy_disable_hlt();
-}
-
-/* sends a command byte to the fdc */
-static int output_byte(char byte)
-{
- int counter;
- unsigned char status = 0;
- unsigned char rstatus;
-
- if (FDCS->reset)
- return -1;
- for (counter = 0; counter < 10000 && !FDCS->reset; counter++) {
- rstatus = fd_inb(FD_STATUS);
- status = rstatus &(STATUS_READY|STATUS_DIR|STATUS_DMA);
- if (!(status & STATUS_READY))
- continue;
- if (status == STATUS_READY){
- fd_outb(byte,FD_DATA);
-
-#ifdef FLOPPY_SANITY_CHECK
- output_log[output_log_pos].data = byte;
- output_log[output_log_pos].status = rstatus;
- output_log[output_log_pos].jiffies = jiffies;
- output_log_pos = (output_log_pos + 1) % OLOGSIZE;
-#endif
- return 0;
- } else
- break;
- }
- FDCS->reset = 1;
- if (!initialising)
- DPRINT2("Unable to send byte %x to FDC. Status=%x\n",
- byte, status);
- return -1;
-}
-#define LAST_OUT(x) if (output_byte(x)){ reset_fdc();return;}
-
-/* gets the response from the fdc */
-static int result(void)
-{
- int i = 0, counter, status = 0;
-
- if (FDCS->reset)
- return -1;
- for (counter = 0; counter < 10000 && !FDCS->reset; counter++) {
- status = fd_inb(FD_STATUS)&
- (STATUS_DIR|STATUS_READY|STATUS_BUSY|STATUS_DMA);
- if (!(status & STATUS_READY))
- continue;
- if (status == STATUS_READY){
-#ifdef FLOPPY_SANITY_CHECK
- resultjiffies = jiffies;
- resultsize = i;
-#endif
- return i;
- }
- if (status & STATUS_DMA)
- break;
- if (status == (STATUS_DIR|STATUS_READY|STATUS_BUSY)) {
- if (i >= MAX_REPLIES) {
- DPRINT("floppy_stat reply overrun\n");
- break;
- }
- reply_buffer[i++] = fd_inb(FD_DATA);
- }
- }
- FDCS->reset = 1;
- if (!initialising)
- DPRINT3("Getstatus times out (%x) on fdc %d [%d]\n",
- status, fdc, i);
- return -1;
-}
-
-/* Set perpendicular mode as required, based on data rate, if supported.
- * 82077 Now tested. 1Mbps data rate only possible with 82077-1.
- */
-static inline void perpendicular_mode(void)
-{
- unsigned char perp_mode;
-
- if (raw_cmd->rate & 0x40){
- switch(raw_cmd->rate & 3){
- case 0:
- perp_mode=2;
- break;
- case 3:
- perp_mode=3;
- break;
- default:
- DPRINT("Invalid data rate for perpendicular mode!\n");
- cont->done(0);
- FDCS->reset = 1; /* convenient way to return to
- * redo without to much hassle (deep
- * stack et al. */
- return;
- }
- } else
- perp_mode = 0;
-
- if (FDCS->perp_mode == perp_mode)
- return;
- if (FDCS->version >= FDC_82077_ORIG && FDCS->has_fifo) {
- output_byte(FD_PERPENDICULAR);
- output_byte(perp_mode);
- FDCS->perp_mode = perp_mode;
- } else if (perp_mode) {
- DPRINT("perpendicular mode not supported by this FDC.\n");
- }
-} /* perpendicular_mode */
-
-#define NOMINAL_DTR 500
-
-/* Issue a "SPECIFY" command to set the step rate time, head unload time,
- * head load time, and DMA disable flag to values needed by floppy.
- *
- * The value "dtr" is the data transfer rate in Kbps. It is needed
- * to account for the data rate-based scaling done by the 82072 and 82077
- * FDC types. This parameter is ignored for other types of FDCs (i.e.
- * 8272a).
- *
- * Note that changing the data transfer rate has a (probably deleterious)
- * effect on the parameters subject to scaling for 82072/82077 FDCs, so
- * fdc_specify is called again after each data transfer rate
- * change.
- *
- * srt: 1000 to 16000 in microseconds
- * hut: 16 to 240 milliseconds
- * hlt: 2 to 254 milliseconds
- *
- * These values are rounded up to the next highest available delay time.
- */
-static void fdc_specify(void)
-{
- unsigned char spec1, spec2;
- int srt, hlt, hut;
- unsigned long dtr = NOMINAL_DTR;
- unsigned long scale_dtr = NOMINAL_DTR;
- int hlt_max_code = 0x7f;
- int hut_max_code = 0xf;
-
- if (FDCS->need_configure && FDCS->has_fifo) {
- if (FDCS->reset)
- return;
- /* Turn on FIFO for 82077-class FDC (improves performance) */
- /* TODO: lock this in via LOCK during initialization */
- output_byte(FD_CONFIGURE);
- output_byte(0);
- output_byte(0x2A); /* FIFO on, polling off, 10 byte threshold */
- output_byte(0); /* precompensation from track 0 upwards */
- if (FDCS->reset){
- FDCS->has_fifo=0;
- return;
- }
- FDCS->need_configure = 0;
- /*DPRINT("FIFO enabled\n");*/
- }
-
- switch (raw_cmd->rate & 0x03) {
- case 3:
- dtr = 1000;
- break;
- case 1:
- dtr = 300;
- break;
- case 2:
- dtr = 250;
- break;
- }
-
- if (FDCS->version >= FDC_82072) {
- scale_dtr = dtr;
- hlt_max_code = 0x00; /* 0==256msec*dtr0/dtr (not linear!) */
- hut_max_code = 0x0; /* 0==256msec*dtr0/dtr (not linear!) */
- }
-
- /* Convert step rate from microseconds to milliseconds and 4 bits */
- srt = 16 - (DP->srt*scale_dtr/1000 + NOMINAL_DTR - 1)/NOMINAL_DTR;
- SUPBOUND(srt, 0xf);
- INFBOUND(srt, 0);
-
- hlt = (DP->hlt*scale_dtr/2 + NOMINAL_DTR - 1)/NOMINAL_DTR;
- if (hlt < 0x01)
- hlt = 0x01;
- else if (hlt > 0x7f)
- hlt = hlt_max_code;
-
- hut = (DP->hut*scale_dtr/16 + NOMINAL_DTR - 1)/NOMINAL_DTR;
- if (hut < 0x1)
- hut = 0x1;
- else if (hut > 0xf)
- hut = hut_max_code;
-
- spec1 = (srt << 4) | hut;
- spec2 = (hlt << 1);
-
- /* If these parameters did not change, just return with success */
- if (FDCS->spec1 != spec1 || FDCS->spec2 != spec2) {
- /* Go ahead and set spec1 and spec2 */
- output_byte(FD_SPECIFY);
- output_byte(FDCS->spec1 = spec1);
- output_byte(FDCS->spec2 = spec2);
- }
-} /* fdc_specify */
-
-/* Set the FDC's data transfer rate on behalf of the specified drive.
- * NOTE: with 82072/82077 FDCs, changing the data rate requires a reissue
- * of the specify command (i.e. using the fdc_specify function).
- */
-static int fdc_dtr(void)
-{
- /* If data rate not already set to desired value, set it. */
- if ((raw_cmd->rate & 3) == FDCS->dtr)
- return 0;
-
- /* Set dtr */
- fd_outb(raw_cmd->rate & 3, FD_DCR);
-
- /* TODO: some FDC/drive combinations (C&T 82C711 with TEAC 1.2MB)
- * need a stabilization period of several milliseconds to be
- * enforced after data rate changes before R/W operations.
- * Pause 5 msec to avoid trouble. (Needs to be 2 jiffies)
- */
- FDCS->dtr = raw_cmd->rate & 3;
- return(wait_for_completion(jiffies+2*HZ/100,
- (timeout_fn) floppy_ready));
-} /* fdc_dtr */
-
-static void tell_sector(void)
-{
- printk(": track %d, head %d, sector %d, size %d",
- R_TRACK, R_HEAD, R_SECTOR, R_SIZECODE);
-} /* tell_sector */
-
-
-/*
- * Ok, this error interpreting routine is called after a
- * DMA read/write has succeeded
- * or failed, so we check the results, and copy any buffers.
- * hhb: Added better error reporting.
- * ak: Made this into a separate routine.
- */
-static int interpret_errors(void)
-{
- char bad;
-
- if (inr!=7) {
- DPRINT("-- FDC reply error");
- FDCS->reset = 1;
- return 1;
- }
-
- /* check IC to find cause of interrupt */
- switch (ST0 & ST0_INTR) {
- case 0x40: /* error occurred during command execution */
- bad = 1;
- if (ST1 & ST1_WP) {
- DPRINT("Drive is write protected\n");
- CLEARF(FD_DISK_WRITABLE);
- cont->done(0);
- bad = 2;
- } else if (ST1 & ST1_ND) {
- SETF(FD_NEED_TWADDLE);
- } else if (ST1 & ST1_OR) {
- if (DP->flags & FTD_MSG)
- DPRINT("Over/Underrun - retrying\n");
- bad = 0;
- }else if (*errors >= DP->max_errors.reporting){
- DPRINT("");
- if (ST0 & ST0_ECE) {
- printk("Recalibrate failed!");
- } else if (ST2 & ST2_CRC) {
- printk("data CRC error");
- tell_sector();
- } else if (ST1 & ST1_CRC) {
- printk("CRC error");
- tell_sector();
- } else if ((ST1 & (ST1_MAM|ST1_ND)) || (ST2 & ST2_MAM)) {
- if (!probing) {
- printk("sector not found");
- tell_sector();
- } else
- printk("probe failed...");
- } else if (ST2 & ST2_WC) { /* seek error */
- printk("wrong cylinder");
- } else if (ST2 & ST2_BC) { /* cylinder marked as bad */
- printk("bad cylinder");
- } else {
- printk("unknown error. ST[0..2] are: 0x%x 0x%x 0x%x", ST0, ST1, ST2);
- tell_sector();
- }
- printk("\n");
-
- }
- if (ST2 & ST2_WC || ST2 & ST2_BC)
- /* wrong cylinder => recal */
- DRS->track = NEED_2_RECAL;
- return bad;
- case 0x80: /* invalid command given */
- DPRINT("Invalid FDC command given!\n");
- cont->done(0);
- return 2;
- case 0xc0:
- DPRINT("Abnormal termination caused by polling\n");
- cont->error();
- return 2;
- default: /* (0) Normal command termination */
- return 0;
- }
-}
-
-/*
- * This routine is called when everything should be correctly set up
- * for the transfer (ie floppy motor is on, the correct floppy is
- * selected, and the head is sitting on the right track).
- */
-static void setup_rw_floppy(void)
-{
- int i,ready_date,r, flags,dflags;
- timeout_fn function;
-
- flags = raw_cmd->flags;
- if (flags & (FD_RAW_READ | FD_RAW_WRITE))
- flags |= FD_RAW_INTR;
-
- if ((flags & FD_RAW_SPIN) && !(flags & FD_RAW_NO_MOTOR)){
- ready_date = DRS->spinup_date + DP->spinup;
- /* If spinup will take a long time, rerun scandrives
- * again just before spinup completion. Beware that
- * after scandrives, we must again wait for selection.
- */
- if (ready_date > jiffies + DP->select_delay){
- ready_date -= DP->select_delay;
- function = (timeout_fn) floppy_start;
- } else
- function = (timeout_fn) setup_rw_floppy;
-
- /* wait until the floppy is spinning fast enough */
- if (wait_for_completion(ready_date,function))
- return;
- }
- dflags = DRS->flags;
-
- if ((flags & FD_RAW_READ) || (flags & FD_RAW_WRITE))
- setup_DMA();
-
- if (flags & FD_RAW_INTR)
- SET_INTR(main_command_interrupt);
-
- r=0;
- for (i=0; i< raw_cmd->cmd_count; i++)
- r|=output_byte(raw_cmd->cmd[i]);
-
-#ifdef DEBUGT
- debugt("rw_command: ");
-#endif
- if (r){
- reset_fdc();
- return;
- }
-
- if (!(flags & FD_RAW_INTR)){
- inr = result();
- cont->interrupt();
- } else if (flags & FD_RAW_NEED_DISK)
- fd_watchdog();
-}
-
-static int blind_seek;
-
-/*
- * This is the routine called after every seek (or recalibrate) interrupt
- * from the floppy controller.
- */
-static void seek_interrupt(void)
-{
-#ifdef DEBUGT
- debugt("seek interrupt:");
-#endif
- if (inr != 2 || (ST0 & 0xF8) != 0x20) {
- DPRINT("seek failed\n");
- DRS->track = NEED_2_RECAL;
- cont->error();
- cont->redo();
- return;
- }
- if (DRS->track >= 0 && DRS->track != ST1 && !blind_seek){
-#ifdef DCL_DEBUG
- if (DP->flags & FD_DEBUG){
- DPRINT("clearing NEWCHANGE flag because of effective seek\n");
- DPRINT1("jiffies=%ld\n", jiffies);
- }
-#endif
- CLEARF(FD_DISK_NEWCHANGE); /* effective seek */
- DRS->select_date = jiffies;
- }
- DRS->track = ST1;
- floppy_ready();
-}
-
-static void check_wp(void)
-{
- if (TESTF(FD_VERIFY)) {
- /* check write protection */
- output_byte(FD_GETSTATUS);
- output_byte(UNIT(current_drive));
- if (result() != 1){
- FDCS->reset = 1;
- return;
- }
- CLEARF(FD_VERIFY);
- CLEARF(FD_NEED_TWADDLE);
-#ifdef DCL_DEBUG
- if (DP->flags & FD_DEBUG){
- DPRINT("checking whether disk is write protected\n");
- DPRINT1("wp=%x\n",ST3 & 0x40);
- }
-#endif
- if (!(ST3 & 0x40))
- SETF(FD_DISK_WRITABLE);
- else
- CLEARF(FD_DISK_WRITABLE);
- }
-}
-
-static void seek_floppy(void)
-{
- int track;
-
- blind_seek=0;
-
-#ifdef DCL_DEBUG
- if (DP->flags & FD_DEBUG){
- DPRINT("calling disk change from seek\n");
- }
-#endif
-
- if (!TESTF(FD_DISK_NEWCHANGE) &&
- disk_change(current_drive) &&
- (raw_cmd->flags & FD_RAW_NEED_DISK)){
- /* the media changed flag should be cleared after the seek.
- * If it isn't, this means that there is really no disk in
- * the drive.
- */
- SETF(FD_DISK_CHANGED);
- cont->done(0);
- cont->redo();
- return;
- }
- if (DRS->track <= NEED_1_RECAL){
- recalibrate_floppy();
- return;
- } else if (TESTF(FD_DISK_NEWCHANGE) &&
- (raw_cmd->flags & FD_RAW_NEED_DISK) &&
- (DRS->track <= NO_TRACK || DRS->track == raw_cmd->track)) {
- /* we seek to clear the media-changed condition. Does anybody
- * know a more elegant way, which works on all drives? */
- if (raw_cmd->track)
- track = raw_cmd->track - 1;
- else {
- if (DP->flags & FD_SILENT_DCL_CLEAR){
- set_dor(fdc, ~(0x10 << UNIT(current_drive)), 0);
- blind_seek = 1;
- raw_cmd->flags |= FD_RAW_NEED_SEEK;
- }
- track = 1;
- }
- } else {
- check_wp();
- if (raw_cmd->track != DRS->track &&
- (raw_cmd->flags & FD_RAW_NEED_SEEK))
- track = raw_cmd->track;
- else {
- setup_rw_floppy();
- return;
- }
- }
-
- SET_INTR(seek_interrupt);
- output_byte(FD_SEEK);
- output_byte(UNIT(current_drive));
- LAST_OUT(track);
-#ifdef DEBUGT
- debugt("seek command:");
-#endif
-}
-
-static void recal_interrupt(void)
-{
-#ifdef DEBUGT
- debugt("recal interrupt:");
-#endif
- if (inr !=2)
- FDCS->reset = 1;
- else if (ST0 & ST0_ECE) {
- switch(DRS->track){
- case NEED_1_RECAL:
-#ifdef DEBUGT
- debugt("recal interrupt need 1 recal:");
-#endif
- /* after a second recalibrate, we still haven't
- * reached track 0. Probably no drive. Raise an
- * error, as failing immediately might upset
- * computers possessed by the Devil :-) */
- cont->error();
- cont->redo();
- return;
- case NEED_2_RECAL:
-#ifdef DEBUGT
- debugt("recal interrupt need 2 recal:");
-#endif
- /* If we already did a recalibrate,
- * and we are not at track 0, this
- * means we have moved. (The only way
- * not to move at recalibration is to
- * be already at track 0.) Clear the
- * new change flag */
-#ifdef DCL_DEBUG
- if (DP->flags & FD_DEBUG){
- DPRINT("clearing NEWCHANGE flag because of second recalibrate\n");
- }
-#endif
-
- CLEARF(FD_DISK_NEWCHANGE);
- DRS->select_date = jiffies;
- /* fall through */
- default:
-#ifdef DEBUGT
- debugt("recal interrupt default:");
-#endif
- /* Recalibrate moves the head by at
- * most 80 steps. If after one
- * recalibrate we don't have reached
- * track 0, this might mean that we
- * started beyond track 80. Try
- * again. */
- DRS->track = NEED_1_RECAL;
- break;
- }
- } else
- DRS->track = ST1;
- floppy_ready();
-}
-
-/*
- * Unexpected interrupt - Print as much debugging info as we can...
- * All bets are off...
- */
-static void unexpected_floppy_interrupt(void)
-{
- int i;
- if (initialising)
- return;
- if (print_unex){
- DPRINT("unexpected interrupt\n");
- if (inr >= 0)
- for (i=0; i<inr; i++)
- printk("%d %x\n", i, reply_buffer[i]);
- }
- while(1){
- output_byte(FD_SENSEI);
- inr=result();
- if (inr != 2)
- break;
- if (print_unex){
- printk("sensei\n");
- for (i=0; i<inr; i++)
- printk("%d %x\n", i, reply_buffer[i]);
- }
- }
- FDCS->reset = 1;
-}
-
-static struct tq_struct floppy_tq =
-{ 0, 0, (void *) (void *) unexpected_floppy_interrupt, 0 };
-
-/* interrupt handler */
-static void floppy_interrupt(int irq, struct pt_regs * regs)
-{
- void (*handler)(void) = DEVICE_INTR;
-
- lasthandler = handler;
- interruptjiffies = jiffies;
-
- floppy_enable_hlt();
- CLEAR_INTR;
- if (fdc >= N_FDC || FDCS->address == -1){
- /* we don't even know which FDC is the culprit */
- printk("DOR0=%x\n", fdc_state[0].dor);
- printk("floppy interrupt on bizarre fdc %d\n",fdc);
- printk("handler=%p\n", handler);
- is_alive("bizarre fdc");
- return;
- }
- inr = result();
- if (!handler){
- unexpected_floppy_interrupt();
- is_alive("unexpected");
- return;
- }
- if (inr == 0){
- do {
- output_byte(FD_SENSEI);
- inr = result();
- } while ((ST0 & 0x83) != UNIT(current_drive) && inr == 2);
- }
- floppy_tq.routine = (void *)(void *) handler;
- queue_task_irq(&floppy_tq, &tq_timer);
- is_alive("normal interrupt end");
-}
-
-static void recalibrate_floppy(void)
-{
-#ifdef DEBUGT
- debugt("recalibrate floppy:");
-#endif
- SET_INTR(recal_interrupt);
- output_byte(FD_RECALIBRATE);
- LAST_OUT(UNIT(current_drive));
-}
-
-/*
- * Must do 4 FD_SENSEIs after reset because of ``drive polling''.
- */
-static void reset_interrupt(void)
-{
-#ifdef DEBUGT
- debugt("reset interrupt:");
-#endif
- /* fdc_specify(); reprogram fdc */
- result(); /* get the status ready for set_fdc */
- if (FDCS->reset) {
- printk("reset set in interrupt, calling %p\n", cont->error);
- cont->error(); /* a reset just after a reset. BAD! */
- }
- cont->redo();
-}
-
-/*
- * reset is done by pulling bit 2 of DOR low for a while (old FDC's),
- * or by setting the self clearing bit 7 of STATUS (newer FDC's)
- */
-static void reset_fdc(void)
-{
- SET_INTR(reset_interrupt);
- FDCS->reset = 0;
- reset_fdc_info(0);
- if (FDCS->version >= FDC_82077)
- fd_outb(0x80 | (FDCS->dtr &3), FD_STATUS);
- else {
- fd_outb(FDCS->dor & ~0x04, FD_DOR);
- udelay(FD_RESET_DELAY);
- outb(FDCS->dor, FD_DOR);
- }
-}
-
-static void empty(void)
-{
-}
-
-void show_floppy(void)
-{
- int i;
-
- printk("\n");
- printk("floppy driver state\n");
- printk("-------------------\n");
- printk("now=%ld last interrupt=%d last called handler=%p\n",
- jiffies, interruptjiffies, lasthandler);
-
-
-#ifdef FLOPPY_SANITY_CHECK
- printk("timeout_message=%s\n", timeout_message);
- printk("last output bytes:\n");
- for (i=0; i < OLOGSIZE; i++)
- printk("%2x %2x %ld\n",
- output_log[(i+output_log_pos) % OLOGSIZE].data,
- output_log[(i+output_log_pos) % OLOGSIZE].status,
- output_log[(i+output_log_pos) % OLOGSIZE].jiffies);
- printk("last result at %d\n", resultjiffies);
- printk("last redo_fd_request at %d\n", lastredo);
- for (i=0; i<resultsize; i++){
- printk("%2x ", reply_buffer[i]);
- }
- printk("\n");
-#endif
-
- printk("status=%x\n", fd_inb(FD_STATUS));
- printk("fdc_busy=%d\n", fdc_busy);
- if (DEVICE_INTR)
- printk("DEVICE_INTR=%p\n", DEVICE_INTR);
- if (floppy_tq.sync)
- printk("floppy_tq.routine=%p\n", floppy_tq.routine);
- if (fd_timer.prev)
- printk("fd_timer.function=%p\n", fd_timer.function);
- if (fd_timeout.prev){
- printk("timer_table=%p\n",fd_timeout.function);
- printk("expires=%ld\n",fd_timeout.expires-jiffies);
- printk("now=%ld\n",jiffies);
- }
- printk("cont=%p\n", cont);
- printk("CURRENT=%p\n", CURRENT);
- printk("command_status=%d\n", command_status);
- printk("\n");
-}
-
-static void floppy_shutdown(void)
-{
- if (!initialising)
- show_floppy();
- CLEAR_INTR;
- floppy_tq.routine = (void *)(void *) empty;
- del_timer(&fd_timer);
- sti();
-
- floppy_enable_hlt();
- fd_disable_dma();
- /* avoid dma going to a random drive after shutdown */
-
- if (!initialising)
- DPRINT("floppy timeout\n");
- FDCS->reset = 1;
- if (cont){
- cont->done(0);
- cont->redo(); /* this will recall reset when needed */
- } else {
- printk("no cont in shutdown!\n");
- process_fd_request();
- }
- is_alive("floppy shutdown");
-}
-/*typedef void (*timeout_fn)(unsigned long);*/
-
-/* start motor, check media-changed condition and write protection */
-static int start_motor(void (*function)(void) )
-{
- int mask, data;
-
- mask = 0xfc;
- data = UNIT(current_drive);
- if (!(raw_cmd->flags & FD_RAW_NO_MOTOR)){
- if (!(FDCS->dor & (0x10 << UNIT(current_drive)))){
- set_debugt();
- /* no read since this drive is running */
- DRS->first_read_date = 0;
- /* note motor start time if motor is not yet running */
- DRS->spinup_date = jiffies;
- data |= (0x10 << UNIT(current_drive));
- }
- } else
- if (FDCS->dor & (0x10 << UNIT(current_drive)))
- mask &= ~(0x10 << UNIT(current_drive));
-
- /* starts motor and selects floppy */
- del_timer(motor_off_timer + current_drive);
- set_dor(fdc, mask, data);
-
- /* wait_for_completion also schedules reset if needed. */
- return(wait_for_completion(DRS->select_date+DP->select_delay,
- (timeout_fn) function));
-}
-
-static void floppy_ready(void)
-{
- CHECK_RESET;
- if (start_motor(floppy_ready)) return;
- if (fdc_dtr()) return;
-
-#ifdef DCL_DEBUG
- if (DP->flags & FD_DEBUG){
- DPRINT("calling disk change from floppy_ready\n");
- }
-#endif
-
- if (!(raw_cmd->flags & FD_RAW_NO_MOTOR) &&
- disk_change(current_drive) &&
- !DP->select_delay)
- twaddle(); /* this clears the dcl on certain drive/controller
- * combinations */
-
- if (raw_cmd->flags & (FD_RAW_NEED_SEEK | FD_RAW_NEED_DISK)){
- perpendicular_mode();
- fdc_specify(); /* must be done here because of hut, hlt ... */
- seek_floppy();
- } else
- setup_rw_floppy();
-}
-
-static void floppy_start(void)
-{
- reschedule_timeout(CURRENTD, "floppy start", 0);
-
- scandrives();
-#ifdef DCL_DEBUG
- if (DP->flags & FD_DEBUG){
- DPRINT("setting NEWCHANGE in floppy_start\n");
- }
-#endif
- SETF(FD_DISK_NEWCHANGE);
- floppy_ready();
-}
-
-/*
- * ========================================================================
- * here ends the bottom half. Exported routines are:
- * floppy_start, floppy_off, floppy_ready, lock_fdc, unlock_fdc, set_fdc,
- * start_motor, reset_fdc, reset_fdc_info, interpret_errors.
- * Initialisation also uses output_byte, result, set_dor, floppy_interrupt
- * and set_dor.
- * ========================================================================
- */
-/*
- * General purpose continuations.
- * ==============================
- */
-
-static void do_wakeup(void)
-{
- reschedule_timeout(MAXTIMEOUT, "do wakeup", 0);
- cont = 0;
- command_status += 2;
- wake_up(&command_done);
-}
-
-static struct cont_t wakeup_cont={
- empty,
- do_wakeup,
- empty,
- (done_f)empty
-};
-
-static int wait_til_done(void (*handler)(void), int interruptible)
-{
- int ret;
-
- floppy_tq.routine = (void *)(void *) handler;
- queue_task(&floppy_tq, &tq_timer);
-
- cli();
- while(command_status < 2 && NO_SIGNAL){
- is_alive("wait_til_done");
- if (interruptible)
- interruptible_sleep_on(&command_done);
- else
- sleep_on(&command_done);
- }
- if (command_status < 2){
- floppy_shutdown();
- sti();
- process_fd_request();
- return -EINTR;
- }
- sti();
-
- if (FDCS->reset)
- command_status = FD_COMMAND_ERROR;
- if (command_status == FD_COMMAND_OKAY)
- ret=0;
- else
- ret=-EIO;
- command_status = FD_COMMAND_NONE;
- return ret;
-}
-
-static void generic_done(int result)
-{
- command_status = result;
- cont = &wakeup_cont;
-}
-
-static void generic_success(void)
-{
- cont->done(1);
-}
-
-static void generic_failure(void)
-{
- cont->done(0);
-}
-
-static void success_and_wakeup(void)
-{
- generic_success();
- cont->redo();
-}
-
-
-/*
- * formatting and rw support.
- * ==========================
- */
-
-static int next_valid_format(void)
-{
- int probed_format;
-
- probed_format = DRS->probed_format;
- while(1){
- if (probed_format >= 8 ||
- !DP->autodetect[probed_format]){
- DRS->probed_format = 0;
- return 1;
- }
- if (floppy_type[DP->autodetect[probed_format]].sect){
- DRS->probed_format = probed_format;
- return 0;
- }
- probed_format++;
- }
-}
-
-static void bad_flp_intr(void)
-{
- if (probing){
- DRS->probed_format++;
- if (!next_valid_format())
- return;
- }
- (*errors)++;
- INFBOUND(DRWE->badness, *errors);
- if (*errors > DP->max_errors.abort)
- cont->done(0);
- if (*errors > DP->max_errors.reset)
- FDCS->reset = 1;
- else if (*errors > DP->max_errors.recal)
- DRS->track = NEED_2_RECAL;
-}
-
-static void set_floppy(kdev_t device)
-{
- if (TYPE(device))
- floppy = TYPE(device) + floppy_type;
- else
- floppy = current_type[ DRIVE(device) ];
-}
-
-/*
- * formatting and support.
- * =======================
- */
-static void format_interrupt(void)
-{
- switch (interpret_errors()){
- case 1:
- cont->error();
- case 2:
- break;
- case 0:
- cont->done(1);
- }
- cont->redo();
-}
-
-#define CODE2SIZE (ssize = ((1 << SIZECODE) + 3) >> 2)
-#define FM_MODE(x,y) ((y) & ~(((x)->rate & 0x80) >>1))
-#define CT(x) ((x) | 0x40)
-static void setup_format_params(int track)
-{
- struct fparm {
- unsigned char track,head,sect,size;
- } *here = (struct fparm *)floppy_track_buffer;
- int il,n;
- int count,head_shift,track_shift;
-
- raw_cmd = &default_raw_cmd;
- raw_cmd->track = track;
-
- raw_cmd->flags = FD_RAW_WRITE | FD_RAW_INTR | FD_RAW_SPIN |
- /*FD_RAW_NEED_DISK |*/ FD_RAW_NEED_SEEK;
- raw_cmd->rate = floppy->rate & 0x43;
- raw_cmd->cmd_count = NR_F;
- COMMAND = FM_MODE(floppy,FD_FORMAT);
- DR_SELECT = UNIT(current_drive) + PH_HEAD(floppy,format_req.head);
- F_SIZECODE = FD_SIZECODE(floppy);
- F_SECT_PER_TRACK = floppy->sect << 2 >> F_SIZECODE;
- F_GAP = floppy->fmt_gap;
- F_FILL = FD_FILL_BYTE;
-
- raw_cmd->kernel_data = floppy_track_buffer;
- raw_cmd->length = 4 * F_SECT_PER_TRACK;
-
- /* allow for about 30ms for data transport per track */
- head_shift = (F_SECT_PER_TRACK + 5) / 6;
-
- /* a ``cylinder'' is two tracks plus a little stepping time */
- track_shift = 2 * head_shift + 3;
-
- /* position of logical sector 1 on this track */
- n = (track_shift * format_req.track + head_shift * format_req.head)
- % F_SECT_PER_TRACK;
-
- /* determine interleave */
- il = 1;
- if (floppy->sect > DP->interleave_sect && F_SIZECODE == 2)
- il++;
-
- /* initialize field */
- for (count = 0; count < F_SECT_PER_TRACK; ++count) {
- here[count].track = format_req.track;
- here[count].head = format_req.head;
- here[count].sect = 0;
- here[count].size = F_SIZECODE;
- }
- /* place logical sectors */
- for (count = 1; count <= F_SECT_PER_TRACK; ++count) {
- here[n].sect = count;
- n = (n+il) % F_SECT_PER_TRACK;
- if (here[n].sect) { /* sector busy, find next free sector */
- ++n;
- if (n>= F_SECT_PER_TRACK) {
- n-=F_SECT_PER_TRACK;
- while (here[n].sect) ++n;
- }
- }
- }
-}
-
-static void redo_format(void)
-{
- buffer_track = -1;
- setup_format_params(format_req.track << STRETCH(floppy));
- floppy_start();
-#ifdef DEBUGT
- debugt("queue format request");
-#endif
-}
-
-static struct cont_t format_cont={
- format_interrupt,
- redo_format,
- bad_flp_intr,
- generic_done };
-
-static int do_format(kdev_t device, struct format_descr *tmp_format_req)
-{
- int ret;
- int drive=DRIVE(device);
-
- LOCK_FDC(drive,1);
- set_floppy(device);
- if (!floppy ||
- floppy->track > DP->tracks ||
- tmp_format_req->track >= floppy->track ||
- tmp_format_req->head >= floppy->head ||
- (floppy->sect << 2) % (1 << FD_SIZECODE(floppy)) ||
- !floppy->fmt_gap) {
- process_fd_request();
- return -EINVAL;
- }
- format_req = *tmp_format_req;
- format_errors = 0;
- cont = &format_cont;
- errors = &format_errors;
- IWAIT(redo_format);
- process_fd_request();
- return ret;
-}
-
-/*
- * Buffer read/write and support
- * =============================
- */
-
-/* new request_done. Can handle physical sectors which are smaller than a
- * logical buffer */
-static void request_done(int uptodate)
-{
- int block;
-
- probing = 0;
- reschedule_timeout(MAXTIMEOUT, "request done %d", uptodate);
-
- if (!CURRENT){
- DPRINT("request list destroyed in floppy request done\n");
- return;
- }
- if (uptodate){
- /* maintain values for invalidation on geometry
- * change */
- block = current_count_sectors + CURRENT->sector;
- INFBOUND(DRS->maxblock, block);
- if (block > floppy->sect)
- DRS->maxtrack = 1;
-
- /* unlock chained buffers */
- while (current_count_sectors && CURRENT &&
- current_count_sectors >= CURRENT->current_nr_sectors){
- current_count_sectors -= CURRENT->current_nr_sectors;
- CURRENT->nr_sectors -= CURRENT->current_nr_sectors;
- CURRENT->sector += CURRENT->current_nr_sectors;
- end_request(1);
- }
- if (current_count_sectors && CURRENT){
- /* "unlock" last subsector */
- CURRENT->buffer += current_count_sectors <<9;
- CURRENT->current_nr_sectors -= current_count_sectors;
- CURRENT->nr_sectors -= current_count_sectors;
- CURRENT->sector += current_count_sectors;
- return;
- }
-
- if (current_count_sectors && !CURRENT)
- DPRINT("request list destroyed in floppy request done\n");
-
- } else {
- if (CURRENT->cmd == WRITE) {
- /* record write error information */
- DRWE->write_errors++;
- if (DRWE->write_errors == 1) {
- DRWE->first_error_sector = CURRENT->sector;
- DRWE->first_error_generation = DRS->generation;
- }
- DRWE->last_error_sector = CURRENT->sector;
- DRWE->last_error_generation = DRS->generation;
- }
- end_request(0);
- }
-}
-
-/* Interrupt handler evaluating the result of the r/w operation */
-static void rw_interrupt(void)
-{
- int nr_sectors, ssize;
-
- if (!DRS->first_read_date)
- DRS->first_read_date = jiffies;
-
- nr_sectors = 0;
- CODE2SIZE;
- nr_sectors = ((R_TRACK-TRACK)*floppy->head+R_HEAD-HEAD) *
- floppy->sect + ((R_SECTOR-SECTOR) << SIZECODE >> 2) -
- (sector_t % floppy->sect) % ssize;
-
-#ifdef FLOPPY_SANITY_CHECK
- if (nr_sectors > current_count_sectors + ssize -
- (current_count_sectors + sector_t) % ssize +
- sector_t % ssize){
- DPRINT2("long rw: %x instead of %lx\n",
- nr_sectors, current_count_sectors);
- printk("rs=%d s=%d\n", R_SECTOR, SECTOR);
- printk("rh=%d h=%d\n", R_HEAD, HEAD);
- printk("rt=%d t=%d\n", R_TRACK, TRACK);
- printk("spt=%d st=%d ss=%d\n", SECT_PER_TRACK,
- sector_t, ssize);
- }
-#endif
- INFBOUND(nr_sectors,0);
- SUPBOUND(current_count_sectors, nr_sectors);
-
- switch (interpret_errors()){
- case 2:
- cont->redo();
- return;
- case 1:
- if (!current_count_sectors){
- cont->error();
- cont->redo();
- return;
- }
- break;
- case 0:
- if (!current_count_sectors){
- cont->redo();
- return;
- }
- current_type[current_drive] = floppy;
- floppy_sizes[TOMINOR(current_drive) ]= floppy->size>>1;
- break;
- }
-
- if (probing) {
- if (DP->flags & FTD_MSG)
- DPRINT2("Auto-detected floppy type %s in fd%d\n",
- floppy->name,current_drive);
- current_type[current_drive] = floppy;
- floppy_sizes[TOMINOR(current_drive)] = floppy->size >> 1;
- probing = 0;
- }
-
- if (CT(COMMAND) != FD_READ ||
- raw_cmd->kernel_data == CURRENT->buffer){
- /* transfer directly from buffer */
- cont->done(1);
- } else if (CT(COMMAND) == FD_READ){
- buffer_track = raw_cmd->track;
- buffer_drive = current_drive;
- INFBOUND(buffer_max, nr_sectors + sector_t);
- }
- cont->redo();
-}
-
-/* Compute maximal contiguous buffer size. */
-static int buffer_chain_size(void)
-{
- struct buffer_head *bh;
- int size;
- char *base;
-
- base = CURRENT->buffer;
- size = CURRENT->current_nr_sectors << 9;
- bh = CURRENT->bh;
-
- if (bh){
- bh = bh->b_reqnext;
- while (bh && bh->b_data == base + size){
- size += bh->b_size;
- bh = bh->b_reqnext;
- }
- }
- return size >> 9;
-}
-
-/* Compute the maximal transfer size */
-static int transfer_size(int ssize, int max_sector, int max_size)
-{
- SUPBOUND(max_sector, sector_t + max_size);
-
- /* alignment */
- max_sector -= (max_sector % floppy->sect) % ssize;
-
- /* transfer size, beginning not aligned */
- current_count_sectors = max_sector - sector_t ;
-
- return max_sector;
-}
-
-/*
- * Move data from/to the track buffer to/from the buffer cache.
- */
-static void copy_buffer(int ssize, int max_sector, int max_sector_2)
-{
- int remaining; /* number of transferred 512-byte sectors */
- struct buffer_head *bh;
- char *buffer, *dma_buffer;
- int size;
-
- max_sector = transfer_size(ssize,
- minimum(max_sector, max_sector_2),
- CURRENT->nr_sectors);
-
- if (current_count_sectors <= 0 && CT(COMMAND) == FD_WRITE &&
- buffer_max > sector_t + CURRENT->nr_sectors)
- current_count_sectors = minimum(buffer_max - sector_t,
- CURRENT->nr_sectors);
-
- remaining = current_count_sectors << 9;
-#ifdef FLOPPY_SANITY_CHECK
- if ((remaining >> 9) > CURRENT->nr_sectors &&
- CT(COMMAND) == FD_WRITE){
- DPRINT("in copy buffer\n");
- printk("current_count_sectors=%ld\n", current_count_sectors);
- printk("remaining=%d\n", remaining >> 9);
- printk("CURRENT->nr_sectors=%ld\n",CURRENT->nr_sectors);
- printk("CURRENT->current_nr_sectors=%ld\n",
- CURRENT->current_nr_sectors);
- printk("max_sector=%d\n", max_sector);
- printk("ssize=%d\n", ssize);
- }
-#endif
-
- buffer_max = maximum(max_sector, buffer_max);
-
- dma_buffer = floppy_track_buffer + ((sector_t - buffer_min) << 9);
-
- bh = CURRENT->bh;
- size = CURRENT->current_nr_sectors << 9;
- buffer = CURRENT->buffer;
-
- while (remaining > 0){
- SUPBOUND(size, remaining);
-#ifdef FLOPPY_SANITY_CHECK
- if (dma_buffer + size >
- floppy_track_buffer + (max_buffer_sectors << 10) ||
- dma_buffer < floppy_track_buffer){
- DPRINT1("buffer overrun in copy buffer %d\n",
- (int) ((floppy_track_buffer - dma_buffer) >>9));
- printk("sector_t=%d buffer_min=%d\n",
- sector_t, buffer_min);
- printk("current_count_sectors=%ld\n",
- current_count_sectors);
- if (CT(COMMAND) == FD_READ)
- printk("read\n");
- if (CT(COMMAND) == FD_READ)
- printk("write\n");
- break;
- }
- if (((unsigned long)buffer) % 512)
- DPRINT1("%p buffer not aligned\n", buffer);
-#endif
- if (CT(COMMAND) == FD_READ) {
- fd_cacheflush(dma_buffer, size);
- memcpy(buffer, dma_buffer, size);
- } else {
- memcpy(dma_buffer, buffer, size);
- fd_cacheflush(dma_buffer, size);
- }
- remaining -= size;
- if (!remaining)
- break;
-
- dma_buffer += size;
- bh = bh->b_reqnext;
-#ifdef FLOPPY_SANITY_CHECK
- if (!bh){
- DPRINT("bh=null in copy buffer after copy\n");
- break;
- }
-#endif
- size = bh->b_size;
- buffer = bh->b_data;
- }
-#ifdef FLOPPY_SANITY_CHECK
- if (remaining){
- if (remaining > 0)
- max_sector -= remaining >> 9;
- DPRINT1("weirdness: remaining %d\n", remaining>>9);
- }
-#endif
-}
-
-/*
- * Formulate a read/write request.
- * this routine decides where to load the data (directly to buffer, or to
- * tmp floppy area), how much data to load (the size of the buffer, the whole
- * track, or a single sector)
- * All floppy_track_buffer handling goes in here. If we ever add track buffer
- * allocation on the fly, it should be done here. No other part should need
- * modification.
- */
-
-static int make_raw_rw_request(void)
-{
- int aligned_sector_t;
- int max_sector, max_size, tracksize, ssize;
-
- set_fdc(DRIVE(CURRENT->rq_dev));
-
- raw_cmd = &default_raw_cmd;
- raw_cmd->flags = FD_RAW_SPIN | FD_RAW_NEED_DISK | FD_RAW_NEED_DISK |
- FD_RAW_NEED_SEEK;
- raw_cmd->cmd_count = NR_RW;
- if (CURRENT->cmd == READ){
- raw_cmd->flags |= FD_RAW_READ;
- COMMAND = FM_MODE(floppy,FD_READ);
- } else if (CURRENT->cmd == WRITE){
- raw_cmd->flags |= FD_RAW_WRITE;
- COMMAND = FM_MODE(floppy,FD_WRITE);
- } else {
- DPRINT("make_raw_rw_request: unknown command\n");
- return 0;
- }
-
- max_sector = floppy->sect * floppy->head;
-
- TRACK = CURRENT->sector / max_sector;
- sector_t = CURRENT->sector % max_sector;
- if (floppy->track && TRACK >= floppy->track)
- return 0;
- HEAD = sector_t / floppy->sect;
-
- if (((floppy->stretch & FD_SWAPSIDES) || TESTF(FD_NEED_TWADDLE)) &&
- sector_t < floppy->sect)
- max_sector = floppy->sect;
-
- /* 2M disks have phantom sectors on the first track */
- if ((floppy->rate & FD_2M) && (!TRACK) && (!HEAD)){
- max_sector = 2 * floppy->sect / 3;
- if (sector_t >= max_sector){
- current_count_sectors = minimum(floppy->sect - sector_t,
- CURRENT->nr_sectors);
- return 1;
- }
- SIZECODE = 2;
- } else
- SIZECODE = FD_SIZECODE(floppy);
- raw_cmd->rate = floppy->rate & 0x43;
- if ((floppy->rate & FD_2M) &&
- (TRACK || HEAD) &&
- raw_cmd->rate == 2)
- raw_cmd->rate = 1;
-
- if (SIZECODE)
- SIZECODE2 = 0xff;
- else
- SIZECODE2 = 0x80;
- raw_cmd->track = TRACK << STRETCH(floppy);
- DR_SELECT = UNIT(current_drive) + PH_HEAD(floppy,HEAD);
- GAP = floppy->gap;
- CODE2SIZE;
- SECT_PER_TRACK = floppy->sect << 2 >> SIZECODE;
- SECTOR = ((sector_t % floppy->sect) << 2 >> SIZECODE) + 1;
- tracksize = floppy->sect - floppy->sect % ssize;
- if (tracksize < floppy->sect){
- SECT_PER_TRACK ++;
- if (tracksize <= sector_t % floppy->sect)
- SECTOR--;
- while (tracksize <= sector_t % floppy->sect){
- while(tracksize + ssize > floppy->sect){
- SIZECODE--;
- ssize >>= 1;
- }
- SECTOR++; SECT_PER_TRACK ++;
- tracksize += ssize;
- }
- max_sector = HEAD * floppy->sect + tracksize;
- } else if (!TRACK && !HEAD && !(floppy->rate & FD_2M) && probing)
- max_sector = floppy->sect;
-
- aligned_sector_t = sector_t - (sector_t % floppy->sect) % ssize;
- max_size = CURRENT->nr_sectors;
- if ((raw_cmd->track == buffer_track) &&
- (current_drive == buffer_drive) &&
- (sector_t >= buffer_min) && (sector_t < buffer_max)) {
- /* data already in track buffer */
- if (CT(COMMAND) == FD_READ) {
- copy_buffer(1, max_sector, buffer_max);
- return 1;
- }
- } else if (aligned_sector_t != sector_t || CURRENT->nr_sectors < ssize){
- if (CT(COMMAND) == FD_WRITE){
- if (sector_t + CURRENT->nr_sectors > ssize &&
- sector_t + CURRENT->nr_sectors < ssize + ssize)
- max_size = ssize + ssize;
- else
- max_size = ssize;
- }
- raw_cmd->flags &= ~FD_RAW_WRITE;
- raw_cmd->flags |= FD_RAW_READ;
- COMMAND = FM_MODE(floppy,FD_READ);
- } else if ((unsigned long)CURRENT->buffer < MAX_DMA_ADDRESS) {
- unsigned long dma_limit;
- int direct, indirect;
-
- indirect= transfer_size(ssize,max_sector,max_buffer_sectors*2) -
- sector_t;
-
- /*
- * Do NOT use minimum() here---MAX_DMA_ADDRESS is 64 bits wide
- * on a 64 bit machine!
- */
- max_size = buffer_chain_size();
- dma_limit = (MAX_DMA_ADDRESS - ((unsigned long) CURRENT->buffer)) >> 9;
- if ((unsigned long) max_size > dma_limit) {
- max_size = dma_limit;
- }
- /* 64 kb boundaries */
- if (CROSS_64KB(CURRENT->buffer, max_size << 9))
- max_size = (K_64 - ((long) CURRENT->buffer) % K_64)>>9;
- direct = transfer_size(ssize,max_sector,max_size) - sector_t;
- /*
- * We try to read tracks, but if we get too many errors, we
- * go back to reading just one sector at a time.
- *
- * This means we should be able to read a sector even if there
- * are other bad sectors on this track.
- */
- if (!direct ||
- (indirect * 2 > direct * 3 &&
- *errors < DP->max_errors.read_track &&
- /*!TESTF(FD_NEED_TWADDLE) &&*/
- ((!probing || (DP->read_track&(1<<DRS->probed_format)))))){
- max_size = CURRENT->nr_sectors;
- } else {
- raw_cmd->kernel_data = CURRENT->buffer;
- raw_cmd->length = current_count_sectors << 9;
- if (raw_cmd->length == 0){
- DPRINT("zero dma transfer attempted from make_raw_request\n");
- DPRINT3("indirect=%d direct=%d sector_t=%d",
- indirect, direct, sector_t);
- return 0;
- }
- return 2;
- }
- }
-
- if (CT(COMMAND) == FD_READ)
- max_size = max_sector; /* unbounded */
-
- /* claim buffer track if needed */
- if (buffer_track != raw_cmd->track || /* bad track */
- buffer_drive !=current_drive || /* bad drive */
- sector_t > buffer_max ||
- sector_t < buffer_min ||
- ((CT(COMMAND) == FD_READ ||
- (aligned_sector_t == sector_t && CURRENT->nr_sectors >= ssize))&&
- max_sector > 2 * max_buffer_sectors + buffer_min &&
- max_size + sector_t > 2 * max_buffer_sectors + buffer_min)
- /* not enough space */){
- buffer_track = -1;
- buffer_drive = current_drive;
- buffer_max = buffer_min = aligned_sector_t;
- }
- raw_cmd->kernel_data = floppy_track_buffer +
- ((aligned_sector_t-buffer_min)<<9);
-
- if (CT(COMMAND) == FD_WRITE){
- /* copy write buffer to track buffer.
- * if we get here, we know that the write
- * is either aligned or the data already in the buffer
- * (buffer will be overwritten) */
-#ifdef FLOPPY_SANITY_CHECK
- if (sector_t != aligned_sector_t && buffer_track == -1)
- DPRINT("internal error offset !=0 on write\n");
-#endif
- buffer_track = raw_cmd->track;
- buffer_drive = current_drive;
- copy_buffer(ssize, max_sector, 2*max_buffer_sectors+buffer_min);
- } else
- transfer_size(ssize, max_sector,
- 2*max_buffer_sectors+buffer_min-aligned_sector_t);
-
- /* round up current_count_sectors to get dma xfer size */
- raw_cmd->length = sector_t+current_count_sectors-aligned_sector_t;
- raw_cmd->length = ((raw_cmd->length -1)|(ssize-1))+1;
- raw_cmd->length <<= 9;
-#ifdef FLOPPY_SANITY_CHECK
- if ((raw_cmd->length < current_count_sectors << 9) ||
- (raw_cmd->kernel_data != CURRENT->buffer &&
- CT(COMMAND) == FD_WRITE &&
- (aligned_sector_t + (raw_cmd->length >> 9) > buffer_max ||
- aligned_sector_t < buffer_min)) ||
- raw_cmd->length % (128 << SIZECODE) ||
- raw_cmd->length <= 0 || current_count_sectors <= 0){
- DPRINT2("fractionary current count b=%lx s=%lx\n",
- raw_cmd->length, current_count_sectors);
- if (raw_cmd->kernel_data != CURRENT->buffer)
- printk("addr=%d, length=%ld\n",
- (int) ((raw_cmd->kernel_data -
- floppy_track_buffer) >> 9),
- current_count_sectors);
- printk("st=%d ast=%d mse=%d msi=%d\n",
- sector_t, aligned_sector_t, max_sector, max_size);
- printk("ssize=%x SIZECODE=%d\n", ssize, SIZECODE);
- printk("command=%x SECTOR=%d HEAD=%d, TRACK=%d\n",
- COMMAND, SECTOR, HEAD, TRACK);
- printk("buffer drive=%d\n", buffer_drive);
- printk("buffer track=%d\n", buffer_track);
- printk("buffer_min=%d\n", buffer_min);
- printk("buffer_max=%d\n", buffer_max);
- return 0;
- }
-
- if (raw_cmd->kernel_data != CURRENT->buffer){
- if (raw_cmd->kernel_data < floppy_track_buffer ||
- current_count_sectors < 0 ||
- raw_cmd->length < 0 ||
- raw_cmd->kernel_data + raw_cmd->length >
- floppy_track_buffer + (max_buffer_sectors << 10)){
- DPRINT("buffer overrun in schedule dma\n");
- printk("sector_t=%d buffer_min=%d current_count=%ld\n",
- sector_t, buffer_min,
- raw_cmd->length >> 9);
- printk("current_count_sectors=%ld\n",
- current_count_sectors);
- if (CT(COMMAND) == FD_READ)
- printk("read\n");
- if (CT(COMMAND) == FD_READ)
- printk("write\n");
- return 0;
- }
- } else if (raw_cmd->length > CURRENT->nr_sectors << 9 ||
- current_count_sectors > CURRENT->nr_sectors){
- DPRINT("buffer overrun in direct transfer\n");
- return 0;
- } else if (raw_cmd->length < current_count_sectors << 9){
- DPRINT("more sectors than bytes\n");
- printk("bytes=%ld\n", raw_cmd->length >> 9);
- printk("sectors=%ld\n", current_count_sectors);
- }
- if (raw_cmd->length == 0){
- DPRINT("zero dma transfer attempted from make_raw_request\n");
- return 0;
- }
-#endif
- return 2;
-}
-
-static void redo_fd_request(void)
-{
-#define REPEAT {request_done(0); continue; }
- kdev_t device;
- int tmp;
-
- lastredo = jiffies;
- if (current_drive < N_DRIVE)
- floppy_off(current_drive);
-
- if (CURRENT && CURRENT->rq_status == RQ_INACTIVE){
- DPRINT("current not active!\n");
- return;
- }
-
- while(1){
- if (!CURRENT) {
- CLEAR_INTR;
- unlock_fdc();
- return;
- }
- if (MAJOR(CURRENT->rq_dev) != MAJOR_NR)
- panic(DEVICE_NAME ": request list destroyed");
- if (CURRENT->bh && !buffer_locked(CURRENT->bh))
- panic(DEVICE_NAME ": block not locked");
-
- device = CURRENT->rq_dev;
- set_fdc(DRIVE(device));
- reschedule_timeout(CURRENTD, "redo fd request", 0);
-
- set_floppy(device);
- raw_cmd = & default_raw_cmd;
- raw_cmd->flags = 0;
- if (start_motor(redo_fd_request)) return;
- if (test_bit(current_drive, &fake_change) ||
- TESTF(FD_DISK_CHANGED)){
- DPRINT("disk absent or changed during operation\n");
- REPEAT;
- }
- if (!floppy) { /* Autodetection */
- if (!probing){
- DRS->probed_format = 0;
- if (next_valid_format()){
- DPRINT("no autodetectable formats\n");
- floppy = NULL;
- REPEAT;
- }
- }
- probing = 1;
- floppy = floppy_type+DP->autodetect[DRS->probed_format];
- } else
- probing = 0;
- errors = & (CURRENT->errors);
- tmp = make_raw_rw_request();
- if (tmp < 2){
- request_done(tmp);
- continue;
- }
-
- if (TESTF(FD_NEED_TWADDLE))
- twaddle();
- floppy_tq.routine = (void *)(void *) floppy_start;
- queue_task(&floppy_tq, &tq_timer);
-#ifdef DEBUGT
- debugt("queue fd request");
-#endif
- return;
- }
-#undef REPEAT
-}
-
-static struct cont_t rw_cont={
- rw_interrupt,
- redo_fd_request,
- bad_flp_intr,
- request_done };
-
-static struct tq_struct request_tq =
-{ 0, 0, (void *) (void *) redo_fd_request, 0 };
-
-static void process_fd_request(void)
-{
- cont = &rw_cont;
- queue_task(&request_tq, &tq_timer);
-}
-
-static void do_fd_request(void)
-{
- if (fdc_busy){
- /* fdc busy, this new request will be treated when the
- current one is done */
- is_alive("do fd request, old request running");
- return;
- }
- lock_fdc(MAXTIMEOUT,0);
- process_fd_request();
- is_alive("do fd request");
-}
-
-static struct cont_t poll_cont={
- success_and_wakeup,
- floppy_ready,
- generic_failure,
- generic_done };
-
-static int poll_drive(int interruptible, int flag)
-{
- int ret;
- /* no auto-sense, just clear dcl */
- raw_cmd = &default_raw_cmd;
- raw_cmd->flags= flag;
- raw_cmd->track=0;
- raw_cmd->cmd_count=0;
- cont = &poll_cont;
-#ifdef DCL_DEBUG
- if (DP->flags & FD_DEBUG){
- DPRINT("setting NEWCHANGE in poll_drive\n");
- }
-#endif
- SETF(FD_DISK_NEWCHANGE);
- WAIT(floppy_ready);
- return ret;
-}
-
-/*
- * User triggered reset
- * ====================
- */
-
-static void reset_intr(void)
-{
- printk("weird, reset interrupt called\n");
-}
-
-static struct cont_t reset_cont={
- reset_intr,
- success_and_wakeup,
- generic_failure,
- generic_done };
-
-static int user_reset_fdc(int drive, int arg, int interruptible)
-{
- int ret;
-
- ret=0;
- LOCK_FDC(drive,interruptible);
- if (arg == FD_RESET_ALWAYS)
- FDCS->reset=1;
- if (FDCS->reset){
- cont = &reset_cont;
- WAIT(reset_fdc);
- }
- process_fd_request();
- return ret;
-}
-
-/*
- * Misc Ioctl's and support
- * ========================
- */
-static int fd_copyout(void *param, const void *address, int size)
-{
- int ret;
-
- ECALL(verify_area(VERIFY_WRITE,param,size));
- fd_cacheflush(address, size); /* is this necessary ??? */
- /* Ralf: Yes; only the l2 cache is completly chipset
- controlled */
- memcpy_tofs(param,(void *) address, size);
- return 0;
-}
-
-static int fd_copyin(void *param, void *address, int size)
-{
- int ret;
-
- ECALL(verify_area(VERIFY_READ,param,size));
- memcpy_fromfs((void *) address, param, size);
- return 0;
-}
-
-#define COPYOUT(x) ECALL(fd_copyout((void *)param, &(x), sizeof(x)))
-#define COPYIN(x) ECALL(fd_copyin((void *)param, &(x), sizeof(x)))
-
-static inline const char *drive_name(int type, int drive)
-{
- struct floppy_struct *floppy;
-
- if (type)
- floppy = floppy_type + type;
- else {
- if (UDP->native_format)
- floppy = floppy_type + UDP->native_format;
- else
- return "(null)";
- }
- if (floppy->name)
- return floppy->name;
- else
- return "(null)";
-}
-
-
-/* raw commands */
-static void raw_cmd_done(int flag)
-{
- int i;
-
- if (!flag) {
- raw_cmd->flags = FD_RAW_FAILURE;
- raw_cmd->flags |= FD_RAW_HARDFAILURE;
- } else {
- raw_cmd->reply_count = inr;
- for (i=0; i< raw_cmd->reply_count; i++)
- raw_cmd->reply[i] = reply_buffer[i];
-
- if (raw_cmd->flags & (FD_RAW_READ | FD_RAW_WRITE))
- raw_cmd->length = get_dma_residue(FLOPPY_DMA);
-
- if ((raw_cmd->flags & FD_RAW_SOFTFAILURE) &&
- (!raw_cmd->reply_count || (raw_cmd->reply[0] & 0xc0)))
- raw_cmd->flags |= FD_RAW_FAILURE;
-
- if (disk_change(current_drive))
- raw_cmd->flags |= FD_RAW_DISK_CHANGE;
- else
- raw_cmd->flags &= ~FD_RAW_DISK_CHANGE;
- if (raw_cmd->flags & FD_RAW_NO_MOTOR_AFTER)
- motor_off_callback(current_drive);
-
- if (raw_cmd->next &&
- (!(raw_cmd->flags & FD_RAW_FAILURE) ||
- !(raw_cmd->flags & FD_RAW_STOP_IF_FAILURE)) &&
- ((raw_cmd->flags & FD_RAW_FAILURE) ||
- !(raw_cmd->flags &FD_RAW_STOP_IF_SUCCESS))) {
- raw_cmd = raw_cmd->next;
- return;
- }
- }
- generic_done(flag);
-}
-
-
-static struct cont_t raw_cmd_cont={
- success_and_wakeup,
- floppy_start,
- generic_failure,
- raw_cmd_done
-};
-
-static inline int raw_cmd_copyout(int cmd, char *param,
- struct floppy_raw_cmd *ptr)
-{
- struct old_floppy_raw_cmd old_raw_cmd;
- int ret;
-
- while(ptr) {
- if (cmd == OLDFDRAWCMD) {
- old_raw_cmd.flags = ptr->flags;
- old_raw_cmd.data = ptr->data;
- old_raw_cmd.length = ptr->length;
- old_raw_cmd.rate = ptr->rate;
- old_raw_cmd.reply_count = ptr->reply_count;
- memcpy(old_raw_cmd.reply, ptr->reply, 7);
- COPYOUT(old_raw_cmd);
- param += sizeof(old_raw_cmd);
- } else {
- COPYOUT(*ptr);
- param += sizeof(struct floppy_raw_cmd);
- }
-
- if ((ptr->flags & FD_RAW_READ) && ptr->buffer_length){
- if (ptr->length>=0 && ptr->length<=ptr->buffer_length)
- ECALL(fd_copyout(ptr->data,
- ptr->kernel_data,
- ptr->buffer_length -
- ptr->length));
- }
- ptr = ptr->next;
- }
- return 0;
-}
-
-
-static void raw_cmd_free(struct floppy_raw_cmd **ptr)
-{
- struct floppy_raw_cmd *next,*this;
-
- this = *ptr;
- *ptr = 0;
- while(this) {
- if (this->buffer_length) {
- free_pages((unsigned long)this->kernel_data,
- __get_order(this->buffer_length));
- this->buffer_length = 0;
- }
- next = this->next;
- kfree(this);
- this = next;
- }
-}
-
-
-static inline int raw_cmd_copyin(int cmd, char *param,
- struct floppy_raw_cmd **rcmd)
-{
- struct floppy_raw_cmd *ptr;
- struct old_floppy_raw_cmd old_raw_cmd;
- int ret;
- int i;
-
- *rcmd = 0;
- while(1) {
- ptr = (struct floppy_raw_cmd *)
- kmalloc(sizeof(struct floppy_raw_cmd), GFP_USER);
- if (!ptr)
- return -ENOMEM;
- *rcmd = ptr;
- if (cmd == OLDFDRAWCMD){
- COPYIN(old_raw_cmd);
- ptr->flags = old_raw_cmd.flags;
- ptr->data = old_raw_cmd.data;
- ptr->length = old_raw_cmd.length;
- ptr->rate = old_raw_cmd.rate;
- ptr->cmd_count = old_raw_cmd.cmd_count;
- ptr->track = old_raw_cmd.track;
- ptr->phys_length = 0;
- ptr->next = 0;
- ptr->buffer_length = 0;
- memcpy(ptr->cmd, old_raw_cmd.cmd, 9);
- param += sizeof(struct old_floppy_raw_cmd);
- if (ptr->cmd_count > 9)
- return -EINVAL;
- } else {
- COPYIN(*ptr);
- ptr->next = 0;
- ptr->buffer_length = 0;
- param += sizeof(struct floppy_raw_cmd);
- if (ptr->cmd_count > 16)
- return -EINVAL;
- }
-
- for (i=0; i< 16; i++)
- ptr->reply[i] = 0;
- ptr->resultcode = 0;
- ptr->kernel_data = 0;
-
- if (ptr->flags & (FD_RAW_READ | FD_RAW_WRITE)) {
- if (ptr->length <= 0)
- return -EINVAL;
- ptr->kernel_data =(char*)dma_mem_alloc(ptr->length);
- if (!ptr->kernel_data)
- return -ENOMEM;
- ptr->buffer_length = ptr->length;
- }
- if ( ptr->flags & FD_RAW_READ )
- ECALL( verify_area( VERIFY_WRITE, ptr->data,
- ptr->length ));
- if (ptr->flags & FD_RAW_WRITE)
- ECALL(fd_copyin(ptr->data, ptr->kernel_data,
- ptr->length));
- rcmd = & (ptr->next);
- if (!(ptr->flags & FD_RAW_MORE))
- return 0;
- ptr->rate &= 0x43;
- }
-}
-
-
-static int raw_cmd_ioctl(int cmd, void *param)
-{
- int drive, ret, ret2;
- struct floppy_raw_cmd *my_raw_cmd;
-
- if (FDCS->rawcmd <= 1)
- FDCS->rawcmd = 1;
- for (drive= 0; drive < N_DRIVE; drive++){
- if (FDC(drive) != fdc)
- continue;
- if (drive == current_drive){
- if (UDRS->fd_ref > 1){
- FDCS->rawcmd = 2;
- break;
- }
- } else if (UDRS->fd_ref){
- FDCS->rawcmd = 2;
- break;
- }
- }
-
- if (FDCS->reset)
- return -EIO;
-
- ret = raw_cmd_copyin(cmd, param, &my_raw_cmd);
- if (ret) {
- raw_cmd_free(&my_raw_cmd);
- return ret;
- }
-
- raw_cmd = my_raw_cmd;
- cont = &raw_cmd_cont;
- ret=wait_til_done(floppy_start,1);
-#ifdef DCL_DEBUG
- if (DP->flags & FD_DEBUG){
- DPRINT("calling disk change from raw_cmd ioctl\n");
- }
-#endif
-
- if (ret != -EINTR && FDCS->reset)
- ret = -EIO;
-
- DRS->track = NO_TRACK;
-
- ret2 = raw_cmd_copyout(cmd, param, my_raw_cmd);
- if (!ret)
- ret = ret2;
- raw_cmd_free(&my_raw_cmd);
- return ret;
-}
-
-static int invalidate_drive(kdev_t rdev)
-{
- /* invalidate the buffer track to force a reread */
- set_bit(DRIVE(rdev), &fake_change);
- process_fd_request();
- check_disk_change(rdev);
- return 0;
-}
-
-
-static inline void clear_write_error(int drive)
-{
- CLEARSTRUCT(UDRWE);
-}
-
-static inline int set_geometry(unsigned int cmd, struct floppy_struct *g,
- int drive, int type, kdev_t device)
-{
- int cnt;
-
- /* sanity checking for parameters.*/
- if (g->sect <= 0 ||
- g->head <= 0 ||
- g->track <= 0 ||
- g->track > UDP->tracks>>STRETCH(g) ||
- /* check if reserved bits are set */
- (g->stretch&~(FD_STRETCH|FD_SWAPSIDES)) != 0)
- return -EINVAL;
- if (type){
- if (!suser())
- return -EPERM;
- LOCK_FDC(drive,1);
- for (cnt = 0; cnt < N_DRIVE; cnt++){
- if (ITYPE(drive_state[cnt].fd_device) == type &&
- drive_state[cnt].fd_ref)
- set_bit(drive, &fake_change);
- }
- floppy_type[type] = *g;
- floppy_type[type].name="user format";
- for (cnt = type << 2; cnt < (type << 2) + 4; cnt++)
- floppy_sizes[cnt]= floppy_sizes[cnt+0x80]=
- floppy_type[type].size>>1;
- process_fd_request();
- for (cnt = 0; cnt < N_DRIVE; cnt++){
- if (ITYPE(drive_state[cnt].fd_device) == type &&
- drive_state[cnt].fd_ref)
- check_disk_change(
- MKDEV(FLOPPY_MAJOR,
- drive_state[cnt].fd_device));
- }
- } else {
- LOCK_FDC(drive,1);
- if (cmd != FDDEFPRM)
- /* notice a disk change immediately, else
- * we loose our settings immediately*/
- CALL(poll_drive(1,0));
- user_params[drive] = *g;
- if (buffer_drive == drive)
- SUPBOUND(buffer_max, user_params[drive].sect);
- current_type[drive] = &user_params[drive];
- floppy_sizes[drive] = user_params[drive].size >> 1;
- if (cmd == FDDEFPRM)
- DRS->keep_data = -1;
- else
- DRS->keep_data = 1;
- /* invalidation. Invalidate only when needed, i.e.
- * when there are already sectors in the buffer cache
- * whose number will change. This is useful, because
- * mtools often changes the geometry of the disk after
- * looking at the boot block */
- if (DRS->maxblock > user_params[drive].sect || DRS->maxtrack)
- invalidate_drive(device);
- else
- process_fd_request();
- }
- return 0;
-}
-
-/* handle obsolete ioctl's */
-static struct translation_entry {
- int newcmd;
- int oldcmd;
- int oldsize; /* size of 0x00xx-style ioctl. Reflects old structures, thus
- * use numeric values. NO SIZEOFS */
-} translation_table[]= {
- {FDCLRPRM, 0, 0},
- {FDSETPRM, 1, 28},
- {FDDEFPRM, 2, 28},
- {FDGETPRM, 3, 28},
- {FDMSGON, 4, 0},
- {FDMSGOFF, 5, 0},
- {FDFMTBEG, 6, 0},
- {FDFMTTRK, 7, 12},
- {FDFMTEND, 8, 0},
- {FDSETEMSGTRESH, 10, 0},
- {FDFLUSH, 11, 0},
- {FDSETMAXERRS, 12, 20},
- {OLDFDRAWCMD, 30, 0},
- {FDGETMAXERRS, 14, 20},
- {FDGETDRVTYP, 16, 16},
- {FDSETDRVPRM, 20, 88},
- {FDGETDRVPRM, 21, 88},
- {FDGETDRVSTAT, 22, 52},
- {FDPOLLDRVSTAT, 23, 52},
- {FDRESET, 24, 0},
- {FDGETFDCSTAT, 25, 40},
- {FDWERRORCLR, 27, 0},
- {FDWERRORGET, 28, 24},
- {FDRAWCMD, 0, 0},
- {FDTWADDLE, 40, 0} };
-
-static inline int normalize_0x02xx_ioctl(int *cmd, int *size)
-{
- int i;
-
- for (i=0; i < ARRAY_SIZE(translation_table); i++) {
- if ((*cmd & 0xffff) == (translation_table[i].newcmd & 0xffff)){
- *size = _IOC_SIZE(*cmd);
- *cmd = translation_table[i].newcmd;
- if (*size > _IOC_SIZE(*cmd)) {
- printk("ioctl not yet supported\n");
- return -EFAULT;
- }
- return 0;
- }
- }
- return -EINVAL;
-}
-
-static inline int xlate_0x00xx_ioctl(int *cmd, int *size)
-{
- int i;
- /* old ioctls' for kernels <= 1.3.33 */
- /* When the next even release will come around, we'll start
- * warning against these.
- * When the next odd release will come around, we'll fail with
- * -EINVAL */
- if(strcmp(system_utsname.version, "1.4.0") >= 0)
- printk("obsolete floppy ioctl %x\n", *cmd);
- if((system_utsname.version[0] == '1' &&
- strcmp(system_utsname.version, "1.5.0") >= 0) ||
- (system_utsname.version[0] >= '2' &&
- strcmp(system_utsname.version, "2.1.0") >= 0))
- return -EINVAL;
- for (i=0; i < ARRAY_SIZE(translation_table); i++) {
- if (*cmd == translation_table[i].oldcmd) {
- *size = translation_table[i].oldsize;
- *cmd = translation_table[i].newcmd;
- return 0;
- }
- }
- return -EINVAL;
-}
-
-static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
- unsigned long param)
-{
-#define IOCTL_MODE_BIT 8
-#define OPEN_WRITE_BIT 16
-#define IOCTL_ALLOWED (filp && (filp->f_mode & IOCTL_MODE_BIT))
-#define OUT(c,x) case c: outparam = (const char *) (x); break
-#define IN(c,x,tag) case c: *(x) = inparam. tag ; return 0
-
- int i,drive,type;
- kdev_t device;
- int ret;
- int size;
- union inparam {
- struct floppy_struct g; /* geometry */
- struct format_descr f;
- struct floppy_max_errors max_errors;
- struct floppy_drive_params dp;
- } inparam; /* parameters coming from user space */
- const char *outparam; /* parameters passed back to user space */
-
- device = inode->i_rdev;
- switch (cmd) {
- RO_IOCTLS(device,param);
- }
- type = TYPE(device);
- drive = DRIVE(device);
-
- /* convert the old style command into a new style command */
- if ((cmd & 0xff00) == 0x0200) {
- ECALL(normalize_0x02xx_ioctl(&cmd, &size));
- } else if ((cmd & 0xff00) == 0x0000) {
- ECALL(xlate_0x00xx_ioctl(&cmd, &size));
- } else
- return -EINVAL;
-
- /* permission checks */
- if (((cmd & 0x80) && !suser()) ||
- ((cmd & 0x40) && !IOCTL_ALLOWED))
- return -EPERM;
-
- /* verify writability of result, and fail early */
- if (_IOC_DIR(cmd) & _IOC_READ)
- ECALL(verify_area(VERIFY_WRITE,(void *) param, size));
-
- /* copyin */
- CLEARSTRUCT(&inparam);
- if (_IOC_DIR(cmd) & _IOC_WRITE)
- ECALL(fd_copyin((void *)param, &inparam, size))
-
- switch (cmd) {
- case FDCLRPRM:
- LOCK_FDC(drive,1);
- current_type[drive] = NULL;
- floppy_sizes[drive] = MAX_DISK_SIZE;
- UDRS->keep_data = 0;
- return invalidate_drive(device);
- case FDSETPRM:
- case FDDEFPRM:
- return set_geometry(cmd, & inparam.g,
- drive, type, device);
- case FDGETPRM:
- if (type)
- outparam = (char *) &floppy_type[type];
- else
- outparam = (char *) current_type[drive];
- if(!outparam)
- return -ENODEV;
- break;
-
- case FDMSGON:
- UDP->flags |= FTD_MSG;
- return 0;
- case FDMSGOFF:
- UDP->flags &= ~FTD_MSG;
- return 0;
-
- case FDFMTBEG:
- LOCK_FDC(drive,1);
- CALL(poll_drive(1, FD_RAW_NEED_DISK));
- ret = UDRS->flags;
- process_fd_request();
- if(ret & FD_VERIFY)
- return -ENODEV;
- if(!(ret & FD_DISK_WRITABLE))
- return -EROFS;
- return 0;
- case FDFMTTRK:
- if (UDRS->fd_ref != 1)
- return -EBUSY;
- return do_format(device, &inparam.f);
- case FDFMTEND:
- case FDFLUSH:
- LOCK_FDC(drive,1);
- return invalidate_drive(device);
-
- case FDSETEMSGTRESH:
- UDP->max_errors.reporting =
- (unsigned short) (param & 0x0f);
- return 0;
- OUT(FDGETMAXERRS, &UDP->max_errors);
- IN(FDSETMAXERRS, &UDP->max_errors, max_errors);
-
- case FDGETDRVTYP:
- outparam = drive_name(type,drive);
- SUPBOUND(size,strlen(outparam)+1);
- break;
-
- IN(FDSETDRVPRM, UDP, dp);
- OUT(FDGETDRVPRM, UDP);
-
- case FDPOLLDRVSTAT:
- LOCK_FDC(drive,1);
- CALL(poll_drive(1, FD_RAW_NEED_DISK));
- process_fd_request();
- /* fall through */
- OUT(FDGETDRVSTAT, UDRS);
-
- case FDRESET:
- return user_reset_fdc(drive, (int)param, 1);
-
- OUT(FDGETFDCSTAT,UFDCS);
-
- case FDWERRORCLR:
- CLEARSTRUCT(UDRWE);
- return 0;
- OUT(FDWERRORGET,UDRWE);
-
- case OLDFDRAWCMD:
- case FDRAWCMD:
- if (type)
- return -EINVAL;
- LOCK_FDC(drive,1);
- set_floppy(device);
- CALL(i = raw_cmd_ioctl(cmd,(void *) param));
- process_fd_request();
- return i;
-
- case FDTWADDLE:
- LOCK_FDC(drive,1);
- twaddle();
- process_fd_request();
- return 0;
-
- default:
- return -EINVAL;
- }
-
- if (_IOC_DIR(cmd) & _IOC_READ)
- return fd_copyout((void *)param, outparam, size);
- else
- return 0;
-#undef IOCTL_ALLOWED
-#undef OUT
-#undef IN
-}
-
-static void config_types(void)
-{
- int first=1;
- int drive;
-
- /* read drive info out of physical cmos */
- drive=0;
- if (!UDP->cmos)
- UDP->cmos= FLOPPY0_TYPE;
- drive=1;
- if (!UDP->cmos && FLOPPY1_TYPE)
- UDP->cmos = FLOPPY1_TYPE;
-
- /* XXX */
- /* additional physical CMOS drive detection should go here */
-
- for (drive=0; drive < N_DRIVE; drive++){
- if (UDP->cmos >= 0 && UDP->cmos <= NUMBER(default_drive_params))
- memcpy((char *) UDP,
- (char *) (&default_drive_params[(int)UDP->cmos].params),
- sizeof(struct floppy_drive_params));
- if (UDP->cmos){
- if (first)
- printk("Floppy drive(s): ");
- else
- printk(", ");
- first=0;
- if (UDP->cmos > 0){
- allowed_drive_mask |= 1 << drive;
- printk("fd%d is %s", drive,
- default_drive_params[(int)UDP->cmos].name);
- } else
- printk("fd%d is unknown type %d",drive,
- UDP->cmos);
- }
- }
- if (!first)
- printk("\n");
-}
-
-static int floppy_read(struct inode * inode, struct file * filp,
- char * buf, int count)
-{
- int drive = DRIVE(inode->i_rdev);
-
- check_disk_change(inode->i_rdev);
- if (UTESTF(FD_DISK_CHANGED))
- return -ENXIO;
- return block_read(inode, filp, buf, count);
-}
-
-static int floppy_write(struct inode * inode, struct file * filp,
- const char * buf, int count)
-{
- int block;
- int ret;
- int drive = DRIVE(inode->i_rdev);
-
- if (!UDRS->maxblock)
- UDRS->maxblock=1;/* make change detectable */
- check_disk_change(inode->i_rdev);
- if (UTESTF(FD_DISK_CHANGED))
- return -ENXIO;
- if (!UTESTF(FD_DISK_WRITABLE))
- return -EROFS;
- block = (filp->f_pos + count) >> 9;
- INFBOUND(UDRS->maxblock, block);
- ret= block_write(inode, filp, buf, count);
- return ret;
-}
-
-static void floppy_release(struct inode * inode, struct file * filp)
-{
- int drive;
-
- drive = DRIVE(inode->i_rdev);
-
- if (!filp || (filp->f_mode & (2 | OPEN_WRITE_BIT)))
- /* if the file is mounted OR (writable now AND writable at
- * open time) Linus: Does this cover all cases? */
- block_fsync(inode,filp);
-
- if (UDRS->fd_ref < 0)
- UDRS->fd_ref=0;
- else if (!UDRS->fd_ref--) {
- DPRINT("floppy_release with fd_ref == 0");
- UDRS->fd_ref = 0;
- }
- floppy_release_irq_and_dma();
-}
-
-/*
- * floppy_open check for aliasing (/dev/fd0 can be the same as
- * /dev/PS0 etc), and disallows simultaneous access to the same
- * drive with different device numbers.
- */
-#define RETERR(x) do{floppy_release(inode,filp); return -(x);}while(0)
-
-static int floppy_open(struct inode * inode, struct file * filp)
-{
- int drive;
- int old_dev;
- int try;
- char *tmp;
-
- if (!filp) {
- DPRINT("Weird, open called with filp=0\n");
- return -EIO;
- }
-
- drive = DRIVE(inode->i_rdev);
- if (drive >= N_DRIVE ||
- !(allowed_drive_mask & (1 << drive)) ||
- fdc_state[FDC(drive)].version == FDC_NONE)
- return -ENXIO;
-
- if (TYPE(inode->i_rdev) >= NUMBER(floppy_type))
- return -ENXIO;
- old_dev = UDRS->fd_device;
- if (UDRS->fd_ref && old_dev != MINOR(inode->i_rdev))
- return -EBUSY;
-
- if (!UDRS->fd_ref && (UDP->flags & FD_BROKEN_DCL)){
- USETF(FD_DISK_CHANGED);
- USETF(FD_VERIFY);
- }
-
- if (UDRS->fd_ref == -1 ||
- (UDRS->fd_ref && (filp->f_flags & O_EXCL)))
- return -EBUSY;
-
- if (floppy_grab_irq_and_dma())
- return -EBUSY;
-
- if (filp->f_flags & O_EXCL)
- UDRS->fd_ref = -1;
- else
- UDRS->fd_ref++;
-
- if (!floppy_track_buffer){
- /* if opening an ED drive, reserve a big buffer,
- * else reserve a small one */
- if ((UDP->cmos == 6) || (UDP->cmos == 5))
- try = 64; /* Only 48 actually useful */
- else
- try = 32; /* Only 24 actually useful */
-
- tmp=(char *)dma_mem_alloc(1024 * try);
- if (!tmp) {
- try >>= 1; /* buffer only one side */
- INFBOUND(try, 16);
- tmp= (char *)dma_mem_alloc(1024*try);
- }
- if (!tmp) {
- DPRINT("Unable to allocate DMA memory\n");
- RETERR(ENXIO);
- }
- if (floppy_track_buffer){
- free_pages((unsigned long)tmp,__get_order(try*1024));
- }else {
- buffer_min = buffer_max = -1;
- floppy_track_buffer = tmp;
- max_buffer_sectors = try;
- }
- }
-
- UDRS->fd_device = MINOR(inode->i_rdev);
- if (old_dev != -1 && old_dev != MINOR(inode->i_rdev)) {
- if (buffer_drive == drive)
- buffer_track = -1;
- invalidate_buffers(MKDEV(FLOPPY_MAJOR,old_dev));
- }
-
- /* Allow ioctls if we have write-permissions even if read-only open */
- if ((filp->f_mode & 2) || (permission(inode,2) == 0))
- filp->f_mode |= IOCTL_MODE_BIT;
- if (filp->f_mode & 2)
- filp->f_mode |= OPEN_WRITE_BIT;
-
- if (UFDCS->rawcmd == 1)
- UFDCS->rawcmd = 2;
-
- if (filp->f_flags & O_NDELAY)
- return 0;
- if (filp->f_mode & 3) {
- UDRS->last_checked = 0;
- check_disk_change(inode->i_rdev);
- if (UTESTF(FD_DISK_CHANGED))
- RETERR(ENXIO);
- }
- if ((filp->f_mode & 2) && !(UTESTF(FD_DISK_WRITABLE)))
- RETERR(EROFS);
- return 0;
-#undef RETERR
-}
-
-/*
- * Check if the disk has been changed or if a change has been faked.
- */
-static int check_floppy_change(kdev_t dev)
-{
- int drive = DRIVE(dev);
-
- if (MAJOR(dev) != MAJOR_NR) {
- DPRINT("floppy_changed: not a floppy\n");
- return 0;
- }
-
- if (UTESTF(FD_DISK_CHANGED) || UTESTF(FD_VERIFY))
- return 1;
-
- if (UDRS->last_checked + UDP->checkfreq < jiffies){
- lock_fdc(drive,0);
- poll_drive(0,0);
- process_fd_request();
- }
-
- if (UTESTF(FD_DISK_CHANGED) ||
- UTESTF(FD_VERIFY) ||
- test_bit(drive, &fake_change) ||
- (!TYPE(dev) && !current_type[drive]))
- return 1;
- return 0;
-}
-
-/* revalidate the floppy disk, i.e. trigger format autodetection by reading
- * the bootblock (block 0). "Autodetection" is also needed to check whether
- * there is a disk in the drive at all... Thus we also do it for fixed
- * geometry formats */
-static int floppy_revalidate(kdev_t dev)
-{
-#define NO_GEOM (!current_type[drive] && !TYPE(dev))
- struct buffer_head * bh;
- int drive=DRIVE(dev);
- int cf;
-
- if (UTESTF(FD_DISK_CHANGED) ||
- UTESTF(FD_VERIFY) ||
- test_bit(drive, &fake_change) ||
- NO_GEOM){
- lock_fdc(drive,0);
- cf = UTESTF(FD_DISK_CHANGED) || UTESTF(FD_VERIFY);
- if (!(cf || test_bit(drive, &fake_change) || NO_GEOM)){
- process_fd_request(); /*already done by another thread*/
- return 0;
- }
- UDRS->maxblock = 0;
- UDRS->maxtrack = 0;
- if (buffer_drive == drive)
- buffer_track = -1;
- clear_bit(drive, &fake_change);
- UCLEARF(FD_DISK_CHANGED);
- if (cf)
- UDRS->generation++;
- if (NO_GEOM){
- /* auto-sensing */
- int size = floppy_blocksizes[MINOR(dev)];
- if (!size)
- size = 1024;
- if (!(bh = getblk(dev,0,size))){
- process_fd_request();
- return 1;
- }
- if (bh && !buffer_uptodate(bh))
- ll_rw_block(READ, 1, &bh);
- process_fd_request();
- wait_on_buffer(bh);
- brelse(bh);
- return 0;
- }
- if (cf)
- poll_drive(0, FD_RAW_NEED_DISK);
- process_fd_request();
- }
- return 0;
-}
-
-static struct file_operations floppy_fops = {
- NULL, /* lseek - default */
- floppy_read, /* read - general block-dev read */
- floppy_write, /* write - general block-dev write */
- NULL, /* readdir - bad */
- NULL, /* select */
- fd_ioctl, /* ioctl */
- NULL, /* mmap */
- floppy_open, /* open */
- floppy_release, /* release */
- block_fsync, /* fsync */
- NULL, /* fasync */
- check_floppy_change, /* media_change */
- floppy_revalidate, /* revalidate */
-};
-
-/*
- * Floppy Driver initialisation
- * =============================
- */
-
-/* Determine the floppy disk controller type */
-/* This routine was written by David C. Niemi */
-static char get_fdc_version(void)
-{
- int r;
-
- output_byte(FD_DUMPREGS); /* 82072 and better know DUMPREGS */
- if (FDCS->reset)
- return FDC_NONE;
- if ((r = result()) <= 0x00)
- return FDC_NONE; /* No FDC present ??? */
- if ((r==1) && (reply_buffer[0] == 0x80)){
- printk("FDC %d is a 8272A\n",fdc);
- return FDC_8272A; /* 8272a/765 don't know DUMPREGS */
- }
- if (r != 10) {
- printk("FDC %d init: DUMPREGS: unexpected return of %d bytes.\n",
- fdc, r);
- return FDC_UNKNOWN;
- }
- output_byte(FD_VERSION);
- r = result();
- if ((r == 1) && (reply_buffer[0] == 0x80)){
- printk("FDC %d is a 82072\n",fdc);
- return FDC_82072; /* 82072 doesn't know VERSION */
- }
- if ((r != 1) || (reply_buffer[0] != 0x90)) {
- printk("FDC %d init: VERSION: unexpected return of %d bytes.\n",
- fdc, r);
- return FDC_UNKNOWN;
- }
- output_byte(FD_UNLOCK);
- r = result();
- if ((r == 1) && (reply_buffer[0] == 0x80)){
- printk("FDC %d is a pre-1991 82077\n", fdc);
- return FDC_82077_ORIG; /* Pre-1991 82077 doesn't know LOCK/UNLOCK */
- }
- if ((r != 1) || (reply_buffer[0] != 0x00)) {
- printk("FDC %d init: UNLOCK: unexpected return of %d bytes.\n",
- fdc, r);
- return FDC_UNKNOWN;
- }
- output_byte(FD_PARTID);
- r = result();
- if (r != 1) {
- printk("FDC %d init: PARTID: unexpected return of %d bytes.\n",
- fdc, r);
- return FDC_UNKNOWN;
- }
- if (reply_buffer[0] == 0x80) {
- printk("FDC %d is a post-1991 82077\n",fdc);
- return FDC_82077; /* Revised 82077AA passes all the tests */
- }
- switch (reply_buffer[0] >> 5) {
- case 0x0:
- output_byte(FD_SAVE);
- r = result();
- if (r != 16) {
- printk("FDC %d init: SAVE: unexpected return of %d bytes.\n", fdc, r);
- return FDC_UNKNOWN;
- }
- if (!(reply_buffer[0] & 0x40)) {
- printk("FDC %d is a 3Volt 82078SL.\n",fdc);
- return FDC_82078;
- }
- /* Either a 82078-1 or a 82078SL running at 5Volt */
- printk("FDC %d is a 82078-1.\n",fdc);
- return FDC_82078_1;
- case 0x1:
- printk("FDC %d is a 44pin 82078\n",fdc);
- return FDC_82078;
- case 0x2:
- printk("FDC %d is a S82078B\n", fdc);
- return FDC_S82078B;
- case 0x3:
- printk("FDC %d is a National Semiconductor PC87306\n", fdc);
- return FDC_87306;
- default:
- printk("FDC %d init: 82077 variant with PARTID=%d.\n",
- fdc, reply_buffer[0] >> 5);
- return FDC_82077_UNKN;
- }
-} /* get_fdc_version */
-
-/* lilo configuration */
-
-/* we make the invert_dcl function global. One day, somebody might
- * want to centralize all thinkpad related options into one lilo option,
- * there are just so many thinkpad related quirks! */
-void floppy_invert_dcl(int *ints,int param)
-{
- int i;
-
- for (i=0; i < ARRAY_SIZE(default_drive_params); i++){
- if (param)
- default_drive_params[i].params.flags |= 0x80;
- else
- default_drive_params[i].params.flags &= ~0x80;
- }
- DPRINT("Configuring drives for inverted dcl\n");
-}
-
-static void daring(int *ints,int param)
-{
- int i;
-
- for (i=0; i < ARRAY_SIZE(default_drive_params); i++){
- if (param){
- default_drive_params[i].params.select_delay = 0;
- default_drive_params[i].params.flags |= FD_SILENT_DCL_CLEAR;
- } else {
- default_drive_params[i].params.select_delay = 2*HZ/100;
- default_drive_params[i].params.flags &= ~FD_SILENT_DCL_CLEAR;
- }
- }
- DPRINT1("Assuming %s floppy hardware\n", param ? "standard" : "broken");
-}
-
-static void allow_drives(int *ints, int param)
-{
- allowed_drive_mask=param;
- DPRINT1("setting allowed_drive_mask to 0x%x\n", param);
-}
-
-static void fdc2_adr(int *ints, int param)
-{
- FDC2 = param;
- if (param)
- DPRINT1("enabling second fdc at address 0x%3x\n", FDC2);
- else
- DPRINT("disabling second fdc\n");
-}
-
-static void unex(int *ints,int param)
-{
- print_unex = param;
- DPRINT1("%sprinting messages for unexpected interrupts\n",
- param ? "" : "not ");
-}
-
-static void set_cmos(int *ints, int dummy)
-{
- int current_drive=0;
-
- if (ints[0] != 2){
- DPRINT("wrong number of parameter for cmos\n");
- return;
- }
- current_drive = ints[1];
- if (current_drive < 0 || current_drive >= 8){
- DPRINT("bad drive for set_cmos\n");
- return;
- }
- if (current_drive >= 4 && !FDC2)
- fdc2_adr(0, 0x370);
- if (ints[2] <= 0 || ints[2] >= NUMBER(default_drive_params)){
- DPRINT1("bad cmos code %d\n", ints[2]);
- return;
- }
- DP->cmos = ints[2];
- DPRINT1("setting cmos code to %d\n", ints[2]);
-}
-
-static struct param_table {
- const char *name;
- void (*fn)(int *ints, int param);
- int def_param;
-} config_params[]={
- { "allowed_drive_mask", allow_drives, 0xff },
- { "all_drives", allow_drives, 0xff },
- { "asus_pci", allow_drives, 0x33 },
-
- { "daring", daring, 1},
-
- { "two_fdc", fdc2_adr, 0x370 },
- { "one_fdc", fdc2_adr, 0 },
-
- { "thinkpad", floppy_invert_dcl, 1 },
-
- { "cmos", set_cmos, 0 },
-
- { "unexpected_interrupts", unex, 1 },
- { "no_unexpected_interrupts", unex, 0 },
- { "L40SX", unex, 0 } };
-
-#define FLOPPY_SETUP
-void floppy_setup(char *str, int *ints)
-{
- int i;
- int param;
- if (str)
- for (i=0; i< ARRAY_SIZE(config_params); i++){
- if (strcmp(str,config_params[i].name) == 0){
- if (ints[0])
- param = ints[1];
- else
- param = config_params[i].def_param;
- config_params[i].fn(ints,param);
- return;
- }
- }
- if (str) {
- DPRINT1("unknown floppy option [%s]\n", str);
-
- DPRINT("allowed options are:");
- for (i=0; i< ARRAY_SIZE(config_params); i++)
- printk(" %s",config_params[i].name);
- printk("\n");
- } else
- DPRINT("botched floppy option\n");
- DPRINT("Read linux/drivers/block/README.fd\n");
-}
-
-int floppy_init(void)
-{
- int i,unit,drive;
- int have_no_fdc= -EIO;
-
- raw_cmd = 0;
-
- sti();
-
- if (register_blkdev(MAJOR_NR,"fd",&floppy_fops)) {
- printk("Unable to get major %d for floppy\n",MAJOR_NR);
- return -EBUSY;
- }
-
- for (i=0; i<256; i++)
- if (ITYPE(i))
- floppy_sizes[i] = floppy_type[ITYPE(i)].size >> 1;
- else
- floppy_sizes[i] = MAX_DISK_SIZE;
-
- blk_size[MAJOR_NR] = floppy_sizes;
- blksize_size[MAJOR_NR] = floppy_blocksizes;
- blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
- reschedule_timeout(MAXTIMEOUT, "floppy init", MAXTIMEOUT);
- config_types();
-
- for (i = 0; i < N_FDC; i++) {
- fdc = i;
- CLEARSTRUCT(FDCS);
- FDCS->dtr = -1;
- FDCS->dor = 0x4;
- }
-
- fdc_state[0].address = FDC1;
-#if N_FDC > 1
- fdc_state[1].address = FDC2;
-#endif
-
- if (floppy_grab_irq_and_dma()){
- unregister_blkdev(MAJOR_NR,"fd");
- return -EBUSY;
- }
-
- /* initialise drive state */
- for (drive = 0; drive < N_DRIVE; drive++) {
- CLEARSTRUCT(UDRS);
- CLEARSTRUCT(UDRWE);
- UDRS->flags = FD_VERIFY | FD_DISK_NEWCHANGE | FD_DISK_CHANGED;
- UDRS->fd_device = -1;
- floppy_track_buffer = NULL;
- max_buffer_sectors = 0;
- }
-
- for (i = 0; i < N_FDC; i++) {
- fdc = i;
- FDCS->driver_version = FD_DRIVER_VERSION;
- for (unit=0; unit<4; unit++)
- FDCS->track[unit] = 0;
- if (FDCS->address == -1)
- continue;
- FDCS->rawcmd = 2;
- if (user_reset_fdc(-1,FD_RESET_ALWAYS,0)){
- FDCS->address = -1;
- continue;
- }
- /* Try to determine the floppy controller type */
- FDCS->version = get_fdc_version();
- if (FDCS->version == FDC_NONE){
- FDCS->address = -1;
- continue;
- }
-
- request_region(FDCS->address, 6, "floppy");
- request_region(FDCS->address+7, 1, "floppy DIR");
- /* address + 6 is reserved, and may be taken by IDE.
- * Unfortunately, Adaptec doesn't know this :-(, */
-
- have_no_fdc = 0;
- /* Not all FDCs seem to be able to handle the version command
- * properly, so force a reset for the standard FDC clones,
- * to avoid interrupt garbage.
- */
- FDCS->has_fifo = FDCS->version >= FDC_82077_ORIG;
- user_reset_fdc(-1,FD_RESET_ALWAYS,0);
- }
- fdc=0;
- del_timer(&fd_timeout);
- current_drive = 0;
- floppy_release_irq_and_dma();
- initialising=0;
- if (have_no_fdc) {
- DPRINT("no floppy controllers found\n");
- unregister_blkdev(MAJOR_NR,"fd");
- } else
- virtual_dma_init();
- return have_no_fdc;
-}
-
-static int floppy_grab_irq_and_dma(void)
-{
- int i;
- cli();
- if (usage_count++){
- sti();
- return 0;
- }
- sti();
- MOD_INC_USE_COUNT;
- for (i=0; i< N_FDC; i++){
- if (FDCS->address != -1){
- fdc = i;
- reset_fdc_info(1);
- fd_outb(FDCS->dor, FD_DOR);
- }
- }
- set_dor(0, ~0, 8); /* avoid immediate interrupt */
-
- if (fd_request_irq()) {
- DPRINT1("Unable to grab IRQ%d for the floppy driver\n",
- FLOPPY_IRQ);
- return -1;
- }
- if (fd_request_dma()) {
- DPRINT1("Unable to grab DMA%d for the floppy driver\n",
- FLOPPY_DMA);
- fd_free_irq();
- return -1;
- }
- for (fdc = 0; fdc < N_FDC; fdc++)
- if (FDCS->address != -1)
- fd_outb(FDCS->dor, FD_DOR);
- fdc = 0;
- fd_enable_irq();
- return 0;
-}
-
-static void floppy_release_irq_and_dma(void)
-{
-#ifdef FLOPPY_SANITY_CHECK
- int drive;
-#endif
- long tmpsize;
- void *tmpaddr;
-
- cli();
- if (--usage_count){
- sti();
- return;
- }
- sti();
- MOD_DEC_USE_COUNT;
- fd_disable_dma();
- fd_free_dma();
- fd_disable_irq();
- fd_free_irq();
-
- set_dor(0, ~0, 8);
-#if N_FDC > 1
- set_dor(1, ~8, 0);
-#endif
- floppy_enable_hlt();
-
- if (floppy_track_buffer && max_buffer_sectors) {
- tmpsize = max_buffer_sectors*1024;
- tmpaddr = (void *)floppy_track_buffer;
- floppy_track_buffer = 0;
- max_buffer_sectors = 0;
- buffer_min = buffer_max = -1;
- free_pages((unsigned long)tmpaddr, __get_order(tmpsize));
- }
-
-#ifdef FLOPPY_SANITY_CHECK
- for (drive=0; drive < N_FDC * 4; drive++)
- if (motor_off_timer[drive].next)
- printk("motor off timer %d still active\n", drive);
-
- if (fd_timeout.next)
- printk("floppy timer still active:%s\n", timeout_message);
- if (fd_timer.next)
- printk("auxiliary floppy timer still active\n");
- if (floppy_tq.sync)
- printk("task queue still active\n");
-#endif
-}
-
-
-#ifdef MODULE
-
-extern char *get_options(char *str, int *ints);
-
-static void mod_setup(char *pattern, void (*setup)(char *, int *))
-{
- int i;
- char c;
- int j;
- int match;
- char buffer[100];
- int ints[11];
- int length = strlen(pattern)+1;
-
- match=0;
- j=1;
-
- for (i=current->mm->env_start; i< current->mm->env_end; i ++){
- c= get_fs_byte(i);
- if (match){
- if (j==99)
- c='\0';
- buffer[j] = c;
- if (!c || c == ' ' || c == '\t'){
- if (j){
- buffer[j] = '\0';
- setup(get_options(buffer,ints),ints);
- }
- j=0;
- } else
- j++;
- if (!c)
- break;
- continue;
- }
- if ((!j && !c) || (j && c == pattern[j-1]))
- j++;
- else
- j=0;
- if (j==length){
- match=1;
- j=0;
- }
- }
-}
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-int init_module(void)
-{
- printk("inserting floppy driver for %s\n", kernel_version);
-
- mod_setup("floppy=", floppy_setup);
-
- return floppy_init();
-}
-
-void cleanup_module(void)
-{
- int fdc;
-
- for (fdc=0; fdc<2; fdc++)
- if (FDCS->address != -1){
- release_region(FDCS->address, 6);
- release_region(FDCS->address+7, 1);
- }
-
- unregister_blkdev(MAJOR_NR, "fd");
-
- blk_dev[MAJOR_NR].request_fn = 0;
-}
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/i386/i386at/gpl/linux/block/genhd.c b/i386/i386at/gpl/linux/block/genhd.c
deleted file mode 100644
index cebc7ea..0000000
--- a/i386/i386at/gpl/linux/block/genhd.c
+++ /dev/null
@@ -1,610 +0,0 @@
-/*
- * Code extracted from
- * linux/kernel/hd.c
- *
- * Copyright (C) 1991, 1992 Linus Torvalds
- *
- *
- * Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug
- * in the early extended-partition checks and added DM partitions
- *
- * Support for DiskManager v6.0x added by Mark Lord (mlord@bnr.ca)
- * with information provided by OnTrack. This now works for linux fdisk
- * and LILO, as well as loadlin and bootln. Note that disks other than
- * /dev/hda *must* have a "DOS" type 0x51 partition in the first slot (hda1).
- *
- * More flexible handling of extended partitions - aeb, 950831
- *
- * Check partition table on IDE disks for common CHS translations
- */
-
-#include <linux/config.h>
-#include <linux/fs.h>
-#include <linux/genhd.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/string.h>
-
-#include <asm/system.h>
-
-#ifdef __alpha__
-/*
- * On the Alpha, we get unaligned access exceptions on
- * p->nr_sects and p->start_sect, when the partition table
- * is not on a 4-byte boundary, which is frequently the case.
- * This code uses unaligned load instructions to prevent
- * such exceptions.
- */
-#include <asm/unaligned.h>
-#define NR_SECTS(p) ldl_u(&p->nr_sects)
-#define START_SECT(p) ldl_u(&p->start_sect)
-#else /* __alpha__ */
-#define NR_SECTS(p) p->nr_sects
-#define START_SECT(p) p->start_sect
-#endif /* __alpha__ */
-
-#ifdef MACH
-#include <i386/ipl.h>
-#endif
-
-struct gendisk *gendisk_head = NULL;
-
-static int current_minor = 0;
-extern int *blk_size[];
-extern void rd_load(void);
-
-extern int chr_dev_init(void);
-extern int blk_dev_init(void);
-extern int scsi_dev_init(void);
-extern int net_dev_init(void);
-
-static void print_minor_name (struct gendisk *hd, int minor)
-{
- unsigned int unit = minor >> hd->minor_shift;
- unsigned int part = minor & ((1 << hd->minor_shift) - 1);
-
-#ifdef CONFIG_BLK_DEV_IDE
- /*
- * IDE devices use multiple major numbers, but the drives
- * are named as: {hda,hdb}, {hdc,hdd}, {hde,hdf}, {hdg,hdh}..
- * This requires some creative handling here to find the
- * correct name to use, with some help from ide.c
- */
- if (!strcmp(hd->major_name,"ide")) {
- char name[16]; /* more than large enough */
- strcpy(name, hd->real_devices); /* courtesy ide.c */
- name[strlen(name)-1] += unit;
- printk(" %s", name);
- } else
-#endif
- printk(" %s%c", hd->major_name, 'a' + unit);
- if (part)
- printk("%d", part);
- else
- printk(":");
-}
-
-static void add_partition (struct gendisk *hd, int minor, int start, int size)
-{
- hd->part[minor].start_sect = start;
- hd->part[minor].nr_sects = size;
- /* print_minor_name(hd, minor);*/
-}
-
-static inline int is_extended_partition(struct partition *p)
-{
- return (p->sys_ind == DOS_EXTENDED_PARTITION ||
- p->sys_ind == LINUX_EXTENDED_PARTITION);
-}
-
-#ifdef CONFIG_MSDOS_PARTITION
-/*
- * Create devices for each logical partition in an extended partition.
- * The logical partitions form a linked list, with each entry being
- * a partition table with two entries. The first entry
- * is the real data partition (with a start relative to the partition
- * table start). The second is a pointer to the next logical partition
- * (with a start relative to the entire extended partition).
- * We do not create a Linux partition for the partition tables, but
- * only for the actual data partitions.
- */
-
-static void extended_partition(struct gendisk *hd, kdev_t dev)
-{
- struct buffer_head *bh;
- struct partition *p;
- unsigned long first_sector, first_size, this_sector, this_size;
- int mask = (1 << hd->minor_shift) - 1;
- int i;
-
- first_sector = hd->part[MINOR(dev)].start_sect;
- first_size = hd->part[MINOR(dev)].nr_sects;
- this_sector = first_sector;
-
- while (1) {
- if ((current_minor & mask) == 0)
- return;
- if (!(bh = bread(dev,0,1024)))
- return;
- /*
- * This block is from a device that we're about to stomp on.
- * So make sure nobody thinks this block is usable.
- */
- bh->b_state = 0;
-
- if (*(unsigned short *) (bh->b_data+510) != 0xAA55)
- goto done;
-
- p = (struct partition *) (0x1BE + bh->b_data);
-
- this_size = hd->part[MINOR(dev)].nr_sects;
-
- /*
- * Usually, the first entry is the real data partition,
- * the 2nd entry is the next extended partition, or empty,
- * and the 3rd and 4th entries are unused.
- * However, DRDOS sometimes has the extended partition as
- * the first entry (when the data partition is empty),
- * and OS/2 seems to use all four entries.
- */
-
- /*
- * First process the data partition(s)
- */
- for (i=0; i<4; i++, p++) {
- if (!NR_SECTS(p) || is_extended_partition(p))
- continue;
-
- /* Check the 3rd and 4th entries -
- these sometimes contain random garbage */
- if (i >= 2
- && START_SECT(p) + NR_SECTS(p) > this_size
- && (this_sector + START_SECT(p) < first_sector ||
- this_sector + START_SECT(p) + NR_SECTS(p) >
- first_sector + first_size))
- continue;
-
- add_partition(hd, current_minor, this_sector+START_SECT(p), NR_SECTS(p));
- current_minor++;
- if ((current_minor & mask) == 0)
- goto done;
- }
- /*
- * Next, process the (first) extended partition, if present.
- * (So far, there seems to be no reason to make
- * extended_partition() recursive and allow a tree
- * of extended partitions.)
- * It should be a link to the next logical partition.
- * Create a minor for this just long enough to get the next
- * partition table. The minor will be reused for the next
- * data partition.
- */
- p -= 4;
- for (i=0; i<4; i++, p++)
- if(NR_SECTS(p) && is_extended_partition(p))
- break;
- if (i == 4)
- goto done; /* nothing left to do */
-
- hd->part[current_minor].nr_sects = NR_SECTS(p);
- hd->part[current_minor].start_sect = first_sector + START_SECT(p);
- this_sector = first_sector + START_SECT(p);
- dev = MKDEV(hd->major, current_minor);
- brelse(bh);
- }
-done:
- brelse(bh);
-}
-
-static int msdos_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector)
-{
- int i, minor = current_minor;
- struct buffer_head *bh;
- struct partition *p;
- unsigned char *data;
- int mask = (1 << hd->minor_shift) - 1;
-#ifdef CONFIG_BLK_DEV_IDE
- int tested_for_xlate = 0;
-
-read_mbr:
-#endif
- if (!(bh = bread(dev,0,1024))) {
- printk(" unable to read partition table\n");
- return -1;
- }
- data = bh->b_data;
- /* In some cases we modify the geometry */
- /* of the drive (below), so ensure that */
- /* nobody else tries to re-use this data. */
- bh->b_state = 0;
-#ifdef CONFIG_BLK_DEV_IDE
-check_table:
-#endif
- if (*(unsigned short *) (0x1fe + data) != 0xAA55) {
- brelse(bh);
- return 0;
- }
- p = (struct partition *) (0x1be + data);
-
-#ifdef CONFIG_BLK_DEV_IDE
- if (!tested_for_xlate++) { /* Do this only once per disk */
- /*
- * Look for various forms of IDE disk geometry translation
- */
- extern int ide_xlate_1024(kdev_t, int, const char *);
- unsigned int sig = *(unsigned short *)(data + 2);
- if (p->sys_ind == EZD_PARTITION) {
- /*
- * The remainder of the disk must be accessed using
- * a translated geometry that reduces the number of
- * apparent cylinders to less than 1024 if possible.
- *
- * ide_xlate_1024() will take care of the necessary
- * adjustments to fool fdisk/LILO and partition check.
- */
- if (ide_xlate_1024(dev, -1, " [EZD]")) {
- data += 512;
- goto check_table;
- }
- } else if (p->sys_ind == DM6_PARTITION) {
-
- /*
- * Everything on the disk is offset by 63 sectors,
- * including a "new" MBR with its own partition table,
- * and the remainder of the disk must be accessed using
- * a translated geometry that reduces the number of
- * apparent cylinders to less than 1024 if possible.
- *
- * ide_xlate_1024() will take care of the necessary
- * adjustments to fool fdisk/LILO and partition check.
- */
- if (ide_xlate_1024(dev, 1, " [DM6:DDO]")) {
- brelse(bh);
- goto read_mbr; /* start over with new MBR */
- }
- } else if (sig <= 0x1ae && *(unsigned short *)(data + sig) == 0x55AA
- && (1 & *(unsigned char *)(data + sig + 2)) )
- {
- /*
- * DM6 signature in MBR, courtesy of OnTrack
- */
- (void) ide_xlate_1024 (dev, 0, " [DM6:MBR]");
- } else if (p->sys_ind == DM6_AUX1PARTITION || p->sys_ind == DM6_AUX3PARTITION) {
- /*
- * DM6 on other than the first (boot) drive
- */
- (void) ide_xlate_1024(dev, 0, " [DM6:AUX]");
- } else {
- /*
- * Examine the partition table for common translations.
- * This is necessary for drives for situations where
- * the translated geometry is unavailable from the BIOS.
- */
- for (i = 0; i < 4 ; i++) {
- struct partition *q = &p[i];
- if (NR_SECTS(q) && q->sector == 1 && q->end_sector == 63) {
- unsigned int heads = q->end_head + 1;
- if (heads == 32 || heads == 64 || heads == 128) {
-
- (void) ide_xlate_1024(dev, heads, " [PTBL]");
- break;
- }
- }
- }
- }
- }
-#endif /* CONFIG_BLK_DEV_IDE */
-
- current_minor += 4; /* first "extra" minor (for extended partitions) */
- for (i=1 ; i<=4 ; minor++,i++,p++) {
- if (!NR_SECTS(p))
- continue;
- add_partition(hd, minor, first_sector+START_SECT(p), NR_SECTS(p));
- if (is_extended_partition(p)) {
- /* printk(" <");*/
- /*
- * If we are rereading the partition table, we need
- * to set the size of the partition so that we will
- * be able to bread the block containing the extended
- * partition info.
- */
- hd->sizes[minor] = hd->part[minor].nr_sects
- >> (BLOCK_SIZE_BITS - 9);
- extended_partition(hd, MKDEV(hd->major, minor));
- /* printk(" >");*/
- /* prevent someone doing mkfs or mkswap on an
- extended partition, but leave room for LILO */
- if (hd->part[minor].nr_sects > 2)
- hd->part[minor].nr_sects = 2;
- }
- }
- /*
- * Check for old-style Disk Manager partition table
- */
- if (*(unsigned short *) (data+0xfc) == 0x55AA) {
- p = (struct partition *) (0x1be + data);
- for (i = 4 ; i < 16 ; i++, current_minor++) {
- p--;
- if ((current_minor & mask) == 0)
- break;
- if (!(START_SECT(p) && NR_SECTS(p)))
- continue;
- add_partition(hd, current_minor, START_SECT(p), NR_SECTS(p));
- }
- }
- /* printk("\n");*/
- brelse(bh);
- return 1;
-}
-
-#endif /* CONFIG_MSDOS_PARTITION */
-
-#ifdef CONFIG_OSF_PARTITION
-
-static int osf_partition(struct gendisk *hd, unsigned int dev, unsigned long first_sector)
-{
- int i;
- int mask = (1 << hd->minor_shift) - 1;
- struct buffer_head *bh;
- struct disklabel {
- u32 d_magic;
- u16 d_type,d_subtype;
- u8 d_typename[16];
- u8 d_packname[16];
- u32 d_secsize;
- u32 d_nsectors;
- u32 d_ntracks;
- u32 d_ncylinders;
- u32 d_secpercyl;
- u32 d_secprtunit;
- u16 d_sparespertrack;
- u16 d_sparespercyl;
- u32 d_acylinders;
- u16 d_rpm, d_interleave, d_trackskew, d_cylskew;
- u32 d_headswitch, d_trkseek, d_flags;
- u32 d_drivedata[5];
- u32 d_spare[5];
- u32 d_magic2;
- u16 d_checksum;
- u16 d_npartitions;
- u32 d_bbsize, d_sbsize;
- struct d_partition {
- u32 p_size;
- u32 p_offset;
- u32 p_fsize;
- u8 p_fstype;
- u8 p_frag;
- u16 p_cpg;
- } d_partitions[8];
- } * label;
- struct d_partition * partition;
-#define DISKLABELMAGIC (0x82564557UL)
-
- if (!(bh = bread(dev,0,1024))) {
- printk("unable to read partition table\n");
- return -1;
- }
- label = (struct disklabel *) (bh->b_data+64);
- partition = label->d_partitions;
- if (label->d_magic != DISKLABELMAGIC) {
- printk("magic: %08x\n", label->d_magic);
- brelse(bh);
- return 0;
- }
- if (label->d_magic2 != DISKLABELMAGIC) {
- printk("magic2: %08x\n", label->d_magic2);
- brelse(bh);
- return 0;
- }
- for (i = 0 ; i < label->d_npartitions; i++, partition++) {
- if ((current_minor & mask) == 0)
- break;
- if (partition->p_size)
- add_partition(hd, current_minor,
- first_sector+partition->p_offset,
- partition->p_size);
- current_minor++;
- }
- /* printk("\n");*/
- brelse(bh);
- return 1;
-}
-
-#endif /* CONFIG_OSF_PARTITION */
-
-#ifdef CONFIG_SUN_PARTITION
-
-static int sun_partition(struct gendisk *hd, unsigned int dev, unsigned long first_sector)
-{
- int i, csum;
- unsigned short *ush;
- struct buffer_head *bh;
- struct sun_disklabel {
- unsigned char info[128]; /* Informative text string */
- unsigned char spare[292]; /* Boot information etc. */
- unsigned short rspeed; /* Disk rotational speed */
- unsigned short pcylcount; /* Physical cylinder count */
- unsigned short sparecyl; /* extra sects per cylinder */
- unsigned char spare2[4]; /* More magic... */
- unsigned short ilfact; /* Interleave factor */
- unsigned short ncyl; /* Data cylinder count */
- unsigned short nacyl; /* Alt. cylinder count */
- unsigned short ntrks; /* Tracks per cylinder */
- unsigned short nsect; /* Sectors per track */
- unsigned char spare3[4]; /* Even more magic... */
- struct sun_partition {
- unsigned long start_cylinder;
- unsigned long num_sectors;
- } partitions[8];
- unsigned short magic; /* Magic number */
- unsigned short csum; /* Label xor'd checksum */
- } * label;
- struct sun_partition *p;
- unsigned long spc;
-#define SUN_LABEL_MAGIC 0xDABE
-
- if(!(bh = bread(dev, 0, 1024))) {
- printk("Dev %d: unable to read partition table\n", dev);
- return -1;
- }
- label = (struct sun_disklabel *) bh->b_data;
- p = label->partitions;
- if(label->magic != SUN_LABEL_MAGIC) {
- printk("Dev %d Sun disklabel: bad magic %08x\n", dev, label->magic);
- brelse(bh);
- return 0;
- }
- /* Look at the checksum */
- ush = ((unsigned short *) (label+1)) - 1;
- for(csum = 0; ush >= ((unsigned short *) label);)
- csum ^= *ush--;
- if(csum) {
- printk("Dev %d Sun disklabel: Csum bad, label corrupted\n", dev);
- brelse(bh);
- return 0;
- }
- /* All Sun disks have 8 partition entries */
- spc = (label->ntrks * label->nsect);
- for(i=0; i < 8; i++, p++) {
- unsigned long st_sector;
-
- /* We register all partitions, even if zero size, so that
- * the minor numbers end up ok as per SunOS interpretation.
- */
- st_sector = first_sector + (p->start_cylinder * spc);
- add_partition(hd, current_minor, st_sector, p->num_sectors);
- current_minor++;
- }
- /* printk("\n");*/
- brelse(bh);
- return 1;
-}
-
-#endif /* CONFIG_SUN_PARTITION */
-
-static void check_partition(struct gendisk *hd, kdev_t dev)
-{
- static int first_time = 1;
- unsigned long first_sector;
-
- /* if (first_time)
- printk("Partition check:\n");*/
- first_time = 0;
- first_sector = hd->part[MINOR(dev)].start_sect;
-
- /*
- * This is a kludge to allow the partition check to be
- * skipped for specific drives (e.g. IDE cd-rom drives)
- */
- if ((int)first_sector == -1) {
- hd->part[MINOR(dev)].start_sect = 0;
- return;
- }
-
- /* printk(" ");
- print_minor_name(hd, MINOR(dev));*/
-#ifdef CONFIG_MSDOS_PARTITION
- if (msdos_partition(hd, dev, first_sector))
- return;
-#endif
-#ifdef CONFIG_OSF_PARTITION
- if (osf_partition(hd, dev, first_sector))
- return;
-#endif
-#ifdef CONFIG_SUN_PARTITION
- if(sun_partition(hd, dev, first_sector))
- return;
-#endif
- printk(" unknown partition table\n");
-}
-
-/* This function is used to re-read partition tables for removable disks.
- Much of the cleanup from the old partition tables should have already been
- done */
-
-/* This function will re-read the partition tables for a given device,
-and set things back up again. There are some important caveats,
-however. You must ensure that no one is using the device, and no one
-can start using the device while this function is being executed. */
-
-void resetup_one_dev(struct gendisk *dev, int drive)
-{
- int i;
- int first_minor = drive << dev->minor_shift;
- int end_minor = first_minor + dev->max_p;
-
- blk_size[dev->major] = NULL;
- current_minor = 1 + first_minor;
- check_partition(dev, MKDEV(dev->major, first_minor));
-
- /*
- * We need to set the sizes array before we will be able to access
- * any of the partitions on this device.
- */
- if (dev->sizes != NULL) { /* optional safeguard in ll_rw_blk.c */
- for (i = first_minor; i < end_minor; i++)
- dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9);
- blk_size[dev->major] = dev->sizes;
- }
-}
-
-static void setup_dev(struct gendisk *dev)
-{
- int i, drive;
- int end_minor = dev->max_nr * dev->max_p;
-
- blk_size[dev->major] = NULL;
- for (i = 0 ; i < end_minor; i++) {
- dev->part[i].start_sect = 0;
- dev->part[i].nr_sects = 0;
- }
- dev->init(dev);
- for (drive = 0 ; drive < dev->nr_real ; drive++) {
- int first_minor = drive << dev->minor_shift;
- current_minor = 1 + first_minor;
- check_partition(dev, MKDEV(dev->major, first_minor));
- }
- if (dev->sizes != NULL) { /* optional safeguard in ll_rw_blk.c */
- for (i = 0; i < end_minor; i++)
- dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9);
- blk_size[dev->major] = dev->sizes;
- }
-}
-
-void device_setup(void)
-{
- extern void console_map_init(void);
- struct gendisk *p;
- int nr=0;
-#ifdef MACH
- extern int linux_intr_pri;
-
- linux_intr_pri = SPL5;
-#endif
-
-#ifndef MACH
- chr_dev_init();
-#endif
- blk_dev_init();
- sti();
-#ifdef CONFIG_SCSI
- scsi_dev_init();
-#endif
-#ifdef CONFIG_INET
-#ifdef MACH
- linux_intr_pri = SPL6;
-#endif
- net_dev_init();
-#endif
-#ifndef MACH
- console_map_init();
-#endif
-
- for (p = gendisk_head ; p ; p=p->next) {
- setup_dev(p);
- nr += p->nr_real;
- }
-#ifdef CONFIG_BLK_DEV_RAM
- rd_load();
-#endif
-}
diff --git a/i386/i386at/gpl/linux/block/ide-cd.c b/i386/i386at/gpl/linux/block/ide-cd.c
deleted file mode 100644
index 6dc9380..0000000
--- a/i386/i386at/gpl/linux/block/ide-cd.c
+++ /dev/null
@@ -1,2770 +0,0 @@
-/*
- * linux/drivers/block/ide-cd.c
- *
- * 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 occuring 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
- *
- * NOTE: Direct audio reads will only work on some types of drive.
- * So far, i've received reports of success for Sony and Toshiba drives.
- *
- * ATAPI cd-rom driver. To be used with ide.c.
- *
- * Copyright (C) 1994, 1995, 1996 scott snyder <snyder@fnald0.fnal.gov>
- * May be copied or modified under the terms of the GNU General Public License
- * (../../COPYING).
- */
-
-
-/***************************************************************************/
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/timer.h>
-#include <linux/malloc.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/blkdev.h>
-#include <linux/errno.h>
-#include <linux/hdreg.h>
-#include <linux/cdrom.h>
-#include <asm/irq.h>
-#include <asm/io.h>
-#include <asm/byteorder.h>
-#include <asm/segment.h>
-#ifdef __alpha__
-# include <asm/unaligned.h>
-#endif
-
-#include "ide.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 0
-#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 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
-
-/* Some ATAPI command opcodes (just like SCSI).
- (Some other cdrom-specific codes are in cdrom.h.) */
-#define TEST_UNIT_READY 0x00
-#define REQUEST_SENSE 0x03
-#define START_STOP 0x1b
-#define ALLOW_MEDIUM_REMOVAL 0x1e
-#define READ_CAPACITY 0x25
-#define READ_10 0x28
-#define MODE_SENSE_10 0x5a
-#define MODE_SELECT_10 0x55
-#define READ_CD 0xbe
-
-
-/* ATAPI sense keys (mostly copied from scsi.h). */
-
-#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
-
-/* We want some additional flags for cd-rom drives.
- To save space in the ide_drive_t struct, use some fields which
- doesn't make sense for cd-roms -- `bios_sect' and `bios_head'. */
-
-/* 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. */
-#if ! STANDARD_ATAPI
- __u8 no_playaudio12: 1; /* The PLAYAUDIO12 command is not supported. */
-
- __u8 no_lba_toc : 1; /* Drive cannot return TOC info in LBA format. */
- __u8 playmsf_uses_bcd : 1; /* Drive uses BCD in PLAYAUDIO_MSF. */
- __u8 old_readcd : 1; /* Drive uses old READ CD opcode. */
- __u8 vertos_lossage: 1; /* Drive is a Vertos 300,
- and likes to speak BCD. */
-#endif /* not STANDARD_ATAPI */
- __u8 reserved : 1;
-};
-#define CDROM_CONFIG_FLAGS(drive) ((struct ide_cd_config_flags *)&((drive)->bios_sect))
-
-
-/* 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 eject_on_close: 1; /* Drive should eject when device is closed. */
- __u8 reserved : 4;
-};
-#define CDROM_STATE_FLAGS(drive) ((struct ide_cd_state_flags *)&((drive)->bios_head))
-
-
-#define SECTOR_BUFFER_SIZE CD_FRAMESIZE
-
-
-
-/****************************************************************************
- * Routines to read and write data from/to the drive, using
- * the routines input_ide_data() and output_ide_data() from ide.c.
- *
- * 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.
- */
-
-
-static inline
-void cdrom_in_bytes (ide_drive_t *drive, void *buffer, uint bytecount)
-{
- ++bytecount;
- ide_input_data (drive, buffer, bytecount / 4);
- if ((bytecount & 0x03) >= 2)
- {
- insw (IDE_DATA_REG, ((byte *)buffer) + (bytecount & ~0x03), 1);
- }
-}
-
-
-static inline
-void cdrom_out_bytes (ide_drive_t *drive, void *buffer, uint bytecount)
-{
- ++bytecount;
- ide_output_data (drive, buffer, bytecount / 4);
- if ((bytecount & 0x03) >= 2)
- {
- outsw (IDE_DATA_REG, ((byte *)buffer) + (bytecount & ~0x03), 1);
- }
-}
-
-
-
-/****************************************************************************
- * Descriptions of ATAPI error codes.
- */
-
-#define ARY_LEN(a) ((sizeof(a) / sizeof(a[0])))
-
-#if VERBOSE_IDE_CD_ERRORS
-
-/* From Table 124 of the ATAPI 1.2 spec. */
-
-char *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 125 of the ATAPI 1.2 spec. */
-
-struct {
- short asc_ascq;
- char *text;
-} sense_data_texts[] = {
- { 0x0000, "No additional sense information" },
- { 0x0011, "Audio play operation in progress" },
- { 0x0012, "Audio play operation paused" },
- { 0x0013, "Audio play operation successfully completed" },
- { 0x0014, "Audio play operation stopped due to error" },
- { 0x0015, "No current audio status to return" },
-
- { 0x0200, "No seek complete" },
-
- { 0x0400, "Logical unit not ready - cause not reportable" },
- { 0x0401, "Logical unit not ready - in progress (sic) of becoming ready" },
- { 0x0402, "Logical unit not ready - initializing command required" },
- { 0x0403, "Logical unit not ready - manual intervention required" },
-
- { 0x0600, "No reference position found" },
-
- { 0x0900, "Track following error" },
- { 0x0901, "Tracking servo failure" },
- { 0x0902, "Focus servo failure" },
- { 0x0903, "Spindle servo failure" },
-
- { 0x1100, "Unrecovered read error" },
- { 0x1106, "CIRC unrecovered error" },
-
- { 0x1500, "Random positioning error" },
- { 0x1501, "Mechanical positioning error" },
- { 0x1502, "Positioning error detected by read of medium" },
-
- { 0x1700, "Recovered data with no error correction applied" },
- { 0x1701, "Recovered data with retries" },
- { 0x1702, "Recovered data with positive head offset" },
- { 0x1703, "Recovered data with negative head offset" },
- { 0x1704, "Recovered data with retries and/or CIRC applied" },
- { 0x1705, "Recovered data using previous sector ID" },
-
- { 0x1800, "Recovered data with error correction applied" },
- { 0x1801, "Recovered data with error correction and retries applied" },
- { 0x1802, "Recovered data - the data was auto-reallocated" },
- { 0x1803, "Recovered data with CIRC" },
- { 0x1804, "Recovered data with L-EC" },
- { 0x1805, "Recovered data - recommend reassignment" },
- { 0x1806, "Recovered data - recommend rewrite" },
-
- { 0x1a00, "Parameter list length error" },
-
- { 0x2000, "Invalid command operation code" },
-
- { 0x2100, "Logical block address out of range" },
-
- { 0x2400, "Invalid field in command packet" },
-
- { 0x2600, "Invalid field in parameter list" },
- { 0x2601, "Parameter not supported" },
- { 0x2602, "Parameter value invalid" },
- { 0x2603, "Threshold parameters not supported" },
-
- { 0x2800, "Not ready to ready transition, medium may have changed" },
-
- { 0x2900, "Power on, reset or bus device reset occurred" },
-
- { 0x2a00, "Parameters changed" },
- { 0x2a01, "Mode parameters changed" },
-
- { 0x3000, "Incompatible medium installed" },
- { 0x3001, "Cannot read medium - unknown format" },
- { 0x3002, "Cannot read medium - incompatible format" },
-
- { 0x3700, "Rounded parameter" },
-
- { 0x3900, "Saving parameters not supported" },
-
- { 0x3a00, "Medium not present" },
-
- { 0x3f00, "ATAPI CD-ROM drive operating conditions have changed" },
- { 0x3f01, "Microcode has been changed" },
- { 0x3f02, "Changed operating definition" },
- { 0x3f03, "Inquiry data has changed" },
-
- { 0x4000, "Diagnostic failure on component (ASCQ)" },
-
- { 0x4400, "Internal ATAPI CD-ROM drive failure" },
-
- { 0x4e00, "Overlapped commands attempted" },
-
- { 0x5300, "Media load or eject failed" },
- { 0x5302, "Medium removal prevented" },
-
- { 0x5700, "Unable to recover table of contents" },
-
- { 0x5a00, "Operator request or state change input (unspecified)" },
- { 0x5a01, "Operator medium removal request" },
-
- { 0x5b00, "Threshold condition met" },
-
- { 0x5c00, "Status change" },
-
- { 0x6300, "End of user area encountered on this track" },
-
- { 0x6400, "Illegal mode for this track" },
-
- { 0xbf00, "Loss of streaming" },
-};
-#endif
-
-
-
-/****************************************************************************
- * Generic packet command support and error handling routines.
- */
-
-
-static
-void cdrom_analyze_sense_data (ide_drive_t *drive,
- struct atapi_request_sense *reqbuf,
- struct packet_command *failed_command)
-{
- /* 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] == SCMD_READ_SUBCHANNEL &&
- (reqbuf->sense_key == NOT_READY || reqbuf->sense_key == UNIT_ATTENTION))
- return;
-
-#if VERBOSE_IDE_CD_ERRORS
- {
- int i;
- char *s;
- char buf[80];
-
- printk ("ATAPI device %s:\n", drive->name);
-
- printk (" Error code: 0x%02x\n", reqbuf->error_code);
-
- if (reqbuf->sense_key >= 0 &&
- reqbuf->sense_key < ARY_LEN (sense_key_texts))
- s = sense_key_texts[reqbuf->sense_key];
- else
- s = "(bad sense key)";
-
- printk (" Sense key: 0x%02x - %s\n", reqbuf->sense_key, s);
-
- if (reqbuf->asc == 0x40) {
- sprintf (buf, "Diagnostic failure on component 0x%02x", reqbuf->ascq);
- s = buf;
- }
-
- else {
- int lo, hi;
- int key = (reqbuf->asc << 8);
- if ( ! (reqbuf->ascq >= 0x80 && reqbuf->ascq <= 0xdd) )
- key |= reqbuf->ascq;
-
- lo = 0;
- hi = ARY_LEN (sense_data_texts);
- s = NULL;
-
- while (hi > lo) {
- int mid = (lo + hi) / 2;
- if (sense_data_texts[mid].asc_ascq == 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 (" Additional sense data: 0x%02x, 0x%02x - %s\n",
- reqbuf->asc, reqbuf->ascq, s);
-
- if (failed_command != NULL) {
- printk (" Failed packet command: ");
- for (i=0; i<sizeof (failed_command->c); i++)
- printk ("%02x ", failed_command->c[i]);
- printk ("\n");
- }
-
- if (reqbuf->sense_key == ILLEGAL_REQUEST &&
- (reqbuf->sense_key_specific[0] & 0x80) != 0)
- {
- printk (" Error in %s byte %d",
- (reqbuf->sense_key_specific[0] & 0x40) != 0
- ? "command packet"
- : "command data",
- (reqbuf->sense_key_specific[1] << 8) +
- reqbuf->sense_key_specific[2]);
-
- if ((reqbuf->sense_key_specific[0] & 0x40) != 0)
- {
- printk (" bit %d", reqbuf->sense_key_specific[0] & 0x07);
- }
-
- printk ("\n");
- }
- }
-
-#else
-
- /* 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: code: 0x%02x key: 0x%02x asc: 0x%02x ascq: 0x%02x\n",
- drive->name,
- reqbuf->error_code, reqbuf->sense_key, reqbuf->asc, reqbuf->ascq);
-#endif
-}
-
-
-/* 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;
-}
-
-
-static void cdrom_queue_request_sense (ide_drive_t *drive,
- struct semaphore *sem,
- struct atapi_request_sense *reqbuf,
- struct packet_command *failed_command)
-{
- struct request *rq;
- struct packet_command *pc;
- int len;
-
- /* If the request didn't explicitly specify where to put the sense data,
- use the statically allocated structure. */
- if (reqbuf == NULL)
- reqbuf = &drive->cdrom_info.sense_data;
-
- /* Make up a new request to retrieve sense information. */
-
- pc = &HWIF(drive)->request_sense_pc;
- memset (pc, 0, sizeof (*pc));
-
- /* The request_sense structure has an odd number of (16-bit) words,
- which won't work well with 32-bit transfers. However, we don't care
- about the last two bytes, so just truncate the structure down
- to an even length. */
- len = sizeof (*reqbuf) / 4;
- len *= 4;
-
- pc->c[0] = REQUEST_SENSE;
- pc->c[4] = len;
- pc->buffer = (char *)reqbuf;
- pc->buflen = len;
- pc->sense_data = (struct atapi_request_sense *)failed_command;
-
- /* stuff the sense request in front of our current request */
-
- rq = &HWIF(drive)->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;
-
- /* The code in blk.h can screw us up on error recovery if the block
- size is larger than 1k. Fix that up here. */
- if (!uptodate && rq->bh != 0)
- {
- int adj = rq->current_nr_sectors - 1;
- rq->current_nr_sectors -= adj;
- rq->sector += adj;
- }
-
- if (rq->cmd == REQUEST_SENSE_COMMAND && uptodate)
- {
- struct packet_command *pc = (struct packet_command *)rq->buffer;
- cdrom_analyze_sense_data (drive,
- (struct atapi_request_sense *)(pc->buffer - pc->c[4]),
- (struct packet_command *)pc->sense_data);
- }
-
- ide_end_request (uptodate, HWGROUP(drive));
-}
-
-
-/* Mark that we've seen a media change, and invalidate our internal
- buffers. */
-static void cdrom_saw_media_change (ide_drive_t *drive)
-{
- CDROM_STATE_FLAGS (drive)->media_changed = 1;
- CDROM_STATE_FLAGS (drive)->toc_valid = 0;
- drive->cdrom_info.nsectors_buffered = 0;
-}
-
-
-/* Returns 0 if the request should be continued.
- Returns 1 if the request was ended. */
-static int cdrom_decode_status (ide_drive_t *drive, int good_stat, int *stat_ret)
-{
- struct request *rq = HWGROUP(drive)->rq;
- int stat, err, sense_key, cmd;
-
- /* Check for errors. */
- stat = GET_STAT();
- *stat_ret = stat;
-
- if (OK_STAT (stat, good_stat, BAD_R_STAT))
- return 0;
-
- /* Got an error. */
- err = IN_BYTE (IDE_ERROR_REG);
- 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. */
-
- struct packet_command *pc = (struct packet_command *)rq->buffer;
- pc->stat = 1;
- cdrom_end_request (1, drive);
- ide_error (drive, "request sense failure", stat);
- return 1;
- }
-
- else if (cmd == PACKET_COMMAND)
- {
- /* All other functions, except for READ. */
-
- struct packet_command *pc = (struct packet_command *)rq->buffer;
- struct semaphore *sem = NULL;
-
- /* Check for tray open. */
- if (sense_key == NOT_READY)
- {
- cdrom_saw_media_change (drive);
-
- /* Print an error message to the syslog.
- Exception: don't print anything if this is a read subchannel
- command. This is because workman constantly polls the drive
- with this command, and we don't want to uselessly fill up
- the syslog. */
- if (pc->c[0] != SCMD_READ_SUBCHANNEL)
- printk ("%s : tray open or drive not ready\n", drive->name);
- }
-
- /* Check for media change. */
- else if (sense_key == UNIT_ATTENTION)
- {
- cdrom_saw_media_change (drive);
- printk ("%s: media changed\n", drive->name);
- }
-
- /* Otherwise, print an error. */
- else
- {
- 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->sense_data, pc);
- }
-
- else
- {
- /* Handle errors from READ requests. */
-
- /* Check for tray open. */
- if (sense_key == NOT_READY)
- {
- cdrom_saw_media_change (drive);
-
- /* Fail the request. */
- printk ("%s : tray open\n", drive->name);
- cdrom_end_request (0, drive);
- }
-
- /* Check for media change. */
- else if (sense_key == UNIT_ATTENTION)
- {
- 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);
- }
- }
- /* No point in retrying after an illegal request or
- data protect error.*/
- else if (sense_key == ILLEGAL_REQUEST || sense_key == DATA_PROTECT)
- {
- ide_dump_status (drive, "command error", stat);
- cdrom_end_request (0, drive);
- }
-
- /* If there were other errors, go to the default handler. */
- else if ((err & ~ABRT_ERR) != 0)
- {
- ide_error (drive, "cdrom_decode_status", stat);
- return 1;
- }
-
- /* Else, abort if we've racked up too many retries. */
- else if ((++rq->errors > ERROR_MAX))
- {
- 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, NULL);
- }
- }
-
- /* Retry, or handle the next request. */
- return 1;
-}
-
-
-/* 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 int cdrom_start_packet_command (ide_drive_t *drive, int xferlen,
- ide_handler_t *handler)
-{
- /* Wait for the controller to be idle. */
- if (ide_wait_stat (drive, 0, BUSY_STAT, WAIT_READY)) return 1;
-
- /* Set up the controller registers. */
- OUT_BYTE (0, 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);
- OUT_BYTE (drive->ctl, IDE_CONTROL_REG);
-
- if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt)
- {
- ide_set_handler (drive, handler, WAIT_CMD);
- OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* packet command */
- }
- else
- {
- OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* packet command */
- (*handler) (drive);
- }
-
- return 0;
-}
-
-
-/* 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 int cdrom_transfer_packet_command (ide_drive_t *drive,
- 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;
-
- /* Check for errors. */
- if (cdrom_decode_status (drive, DRQ_STAT, &stat_dum)) return 1;
- }
- else
- {
- /* Otherwise, we must wait for DRQ to get set. */
- if (ide_wait_stat (drive, DRQ_STAT, BUSY_STAT, WAIT_READY)) return 1;
- }
-
- /* Arm the interrupt handler. */
- ide_set_handler (drive, handler, WAIT_CMD);
-
- /* Send the command to the device. */
- cdrom_out_bytes (drive, cmd_buf, cmd_len);
-
- return 0;
-}
-
-
-
-/****************************************************************************
- * 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->cdrom_info;
-
- /* 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 don't yet have a sector buffer, try to allocate one.
- If we can't get one atomically, it's not fatal -- we'll just throw
- the data away rather than caching it. */
- if (info->sector_buffer == NULL)
- {
- info->sector_buffer = (char *) kmalloc (SECTOR_BUFFER_SIZE, GFP_ATOMIC);
-
- /* If we couldn't get a buffer, don't try to buffer anything... */
- if (info->sector_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->sector_buffer + info->nsectors_buffered * SECTOR_SIZE;
- while (sectors_to_buffer > 0)
- {
- cdrom_in_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];
- cdrom_in_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;
- cdrom_out_bytes (drive, &dum, sizeof (dum));
- len -= sizeof (dum);
- }
- }
-
- 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 void cdrom_read_intr (ide_drive_t *drive)
-{
- int stat;
- int ireason, len, sectors_to_transfer, nskip;
-
- struct request *rq = HWGROUP(drive)->rq;
-
- /* Check for errors. */
- if (cdrom_decode_status (drive, 0, &stat)) return;
-
- /* 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;
- }
-
- /* Check that the drive is expecting to do the same thing that we are. */
- if (cdrom_read_check_ireason (drive, len, ireason)) return;
-
- /* 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);
- printk (" This drive is not supported by this version of the driver\n");
- cdrom_end_request (0, drive);
- return;
- }
-
- /* 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];
- cdrom_in_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)
- {
- cdrom_in_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);
-}
-
-
-/*
- * 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->cdrom_info;
- struct request *rq = HWGROUP(drive)->rq;
-
- /* Can't do anything if there's no buffer. */
- if (info->sector_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->sector_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 void 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))
- {
- printk ("%s: cdrom_start_read_continuation: buffer botch (%ld)\n",
- drive->name, rq->current_nr_sectors);
- cdrom_end_request (0, drive);
- return;
- }
-
- 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. */
- nframes = MIN (nframes, 65535);
-
- /* Set up the command */
- memset (&pc.c, 0, sizeof (pc.c));
- pc.c[0] = READ_10;
- pc.c[7] = (nframes >> 8);
- pc.c[8] = (nframes & 0xff);
-#ifdef __alpha__
- stl_u (htonl (frame), (unsigned int *) &pc.c[2]);
-#else
- *(int *)(&pc.c[2]) = htonl (frame);
-#endif
-
- /* Send the command to the drive and return. */
- (void) cdrom_transfer_packet_command (drive, pc.c, sizeof (pc.c),
- &cdrom_read_intr);
-}
-
-
-/*
- * Start a read request from the CD-ROM.
- */
-static void cdrom_start_read (ide_drive_t *drive, unsigned int block)
-{
- 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;
-
- /* Clear the local sector buffer. */
- drive->cdrom_info.nsectors_buffered = 0;
-
- /* Start sending the read request to the drive. */
- 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,
- struct atapi_request_sense *reqbuf);
-
-
-
-/* Interrupt routine for packet command completion. */
-static void 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;
-
- /* Check for errors. */
- if (cdrom_decode_status (drive, 0, &stat)) return;
-
- /* 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] == 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
- {
- printk ("%s: cdrom_pc_intr: data underrun %d\n",
- drive->name, pc->buflen);
- pc->stat = 1;
- cdrom_end_request (1, drive);
- }
- return;
- }
-
- /* Figure out how much data to transfer. */
- thislen = pc->buflen;
- if (thislen < 0) thislen = -thislen;
- if (thislen > len) thislen = len;
-
- /* The drive wants to be written to. */
- if ((ireason & 3) == 0)
- {
- /* Check that we want to write. */
- if (pc->buflen > 0)
- {
- printk ("%s: cdrom_pc_intr: Drive wants to transfer data the wrong way!\n",
- drive->name);
- pc->stat = 1;
- thislen = 0;
- }
-
- /* Transfer the data. */
- cdrom_out_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;
- cdrom_out_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)
- {
- /* Check that we want to read. */
- if (pc->buflen < 0)
- {
- printk ("%s: cdrom_pc_intr: Drive wants to transfer data the wrong way!\n",
- drive->name);
- pc->stat = 1;
- thislen = 0;
- }
-
- /* Transfer the data. */
- cdrom_in_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;
- cdrom_in_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);
-}
-
-
-static void 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. */
- cdrom_transfer_packet_command (drive, pc->c, sizeof (pc->c), &cdrom_pc_intr);
-}
-
-
-static void 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;
-
- len = pc->buflen;
- if (len < 0) len = -len;
-
- pc->stat = 0;
-
- /* Start sending the command to the drive. */
- cdrom_start_packet_command (drive, len, cdrom_do_pc_continuation);
-}
-
-#ifndef MACH
-/* Sleep for TIME jiffies.
- Not to be called from an interrupt handler. */
-static
-void cdrom_sleep (int time)
-{
- current->state = TASK_INTERRUPTIBLE;
- current->timeout = jiffies + time;
- schedule ();
-}
-#endif
-
-static
-int cdrom_queue_packet_command (ide_drive_t *drive, struct packet_command *pc)
-{
- struct atapi_request_sense my_reqbuf;
- int retries = 10;
- struct request req;
-
- /* If our caller has not provided a place to stick any sense data,
- use our own area. */
- if (pc->sense_data == NULL)
- pc->sense_data = &my_reqbuf;
- pc->sense_data->sense_key = 0;
-
- /* Start of retry loop. */
- do {
- ide_init_drive_cmd (&req);
- req.cmd = PACKET_COMMAND;
- req.buffer = (char *)pc;
- (void) ide_do_drive_cmd (drive, &req, ide_wait);
-
- if (pc->stat != 0)
- {
- /* The request failed. Retry if it was due to a unit attention status
- (usually means media was changed). */
- struct atapi_request_sense *reqbuf = pc->sense_data;
-
- if (reqbuf->sense_key == UNIT_ATTENTION)
- ;
-
- /* Also retry if the drive is in the process of loading a disk.
- This time, however, wait a little between retries to give
- the drive time. */
- else if (reqbuf->sense_key == NOT_READY && reqbuf->asc == 4)
- {
- cdrom_sleep (HZ);
- }
-
- /* Otherwise, don't retry. */
- else
- retries = 0;
-
- --retries;
- }
-
- /* End of retry loop. */
- } while (pc->stat != 0 && retries >= 0);
-
-
- /* Return an error if the command failed. */
- if (pc->stat != 0)
- return -EIO;
-
- else
- {
- /* 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] != REQUEST_SENSE &&
- pc->c[0] != ALLOW_MEDIUM_REMOVAL &&
- pc->c[0] != START_STOP))
- {
- (void) cdrom_lockdoor (drive, 1, NULL);
- }
- return 0;
- }
-}
-
-
-
-/****************************************************************************
- * drive_cmd handling.
- *
- * Most of the functions accessed via drive_cmd are not valid for ATAPI
- * devices. Only attempt to execute those which actually should be valid.
- */
-
-static
-void cdrom_do_drive_cmd (ide_drive_t *drive)
-{
- struct request *rq = HWGROUP(drive)->rq;
- byte *args = rq->buffer;
-
- if (args)
- {
-#if 0 /* This bit isn't done yet... */
- if (args[0] == WIN_SETFEATURES &&
- (args[2] == 0x66 || args[2] == 0xcc || args[2] == 0x02 ||
- args[2] == 0xdd || args[2] == 0x5d))
- {
- OUT_BYTE (args[2], io_base + IDE_FEATURE_OFFSET);
- <send cmd>
- }
- else
-#endif
- {
- printk ("%s: Unsupported drive command %02x %02x %02x\n",
- drive->name, args[0], args[1], args[2]);
- rq->errors = 1;
- }
- }
-
- cdrom_end_request (1, drive);
-}
-
-
-
-/****************************************************************************
- * cdrom driver request routine.
- */
-
-void ide_do_rw_cdrom (ide_drive_t *drive, unsigned long block)
-{
- struct request *rq = HWGROUP(drive)->rq;
-
- if (rq -> cmd == PACKET_COMMAND || rq -> cmd == REQUEST_SENSE_COMMAND)
- cdrom_do_packet_command (drive);
-
- else if (rq -> cmd == RESET_DRIVE_COMMAND)
- {
- cdrom_end_request (1, drive);
- ide_do_reset (drive);
- return;
- }
-
- else if (rq -> cmd == IDE_DRIVE_CMD)
- cdrom_do_drive_cmd (drive);
-
- else if (rq -> cmd != READ)
- {
- printk ("ide-cd: bad cmd %d\n", rq -> cmd);
- cdrom_end_request (0, drive);
- }
- else
- cdrom_start_read (drive, block);
-}
-
-
-
-/****************************************************************************
- * Ioctl handling.
- *
- * Routines which queue packet commands take as a final argument a pointer
- * to an atapi_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
-int bin2bcd (int x)
-{
- return (x%10) | ((x/10) << 4);
-}
-
-
-static
-int bcd2bin (int x)
-{
- return (x >> 4) * 10 + (x & 0x0f);
-}
-#endif /* not STANDARD_ATAPI */
-
-
-static inline
-void lba_to_msf (int lba, byte *m, byte *s, byte *f)
-{
- lba += CD_BLOCK_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_BLOCK_OFFSET;
-}
-
-
-static int
-cdrom_check_status (ide_drive_t *drive,
- struct atapi_request_sense *reqbuf)
-{
- struct packet_command pc;
-
- memset (&pc, 0, sizeof (pc));
-
- pc.sense_data = reqbuf;
- pc.c[0] = TEST_UNIT_READY;
-
- 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 atapi_request_sense *reqbuf)
-{
- struct atapi_request_sense my_reqbuf;
- int stat;
- struct packet_command pc;
-
- if (reqbuf == NULL)
- reqbuf = &my_reqbuf;
-
- /* 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.sense_data = reqbuf;
-
- pc.c[0] = ALLOW_MEDIUM_REMOVAL;
- pc.c[4] = (lockflag != 0);
- stat = cdrom_queue_packet_command (drive, &pc);
- }
-
- if (stat == 0)
- CDROM_STATE_FLAGS (drive)->door_locked = lockflag;
- else
- {
- /* If we got an illegal field error, the drive
- probably cannot lock the door. */
- if (reqbuf->sense_key == ILLEGAL_REQUEST && reqbuf->asc == 0x24)
- {
- printk ("%s: door locking not supported\n", drive->name);
- CDROM_CONFIG_FLAGS (drive)->no_doorlock = 1;
- 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 atapi_request_sense *reqbuf)
-{
- struct packet_command pc;
-
- memset (&pc, 0, sizeof (pc));
- pc.sense_data = reqbuf;
-
- pc.c[0] = START_STOP;
- pc.c[4] = 2 + (ejectflag != 0);
- return cdrom_queue_packet_command (drive, &pc);
-}
-
-
-static int
-cdrom_pause (ide_drive_t *drive, int pauseflag,
- struct atapi_request_sense *reqbuf)
-{
- struct packet_command pc;
-
- memset (&pc, 0, sizeof (pc));
- pc.sense_data = reqbuf;
-
- pc.c[0] = SCMD_PAUSE_RESUME;
- pc.c[8] = !pauseflag;
- return cdrom_queue_packet_command (drive, &pc);
-}
-
-
-static int
-cdrom_startstop (ide_drive_t *drive, int startflag,
- struct atapi_request_sense *reqbuf)
-{
- struct packet_command pc;
-
- memset (&pc, 0, sizeof (pc));
- pc.sense_data = reqbuf;
-
- pc.c[0] = START_STOP;
- pc.c[1] = 1;
- pc.c[4] = startflag;
- return cdrom_queue_packet_command (drive, &pc);
-}
-
-
-static int
-cdrom_read_capacity (ide_drive_t *drive, unsigned *capacity,
- struct atapi_request_sense *reqbuf)
-{
- struct {
- unsigned lba;
- unsigned blocklen;
- } capbuf;
-
- int stat;
- struct packet_command pc;
-
- memset (&pc, 0, sizeof (pc));
- pc.sense_data = reqbuf;
-
- pc.c[0] = READ_CAPACITY;
- pc.buffer = (char *)&capbuf;
- pc.buflen = sizeof (capbuf);
-
- stat = cdrom_queue_packet_command (drive, &pc);
- if (stat == 0)
- {
- *capacity = ntohl (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 atapi_request_sense *reqbuf)
-{
- struct packet_command pc;
-
- memset (&pc, 0, sizeof (pc));
- pc.sense_data = reqbuf;
-
- pc.buffer = buf;
- pc.buflen = buflen;
- pc.c[0] = SCMD_READ_TOC;
- 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,
- struct atapi_request_sense *reqbuf)
-{
- int msf_flag;
- int stat, ntracks, i;
- struct atapi_toc *toc = drive->cdrom_info.toc;
- 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);
- drive->cdrom_info.toc = toc;
- }
-
- if (toc == NULL)
- {
- printk ("%s: No cdrom TOC buffer!\n", drive->name);
- return -EIO;
- }
-
- /* 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, NULL);
-
- if (CDROM_STATE_FLAGS (drive)->toc_valid) return 0;
-
-#if STANDARD_ATAPI
- msf_flag = 0;
-#else /* not STANDARD_ATAPI */
- /* Some drives can't return TOC data in LBA format. */
- msf_flag = (CDROM_CONFIG_FLAGS (drive)->no_lba_toc);
-#endif /* not STANDARD_ATAPI */
-
- /* First read just the header, so we know how long the TOC is. */
- stat = cdrom_read_tocentry (drive, 0, msf_flag, 0, (char *)&toc->hdr,
- sizeof (struct atapi_toc_header) +
- sizeof (struct atapi_toc_entry),
- reqbuf);
- if (stat) return stat;
-
-#if ! STANDARD_ATAPI
- if (CDROM_CONFIG_FLAGS (drive)->vertos_lossage)
- {
- toc->hdr.first_track = bcd2bin (toc->hdr.first_track);
- toc->hdr.last_track = bcd2bin (toc->hdr.last_track);
- /* hopefully the length is not BCD, too ;-| */
- }
-#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, 0, msf_flag, 0, (char *)&toc->hdr,
- sizeof (struct atapi_toc_header) +
- (ntracks+1) * sizeof (struct atapi_toc_entry),
- reqbuf);
- if (stat) return stat;
- toc->hdr.toc_length = ntohs (toc->hdr.toc_length);
-
-#if ! STANDARD_ATAPI
- if (CDROM_CONFIG_FLAGS (drive)->vertos_lossage)
- {
- toc->hdr.first_track = bcd2bin (toc->hdr.first_track);
- toc->hdr.last_track = bcd2bin (toc->hdr.last_track);
- /* hopefully the length is not BCD, too ;-| */
- }
-#endif /* not STANDARD_ATAPI */
-
- for (i=0; i<=ntracks; i++)
- {
-#if ! STANDARD_ATAPI
- if (msf_flag)
- {
- if (CDROM_CONFIG_FLAGS (drive)->vertos_lossage)
- {
- toc->ent[i].track = bcd2bin (toc->ent[i].track);
- toc->ent[i].addr.msf.m = bcd2bin (toc->ent[i].addr.msf.m);
- toc->ent[i].addr.msf.s = bcd2bin (toc->ent[i].addr.msf.s);
- toc->ent[i].addr.msf.f = bcd2bin (toc->ent[i].addr.msf.f);
- }
- toc->ent[i].addr.lba = msf_to_lba (toc->ent[i].addr.msf.m,
- toc->ent[i].addr.msf.s,
- toc->ent[i].addr.msf.f);
- }
- else
-#endif /* not STANDARD_ATAPI */
- toc->ent[i].addr.lba = ntohl (toc->ent[i].addr.lba);
- }
-
- /* Read the multisession information. */
- stat = cdrom_read_tocentry (drive, 0, msf_flag, 1,
- (char *)&ms_tmp, sizeof (ms_tmp),
- reqbuf);
- if (stat) return stat;
-#if ! STANDARD_ATAPI
- if (msf_flag)
- toc->last_session_lba = msf_to_lba (ms_tmp.ent.addr.msf.m,
- ms_tmp.ent.addr.msf.s,
- ms_tmp.ent.addr.msf.f);
- else
-#endif /* not STANDARD_ATAPI */
- toc->last_session_lba = ntohl (ms_tmp.ent.addr.lba);
-
- toc->xa_flag = (ms_tmp.hdr.first_track != ms_tmp.hdr.last_track);
-
- /* Now try to get the total cdrom capacity. */
- stat = cdrom_read_capacity (drive, &toc->capacity, reqbuf);
- if (stat) toc->capacity = 0x1fffff;
-
- HWIF(drive)->gd->sizes[drive->select.b.unit << PARTN_BITS]
- = toc->capacity * SECTORS_PER_FRAME;
- drive->part[0].nr_sects = toc->capacity * SECTORS_PER_FRAME;
-
- /* Remember that we've read this stuff. */
- CDROM_STATE_FLAGS (drive)->toc_valid = 1;
-
- return 0;
-}
-
-
-static int
-cdrom_read_subchannel (ide_drive_t *drive,
- char *buf, int buflen,
- struct atapi_request_sense *reqbuf)
-{
- struct packet_command pc;
-
- memset (&pc, 0, sizeof (pc));
- pc.sense_data = reqbuf;
-
- pc.buffer = buf;
- pc.buflen = buflen;
- pc.c[0] = SCMD_READ_SUBCHANNEL;
- pc.c[2] = 0x40; /* request subQ data */
- pc.c[3] = 0x01; /* Format 1: current position */
- pc.c[7] = (buflen >> 8);
- pc.c[8] = (buflen & 0xff);
- return cdrom_queue_packet_command (drive, &pc);
-}
-
-
-/* modeflag: 0 = current, 1 = changeable mask, 2 = default, 3 = saved */
-static int
-cdrom_mode_sense (ide_drive_t *drive, int pageno, int modeflag,
- char *buf, int buflen,
- struct atapi_request_sense *reqbuf)
-{
- struct packet_command pc;
-
- memset (&pc, 0, sizeof (pc));
- pc.sense_data = reqbuf;
-
- pc.buffer = buf;
- pc.buflen = buflen;
- pc.c[0] = MODE_SENSE_10;
- pc.c[2] = pageno | (modeflag << 6);
- pc.c[7] = (buflen >> 8);
- pc.c[8] = (buflen & 0xff);
- return cdrom_queue_packet_command (drive, &pc);
-}
-
-
-static int
-cdrom_mode_select (ide_drive_t *drive, int pageno, char *buf, int buflen,
- struct atapi_request_sense *reqbuf)
-{
- struct packet_command pc;
-
- memset (&pc, 0, sizeof (pc));
- pc.sense_data = reqbuf;
-
- pc.buffer = buf;
- pc.buflen = - buflen;
- pc.c[0] = MODE_SELECT_10;
- pc.c[1] = 0x10;
- pc.c[2] = pageno;
- pc.c[7] = (buflen >> 8);
- pc.c[8] = (buflen & 0xff);
- return cdrom_queue_packet_command (drive, &pc);
-}
-
-
-static int
-cdrom_play_lba_range_play12 (ide_drive_t *drive, int lba_start, int lba_end,
- struct atapi_request_sense *reqbuf)
-{
- struct packet_command pc;
-
- memset (&pc, 0, sizeof (pc));
- pc.sense_data = reqbuf;
-
- pc.c[0] = SCMD_PLAYAUDIO12;
-#ifdef __alpha__
- stq_u(((long) htonl (lba_end - lba_start) << 32) | htonl(lba_start),
- (unsigned long *) &pc.c[2]);
-#else
- *(int *)(&pc.c[2]) = htonl (lba_start);
- *(int *)(&pc.c[6]) = htonl (lba_end - lba_start);
-#endif
-
- return cdrom_queue_packet_command (drive, &pc);
-}
-
-
-#if ! STANDARD_ATAPI
-static int
-cdrom_play_lba_range_msf (ide_drive_t *drive, int lba_start, int lba_end,
- struct atapi_request_sense *reqbuf)
-{
- struct packet_command pc;
-
- memset (&pc, 0, sizeof (pc));
- pc.sense_data = reqbuf;
-
- pc.c[0] = SCMD_PLAYAUDIO_MSF;
- lba_to_msf (lba_start, &pc.c[3], &pc.c[4], &pc.c[5]);
- lba_to_msf (lba_end-1, &pc.c[6], &pc.c[7], &pc.c[8]);
-
- if (CDROM_CONFIG_FLAGS (drive)->playmsf_uses_bcd)
- {
- pc.c[3] = bin2bcd (pc.c[3]);
- pc.c[4] = bin2bcd (pc.c[4]);
- pc.c[5] = bin2bcd (pc.c[5]);
- pc.c[6] = bin2bcd (pc.c[6]);
- pc.c[7] = bin2bcd (pc.c[7]);
- pc.c[8] = bin2bcd (pc.c[8]);
- }
-
- return cdrom_queue_packet_command (drive, &pc);
-}
-#endif /* not STANDARD_ATAPI */
-
-
-static int
-cdrom_play_lba_range_1 (ide_drive_t *drive, int lba_start, int lba_end,
- struct atapi_request_sense *reqbuf)
-{
- /* This is rather annoying.
- My NEC-260 won't recognize group 5 commands such as PLAYAUDIO12;
- the only way to get it to play more than 64k of blocks at once
- seems to be the PLAYAUDIO_MSF command. However, the parameters
- the NEC 260 wants for the PLAYMSF command are incompatible with
- the new version of the spec.
-
- So what i'll try is this. First try for PLAYAUDIO12. If it works,
- great. Otherwise, if the drive reports an illegal command code,
- try PLAYAUDIO_MSF using the NEC 260-style bcd parameters. */
-
-#if ! STANDARD_ATAPI
- if (CDROM_CONFIG_FLAGS (drive)->no_playaudio12)
- return cdrom_play_lba_range_msf (drive, lba_start, lba_end, reqbuf);
- else
-#endif /* not STANDARD_ATAPI */
- {
- int stat;
- struct atapi_request_sense my_reqbuf;
-
- if (reqbuf == NULL)
- reqbuf = &my_reqbuf;
-
- stat = cdrom_play_lba_range_play12 (drive, lba_start, lba_end, reqbuf);
- if (stat == 0) return 0;
-
-#if ! STANDARD_ATAPI
- /* It failed. Try to find out why. */
- if (reqbuf->sense_key == ILLEGAL_REQUEST && reqbuf->asc == 0x20)
- {
- /* The drive didn't recognize the command.
- Retry with the MSF variant. */
- printk ("%s: Drive does not support PLAYAUDIO12; "
- "trying PLAYAUDIO_MSF\n", drive->name);
- CDROM_CONFIG_FLAGS (drive)->no_playaudio12 = 1;
- CDROM_CONFIG_FLAGS (drive)->playmsf_uses_bcd = 1;
- return cdrom_play_lba_range_msf (drive, lba_start, lba_end, reqbuf);
- }
-#endif /* not STANDARD_ATAPI */
-
- /* Failed for some other reason. Give up. */
- return stat;
- }
-}
-
-
-/* Play audio starting at LBA LBA_START and finishing with the
- LBA before LBA_END. */
-static int
-cdrom_play_lba_range (ide_drive_t *drive, int lba_start, int lba_end,
- struct atapi_request_sense *reqbuf)
-{
- int i, stat;
- struct atapi_request_sense my_reqbuf;
-
- if (reqbuf == NULL)
- reqbuf = &my_reqbuf;
-
- /* Some drives, will, for certain audio cds,
- give an error if you ask them to play the entire cd using the
- values which are returned in the TOC. The play will succeed, however,
- if the ending address is adjusted downwards by a few frames. */
- for (i=0; i<75; i++)
- {
- stat = cdrom_play_lba_range_1 (drive, lba_start, lba_end, reqbuf);
-
- if (stat == 0 ||
- !(reqbuf->sense_key == ILLEGAL_REQUEST && reqbuf->asc == 0x24))
- return stat;
-
- --lba_end;
- if (lba_end <= lba_start) break;
- }
-
- return stat;
-}
-
-
-static
-int cdrom_get_toc_entry (ide_drive_t *drive, int track,
- struct atapi_toc_entry **ent,
- struct atapi_request_sense *reqbuf)
-{
- int stat, ntracks;
- struct atapi_toc *toc;
-
- /* Make sure our saved TOC is valid. */
- stat = cdrom_read_toc (drive, reqbuf);
- if (stat) return stat;
-
- toc = drive->cdrom_info.toc;
-
- /* Check validity of requested track number. */
- ntracks = toc->hdr.last_track - toc->hdr.first_track + 1;
- 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;
-}
-
-
-static int
-cdrom_read_block (ide_drive_t *drive, int format, int lba,
- char *buf, int buflen,
- struct atapi_request_sense *reqbuf)
-{
- struct packet_command pc;
- struct atapi_request_sense my_reqbuf;
- int stat;
-
- if (reqbuf == NULL)
- reqbuf = &my_reqbuf;
-
- memset (&pc, 0, sizeof (pc));
- pc.sense_data = reqbuf;
-
- pc.buffer = buf;
- pc.buflen = buflen;
-
-#if ! STANDARD_ATAPI
- if (CDROM_CONFIG_FLAGS (drive)->old_readcd)
- pc.c[0] = 0xd4;
- else
-#endif /* not STANDARD_ATAPI */
- pc.c[0] = READ_CD;
-
- pc.c[1] = (format << 2);
-#ifdef __alpha__
- stl_u(htonl (lba), (unsigned int *) &pc.c[2]);
-#else
- *(int *)(&pc.c[2]) = htonl (lba);
-#endif
- pc.c[8] = 1; /* one block */
- pc.c[9] = 0x10;
-
- stat = cdrom_queue_packet_command (drive, &pc);
-
-#if ! STANDARD_ATAPI
- /* If the drive doesn't recognize the READ CD opcode, retry the command
- with an older opcode for that command. */
- if (stat && reqbuf->sense_key == ILLEGAL_REQUEST && reqbuf->asc == 0x20 &&
- CDROM_CONFIG_FLAGS (drive)->old_readcd == 0)
- {
- printk ("%s: Drive does not recognize READ_CD; trying opcode 0xd4\n",
- drive->name);
- CDROM_CONFIG_FLAGS (drive)->old_readcd = 1;
- return cdrom_read_block (drive, format, lba, buf, buflen, reqbuf);
- }
-#endif /* not STANDARD_ATAPI */
-
- return stat;
-}
-
-
-int ide_cdrom_ioctl (ide_drive_t *drive, struct inode *inode,
- struct file *file, unsigned int cmd, unsigned long arg)
-{
- switch (cmd)
- {
- case CDROMEJECT:
- {
- int stat;
-
- if (drive->usage > 1)
- return -EBUSY;
-
- stat = cdrom_lockdoor (drive, 0, NULL);
- if (stat) return stat;
-
- return cdrom_eject (drive, 0, NULL);
- }
-
- case CDROMEJECT_SW:
- {
- CDROM_STATE_FLAGS (drive)->eject_on_close = arg;
- return 0;
- }
-
- case CDROMPAUSE:
- return cdrom_pause (drive, 1, NULL);
-
- case CDROMRESUME:
- return cdrom_pause (drive, 0, NULL);
-
- case CDROMSTART:
- return cdrom_startstop (drive, 1, NULL);
-
- case CDROMSTOP:
- {
- int stat;
-
- stat = cdrom_startstop (drive, 0, NULL);
- if (stat) return stat;
- /* pit says the Dolphin needs this. */
- return cdrom_eject (drive, 1, NULL);
- }
-
- case CDROMPLAYMSF:
- {
- struct cdrom_msf msf;
- int stat, lba_start, lba_end;
-
- stat = verify_area (VERIFY_READ, (void *)arg, sizeof (msf));
- if (stat) return stat;
-
- memcpy_fromfs (&msf, (void *) arg, sizeof(msf));
-
- lba_start = msf_to_lba (msf.cdmsf_min0, msf.cdmsf_sec0,
- msf.cdmsf_frame0);
- lba_end = msf_to_lba (msf.cdmsf_min1, msf.cdmsf_sec1,
- msf.cdmsf_frame1) + 1;
-
- if (lba_end <= lba_start) return -EINVAL;
-
- return cdrom_play_lba_range (drive, lba_start, lba_end, NULL);
- }
-
- /* Like just about every other Linux cdrom driver, we ignore the
- index part of the request here. */
- case CDROMPLAYTRKIND:
- {
- int stat, lba_start, lba_end;
- struct cdrom_ti ti;
- struct atapi_toc_entry *first_toc, *last_toc;
-
- stat = verify_area (VERIFY_READ, (void *)arg, sizeof (ti));
- if (stat) return stat;
-
- memcpy_fromfs (&ti, (void *) arg, sizeof(ti));
-
- stat = cdrom_get_toc_entry (drive, ti.cdti_trk0, &first_toc, NULL);
- if (stat) return stat;
- stat = cdrom_get_toc_entry (drive, ti.cdti_trk1, &last_toc, NULL);
- if (stat) return stat;
-
- if (ti.cdti_trk1 != CDROM_LEADOUT) ++last_toc;
- lba_start = first_toc->addr.lba;
- lba_end = last_toc->addr.lba;
-
- if (lba_end <= lba_start) return -EINVAL;
-
- return cdrom_play_lba_range (drive, lba_start, lba_end, NULL);
- }
-
- case CDROMREADTOCHDR:
- {
- int stat;
- struct cdrom_tochdr tochdr;
- struct atapi_toc *toc;
-
- stat = verify_area (VERIFY_WRITE, (void *) arg, sizeof (tochdr));
- if (stat) return stat;
-
- /* Make sure our saved TOC is valid. */
- stat = cdrom_read_toc (drive, NULL);
- if (stat) return stat;
-
- toc = drive->cdrom_info.toc;
- tochdr.cdth_trk0 = toc->hdr.first_track;
- tochdr.cdth_trk1 = toc->hdr.last_track;
-
- memcpy_tofs ((void *) arg, &tochdr, sizeof (tochdr));
-
- return stat;
- }
-
- case CDROMREADTOCENTRY:
- {
- int stat;
- struct cdrom_tocentry tocentry;
- struct atapi_toc_entry *toce;
-
- stat = verify_area (VERIFY_READ, (void *) arg, sizeof (tocentry));
- if (stat) return stat;
- stat = verify_area (VERIFY_WRITE, (void *) arg, sizeof (tocentry));
- if (stat) return stat;
-
- memcpy_fromfs (&tocentry, (void *) arg, sizeof (tocentry));
-
- stat = cdrom_get_toc_entry (drive, tocentry.cdte_track, &toce, NULL);
- if (stat) return stat;
-
- tocentry.cdte_ctrl = toce->control;
- tocentry.cdte_adr = toce->adr;
-
- if (tocentry.cdte_format == CDROM_MSF)
- {
- /* convert to 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;
-
- memcpy_tofs ((void *) arg, &tocentry, sizeof (tocentry));
-
- return stat;
- }
-
- case CDROMSUBCHNL:
- {
- struct atapi_cdrom_subchnl scbuf;
- int stat, abs_lba, rel_lba;
- struct cdrom_subchnl subchnl;
-
- stat = verify_area (VERIFY_WRITE, (void *) arg, sizeof (subchnl));
- if (stat) return stat;
- stat = verify_area (VERIFY_READ, (void *) arg, sizeof (subchnl));
- if (stat) return stat;
-
- memcpy_fromfs (&subchnl, (void *) arg, sizeof (subchnl));
-
- stat = cdrom_read_subchannel (drive, (char *)&scbuf, sizeof (scbuf),
- NULL);
- if (stat) return stat;
-
-#if ! STANDARD_ATAPI
- if (CDROM_CONFIG_FLAGS (drive)->vertos_lossage)
- {
- abs_lba = msf_to_lba (bcd2bin (scbuf.acdsc_absaddr.msf.minute),
- bcd2bin (scbuf.acdsc_absaddr.msf.second),
- bcd2bin (scbuf.acdsc_absaddr.msf.frame));
- rel_lba = msf_to_lba (bcd2bin (scbuf.acdsc_reladdr.msf.minute),
- bcd2bin (scbuf.acdsc_reladdr.msf.second),
- bcd2bin (scbuf.acdsc_reladdr.msf.frame));
- scbuf.acdsc_trk = bcd2bin (scbuf.acdsc_trk);
- }
- else
-#endif /* not STANDARD_ATAPI */
- {
- abs_lba = ntohl (scbuf.acdsc_absaddr.lba);
- rel_lba = ntohl (scbuf.acdsc_reladdr.lba);
- }
-
- if (subchnl.cdsc_format == CDROM_MSF)
- {
- lba_to_msf (abs_lba,
- &subchnl.cdsc_absaddr.msf.minute,
- &subchnl.cdsc_absaddr.msf.second,
- &subchnl.cdsc_absaddr.msf.frame);
- lba_to_msf (rel_lba,
- &subchnl.cdsc_reladdr.msf.minute,
- &subchnl.cdsc_reladdr.msf.second,
- &subchnl.cdsc_reladdr.msf.frame);
- }
- else
- {
- subchnl.cdsc_absaddr.lba = abs_lba;
- subchnl.cdsc_reladdr.lba = rel_lba;
- }
-
- subchnl.cdsc_audiostatus = scbuf.acdsc_audiostatus;
- subchnl.cdsc_ctrl = scbuf.acdsc_ctrl;
- subchnl.cdsc_trk = scbuf.acdsc_trk;
- subchnl.cdsc_ind = scbuf.acdsc_ind;
-
- memcpy_tofs ((void *) arg, &subchnl, sizeof (subchnl));
-
- return stat;
- }
-
- case CDROMVOLCTRL:
- {
- struct cdrom_volctrl volctrl;
- char buffer[24], mask[24];
- int stat;
-
- stat = verify_area (VERIFY_READ, (void *) arg, sizeof (volctrl));
- if (stat) return stat;
- memcpy_fromfs (&volctrl, (void *) arg, sizeof (volctrl));
-
- stat = cdrom_mode_sense (drive, 0x0e, 0, buffer, sizeof (buffer),NULL);
- if (stat) return stat;
- stat = cdrom_mode_sense (drive, 0x0e, 1, mask , sizeof (buffer),NULL);
- if (stat) return stat;
-
- buffer[1] = buffer[2] = 0;
-
- buffer[17] = volctrl.channel0 & mask[17];
- buffer[19] = volctrl.channel1 & mask[19];
- buffer[21] = volctrl.channel2 & mask[21];
- buffer[23] = volctrl.channel3 & mask[23];
-
- return cdrom_mode_select (drive, 0x0e, buffer, sizeof (buffer), NULL);
- }
-
- case CDROMVOLREAD:
- {
- struct cdrom_volctrl volctrl;
- char buffer[24];
- int stat;
-
- stat = verify_area (VERIFY_WRITE, (void *) arg, sizeof (volctrl));
- if (stat) return stat;
-
- stat = cdrom_mode_sense (drive, 0x0e, 0, buffer, sizeof (buffer), NULL);
- if (stat) return stat;
-
- volctrl.channel0 = buffer[17];
- volctrl.channel1 = buffer[19];
- volctrl.channel2 = buffer[21];
- volctrl.channel3 = buffer[23];
-
- memcpy_tofs ((void *) arg, &volctrl, sizeof (volctrl));
-
- return 0;
- }
-
- case CDROMMULTISESSION:
- {
- struct cdrom_multisession ms_info;
- struct atapi_toc *toc;
- int stat;
-
- stat = verify_area (VERIFY_READ, (void *)arg, sizeof (ms_info));
- if (stat) return stat;
- stat = verify_area (VERIFY_WRITE, (void *)arg, sizeof (ms_info));
- if (stat) return stat;
-
- memcpy_fromfs (&ms_info, (void *)arg, sizeof (ms_info));
-
- /* Make sure the TOC information is valid. */
- stat = cdrom_read_toc (drive, NULL);
- if (stat) return stat;
-
- toc = drive->cdrom_info.toc;
-
- if (ms_info.addr_format == CDROM_MSF)
- lba_to_msf (toc->last_session_lba,
- &ms_info.addr.msf.minute,
- &ms_info.addr.msf.second,
- &ms_info.addr.msf.frame);
-
- else if (ms_info.addr_format == CDROM_LBA)
- ms_info.addr.lba = toc->last_session_lba;
-
- else
- return -EINVAL;
-
- ms_info.xa_flag = toc->xa_flag;
-
- memcpy_tofs ((void *)arg, &ms_info, sizeof (ms_info));
-
- return 0;
- }
-
- /* Read 2352 byte blocks from audio tracks. */
- case CDROMREADAUDIO:
- {
- int stat, lba;
- struct atapi_toc *toc;
- struct cdrom_read_audio ra;
- char buf[CD_FRAMESIZE_RAW];
-
- /* Make sure the TOC is up to date. */
- stat = cdrom_read_toc (drive, NULL);
- if (stat) return stat;
-
- toc = drive->cdrom_info.toc;
-
- stat = verify_area (VERIFY_READ, (char *)arg, sizeof (ra));
- if (stat) return stat;
-
- memcpy_fromfs (&ra, (void *)arg, sizeof (ra));
-
- if (ra.nframes < 0 || ra.nframes > toc->capacity)
- return -EINVAL;
- else if (ra.nframes == 0)
- return 0;
-
- stat = verify_area (VERIFY_WRITE, (char *)ra.buf,
- ra.nframes * CD_FRAMESIZE_RAW);
- if (stat) return stat;
-
- if (ra.addr_format == CDROM_MSF)
- lba = msf_to_lba (ra.addr.msf.minute, ra.addr.msf.second,
- ra.addr.msf.frame);
-
- else if (ra.addr_format == CDROM_LBA)
- lba = ra.addr.lba;
-
- else
- return -EINVAL;
-
- if (lba < 0 || lba >= toc->capacity)
- return -EINVAL;
-
- while (ra.nframes > 0)
- {
- stat = cdrom_read_block (drive, 1, lba, buf,
- CD_FRAMESIZE_RAW, NULL);
- if (stat) return stat;
- memcpy_tofs (ra.buf, buf, CD_FRAMESIZE_RAW);
- ra.buf += CD_FRAMESIZE_RAW;
- --ra.nframes;
- ++lba;
- }
-
- return 0;
- }
-
- case CDROMREADMODE1:
- case CDROMREADMODE2:
- {
- struct cdrom_msf msf;
- int blocksize, format, stat, lba;
- struct atapi_toc *toc;
- char buf[CD_FRAMESIZE_RAW0];
-
- if (cmd == CDROMREADMODE1)
- {
- blocksize = CD_FRAMESIZE;
- format = 2;
- }
- else
- {
- blocksize = CD_FRAMESIZE_RAW0;
- format = 3;
- }
-
- stat = verify_area (VERIFY_READ, (char *)arg, sizeof (msf));
- if (stat) return stat;
- stat = verify_area (VERIFY_WRITE, (char *)arg, blocksize);
- if (stat) return stat;
-
- memcpy_fromfs (&msf, (void *)arg, sizeof (msf));
-
- lba = msf_to_lba (msf.cdmsf_min0, msf.cdmsf_sec0, msf.cdmsf_frame0);
-
- /* Make sure the TOC is up to date. */
- stat = cdrom_read_toc (drive, NULL);
- if (stat) return stat;
-
- toc = drive->cdrom_info.toc;
-
- if (lba < 0 || lba >= toc->capacity)
- return -EINVAL;
-
- stat = cdrom_read_block (drive, format, lba, buf, blocksize, NULL);
- if (stat) return stat;
-
- memcpy_tofs ((char *)arg, buf, blocksize);
- return 0;
- }
-
-#if 0 /* Doesn't work reliably yet. */
- case CDROMRESET:
- {
- struct request req;
- ide_init_drive_cmd (&req);
- req.cmd = RESET_DRIVE_COMMAND;
- return ide_do_drive_cmd (drive, &req, ide_wait);
- }
-#endif
-
-
-#ifdef TEST
- case 0x1234:
- {
- int stat;
- struct packet_command pc;
- int len, lena;
-
- memset (&pc, 0, sizeof (pc));
-
- stat = verify_area (VERIFY_READ, (void *) arg, sizeof (pc.c));
- if (stat) return stat;
- memcpy_fromfs (&pc.c, (void *) arg, sizeof (pc.c));
- arg += sizeof (pc.c);
-
- stat = verify_area (VERIFY_READ, (void *) arg, sizeof (len));
- if (stat) return stat;
- memcpy_fromfs (&len, (void *) arg , sizeof (len));
- arg += sizeof (len);
-
- if (len > 0) {
- stat = verify_area (VERIFY_WRITE, (void *) arg, len);
- if (stat) return stat;
- }
-
- lena = len;
- if (lena < 0) lena = 0;
-
- {
- char buf[lena];
- if (len > 0) {
- pc.buflen = len;
- pc.buffer = buf;
- }
-
- stat = cdrom_queue_packet_command (drive, &pc);
-
- if (len > 0)
- memcpy_tofs ((void *)arg, buf, len);
- }
-
- return stat;
- }
-#endif
-
- default:
- return -EPERM;
- }
-
-}
-
-
-
-/****************************************************************************
- * Other driver requests (open, close, check media change).
- */
-
-int ide_cdrom_check_media_change (ide_drive_t *drive)
-{
- int retval;
-
- (void) cdrom_check_status (drive, NULL);
-
- retval = CDROM_STATE_FLAGS (drive)->media_changed;
- CDROM_STATE_FLAGS (drive)->media_changed = 0;
-
- return retval;
-}
-
-
-int ide_cdrom_open (struct inode *ip, struct file *fp, ide_drive_t *drive)
-{
- /* no write access */
- if (fp->f_mode & 2)
- {
- --drive->usage;
- return -EROFS;
- }
-
- /* If this is the first open, check the drive status. */
- if (drive->usage == 1)
- {
- int stat;
- struct atapi_request_sense my_reqbuf;
- my_reqbuf.sense_key = 0;
-
- /* Get the drive status. */
- stat = cdrom_check_status (drive, &my_reqbuf);
-
- /* If the tray is open, try to close it. */
- if (stat && my_reqbuf.sense_key == NOT_READY)
- {
- cdrom_eject (drive, 1, &my_reqbuf);
- stat = cdrom_check_status (drive, &my_reqbuf);
- }
-
- /* Return an error if there are still problems. */
- if (stat && my_reqbuf.sense_key != UNIT_ATTENTION)
- {
- --drive->usage;
- return -ENXIO;
- }
-
- /* Now lock the door. */
- (void) cdrom_lockdoor (drive, 1, &my_reqbuf);
-
- /* And try to read the TOC information now. */
- (void) cdrom_read_toc (drive, &my_reqbuf);
- }
-
- return 0;
-}
-
-
-/*
- * Close down the device. Invalidate all cached blocks.
- */
-
-void ide_cdrom_release (struct inode *inode, struct file *file, ide_drive_t *drive)
-{
- if (drive->usage == 0)
- {
- invalidate_buffers (inode->i_rdev);
-
- /* Unlock the door. */
- (void) cdrom_lockdoor (drive, 0, NULL);
-
- /* Do an eject if we were requested to do so. */
- if (CDROM_STATE_FLAGS (drive)->eject_on_close)
- (void) cdrom_eject (drive, 0, NULL);
- }
-}
-
-
-
-/****************************************************************************
- * Device initialization.
- */
-
-void ide_cdrom_setup (ide_drive_t *drive)
-{
- blksize_size[HWIF(drive)->major][drive->select.b.unit << PARTN_BITS] = CD_FRAMESIZE;
-
- drive->special.all = 0;
- drive->ready_stat = 0;
-
- CDROM_STATE_FLAGS (drive)->media_changed = 0;
- CDROM_STATE_FLAGS (drive)->toc_valid = 0;
- CDROM_STATE_FLAGS (drive)->door_locked = 0;
-
- /* Turn this off by default, since many people don't like it. */
- CDROM_STATE_FLAGS (drive)->eject_on_close= 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;
- }
-
-#if ! STANDARD_ATAPI
- CDROM_CONFIG_FLAGS (drive)->no_playaudio12 = 0;
- CDROM_CONFIG_FLAGS (drive)->old_readcd = 0;
- CDROM_CONFIG_FLAGS (drive)->no_lba_toc = 0;
- CDROM_CONFIG_FLAGS (drive)->playmsf_uses_bcd = 0;
- CDROM_CONFIG_FLAGS (drive)->vertos_lossage = 0;
-
- if (drive->id != NULL) {
- /* Accommodate some broken drives... */
- if (strcmp (drive->id->model, "CD220E") == 0 ||
- strcmp (drive->id->model, "CD") == 0) /* Creative Labs */
- CDROM_CONFIG_FLAGS (drive)->no_lba_toc = 1;
-
- else if (strcmp (drive->id->model, "TO-ICSLYAL") == 0 || /* Acer CD525E */
- strcmp (drive->id->model, "OTI-SCYLLA") == 0)
- CDROM_CONFIG_FLAGS (drive)->no_lba_toc = 1;
-
- /* I don't know who makes this.
- Francesco Messineo <sidera@ccii.unipi.it> says this one's broken too. */
- else if (strcmp (drive->id->model, "DCI-2S10") == 0)
- CDROM_CONFIG_FLAGS (drive)->no_lba_toc = 1;
-
- else if (strcmp (drive->id->model, "CDA26803I SE") == 0) /* Aztech */
- {
- CDROM_CONFIG_FLAGS (drive)->no_lba_toc = 1;
-
- /* This drive _also_ does not implement PLAYAUDIO12 correctly. */
- CDROM_CONFIG_FLAGS (drive)->no_playaudio12 = 1;
- }
-
- /* Vertos 300.
- There seem to be at least two different, incompatible versions
- of this drive floating around. Luckily, they appear to return their
- id strings with different byte orderings. */
- else if (strcmp (drive->id->model, "V003S0DS") == 0)
- {
- CDROM_CONFIG_FLAGS (drive)->vertos_lossage = 1;
- CDROM_CONFIG_FLAGS (drive)->playmsf_uses_bcd = 1;
- CDROM_CONFIG_FLAGS (drive)->no_lba_toc = 1;
- }
- else if (strcmp (drive->id->model, "0V300SSD") == 0 ||
- strcmp (drive->id->model, "V003M0DP") == 0)
- CDROM_CONFIG_FLAGS (drive)->no_lba_toc = 1;
-
- /* Vertos 400. */
- else if (strcmp (drive->id->model, "V004E0DT") == 0 ||
- strcmp (drive->id->model, "0V400ETD") == 0)
- CDROM_CONFIG_FLAGS (drive)->no_lba_toc = 1;
-
- else if ( strcmp (drive->id->model, "CD-ROM CDU55D") == 0) /*sony cdu55d */
- CDROM_CONFIG_FLAGS (drive)->no_playaudio12 = 1;
-
- else if (strcmp (drive->id->model, "CD-ROM CDU55E") == 0)
- CDROM_CONFIG_FLAGS (drive)->no_playaudio12 = 1;
- } /* drive-id != NULL */
-#endif /* not STANDARD_ATAPI */
-
- drive->cdrom_info.toc = NULL;
- drive->cdrom_info.sector_buffer = NULL;
- drive->cdrom_info.sector_buffered = 0;
- drive->cdrom_info.nsectors_buffered = 0;
-}
-
-
-
-/*
- * TODO:
- * CDROM_GET_UPC
- * CDROMRESET
- * Lock the door when a read request completes successfully and the
- * door is not already locked. Also try to reorganize to reduce
- * duplicated functionality between read and ioctl paths?
- * Establish interfaces for an IDE port driver, and break out the cdrom
- * code into a loadable module.
- * Support changers.
- * Write some real documentation.
- */
diff --git a/i386/i386at/gpl/linux/block/ide.c b/i386/i386at/gpl/linux/block/ide.c
deleted file mode 100644
index 4b7c5e9..0000000
--- a/i386/i386at/gpl/linux/block/ide.c
+++ /dev/null
@@ -1,3087 +0,0 @@
-/*
- * linux/drivers/block/ide.c Version 5.28 Feb 11, 1996
- *
- * Copyright (C) 1994-1996 Linus Torvalds & authors (see below)
- */
-#define _IDE_C /* needed by <linux/blk.h> */
-
-/*
- * This is the multiple IDE interface driver, as evolved from hd.c.
- * It supports up to four 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 i/f: ide0: major=3; (hda) minor=0; (hdb) minor=64
- * Secondary i/f: ide1: major=22; (hdc or hd1a) minor=0; (hdd or hd1b) minor=64
- * Tertiary i/f: ide2: major=33; (hde) minor=0; (hdf) minor=64
- * Quaternary i/f: ide3: major=34; (hdg) minor=0; (hdh) minor=64
- *
- * It is easy to extend ide.c to handle more than four interfaces:
- *
- * Change the MAX_HWIFS constant in ide.h.
- *
- * Define some new major numbers (in major.h), and insert them into
- * the ide_hwif_to_major table in ide.c.
- *
- * Fill in the extra values for the new interfaces into the two tables
- * inside ide.c: default_io_base[] and default_irqs[].
- *
- * Create the new request handlers by cloning "do_ide3_request()"
- * for each new interface, and add them to the switch statement
- * in the ide_init() function in ide.c.
- *
- * Recompile, create the new /dev/ entries, and it will probably work.
- *
- * 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@bnr.ca).
- *
- * October, 1994 -- Complete line-by-line overhaul for linux 1.1.x, by:
- *
- * Mark Lord (mlord@bnr.ca) (IDE Perf.Pkg)
- * Delman Lee (delman@mipg.upenn.edu) ("Mr. atdisk2")
- * Petri Mattila (ptjmatti@kruuna.helsinki.fi) (EIDE stuff)
- * Scott Snyder (snyder@fnald0.fnal.gov) (ATAPI IDE cd-rom)
- *
- * Maintained by Mark Lord (mlord@bnr.ca): ide.c, ide.h, triton.c, hd.c, ..
- *
- * 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 3.5 correct the bios_cyl field if it's too small
- * (linux 1.1.76) (to help fdisk with brain-dead BIOSs)
- * Version 3.6 cosmetic corrections to comments and stuff
- * (linux 1.1.77) reorganise probing code to make it understandable
- * added halfway retry to probing for drive identification
- * added "hdx=noprobe" command line option
- * allow setting multmode even when identification fails
- * Version 3.7 move set_geometry=1 from do_identify() to ide_init()
- * increase DRQ_WAIT to eliminate nuisance messages
- * wait for DRQ_STAT instead of DATA_READY during probing
- * (courtesy of Gary Thomas gary@efland.UU.NET)
- * Version 3.8 fixed byte-swapping for confused Mitsumi cdrom drives
- * update of ide-cd.c from Scott, allows blocksize=1024
- * cdrom probe fixes, inspired by jprang@uni-duisburg.de
- * Version 3.9 don't use LBA if lba_capacity looks funny
- * correct the drive capacity calculations
- * fix probing for old Seagates without IDE_ALTSTATUS_REG
- * fix byte-ordering for some NEC cdrom drives
- * Version 3.10 disable multiple mode by default; was causing trouble
- * Version 3.11 fix mis-identification of old WD disks as cdroms
- * Version 3,12 simplify logic for selecting initial mult_count
- * (fixes problems with buggy WD drives)
- * Version 3.13 remove excess "multiple mode disabled" messages
- * Version 3.14 fix ide_error() handling of BUSY_STAT
- * fix byte-swapped cdrom strings (again.. arghh!)
- * ignore INDEX bit when checking the ALTSTATUS reg
- * Version 3.15 add SINGLE_THREADED flag for use with dual-CMD i/f
- * ignore WRERR_STAT for non-write operations
- * added vlb_sync support for DC-2000A & others,
- * (incl. some Promise chips), courtesy of Frank Gockel
- * Version 3.16 convert vlb_32bit and vlb_sync into runtime flags
- * add ioctls to get/set VLB flags (HDIO_[SG]ET_CHIPSET)
- * rename SINGLE_THREADED to SUPPORT_SERIALIZE,
- * add boot flag to "serialize" operation for CMD i/f
- * add optional support for DTC2278 interfaces,
- * courtesy of andy@cercle.cts.com (Dyan Wile).
- * add boot flag to enable "dtc2278" probe
- * add probe to avoid EATA (SCSI) interfaces,
- * courtesy of neuffer@goofy.zdv.uni-mainz.de.
- * Version 4.00 tidy up verify_area() calls - heiko@colossus.escape.de
- * add flag to ignore WRERR_STAT for some drives
- * courtesy of David.H.West@um.cc.umich.edu
- * assembly syntax tweak to vlb_sync
- * removeable drive support from scuba@cs.tu-berlin.de
- * add transparent support for DiskManager-6.0x "Dynamic
- * Disk Overlay" (DDO), most of this is in genhd.c
- * eliminate "multiple mode turned off" message at boot
- * Version 4.10 fix bug in ioctl for "hdparm -c3"
- * fix DM6:DDO support -- now works with LILO, fdisk, ...
- * don't treat some naughty WD drives as removeable
- * Version 4.11 updated DM6 support using info provided by OnTrack
- * Version 5.00 major overhaul, multmode setting fixed, vlb_sync fixed
- * added support for 3rd/4th/alternative IDE ports
- * created ide.h; ide-cd.c now compiles separate from ide.c
- * hopefully fixed infinite "unexpected_intr" from cdroms
- * zillions of other changes and restructuring
- * somehow reduced overall memory usage by several kB
- * probably slowed things down slightly, but worth it
- * Version 5.01 AT LAST!! Finally understood why "unexpected_intr"
- * was happening at various times/places: whenever the
- * ide-interface's ctl_port was used to "mask" the irq,
- * it also would trigger an edge in the process of masking
- * which would result in a self-inflicted interrupt!!
- * (such a stupid way to build a hardware interrupt mask).
- * This is now fixed (after a year of head-scratching).
- * Version 5.02 got rid of need for {enable,disable}_irq_list()
- * Version 5.03 tune-ups, comments, remove "busy wait" from drive resets
- * removed PROBE_FOR_IRQS option -- no longer needed
- * OOOPS! fixed "bad access" bug for 2nd drive on an i/f
- * Version 5.04 changed "ira %d" to "irq %d" in DEBUG message
- * added more comments, cleaned up unexpected_intr()
- * OOOPS! fixed null pointer problem in ide reset code
- * added autodetect for Triton chipset -- no effect yet
- * Version 5.05 OOOPS! fixed bug in revalidate_disk()
- * OOOPS! fixed bug in ide_do_request()
- * added ATAPI reset sequence for cdroms
- * Version 5.10 added Bus-Mastered DMA support for Triton Chipset
- * some (mostly) cosmetic changes
- * Version 5.11 added ht6560b support by malafoss@snakemail.hut.fi
- * reworked PCI scanning code
- * added automatic RZ1000 detection/support
- * added automatic PCI CMD640 detection/support
- * added option for VLB CMD640 support
- * tweaked probe to find cdrom on hdb with disks on hda,hdc
- * Version 5.12 some performance tuning
- * added message to alert user to bad /dev/hd[cd] entries
- * OOOPS! fixed bug in atapi reset
- * driver now forces "serialize" again for all cmd640 chips
- * noticed REALLY_SLOW_IO had no effect, moved it to ide.c
- * made do_drive_cmd() into public ide_do_drive_cmd()
- * Version 5.13 fixed typo ('B'), thanks to houston@boyd.geog.mcgill.ca
- * fixed ht6560b support
- * Version 5.13b (sss) fix problem in calling ide_cdrom_setup()
- * don't bother invalidating nonexistent partitions
- * Version 5.14 fixes to cmd640 support.. maybe it works now(?)
- * added & tested full EZ-DRIVE support -- don't use LILO!
- * don't enable 2nd CMD640 PCI port during init - conflict
- * Version 5.15 bug fix in init_cmd640_vlb()
- * bug fix in interrupt sharing code
- * Version 5.16 ugh.. fix "serialize" support, broken in 5.15
- * remove "Huh?" from cmd640 code
- * added qd6580 interface speed select from Colten Edwards
- * Version 5.17 kludge around bug in BIOS32 on Intel triton motherboards
- * Version 5.18 new CMD640 code, moved to cmd640.c, #include'd for now
- * new UMC8672 code, moved to umc8672.c, #include'd for now
- * disallow turning on DMA when h/w not capable of DMA
- * Version 5.19 fix potential infinite timeout on resets
- * extend reset poll into a general purpose polling scheme
- * add atapi tape drive support from Gadi Oxman
- * simplify exit from _intr routines -- no IDE_DO_REQUEST
- * Version 5.20 leave current rq on blkdev request list during I/O
- * generalized ide_do_drive_cmd() for tape/cdrom driver use
- * Version 5.21 fix nasty cdrom/tape bug (ide_preempt was messed up)
- * Version 5.22 fix ide_xlate_1024() to work with/without drive->id
- * Version 5.23 miscellaneous touch-ups
- * Version 5.24 fix #if's for SUPPORT_CMD640
- * Version 5.25 more touch-ups, fix cdrom resets, ...
- * cmd640.c now configs/compiles separate from ide.c
- * Version 5.26 keep_settings now maintains the using_dma flag
- * fix [EZD] remap message to only output at boot time
- * fix "bad /dev/ entry" message to say hdc, not hdc0
- * fix ide_xlate_1024() to respect user specified CHS
- * use CHS from partn table if it looks translated
- * re-merged flags chipset,vlb_32bit,vlb_sync into io_32bit
- * keep track of interface chipset type, when known
- * add generic PIO mode "tuneproc" mechanism
- * fix cmd640_vlb option
- * fix ht6560b support (was completely broken)
- * umc8672.c now configures/compiles separate from ide.c
- * move dtc2278 support to dtc2278.c
- * move ht6560b support to ht6560b.c
- * move qd6580 support to qd6580.c
- * add ali14xx support in ali14xx.c
- * Version 5.27 add [no]autotune parameters to help cmd640
- * move rz1000 support to rz1000.c
- * Version 5.28 #include "ide_modes.h"
- * fix disallow_unmask: now per-interface "no_unmask" bit
- * force io_32bit to be the same on drive pairs of dtc2278
- * improved IDE tape error handling, and tape DMA support
- * bugfix in ide_do_drive_cmd() for cdroms + serialize
- *
- * Some additional driver compile-time options are in ide.h
- *
- * To do, in likely order of completion:
- * - add Promise DC4030VL support from peterd@pnd-pc.demon.co.uk
- * - modify kernel to obtain BIOS geometry for drives on 2nd/3rd/4th i/f
-*/
-
-#if defined (MACH) && !defined (LINUX_IDE_DEBUG)
-#undef DEBUG
-#endif
-
-#undef REALLY_SLOW_IO /* most systems can safely undef this */
-
-#include <linux/config.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/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/major.h>
-#include <linux/blkdev.h>
-#include <linux/errno.h>
-#include <linux/hdreg.h>
-#include <linux/genhd.h>
-#include <linux/malloc.h>
-
-#include <asm/byteorder.h>
-#include <asm/irq.h>
-#include <asm/segment.h>
-#include <asm/io.h>
-
-#ifdef CONFIG_PCI
-#include <linux/bios32.h>
-#include <linux/pci.h>
-#endif /* CONFIG_PCI */
-
-#include "ide.h"
-#include "ide_modes.h"
-
-static ide_hwgroup_t *irq_to_hwgroup [NR_IRQS];
-static const byte ide_hwif_to_major[MAX_HWIFS] = {IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR};
-
-static const unsigned short default_io_base[MAX_HWIFS] = {0x1f0, 0x170, 0x1e8, 0x168};
-static const byte default_irqs[MAX_HWIFS] = {14, 15, 11, 10};
-
-#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);
- cli();
- t = jiffies * 11932;
- outb_p(0, 0x43);
- i = inb_p(0x40);
- i |= inb(0x40) << 8;
- restore_flags(flags);
- return (t - i);
-}
-
-static void set_recovery_timer (ide_hwif_t *hwif)
-{
- hwif->last_time = read_timer();
-}
-#define SET_RECOVERY_TIMER(drive) set_recovery_timer (drive)
-
-#else
-
-#define SET_RECOVERY_TIMER(drive)
-
-#endif /* DISK_RECOVERY_TIME */
-
-/*
- * 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_ide_data (void)
-{
- byte *p;
- unsigned int h, unit;
- static unsigned long magic_cookie = MAGIC_COOKIE;
-
- if (magic_cookie != MAGIC_COOKIE)
- return; /* already initialized */
- magic_cookie = 0;
-
- for (h = 0; h < NR_IRQS; ++h)
- irq_to_hwgroup[h] = NULL;
-
- /* bulk initialize hwif & drive info with zeros */
- p = ((byte *) ide_hwifs) + sizeof(ide_hwifs);
- do {
- *--p = 0;
- } while (p > (byte *) ide_hwifs);
-
- /* fill in any non-zero initial values */
- for (h = 0; h < MAX_HWIFS; ++h) {
- ide_hwif_t *hwif = &ide_hwifs[h];
-
- hwif->index = h;
- hwif->noprobe = (h > 1);
- hwif->io_base = default_io_base[h];
- hwif->ctl_port = hwif->io_base ? hwif->io_base+0x206 : 0x000;
-#ifdef CONFIG_BLK_DEV_HD
- if (hwif->io_base == HD_DATA)
- hwif->noprobe = 1; /* may be overriden by ide_setup() */
-#endif /* CONFIG_BLK_DEV_HD */
- hwif->major = ide_hwif_to_major[h];
- hwif->name[0] = 'i';
- hwif->name[1] = 'd';
- hwif->name[2] = 'e';
- hwif->name[3] = '0' + h;
-#ifdef CONFIG_BLK_DEV_IDETAPE
- hwif->tape_drive = NULL;
-#endif /* CONFIG_BLK_DEV_IDETAPE */
- for (unit = 0; unit < MAX_DRIVES; ++unit) {
- ide_drive_t *drive = &hwif->drives[unit];
-
- 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' + (h * MAX_DRIVES) + unit;
- }
- }
-}
-
-#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 (unsigned short 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)
-{
- unsigned short io_base = HWIF(drive)->io_base;
- unsigned short data_reg = io_base+IDE_DATA_OFFSET;
- byte io_32bit = drive->io_32bit;
-
- if (io_32bit) {
-#if SUPPORT_VLB_SYNC
- if (io_32bit & 2) {
- cli();
- do_vlb_sync(io_base+IDE_NSECTOR_OFFSET);
- insl(data_reg, buffer, wcount);
- if (drive->unmask)
- sti();
- } else
-#endif /* SUPPORT_VLB_SYNC */
- insl(data_reg, buffer, wcount);
- } else
- insw(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)
-{
- unsigned short io_base = HWIF(drive)->io_base;
- unsigned short data_reg = io_base+IDE_DATA_OFFSET;
- byte io_32bit = drive->io_32bit;
-
- if (io_32bit) {
-#if SUPPORT_VLB_SYNC
- if (io_32bit & 2) {
- cli();
- do_vlb_sync(io_base+IDE_NSECTOR_OFFSET);
- outsl(data_reg, buffer, wcount);
- if (drive->unmask)
- sti();
- } else
-#endif /* SUPPORT_VLB_SYNC */
- outsl(data_reg, buffer, wcount);
- } else
- outsw(data_reg, buffer, wcount<<1);
-}
-
-/*
- * 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 timer_expiry() handler later on).
- */
-void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, unsigned int timeout)
-{
- ide_hwgroup_t *hwgroup = HWGROUP(drive);
-#ifdef DEBUG
- if (hwgroup->handler != NULL) {
- printk("%s: ide_set_handler: handler not null; old=%p, new=%p\n",
- drive->name, hwgroup->handler, handler);
- }
-#endif
- hwgroup->handler = handler;
- hwgroup->timer.expires = jiffies + timeout;
- add_timer(&(hwgroup->timer));
-}
-
-/*
- * 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
- */
-static int lba_capacity_is_ok (struct hd_driveid *id)
-{
- unsigned long lba_sects = id->lba_capacity;
- unsigned long chs_sects = id->cyls * id->heads * id->sectors;
- unsigned long _10_percent = chs_sects / 10;
-
- /* perform a rough sanity check on lba_sects: within 10% is "okay" */
- if ((lba_sects - chs_sects) < _10_percent)
- return 1; /* lba_capacity is good */
-
- /* some drives have the word order reversed */
- lba_sects = (lba_sects << 16) | (lba_sects >> 16);
- if ((lba_sects - chs_sects) < _10_percent) {
- id->lba_capacity = lba_sects; /* fix it */
- return 1; /* lba_capacity is (now) good */
- }
- return 0; /* lba_capacity value is bad */
-}
-
-/*
- * current_capacity() returns the capacity (in sectors) of a drive
- * according to its current geometry/LBA settings.
- */
-static unsigned long current_capacity (ide_drive_t *drive)
-{
- struct hd_driveid *id = drive->id;
- unsigned long capacity;
-
- if (!drive->present)
- return 0;
- if (drive->media != ide_disk)
- return 0x7fffffff; /* cdrom or tape */
- /* Determine capacity, and use LBA if the drive properly supports it */
- if (id != NULL && (id->capability & 2) && lba_capacity_is_ok(id)) {
- drive->select.b.lba = 1;
- capacity = id->lba_capacity;
- } else {
- drive->select.b.lba = 0;
- capacity = drive->cyl * drive->head * drive->sect;
- }
- return (capacity - drive->sect0);
-}
-
-/*
- * ide_geninit() is called exactly *once* for each major, from genhd.c,
- * at the beginning of the initial partition check for the drives.
- */
-static void ide_geninit (struct gendisk *gd)
-{
- unsigned int unit;
- ide_hwif_t *hwif = gd->real_devices;
-
- for (unit = 0; unit < gd->nr_real; ++unit) {
- ide_drive_t *drive = &hwif->drives[unit];
-#ifdef CONFIG_BLK_DEV_IDECD
- if (drive->present && drive->media == ide_cdrom)
- ide_cdrom_setup(drive);
-#endif /* CONFIG_BLK_DEV_IDECD */
-#ifdef CONFIG_BLK_DEV_IDETAPE
- if (drive->present && drive->media == ide_tape)
- idetape_setup(drive);
-#endif /* CONFIG_BLK_DEV_IDETAPE */
- drive->part[0].nr_sects = current_capacity(drive);
- if (!drive->present || drive->media != ide_disk) {
- drive->part[0].start_sect = -1; /* skip partition check */
- }
- }
- /*
- * The partition check in genhd.c needs this string to identify
- * our minor devices by name for display purposes.
- * Note that doing this will prevent us from working correctly
- * if ever called a second time for this major (never happens).
- */
- gd->real_devices = hwif->drives[0].name; /* name of first drive */
-}
-
-/*
- * 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;
- unsigned int unit, units, minors;
- int *bs;
-
- /* 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);
-
- /* cdroms and msdos f/s are examples of non-1024 blocksizes */
- blksize_size[hwif->major] = bs;
- for (unit = 0; unit < minors; ++unit)
- *bs++ = BLOCK_SIZE;
-
- 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->max_nr = units; /* max num real drives */
- gd->nr_real = units; /* current num real drives */
- gd->init = ide_geninit; /* initialization function */
- gd->real_devices= hwif; /* ptr to internal data */
-
- gd->next = gendisk_head; /* link new major into list */
- hwif->gd = gendisk_head = gd;
-}
-
-static void do_reset1 (ide_drive_t *, int); /* needed below */
-
-#ifdef CONFIG_BLK_DEV_IDEATAPI
-/*
- * 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 void atapi_reset_pollfunc (ide_drive_t *drive)
-{
- ide_hwgroup_t *hwgroup = HWGROUP(drive);
- byte stat;
-
- OUT_BYTE (drive->select.all, IDE_SELECT_REG);
- udelay (10);
-
- if (OK_STAT(stat=GET_STAT(), 0, BUSY_STAT)) {
- printk("%s: ATAPI reset complete\n", drive->name);
- } else {
- if (jiffies < hwgroup->poll_timeout) {
- ide_set_handler (drive, &atapi_reset_pollfunc, HZ/20);
- return; /* continue polling */
- }
- hwgroup->poll_timeout = 0; /* end of polling */
- printk("%s: ATAPI reset timed-out, status=0x%02x\n", drive->name, stat);
- do_reset1 (drive, 1); /* do it the old fashioned way */
- }
- hwgroup->poll_timeout = 0; /* done polling */
-}
-#endif /* CONFIG_BLK_DEV_IDEATAPI */
-
-/*
- * 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 void 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 (jiffies < hwgroup->poll_timeout) {
- ide_set_handler (drive, &reset_pollfunc, HZ/20);
- return; /* 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 {
- 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");
- }
- }
- hwgroup->poll_timeout = 0; /* done polling */
-}
-
-/*
- * 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 void 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);
- cli(); /* Why ? */
-
-#ifdef CONFIG_BLK_DEV_IDEATAPI
- /* For an ATAPI device, first try an ATAPI SRST. */
- if (drive->media != ide_disk) {
- if (!do_not_try_atapi) {
- if (!drive->keep_settings)
- drive->unmask = 0;
- OUT_BYTE (drive->select.all, IDE_SELECT_REG);
- udelay (20);
- OUT_BYTE (WIN_SRST, IDE_COMMAND_REG);
- hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
- ide_set_handler (drive, &atapi_reset_pollfunc, HZ/20);
- restore_flags (flags);
- return;
- }
- }
-#endif /* CONFIG_BLK_DEV_IDEATAPI */
-
- /*
- * First, reset any device state data we were maintaining
- * for any of the drives on this interface.
- */
- for (unit = 0; unit < MAX_DRIVES; ++unit) {
- ide_drive_t *rdrive = &hwif->drives[unit];
- rdrive->special.all = 0;
- rdrive->special.b.set_geometry = 1;
- rdrive->special.b.recalibrate = 1;
- if (OK_TO_RESET_CONTROLLER)
- rdrive->mult_count = 0;
- if (!rdrive->keep_settings) {
- rdrive->using_dma = 0;
- rdrive->mult_req = 0;
- rdrive->unmask = 0;
- }
- if (rdrive->mult_req != rdrive->mult_count)
- rdrive->special.b.set_multmode = 1;
- }
-
-#if OK_TO_RESET_CONTROLLER
- /*
- * 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(5); /* more than enough time */
- OUT_BYTE(drive->ctl|2,IDE_CONTROL_REG); /* clear SRST, leave nIEN */
- hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
- ide_set_handler (drive, &reset_pollfunc, HZ/20);
-#endif /* OK_TO_RESET_CONTROLLER */
-
- restore_flags (flags);
-}
-
-/*
- * ide_do_reset() is the entry point to the drive/interface reset code.
- */
-void ide_do_reset (ide_drive_t *drive)
-{
- do_reset1 (drive, 0);
-#ifdef CONFIG_BLK_DEV_IDETAPE
- if (drive->media == ide_tape)
- drive->tape.reset_issued=1;
-#endif /* CONFIG_BLK_DEV_IDETAPE */
-}
-
-/*
- * 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);
- }
- }
- save_flags(flags);
- cli();
- blk_dev[MAJOR(rq->rq_dev)].current_request = rq->next;
- HWGROUP(drive)->rq = NULL;
- rq->rq_status = RQ_INACTIVE;
- if (rq->sem != NULL)
- up(rq->sem);
- restore_flags(flags);
-}
-
-/*
- * 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);
- sti();
- printk("%s: %s: status=0x%02x", drive->name, msg, stat);
-#if FANCY_STATUS_DUMPS
- if (drive->media == ide_disk) {
- 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 & BBD_ERR) printk("BadSector ");
- if (err & ECC_ERR) printk("UncorrectableError ");
- if (err & ID_ERR) printk("SectorIdNotFound ");
- if (err & ABRT_ERR) printk("DriveStatusError ");
- if (err & TRK0_ERR) printk("TrackZeroNotFound ");
- if (err & MARK_ERR) printk("AddrMarkNotFound ");
- printk("}");
- if (err & (BBD_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);
- 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;
-
- while (i > 0) {
- unsigned long 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 controller.
- */
-void ide_error (ide_drive_t *drive, const char *msg, byte stat)
-{
- struct request *rq;
- byte err;
-
- err = ide_dump_status(drive, msg, stat);
- if ((rq = HWGROUP(drive)->rq) == NULL || drive == NULL)
- return;
- /* retry only "normal" I/O: */
- if (rq->cmd == IDE_DRIVE_CMD || (rq->cmd != READ && rq->cmd != WRITE && drive->media == ide_disk))
- {
- rq->errors = 1;
- ide_end_drive_cmd(drive, stat, err);
- return;
- }
- if (stat & BUSY_STAT) { /* 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 & (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))
- rq->errors |= ERROR_RESET; /* Mmmm.. timing problem */
-
- if (rq->errors >= ERROR_MAX) {
-#ifdef CONFIG_BLK_DEV_IDETAPE
- if (drive->media == ide_tape) {
- rq->errors = 0;
- idetape_end_request(0, HWGROUP(drive));
- }
- else
-#endif /* CONFIG_BLK_DEV_IDETAPE */
- ide_end_request(0, HWGROUP(drive));
- }
- else {
- if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
- ++rq->errors;
- ide_do_reset(drive);
- return;
- } else if ((rq->errors & ERROR_RECAL) == ERROR_RECAL)
- drive->special.b.recalibrate = 1;
- ++rq->errors;
- }
-}
-
-/*
- * read_intr() is the handler for disk read/multread interrupts
- */
-static void read_intr (ide_drive_t *drive)
-{
- byte stat;
- int i;
- unsigned int msect, nsect;
- struct request *rq;
-
- if (!OK_STAT(stat=GET_STAT(),DATA_READY,BAD_R_STAT)) {
- ide_error(drive, "read_intr", stat);
- return;
- }
- 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;
- ide_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 ((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);
- }
-}
-
-/*
- * write_intr() is the handler for disk write interrupts
- */
-static void 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)) {
-#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 (rq->current_nr_sectors <= 0)
- ide_end_request(1, hwgroup);
- if (i > 0) {
- ide_output_data (drive, rq->buffer, SECTOR_WORDS);
- ide_set_handler (drive, &write_intr, WAIT_CMD);
- }
- return;
- }
- }
- ide_error(drive, "write_intr", stat);
-}
-
-/*
- * multwrite() transfers a block of one or more sectors of data to a drive
- * as part of a disk multwrite operation.
- */
-static void multwrite (ide_drive_t *drive)
-{
- struct request *rq = &HWGROUP(drive)->wrq;
- unsigned int mcount = drive->mult_count;
-
- do {
- unsigned int nsect = rq->current_nr_sectors;
- if (nsect > mcount)
- nsect = mcount;
- mcount -= nsect;
-
- ide_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
- if ((rq->nr_sectors -= nsect) <= 0)
- 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 {
- panic("%s: buffer list corrupted\n", drive->name);
- break;
- }
- } else {
- rq->buffer += nsect << 9;
- }
- } while (mcount);
-}
-
-/*
- * multwrite_intr() is the handler for disk multwrite interrupts
- */
-static void 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) {
- if (rq->nr_sectors) {
- multwrite(drive);
- ide_set_handler (drive, &multwrite_intr, WAIT_CMD);
- return;
- }
- } else {
- 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_error(drive, "multwrite_intr", stat);
-}
-
-/*
- * Issue a simple drive command
- * The drive must be selected beforehand.
- */
-static void ide_cmd(ide_drive_t *drive, byte cmd, byte nsect, ide_handler_t *handler)
-{
- ide_set_handler (drive, handler, WAIT_CMD);
- OUT_BYTE(drive->ctl,IDE_CONTROL_REG);
- OUT_BYTE(nsect,IDE_NSECTOR_REG);
- OUT_BYTE(cmd,IDE_COMMAND_REG);
-}
-
-/*
- * set_multmode_intr() is invoked on completion of a WIN_SETMULT cmd.
- */
-static void set_multmode_intr (ide_drive_t *drive)
-{
- byte stat = GET_STAT();
-
- sti();
- if (OK_STAT(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);
- }
-}
-
-/*
- * set_geometry_intr() is invoked on completion of a WIN_SPECIFY cmd.
- */
-static void set_geometry_intr (ide_drive_t *drive)
-{
- byte stat = GET_STAT();
-
- sti();
- if (!OK_STAT(stat,READY_STAT,BAD_STAT))
- ide_error(drive, "set_geometry_intr", stat);
-}
-
-/*
- * recal_intr() is invoked on completion of a WIN_RESTORE (recalibrate) cmd.
- */
-static void recal_intr (ide_drive_t *drive)
-{
- byte stat = GET_STAT();
-
- sti();
- if (!OK_STAT(stat,READY_STAT,BAD_STAT))
- ide_error(drive, "recal_intr", stat);
-}
-
-/*
- * drive_cmd_intr() is invoked on completion of a special DRIVE_CMD.
- */
-static void drive_cmd_intr (ide_drive_t *drive)
-{
- byte stat = GET_STAT();
-
- sti();
- if (OK_STAT(stat,READY_STAT,BAD_STAT))
- ide_end_drive_cmd (drive, stat, GET_ERR());
- else
- ide_error(drive, "drive_cmd", stat); /* calls ide_end_drive_cmd */
-}
-
-/*
- * 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 inline void do_special (ide_drive_t *drive)
-{
- special_t *s = &drive->special;
-next:
-#ifdef DEBUG
- printk("%s: do_special: 0x%02x\n", drive->name, s->all);
-#endif
- if (s->b.set_geometry) {
- s->b.set_geometry = 0;
- if (drive->media == ide_disk) {
- 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);
- ide_cmd(drive, WIN_SPECIFY, drive->sect, &set_geometry_intr);
- }
- } else if (s->b.recalibrate) {
- s->b.recalibrate = 0;
- if (drive->media == ide_disk) {
- ide_cmd(drive, WIN_RESTORE, drive->sect, &recal_intr);
- }
- } else if (s->b.set_pio) {
- ide_tuneproc_t *tuneproc = HWIF(drive)->tuneproc;
- s->b.set_pio = 0;
- if (tuneproc != NULL)
- tuneproc(drive, drive->pio_req);
- goto next;
- } else if (s->b.set_multmode) {
- s->b.set_multmode = 0;
- if (drive->media == ide_disk) {
- if (drive->id && drive->mult_req > drive->id->max_multsect)
- drive->mult_req = drive->id->max_multsect;
- ide_cmd(drive, WIN_SETMULT, drive->mult_req, &set_multmode_intr);
- } else
- drive->mult_req = 0;
- } else if (s->all) {
- s->all = 0;
- printk("%s: bad special flag: 0x%02x\n", drive->name, s->all);
- }
-}
-
-/*
- * 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_drive_t *drive, byte good, byte bad, unsigned long timeout)
-{
- byte stat;
- unsigned long flags;
-
-test:
- udelay(1); /* spec allows drive 400ns to change "BUSY" */
- if (OK_STAT((stat = GET_STAT()), good, bad))
- return 0; /* fast exit for most frequent case */
- if (!(stat & BUSY_STAT)) {
- ide_error(drive, "status error", stat);
- return 1;
- }
-
- save_flags(flags);
- sti();
- timeout += jiffies;
- do {
- if (!((stat = GET_STAT()) & BUSY_STAT)) {
- restore_flags(flags);
- goto test;
- }
- } while (jiffies <= timeout);
-
- restore_flags(flags);
- ide_error(drive, "status timeout", GET_STAT());
- return 1;
-}
-
-/*
- * do_rw_disk() issues WIN_{MULT}READ and WIN_{MULT}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 inline void do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block)
-{
- unsigned short io_base = HWIF(drive)->io_base;
-
- OUT_BYTE(drive->ctl,IDE_CONTROL_REG);
- OUT_BYTE(rq->nr_sectors,io_base+IDE_NSECTOR_OFFSET);
- if (drive->select.b.lba) {
-#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,io_base+IDE_SECTOR_OFFSET);
- OUT_BYTE(block>>=8,io_base+IDE_LCYL_OFFSET);
- OUT_BYTE(block>>=8,io_base+IDE_HCYL_OFFSET);
- OUT_BYTE(((block>>8)&0x0f)|drive->select.all,io_base+IDE_SELECT_OFFSET);
- } else {
- unsigned int sect,head,cyl,track;
- track = block / drive->sect;
- sect = block % drive->sect + 1;
- OUT_BYTE(sect,io_base+IDE_SECTOR_OFFSET);
- head = track % drive->head;
- cyl = track / drive->head;
- OUT_BYTE(cyl,io_base+IDE_LCYL_OFFSET);
- OUT_BYTE(cyl>>8,io_base+IDE_HCYL_OFFSET);
- OUT_BYTE(head|drive->select.all,io_base+IDE_SELECT_OFFSET);
-#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
- }
- if (rq->cmd == READ) {
-#ifdef CONFIG_BLK_DEV_TRITON
- if (drive->using_dma && !(HWIF(drive)->dmaproc(ide_dma_read, drive)))
- return;
-#endif /* CONFIG_BLK_DEV_TRITON */
- ide_set_handler(drive, &read_intr, WAIT_CMD);
- OUT_BYTE(drive->mult_count ? WIN_MULTREAD : WIN_READ, io_base+IDE_COMMAND_OFFSET);
- return;
- }
- if (rq->cmd == WRITE) {
-#ifdef CONFIG_BLK_DEV_TRITON
- if (drive->using_dma && !(HWIF(drive)->dmaproc(ide_dma_write, drive)))
- return;
-#endif /* CONFIG_BLK_DEV_TRITON */
- OUT_BYTE(drive->mult_count ? WIN_MULTWRITE : WIN_WRITE, io_base+IDE_COMMAND_OFFSET);
- if (ide_wait_stat(drive, DATA_READY, drive->bad_wstat, WAIT_DRQ)) {
- printk("%s: no DRQ after issuing %s\n", drive->name,
- drive->mult_count ? "MULTWRITE" : "WRITE");
- return;
- }
- if (!drive->unmask)
- cli();
- if (drive->mult_count) {
- HWGROUP(drive)->wrq = *rq; /* scratchpad */
- ide_set_handler (drive, &multwrite_intr, WAIT_CMD);
- multwrite(drive);
- } else {
- ide_set_handler (drive, &write_intr, WAIT_CMD);
- ide_output_data(drive, rq->buffer, SECTOR_WORDS);
- }
- return;
- }
- if (rq->cmd == IDE_DRIVE_CMD) {
- byte *args = rq->buffer;
- if (args) {
-#ifdef DEBUG
- printk("%s: DRIVE_CMD cmd=0x%02x sc=0x%02x fr=0x%02x\n",
- drive->name, args[0], args[1], args[2]);
-#endif
- OUT_BYTE(args[2],io_base+IDE_FEATURE_OFFSET);
- ide_cmd(drive, args[0], args[1], &drive_cmd_intr);
- return;
- } 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;
- }
- }
- printk("%s: bad command: %d\n", drive->name, rq->cmd);
- ide_end_request(0, HWGROUP(drive));
-}
-
-/*
- * do_request() initiates handling of a new I/O request
- */
-static inline void do_request (ide_hwif_t *hwif, struct request *rq)
-{
- unsigned int minor, unit;
- unsigned long block, blockend;
- ide_drive_t *drive;
-
- sti();
-#ifdef DEBUG
- printk("%s: do_request: current=0x%08lx\n", hwif->name, (unsigned long) rq);
-#endif
- minor = MINOR(rq->rq_dev);
- unit = minor >> PARTN_BITS;
- if (MAJOR(rq->rq_dev) != hwif->major || unit >= MAX_DRIVES) {
- printk("%s: bad device number: %s\n",
- hwif->name, kdevname(rq->rq_dev));
- goto kill_rq;
- }
- drive = &hwif->drives[unit];
-#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 ((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;
-#if FAKE_FDISK_FOR_EZDRIVE
- if (block == 0 && drive->remap_0_to_1)
- block = 1; /* redirect MBR access to EZ-Drive partn table */
-#endif /* FAKE_FDISK_FOR_EZDRIVE */
- ((ide_hwgroup_t *)hwif->hwgroup)->drive = drive;
-#ifdef CONFIG_BLK_DEV_HT6560B
- if (hwif->selectproc)
- hwif->selectproc (drive);
-#endif /* CONFIG_BLK_DEV_HT6560B */
-#if (DISK_RECOVERY_TIME > 0)
- while ((read_timer() - hwif->last_time) < DISK_RECOVERY_TIME);
-#endif
-
-#ifdef CONFIG_BLK_DEV_IDETAPE
- POLL_HWIF_TAPE_DRIVE; /* macro from ide-tape.h */
-#endif /* CONFIG_BLK_DEV_IDETAPE */
-
- OUT_BYTE(drive->select.all,IDE_SELECT_REG);
- if (ide_wait_stat(drive, drive->ready_stat, BUSY_STAT|DRQ_STAT, WAIT_READY)) {
- printk("%s: drive not ready for command\n", drive->name);
- return;
- }
-
- if (!drive->special.all) {
-#ifdef CONFIG_BLK_DEV_IDEATAPI
- switch (drive->media) {
- case ide_disk:
- do_rw_disk (drive, rq, block);
- return;
-#ifdef CONFIG_BLK_DEV_IDECD
- case ide_cdrom:
- ide_do_rw_cdrom (drive, block);
- return;
-#endif /* CONFIG_BLK_DEV_IDECD */
-#ifdef CONFIG_BLK_DEV_IDETAPE
- case ide_tape:
- if (rq->cmd == IDE_DRIVE_CMD) {
- byte *args = (byte *) rq->buffer;
- OUT_BYTE(args[2],IDE_FEATURE_REG);
- ide_cmd(drive, args[0], args[1], &drive_cmd_intr);
- return;
- }
- idetape_do_request (drive, rq, block);
- return;
-#endif /* CONFIG_BLK_DEV_IDETAPE */
-
- default:
- printk("%s: media type %d not supported\n",
- drive->name, drive->media);
- goto kill_rq;
- }
-#else
- do_rw_disk (drive, rq, block); /* simpler and faster */
- return;
-#endif /* CONFIG_BLK_DEV_IDEATAPI */;
- }
- do_special(drive);
- return;
-kill_rq:
- ide_end_request(0, hwif->hwgroup);
-}
-
-/*
- * The driver enables interrupts as much as possible. In order to do this,
- * (a) the device-interrupt is always masked before entry, and
- * (b) the timeout-interrupt is always disabled before entry.
- *
- * If we enter here from, say irq14, and then start a new request for irq15,
- * (possible with "serialize" option) then we cannot ensure that we exit
- * before the irq15 hits us. So, we must be careful not to let this bother us.
- *
- * 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. For devices which don't suffer from
- * this problem (most don't), the unmask flag can be set using the "hdparm"
- * utility, to permit other interrupts during data/cmd transfers.
- */
-void ide_do_request (ide_hwgroup_t *hwgroup)
-{
- cli(); /* paranoia */
- if (hwgroup->handler != NULL) {
- printk("%s: EEeekk!! handler not NULL in ide_do_request()\n", hwgroup->hwif->name);
- return;
- }
- do {
- ide_hwif_t *hwif = hwgroup->hwif;
- struct request *rq;
- if ((rq = hwgroup->rq) == NULL) {
- do {
- rq = blk_dev[hwif->major].current_request;
- if (rq != NULL && rq->rq_status != RQ_INACTIVE)
- goto got_rq;
- } while ((hwif = hwif->next) != hwgroup->hwif);
- return; /* no work left for this hwgroup */
- }
- got_rq:
- do_request(hwgroup->hwif = hwif, hwgroup->rq = rq);
- cli();
- } while (hwgroup->handler == NULL);
-}
-
-/*
- * do_hwgroup_request() invokes ide_do_request() after first masking
- * all possible interrupts for the current hwgroup. This prevents race
- * conditions in the event that an unexpected interrupt occurs while
- * we are in the driver.
- *
- * Note that when an interrupt is used to reenter the driver, the first level
- * handler will already have masked the irq that triggered, but any other ones
- * for the hwgroup will still be unmasked. The driver tries to be careful
- * about such things.
- */
-static void do_hwgroup_request (ide_hwgroup_t *hwgroup)
-{
- if (hwgroup->handler == NULL) {
- ide_hwif_t *hgif = hwgroup->hwif;
- ide_hwif_t *hwif = hgif;
- do {
- disable_irq(hwif->irq);
- } while ((hwif = hwif->next) != hgif);
- ide_do_request (hwgroup);
- do {
- enable_irq(hwif->irq);
- } while ((hwif = hwif->next) != hgif);
- }
-}
-
-static void do_ide0_request (void) /* invoked with cli() */
-{
- do_hwgroup_request (ide_hwifs[0].hwgroup);
-}
-
-static void do_ide1_request (void) /* invoked with cli() */
-{
- do_hwgroup_request (ide_hwifs[1].hwgroup);
-}
-
-static void do_ide2_request (void) /* invoked with cli() */
-{
- do_hwgroup_request (ide_hwifs[2].hwgroup);
-}
-
-static void do_ide3_request (void) /* invoked with cli() */
-{
- do_hwgroup_request (ide_hwifs[3].hwgroup);
-}
-
-static void timer_expiry (unsigned long data)
-{
- ide_hwgroup_t *hwgroup = (ide_hwgroup_t *) data;
- ide_drive_t *drive = hwgroup->drive;
- unsigned long flags;
-
- save_flags(flags);
- cli();
-
- if (hwgroup->poll_timeout != 0) { /* polling in progress? */
- ide_handler_t *handler = hwgroup->handler;
- hwgroup->handler = NULL;
- handler(drive);
- } else if (hwgroup->handler == NULL) { /* not waiting for anything? */
- sti(); /* drive must have responded just as the timer expired */
- printk("%s: marginal timeout\n", drive->name);
- } else {
- hwgroup->handler = NULL; /* abort the operation */
- if (hwgroup->hwif->dmaproc)
- (void) hwgroup->hwif->dmaproc (ide_dma_abort, drive);
- ide_error(drive, "irq timeout", GET_STAT());
- }
- if (hwgroup->handler == NULL)
- do_hwgroup_request (hwgroup);
- restore_flags(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" (CMD640B), 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;
- unsigned int unit;
- ide_hwif_t *hwif = hwgroup->hwif;
-
- /*
- * handle the unexpected interrupt
- */
- do {
- if (hwif->irq == irq) {
- for (unit = 0; unit < MAX_DRIVES; ++unit) {
- ide_drive_t *drive = &hwif->drives[unit];
- if (!drive->present)
- continue;
-#ifdef CONFIG_BLK_DEV_HT6560B
- if (hwif->selectproc)
- hwif->selectproc (drive);
-#endif /* CONFIG_BLK_DEV_HT6560B */
- if (!OK_STAT(stat=GET_STAT(), drive->ready_stat, BAD_STAT))
- (void) ide_dump_status(drive, "unexpected_intr", stat);
- if ((stat & DRQ_STAT))
- try_to_flush_leftover_data(drive);
- }
- }
- } while ((hwif = hwif->next) != hwgroup->hwif);
-#ifdef CONFIG_BLK_DEV_HT6560B
- if (hwif->selectproc)
- hwif->selectproc (hwgroup->drive);
-#endif /* CONFIG_BLK_DEV_HT6560B */
-}
-
-/*
- * entry point for all interrupts, caller does cli() for us
- */
-static void ide_intr (int irq, struct pt_regs *regs)
-{
- ide_hwgroup_t *hwgroup = irq_to_hwgroup[irq];
- ide_handler_t *handler;
-
- if (irq == hwgroup->hwif->irq && (handler = hwgroup->handler) != NULL) {
- ide_drive_t *drive = hwgroup->drive;
- hwgroup->handler = NULL;
- del_timer(&(hwgroup->timer));
- if (drive->unmask)
- sti();
- handler(drive);
- cli(); /* this is necessary, as next rq may be different irq */
- if (hwgroup->handler == NULL) {
- SET_RECOVERY_TIMER(HWIF(drive));
- ide_do_request(hwgroup);
- }
- } else {
- unexpected_intr(irq, hwgroup);
- }
- cli();
-}
-
-/*
- * 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.
- */
-static ide_drive_t *get_info_ptr (kdev_t i_rdev)
-{
- int major = MAJOR(i_rdev);
- 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 (drive->present)
- return drive;
- } else if (major == IDE0_MAJOR && unit < 4) {
- printk("ide: probable bad entry for /dev/hd%c\n", 'a'+unit);
- printk("ide: to fix it, run: /usr/src/linux/drivers/block/MAKEDEV.ide\n");
- }
- 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->next = NULL;
-
-#if 0 /* these are done each time through ide_do_drive_cmd() */
- rq->errors = 0;
- rq->rq_status = RQ_ACTIVE;
- rq->rq_dev = ????;
-#endif
-}
-
-/*
- * This function issues a special IDE device request
- * onto the request queue.
- *
- * If action is ide_wait, then then 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. (Currently used by ide-tape.c,
- * when operating in the pipelined operation mode).
- */
-int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t action)
-{
- unsigned long flags;
- unsigned int major = HWIF(drive)->major;
- struct request *cur_rq;
- struct blk_dev_struct *bdev = &blk_dev[major];
- struct semaphore sem = MUTEX_LOCKED;
-
- 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;
-
- save_flags(flags);
- cli();
- cur_rq = bdev->current_request;
-
- if (cur_rq == NULL || action == ide_preempt) {
- rq->next = cur_rq;
- bdev->current_request = rq;
- if (action == ide_preempt) {
- HWGROUP(drive)->rq = NULL;
- } else
- if (HWGROUP(drive)->rq == NULL) { /* is this necessary (?) */
- bdev->request_fn();
- cli();
- }
- } else {
- if (action == ide_wait || action == ide_end) {
- while (cur_rq->next != NULL) /* find end of list */
- cur_rq = cur_rq->next;
- }
- rq->next = cur_rq->next;
- cur_rq->next = rq;
- }
- if (action == ide_wait && rq->rq_status != RQ_INACTIVE)
- down(&sem); /* wait for it to be serviced */
- restore_flags(flags);
- return rq->errors ? -EIO : 0; /* return -EIO if errors */
-}
-
-static int ide_open(struct inode * inode, struct file * filp)
-{
- ide_drive_t *drive;
- unsigned long flags;
-
- if ((drive = get_info_ptr(inode->i_rdev)) == NULL)
- return -ENODEV;
- save_flags(flags);
- cli();
- while (drive->busy)
- sleep_on(&drive->wqueue);
- drive->usage++;
- restore_flags(flags);
-#ifdef CONFIG_BLK_DEV_IDECD
- if (drive->media == ide_cdrom)
- return ide_cdrom_open (inode, filp, drive);
-#endif /* CONFIG_BLK_DEV_IDECD */
-#ifdef CONFIG_BLK_DEV_IDETAPE
- if (drive->media == ide_tape)
- return idetape_blkdev_open (inode, filp, drive);
-#endif /* CONFIG_BLK_DEV_IDETAPE */
- if (drive->removeable) {
- byte door_lock[] = {WIN_DOORLOCK,0,0,0};
- struct request rq;
- check_disk_change(inode->i_rdev);
- ide_init_drive_cmd (&rq);
- rq.buffer = door_lock;
- /*
- * Ignore the return code from door_lock,
- * since the open() has already succeeded,
- * and the door_lock is irrelevant at this point.
- */
- (void) ide_do_drive_cmd(drive, &rq, ide_wait);
- }
- return 0;
-}
-
-/*
- * Releasing a block device means we sync() it, so that it can safely
- * be forgotten about...
- */
-static void ide_release(struct inode * inode, struct file * file)
-{
- ide_drive_t *drive;
-
- if ((drive = get_info_ptr(inode->i_rdev)) != NULL) {
- sync_dev(inode->i_rdev);
- drive->usage--;
-#ifdef CONFIG_BLK_DEV_IDECD
- if (drive->media == ide_cdrom) {
- ide_cdrom_release (inode, file, drive);
- return;
- }
-#endif /* CONFIG_BLK_DEV_IDECD */
-#ifdef CONFIG_BLK_DEV_IDETAPE
- if (drive->media == ide_tape) {
- idetape_blkdev_release (inode, file, drive);
- return;
- }
-#endif /* CONFIG_BLK_DEV_IDETAPE */
- if (drive->removeable) {
- byte door_unlock[] = {WIN_DOORUNLOCK,0,0,0};
- struct request rq;
- invalidate_buffers(inode->i_rdev);
- ide_init_drive_cmd (&rq);
- rq.buffer = door_unlock;
- (void) ide_do_drive_cmd(drive, &rq, ide_wait);
- }
- }
-}
-
-/*
- * 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_disk(kdev_t i_rdev)
-{
- ide_drive_t *drive;
- 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;
- save_flags(flags);
- cli();
- if (drive->busy || (drive->usage > 1)) {
- restore_flags(flags);
- return -EBUSY;
- };
- drive->busy = 1;
- restore_flags(flags);
-
- for (p = 0; p < (1<<PARTN_BITS); ++p) {
- if (drive->part[p].nr_sects > 0) {
- kdev_t devp = MKDEV(major, minor+p);
- sync_dev (devp);
- invalidate_inodes (devp);
- invalidate_buffers (devp);
- }
- drive->part[p].start_sect = 0;
- drive->part[p].nr_sects = 0;
- };
-
- drive->part[0].nr_sects = current_capacity(drive);
- if (drive->media == ide_disk)
- resetup_one_dev(HWIF(drive)->gd, drive->select.b.unit);
-
- drive->busy = 0;
- wake_up(&drive->wqueue);
- return 0;
-}
-
-static int write_fs_long (unsigned long useraddr, long value)
-{
- int err;
-
- if (NULL == (long *)useraddr)
- return -EINVAL;
- if ((err = verify_area(VERIFY_WRITE, (long *)useraddr, sizeof(long))))
- return err;
- put_user((unsigned)value, (long *) useraddr);
- return 0;
-}
-
-static int ide_ioctl (struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- struct hd_geometry *loc = (struct hd_geometry *) arg;
- int err;
- ide_drive_t *drive;
- unsigned long flags;
- struct request rq;
-
- ide_init_drive_cmd (&rq);
- if (!inode || !(inode->i_rdev))
- return -EINVAL;
- if ((drive = get_info_ptr(inode->i_rdev)) == NULL)
- return -ENODEV;
- switch (cmd) {
- case HDIO_GETGEO:
- if (!loc || drive->media != ide_disk) return -EINVAL;
- err = verify_area(VERIFY_WRITE, loc, sizeof(*loc));
- if (err) return err;
- put_user(drive->bios_head, (byte *) &loc->heads);
- put_user(drive->bios_sect, (byte *) &loc->sectors);
- put_user(drive->bios_cyl, (unsigned short *) &loc->cylinders);
- put_user((unsigned)drive->part[MINOR(inode->i_rdev)&PARTN_MASK].start_sect,
- (unsigned long *) &loc->start);
- return 0;
-
- case BLKFLSBUF:
- if(!suser()) return -EACCES;
- fsync_dev(inode->i_rdev);
- invalidate_buffers(inode->i_rdev);
- return 0;
-
- case BLKRASET:
- if(!suser()) return -EACCES;
- if(arg > 0xff) return -EINVAL;
- read_ahead[MAJOR(inode->i_rdev)] = arg;
- return 0;
-
- case BLKRAGET:
- return write_fs_long(arg, read_ahead[MAJOR(inode->i_rdev)]);
-
- case BLKGETSIZE: /* Return device size */
- return write_fs_long(arg, drive->part[MINOR(inode->i_rdev)&PARTN_MASK].nr_sects);
- case BLKRRPART: /* Re-read partition tables */
- return revalidate_disk(inode->i_rdev);
-
- case HDIO_GET_KEEPSETTINGS:
- return write_fs_long(arg, drive->keep_settings);
-
- case HDIO_GET_UNMASKINTR:
- return write_fs_long(arg, drive->unmask);
-
- case HDIO_GET_DMA:
- return write_fs_long(arg, drive->using_dma);
-
- case HDIO_GET_32BIT:
- return write_fs_long(arg, drive->io_32bit);
-
- case HDIO_GET_MULTCOUNT:
- return write_fs_long(arg, drive->mult_count);
-
- case HDIO_GET_IDENTITY:
- if (!arg || (MINOR(inode->i_rdev) & PARTN_MASK))
- return -EINVAL;
- if (drive->id == NULL)
- return -ENOMSG;
- err = verify_area(VERIFY_WRITE, (char *)arg, sizeof(*drive->id));
- if (!err)
- memcpy_tofs((char *)arg, (char *)drive->id, sizeof(*drive->id));
- return err;
-
- case HDIO_GET_NOWERR:
- return write_fs_long(arg, drive->bad_wstat == BAD_R_STAT);
-
- case HDIO_SET_DMA:
-#ifdef CONFIG_BLK_DEV_IDECD
- if (drive->media == ide_cdrom)
- return -EPERM;
-#endif /* CONFIG_BLK_DEV_IDECD */
- if (!drive->id || !(drive->id->capability & 1) || !HWIF(drive)->dmaproc)
- return -EPERM;
- case HDIO_SET_KEEPSETTINGS:
- case HDIO_SET_UNMASKINTR:
- case HDIO_SET_NOWERR:
- if (arg > 1)
- return -EINVAL;
- case HDIO_SET_32BIT:
- if (!suser())
- return -EACCES;
- if ((MINOR(inode->i_rdev) & PARTN_MASK))
- return -EINVAL;
- save_flags(flags);
- cli();
- switch (cmd) {
- case HDIO_SET_DMA:
- if (!(HWIF(drive)->dmaproc)) {
- restore_flags(flags);
- return -EPERM;
- }
- drive->using_dma = arg;
- break;
- case HDIO_SET_KEEPSETTINGS:
- drive->keep_settings = arg;
- break;
- case HDIO_SET_UNMASKINTR:
- if (arg && HWIF(drive)->no_unmask) {
- restore_flags(flags);
- return -EPERM;
- }
- drive->unmask = arg;
- break;
- case HDIO_SET_NOWERR:
- drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT;
- break;
- case HDIO_SET_32BIT:
- if (arg > (1 + (SUPPORT_VLB_SYNC<<1)))
- return -EINVAL;
- 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 */
- break;
- }
- restore_flags(flags);
- return 0;
-
- case HDIO_SET_MULTCOUNT:
- if (!suser())
- return -EACCES;
- if (MINOR(inode->i_rdev) & PARTN_MASK)
- return -EINVAL;
- if (drive->id && arg > drive->id->max_multsect)
- return -EINVAL;
- save_flags(flags);
- cli();
- if (drive->special.b.set_multmode) {
- restore_flags(flags);
- return -EBUSY;
- }
- drive->mult_req = arg;
- drive->special.b.set_multmode = 1;
- restore_flags(flags);
- (void) ide_do_drive_cmd (drive, &rq, ide_wait);
- return (drive->mult_count == arg) ? 0 : -EIO;
-
- case HDIO_DRIVE_CMD:
- {
- unsigned long args;
-
- if (NULL == (long *) arg)
- err = ide_do_drive_cmd(drive, &rq, ide_wait);
- else {
- if (!(err = verify_area(VERIFY_READ,(long *)arg,sizeof(long))))
- {
- args = get_user((long *)arg);
- if (!(err = verify_area(VERIFY_WRITE,(long *)arg,sizeof(long)))) {
- rq.buffer = (char *) &args;
- err = ide_do_drive_cmd(drive, &rq, ide_wait);
- put_user(args,(long *)arg);
- }
- }
- }
- return err;
- }
- case HDIO_SET_PIO_MODE:
- if (!suser())
- return -EACCES;
- if (MINOR(inode->i_rdev) & PARTN_MASK)
- return -EINVAL;
- if (!HWIF(drive)->tuneproc)
- return -ENOSYS;
- save_flags(flags);
- cli();
- drive->pio_req = (int) arg;
- drive->special.b.set_pio = 1;
- restore_flags(flags);
- return 0;
-
- RO_IOCTLS(inode->i_rdev, arg);
-
- default:
-#ifdef CONFIG_BLK_DEV_IDECD
- if (drive->media == ide_cdrom)
- return ide_cdrom_ioctl(drive, inode, file, cmd, arg);
-#endif /* CONFIG_BLK_DEV_IDECD */
-#ifdef CONFIG_BLK_DEV_IDETAPE
- if (drive->media == ide_tape)
- return idetape_blkdev_ioctl(drive, inode, file, cmd, arg);
-#endif /* CONFIG_BLK_DEV_IDETAPE */
- 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;
-#ifdef CONFIG_BLK_DEV_IDECD
- if (drive->media == ide_cdrom)
- return ide_cdrom_check_media_change (drive);
-#endif /* CONFIG_BLK_DEV_IDECD */
- if (drive->removeable) /* for disks */
- return 1; /* always assume it was changed */
- 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';
-}
-
-static inline void do_identify (ide_drive_t *drive, byte cmd)
-{
- int bswap;
- struct hd_driveid *id;
- unsigned long capacity, check;
-
- id = drive->id = kmalloc (SECTOR_WORDS*4, GFP_KERNEL);
- ide_input_data(drive, id, SECTOR_WORDS); /* read 512 bytes of id info */
- sti();
-
- /*
- * EATA SCSI controllers do a hardware ATA emulation: ignore them
- */
- 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;
- }
-
- /*
- * WIN_IDENTIFY returns little-endian info,
- * WIN_PIDENTIFY *usually* returns little-endian info.
- */
- bswap = 1;
- 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 = 0; /* 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);
-
- /*
- * Check for an ATAPI device
- */
-
- if (cmd == WIN_PIDENTIFY) {
- byte type = (id->config >> 8) & 0x1f;
- printk("%s: %s, ATAPI ", drive->name, id->model);
- switch (type) {
- case 0: /* Early cdrom models used zero */
- case 5:
-#ifdef CONFIG_BLK_DEV_IDECD
- printk ("CDROM drive\n");
- drive->media = ide_cdrom;
- drive->present = 1;
- drive->removeable = 1;
- return;
-#else
- printk ("CDROM ");
- break;
-#endif /* CONFIG_BLK_DEV_IDECD */
- case 1:
-#ifdef CONFIG_BLK_DEV_IDETAPE
- printk ("TAPE drive");
- if (idetape_identify_device (drive,id)) {
- drive->media = ide_tape;
- drive->present = 1;
- drive->removeable = 1;
- if (HWIF(drive)->dmaproc != NULL &&
- !HWIF(drive)->dmaproc(ide_dma_check, drive))
- printk(", DMA");
- printk("\n");
- }
- else {
- drive->present = 0;
- printk ("\nide-tape: the tape is not supported by this version of the driver\n");
- }
- return;
-#else
- printk ("TAPE ");
- break;
-#endif /* CONFIG_BLK_DEV_IDETAPE */
- default:
- drive->present = 0;
- printk("Type %d - Unknown device\n", type);
- return;
- }
- drive->present = 0;
- printk("- not supported by this kernel\n");
- return;
- }
-
- /* check for removeable disks (eg. SYQUEST), ignore 'WD' drives */
- if (id->config & (1<<7)) { /* removeable disk ? */
- if (id->model[0] != 'W' || id->model[1] != 'D')
- drive->removeable = 1;
- }
-
- drive->media = ide_disk;
- /* Extract geometry if we did not already have one for the drive */
- if (!drive->present) {
- drive->present = 1;
- 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)
- {
- /*
- * Extract the physical drive geometry for our use.
- * Note that we purposely do *not* update the bios info.
- * This way, programs that use it (like fdisk) will
- * still have the same logical view as the BIOS does,
- * which keeps the partition table from being screwed.
- *
- * An exception to this is the cylinder count,
- * which we reexamine later on to correct for 1024 limitations.
- */
- drive->cyl = id->cur_cyls;
- drive->head = id->cur_heads;
- drive->sect = id->cur_sectors;
-
- /* check for word-swapped "capacity" field in id information */
- capacity = drive->cyl * drive->head * drive->sect;
- check = (id->cur_capacity0 << 16) | id->cur_capacity1;
- if (check == capacity) { /* was it swapped? */
- /* yes, bring it into little-endian order: */
- id->cur_capacity0 = (capacity >> 0) & 0xffff;
- id->cur_capacity1 = (capacity >> 16) & 0xffff;
- }
- }
- /* Use physical geometry if what we have still makes no sense */
- if ((!drive->head || drive->head > 16) && id->heads && id->heads <= 16) {
- drive->cyl = id->cyls;
- drive->head = id->heads;
- drive->sect = id->sectors;
- }
- /* Correct the number of cyls if the bios value is too small */
- if (drive->sect == drive->bios_sect && drive->head == drive->bios_head) {
- if (drive->cyl > drive->bios_cyl)
- drive->bios_cyl = drive->cyl;
- }
-
- (void) current_capacity (drive); /* initialize LBA selection */
-
- printk ("%s: %.40s, %ldMB w/%dKB Cache, %sCHS=%d/%d/%d",
- drive->name, id->model, current_capacity(drive)/2048L, id->buf_size/2,
- drive->select.b.lba ? "LBA, " : "",
- drive->bios_cyl, drive->bios_head, drive->bios_sect);
-
- drive->mult_count = 0;
- if (id->max_multsect) {
- 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;
- }
- if (HWIF(drive)->dmaproc != NULL) { /* hwif supports DMA? */
- if (!(HWIF(drive)->dmaproc(ide_dma_check, drive)))
- printk(", DMA");
- }
- printk("\n");
-}
-
-/*
- * Delay for *at least* 10ms. 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.
- */
-static void delay_10ms (void)
-{
- unsigned long timer = jiffies + (HZ + 99)/100 + 1;
- while (timer > jiffies);
-}
-
-/*
- * 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 hd_status, rc;
- unsigned long timeout;
- int irqs = 0;
-
- 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 */
- }
-
- delay_10ms(); /* take a deep breath */
- if ((IN_BYTE(IDE_ALTSTATUS_REG) ^ IN_BYTE(IDE_STATUS_REG)) & ~INDEX_STAT) {
- printk("%s: probing with STATUS instead of ALTSTATUS\n", drive->name);
- hd_status = IDE_STATUS_REG; /* ancient Seagate drives */
- } else
- hd_status = IDE_ALTSTATUS_REG; /* use non-intrusive polling */
-
- OUT_BYTE(cmd,IDE_COMMAND_REG); /* ask drive for ID */
- timeout = ((cmd == WIN_IDENTIFY) ? WAIT_WORSTCASE : WAIT_PIDENTIFY) / 2;
- timeout += jiffies;
- do {
- if (jiffies > timeout) {
- if (!HWIF(drive)->irq)
- (void) probe_irq_off(irqs);
- return 1; /* drive timed-out */
- }
- delay_10ms(); /* give drive a breather */
- } while (IN_BYTE(hd_status) & BUSY_STAT);
-
- delay_10ms(); /* wait for IRQ and DRQ_STAT */
- if (OK_STAT(GET_STAT(),DRQ_STAT,BAD_R_STAT)) {
- cli(); /* some systems need this */
- do_identify(drive, cmd); /* drive returned ID */
- if (drive->present && drive->media != ide_tape) {
- ide_tuneproc_t *tuneproc = HWIF(drive)->tuneproc;
- if (tuneproc != NULL && drive->autotune == 1)
- tuneproc(drive, 255); /* auto-tune PIO mode */
- }
- rc = 0; /* drive responded with ID */
- } else
- rc = 2; /* drive refused ID */
- if (!HWIF(drive)->irq) {
- irqs = probe_irq_off(irqs); /* get irq number */
- if (irqs > 0)
- HWIF(drive)->irq = irqs;
- else /* Mmmm.. multiple IRQs */
- printk("%s: IRQ probe failed (%d)\n", drive->name, irqs);
- }
- 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;
-#ifdef CONFIG_BLK_DEV_IDEATAPI
- if (drive->present) { /* avoid waiting for inappropriate probes */
- if ((drive->media != ide_disk) && (cmd == WIN_IDENTIFY))
- return 4;
- }
-#endif /* CONFIG_BLK_DEV_IDEATAPI */
-#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
-#ifdef CONFIG_BLK_DEV_HT6560B
- if (HWIF(drive)->selectproc)
- HWIF(drive)->selectproc (drive);
-#endif /* CONFIG_BLK_DEV_HT6560B */
- OUT_BYTE(drive->select.all,IDE_SELECT_REG); /* select target drive */
- delay_10ms(); /* wait for BUSY_STAT */
- if (IN_BYTE(IDE_SELECT_REG) != drive->select.all && !drive->present) {
- OUT_BYTE(0xa0,IDE_SELECT_REG); /* exit with drive0 selected */
- return 3; /* no i/f present: avoid killing ethernet cards */
- }
-
- 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)
- 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) {
- OUT_BYTE(0xa0,IDE_SELECT_REG); /* exit with drive0 selected */
- delay_10ms();
- (void) GET_STAT(); /* ensure drive irq is clear */
- }
- return rc;
-}
-
-/*
- * probe_for_drive() tests for existance 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) */
-#ifdef CONFIG_BLK_DEV_IDEATAPI
- (void) do_probe(drive, WIN_PIDENTIFY); /* look for ATAPI device */
-#endif /* CONFIG_BLK_DEV_IDEATAPI */
- }
- 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);
- }
-#ifdef CONFIG_BLK_DEV_IDECD
- else if (drive->media == ide_cdrom) {
- printk("%s: ATAPI cdrom (?)\n", drive->name);
- }
-#endif /* CONFIG_BLK_DEV_IDECD */
- else {
- drive->present = 0; /* nuke it */
- return 1; /* drive was found */
- }
- }
- if (drive->media == ide_disk && !drive->select.b.lba) {
- if (!drive->head || drive->head > 16) {
- printk("%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n",
- drive->name, drive->head);
- drive->present = 0;
- }
- }
- return 1; /* drive was found */
-}
-
-/*
- * 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_for_drives (ide_hwif_t *hwif)
-{
- unsigned int unit;
-
- if (check_region(hwif->io_base,8) || check_region(hwif->ctl_port,1)) {
- 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);
- } else {
- unsigned long flags;
- save_flags(flags);
-
-#if (MAX_DRIVES > 2)
- printk("%s: probing for first 2 of %d possible drives\n", hwif->name, MAX_DRIVES);
-#endif
- sti(); /* needed for jiffies and irq probing */
- /*
- * Second drive should only exist if first drive was found,
- * but a lot of cdrom drives seem to be configured as slave-only
- */
- for (unit = 0; unit < 2; ++unit) { /* note the hardcoded '2' */
- ide_drive_t *drive = &hwif->drives[unit];
- (void) probe_for_drive (drive);
- }
- for (unit = 0; unit < MAX_DRIVES; ++unit) {
- ide_drive_t *drive = &hwif->drives[unit];
- if (drive->present) {
- hwif->present = 1;
- request_region(hwif->io_base, 8, hwif->name);
- request_region(hwif->ctl_port, 1, hwif->name);
- break;
- }
- }
- restore_flags(flags);
- }
-}
-
-/*
- * stridx() returns the offset of c within s,
- * or -1 if c is '\0' or not found within s.
- */
-static int 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 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
- */
- 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;
- }
- 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=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=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.
- *
- * "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.
- *
- * The following two are valid ONLY on ide0,
- * and the defaults for the base,ctl ports must not be altered.
- *
- * "ide0=serialize" : do not overlap operations on ide0 and ide1.
- * "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
- */
-void 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 ();
-
- /*
- * Look for drive options: "hdx="
- */
- if (s[0] == 'h' && s[1] == 'd' && s[2] >= 'a' && s[2] <= max_drive) {
- const char *hd_words[] = {"noprobe", "nowerr", "cdrom", "serialize",
- "autotune", "noautotune", NULL};
- unit = s[2] - 'a';
- hw = unit / MAX_DRIVES;
- unit = unit % MAX_DRIVES;
- hwif = &ide_hwifs[hw];
- drive = &hwif->drives[unit];
- switch (match_parm(&s[3], hd_words, vals, 3)) {
- case -1: /* "noprobe" */
- drive->noprobe = 1;
- goto done;
- case -2: /* "nowerr" */
- drive->bad_wstat = BAD_R_STAT;
- hwif->noprobe = 0;
- goto done;
- case -3: /* "cdrom" */
- drive->present = 1;
- drive->media = ide_cdrom;
- hwif->noprobe = 0;
- goto done;
- case -4: /* "serialize" */
- printk(" -- USE \"ide%c=serialize\" INSTEAD", '0'+hw);
- goto do_serialize;
- case -5: /* "autotune" */
- drive->autotune = 1;
- goto done;
- case -6: /* "noautotune" */
- drive->autotune = 2;
- goto done;
- 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;
- }
- }
- /*
- * Look for interface options: "idex="
- */
- if (s[0] == 'i' && s[1] == 'd' && s[2] == 'e' && s[3] >= '0' && s[3] <= max_hwif) {
- /*
- * Be VERY CAREFUL changing this: note hardcoded indexes below
- */
- const char *ide_words[] = {"noprobe", "serialize", "autotune", "noautotune",
- "qd6580", "ht6560b", "cmd640_vlb", "dtc2278", "umc8672", "ali14xx", 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 != -1 && i != -2) {
- if (hwif->chipset != ide_unknown)
- goto bad_option;
- if (i < 0 && ide_hwifs[1].chipset != ide_unknown)
- goto bad_option;
- }
- /*
- * Interface keywords work only for ide0:
- */
- if (i <= -6 && hw != 0)
- goto bad_hwif;
-
- switch (i) {
-#ifdef CONFIG_BLK_DEV_ALI14XX
- case -10: /* "ali14xx" */
- {
- extern void init_ali14xx (void);
- init_ali14xx();
- goto done;
- }
-#endif /* CONFIG_BLK_DEV_ALI14XX */
-#ifdef CONFIG_BLK_DEV_UMC8672
- case -9: /* "umc8672" */
- {
- extern void init_umc8672 (void);
- init_umc8672();
- goto done;
- }
-#endif /* CONFIG_BLK_DEV_UMC8672 */
-#ifdef CONFIG_BLK_DEV_DTC2278
- case -8: /* "dtc2278" */
- {
- extern void init_dtc2278 (void);
- init_dtc2278();
- goto done;
- }
-#endif /* CONFIG_BLK_DEV_DTC2278 */
-#ifdef CONFIG_BLK_DEV_CMD640
- case -7: /* "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 -6: /* "ht6560b" */
- {
- extern void init_ht6560b (void);
- init_ht6560b();
- goto done;
- }
-#endif /* CONFIG_BLK_DEV_HT6560B */
-#if CONFIG_BLK_DEV_QD6580
- case -5: /* "qd6580" (no secondary i/f) */
- {
- extern void init_qd6580 (void);
- init_qd6580();
- goto done;
- }
-#endif /* CONFIG_BLK_DEV_QD6580 */
- 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:
- if (hw > 1) goto bad_hwif;
- ide_hwifs[0].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->io_base = vals[0];
- hwif->ctl_port = vals[1];
- 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;
- }
- }
-bad_option:
- printk(" -- BAD OPTION\n");
- return;
-bad_hwif:
- printk("-- NOT SUPPORTED ON ide%d", hw);
-done:
- printk("\n");
-}
-
-/*
- * This routine is called from the partition-table code in genhd.c
- * to "convert" a drive to a logical geometry with fewer than 1024 cyls.
- *
- * The second parameter, "xparm", determines exactly how the translation
- * will be handled:
- * 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.
- * >1 = convert to a CHS geometry with "xparm" 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, const char *msg)
-{
- ide_drive_t *drive;
- static const byte head_vals[] = {4, 8, 16, 32, 64, 128, 255, 0};
- const byte *heads = head_vals;
- unsigned long tracks;
-
- if ((drive = get_info_ptr(i_rdev)) == NULL || drive->forced_geom)
- return 0;
-
- if (xparm > 1 && xparm <= drive->bios_head && drive->bios_sect == 63)
- return 0; /* we already have a translation */
-
- printk("%s ", msg);
-
- if (drive->id) {
- drive->cyl = drive->id->cyls;
- drive->head = drive->id->heads;
- drive->sect = drive->id->sectors;
- }
- drive->bios_cyl = drive->cyl;
- drive->bios_head = drive->head;
- drive->bios_sect = drive->sect;
- drive->special.b.set_geometry = 1;
-
- tracks = drive->bios_cyl * drive->bios_head * drive->bios_sect / 63;
- drive->bios_sect = 63;
- if (xparm > 1) {
- drive->bios_head = xparm;
- drive->bios_cyl = tracks / drive->bios_head;
- } else {
- while (drive->bios_cyl >= 1024) {
- drive->bios_head = *heads;
- drive->bios_cyl = tracks / drive->bios_head;
- if (0 == *++heads)
- break;
- }
-#if FAKE_FDISK_FOR_EZDRIVE
- if (xparm == -1) {
- drive->remap_0_to_1 = 1;
- msg = "0->1";
- } else
-#endif /* FAKE_FDISK_FOR_EZDRIVE */
- if (xparm == 1) {
- drive->sect0 = 63;
- drive->bios_cyl = (tracks - 1) / drive->bios_head;
- msg = "+63";
- }
- printk("[remap %s] ", msg);
- }
- drive->part[0].nr_sects = current_capacity(drive);
- printk("[%d/%d/%d]", drive->bios_cyl, drive->bios_head, drive->bios_sect);
- return 1;
-}
-
-/*
- * 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
- */
-
-static 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;
-
- 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->cyl = drive->bios_cyl = *(unsigned short *)BIOS;
- drive->head = drive->bios_head = *(BIOS+2);
- drive->sect = drive->bios_sect = *(BIOS+14);
- drive->ctl = *(BIOS+8);
- drive->present = 1;
- }
- BIOS += 16;
- }
-#endif
-}
-
-/*
- * This routine sets up the irq for an ide interface, and creates a new
- * hwgroup for the irq/hwif if none was previously assigned.
- *
- * 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;
- int irq = hwif->irq;
- ide_hwgroup_t *hwgroup = irq_to_hwgroup[irq];
-
- save_flags(flags);
- cli();
-
- /*
- * Grab the irq if we don't already have it from a previous hwif
- */
- if (hwgroup == NULL) {
- if (request_irq(irq, ide_intr, SA_INTERRUPT|SA_SAMPLE_RANDOM, hwif->name)) {
- restore_flags(flags);
- printk(" -- FAILED!");
- return 1;
- }
- }
- /*
- * Check for serialization with ide1.
- * This code depends on us having already taken care of ide1.
- */
- if (hwif->serialized && hwif->name[3] == '0' && ide_hwifs[1].present)
- hwgroup = ide_hwifs[1].hwgroup;
- /*
- * If this is the first interface in a group,
- * then we need to create the hwgroup structure
- */
- if (hwgroup == NULL) {
- hwgroup = kmalloc (sizeof(ide_hwgroup_t), GFP_KERNEL);
- hwgroup->hwif = hwif->next = hwif;
- hwgroup->rq = NULL;
- hwgroup->handler = NULL;
- hwgroup->drive = &hwif->drives[0];
- hwgroup->poll_timeout = 0;
- init_timer(&hwgroup->timer);
- hwgroup->timer.function = &timer_expiry;
- hwgroup->timer.data = (unsigned long) hwgroup;
- } else {
- hwif->next = hwgroup->hwif->next;
- hwgroup->hwif->next = hwif;
- }
- hwif->hwgroup = hwgroup;
- irq_to_hwgroup[irq] = hwgroup;
-
- restore_flags(flags); /* safe now that hwif->hwgroup is set up */
-
- printk("%s at 0x%03x-0x%03x,0x%03x on irq %d", hwif->name,
- hwif->io_base, hwif->io_base+7, hwif->ctl_port, irq);
- if (hwgroup->hwif != hwif)
- printk(" (serialized with %s)", hwgroup->hwif->name);
- printk("\n");
- return 0;
-}
-
-static struct file_operations ide_fops = {
- NULL, /* lseek - default */
- block_read, /* read - general block-dev read */
- block_write, /* write - general block-dev write */
- NULL, /* readdir - bad */
- NULL, /* select */
- ide_ioctl, /* ioctl */
- NULL, /* mmap */
- ide_open, /* open */
- ide_release, /* release */
- block_fsync /* fsync */
- ,NULL, /* fasync */
- ide_check_media_change, /* check_media_change */
- revalidate_disk /* revalidate */
-};
-
-#ifdef CONFIG_PCI
-#if defined(CONFIG_BLK_DEV_RZ1000) || defined(CONFIG_BLK_DEV_TRITON)
-
-typedef void (ide_pci_init_proc_t)(byte, byte);
-
-/*
- * ide_probe_pci() scans PCI for a specific vendor/device function,
- * and invokes the supplied init routine for each instance detected.
- */
-static void ide_probe_pci (unsigned short vendor, unsigned short device, ide_pci_init_proc_t *init, int func_adj)
-{
- unsigned long flags;
- unsigned index;
- byte fn, bus;
-
- save_flags(flags);
- cli();
- for (index = 0; !pcibios_find_device (vendor, device, index, &bus, &fn); ++index) {
- init (bus, fn + func_adj);
- }
- restore_flags(flags);
-}
-
-#endif /* defined(CONFIG_BLK_DEV_RZ1000) || defined(CONFIG_BLK_DEV_TRITON) */
-#endif /* CONFIG_PCI */
-
-/*
- * ide_init_pci() finds/initializes "known" PCI IDE interfaces
- *
- * This routine should ideally be using pcibios_find_class() to find
- * all IDE interfaces, but that function causes some systems to "go weird".
- */
-static void probe_for_hwifs (void)
-{
-#ifdef CONFIG_PCI
- /*
- * Find/initialize PCI IDE interfaces
- */
- if (pcibios_present()) {
-#ifdef CONFIG_BLK_DEV_RZ1000
- ide_pci_init_proc_t init_rz1000;
- ide_probe_pci (PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1000, &init_rz1000, 0);
-#endif /* CONFIG_BLK_DEV_RZ1000 */
-#ifdef CONFIG_BLK_DEV_TRITON
- /*
- * Apparently the BIOS32 services on Intel motherboards are
- * buggy and won't find the PCI_DEVICE_ID_INTEL_82371_1 for us.
- * So instead, we search for PCI_DEVICE_ID_INTEL_82371_0,
- * and then add 1.
- */
- ide_probe_pci (PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371_0, &ide_init_triton, 1);
-#endif /* CONFIG_BLK_DEV_TRITON */
- }
-#endif /* CONFIG_PCI */
-#ifdef CONFIG_BLK_DEV_CMD640
- {
- extern void ide_probe_for_cmd640x (void);
- ide_probe_for_cmd640x();
- }
-#endif
-}
-
-/*
- * This is gets invoked once during initialization, to set *everything* up
- */
-int ide_init (void)
-{
- int h;
-
- init_ide_data ();
- /*
- * Probe for special "known" interface chipsets
- */
- probe_for_hwifs ();
-
- /*
- * Probe for drives in the usual way.. CMOS/BIOS, then poke at ports
- */
- for (h = 0; h < MAX_HWIFS; ++h) {
- ide_hwif_t *hwif = &ide_hwifs[h];
- if (!hwif->noprobe) {
- if (hwif->io_base == HD_DATA)
- probe_cmos_for_drives (hwif);
- probe_for_drives (hwif);
- }
- if (hwif->present) {
- if (!hwif->irq) {
- if (!(hwif->irq = default_irqs[h])) {
- printk("%s: DISABLED, NO IRQ\n", hwif->name);
- hwif->present = 0;
- continue;
- }
- }
-#ifdef CONFIG_BLK_DEV_HD
- if (hwif->irq == HD_IRQ && hwif->io_base != HD_DATA) {
- printk("%s: CANNOT SHARE IRQ WITH OLD HARDDISK DRIVER (hd.c)\n", hwif->name);
- hwif->present = 0;
- }
-#endif /* CONFIG_BLK_DEV_HD */
- }
- }
-
- /*
- * Now we try to set up irqs and major devices for what was found
- */
- for (h = MAX_HWIFS-1; h >= 0; --h) {
- void (*rfn)(void);
- ide_hwif_t *hwif = &ide_hwifs[h];
- if (!hwif->present)
- continue;
- 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;
- case IDE1_MAJOR: rfn = &do_ide1_request; break;
- case IDE2_MAJOR: rfn = &do_ide2_request; break;
- case IDE3_MAJOR: rfn = &do_ide3_request; break;
- default:
- printk("%s: request_fn NOT DEFINED\n", hwif->name);
- continue;
- }
- if (register_blkdev (hwif->major, hwif->name, &ide_fops)) {
- printk("%s: UNABLE TO GET MAJOR NUMBER %d\n", hwif->name, hwif->major);
- } else if (init_irq (hwif)) {
- printk("%s: UNABLE TO GET IRQ %d\n", hwif->name, hwif->irq);
- (void) unregister_blkdev (hwif->major, hwif->name);
- } else {
- init_gendisk(hwif);
- blk_dev[hwif->major].request_fn = rfn;
- read_ahead[hwif->major] = 8; /* (4kB) */
- hwif->present = 1; /* success */
- }
- }
-
-#ifdef CONFIG_BLK_DEV_IDETAPE
- idetape_register_chrdev(); /* Register character device interface to the ide tape */
-#endif /* CONFIG_BLK_DEV_IDETAPE */
-
- return 0;
-}
diff --git a/i386/i386at/gpl/linux/block/ide.h b/i386/i386at/gpl/linux/block/ide.h
deleted file mode 100644
index b1ebc4c..0000000
--- a/i386/i386at/gpl/linux/block/ide.h
+++ /dev/null
@@ -1,655 +0,0 @@
-/*
- * linux/drivers/block/ide.h
- *
- * Copyright (C) 1994, 1995 Linus Torvalds & authors
- */
-
-#include <linux/config.h>
-
-/*
- * This is the multiple IDE interface driver, as evolved from hd.c.
- * It supports up to four 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 i/f: ide0: major=3; (hda) minor=0; (hdb) minor=64
- * Secondary i/f: ide1: major=22; (hdc or hd1a) minor=0; (hdd or hd1b) minor=64
- * Tertiary i/f: ide2: major=33; (hde) minor=0; (hdf) minor=64
- * Quaternary i/f: ide3: major=34; (hdg) minor=0; (hdh) minor=64
- */
-
-/******************************************************************************
- * IDE driver configuration options (play with these as desired):
- *
- * REALLY_SLOW_IO can be defined in ide.c and ide-cd.c, if necessary
- */
-#undef REALLY_FAST_IO /* define if ide ports are perfect */
-#define INITIAL_MULT_COUNT 0 /* off=0; on=2,4,8,16,32, etc.. */
-
-#ifndef SUPPORT_VLB_SYNC /* 1 to support weird 32-bit chips */
-#define SUPPORT_VLB_SYNC 1 /* 0 to reduce kernel size */
-#endif
-#ifndef DISK_RECOVERY_TIME /* off=0; on=access_delay_time */
-#define DISK_RECOVERY_TIME 0 /* for hardware that needs it */
-#endif
-#ifndef OK_TO_RESET_CONTROLLER /* 1 needed for good error recovery */
-#define OK_TO_RESET_CONTROLLER 1 /* 0 for use with AH2372A/B interface */
-#endif
-#ifndef FAKE_FDISK_FOR_EZDRIVE /* 1 to help linux fdisk with EZDRIVE */
-#define FAKE_FDISK_FOR_EZDRIVE 1 /* 0 to reduce kernel size */
-#endif
-#ifndef FANCY_STATUS_DUMPS /* 1 for human-readable drive errors */
-#define FANCY_STATUS_DUMPS 1 /* 0 to reduce kernel size */
-#endif
-
-#if defined(CONFIG_BLK_DEV_IDECD) || defined(CONFIG_BLK_DEV_IDETAPE)
-#define CONFIG_BLK_DEV_IDEATAPI 1
-#endif
-
-/*
- * IDE_DRIVE_CMD is used to implement many features of the hdparm utility
- */
-#define IDE_DRIVE_CMD 99 /* (magic) undef to reduce kernel size*/
-
-/*
- * "No user-serviceable parts" beyond this point :)
- *****************************************************************************/
-
-typedef unsigned char byte; /* used everywhere */
-
-/*
- * Probably not wise to fiddle with these
- */
-#define ERROR_MAX 8 /* Max read/write errors per sector */
-#define ERROR_RESET 3 /* Reset controller every 4th retry */
-#define ERROR_RECAL 1 /* Recalibrate every 2nd retry */
-
-/*
- * Ensure that various configuration flags have compatible settings
- */
-#ifdef REALLY_SLOW_IO
-#undef REALLY_FAST_IO
-#endif
-
-/*
- * Definitions for accessing IDE controller registers
- */
-
-#define HWIF(drive) ((ide_hwif_t *)drive->hwif)
-#define HWGROUP(drive) ((ide_hwgroup_t *)(HWIF(drive)->hwgroup))
-
-#define IDE_DATA_OFFSET (0)
-#define IDE_ERROR_OFFSET (1)
-#define IDE_NSECTOR_OFFSET (2)
-#define IDE_SECTOR_OFFSET (3)
-#define IDE_LCYL_OFFSET (4)
-#define IDE_HCYL_OFFSET (5)
-#define IDE_SELECT_OFFSET (6)
-#define IDE_STATUS_OFFSET (7)
-#define IDE_FEATURE_OFFSET IDE_ERROR_OFFSET
-#define IDE_COMMAND_OFFSET IDE_STATUS_OFFSET
-
-#define IDE_DATA_REG (HWIF(drive)->io_base+IDE_DATA_OFFSET)
-#define IDE_ERROR_REG (HWIF(drive)->io_base+IDE_ERROR_OFFSET)
-#define IDE_NSECTOR_REG (HWIF(drive)->io_base+IDE_NSECTOR_OFFSET)
-#define IDE_SECTOR_REG (HWIF(drive)->io_base+IDE_SECTOR_OFFSET)
-#define IDE_LCYL_REG (HWIF(drive)->io_base+IDE_LCYL_OFFSET)
-#define IDE_HCYL_REG (HWIF(drive)->io_base+IDE_HCYL_OFFSET)
-#define IDE_SELECT_REG (HWIF(drive)->io_base+IDE_SELECT_OFFSET)
-#define IDE_STATUS_REG (HWIF(drive)->io_base+IDE_STATUS_OFFSET)
-#define IDE_CONTROL_REG (HWIF(drive)->ctl_port)
-#define IDE_FEATURE_REG IDE_ERROR_REG
-#define IDE_COMMAND_REG IDE_STATUS_REG
-#define IDE_ALTSTATUS_REG IDE_CONTROL_REG
-
-#ifdef REALLY_FAST_IO
-#define OUT_BYTE(b,p) outb((b),p)
-#define IN_BYTE(p) (byte)inb(p)
-#else
-#define OUT_BYTE(b,p) outb_p((b),p)
-#define IN_BYTE(p) (byte)inb_p(p)
-#endif /* REALLY_FAST_IO */
-
-#define GET_ERR() IN_BYTE(IDE_ERROR_REG)
-#define GET_STAT() IN_BYTE(IDE_STATUS_REG)
-#define OK_STAT(stat,good,bad) (((stat)&((good)|(bad)))==(good))
-#define BAD_R_STAT (BUSY_STAT | ERR_STAT)
-#define BAD_W_STAT (BAD_R_STAT | WRERR_STAT)
-#define BAD_STAT (BAD_R_STAT | DRQ_STAT)
-#define DRIVE_READY (READY_STAT | SEEK_STAT)
-#define DATA_READY (DRIVE_READY | DRQ_STAT)
-
-/*
- * Some more useful definitions
- */
-#define IDE_MAJOR_NAME "ide" /* the same for all i/f; see also genhd.c */
-#define MAJOR_NAME IDE_MAJOR_NAME
-#define PARTN_BITS 6 /* number of minor dev bits for partitions */
-#define PARTN_MASK ((1<<PARTN_BITS)-1) /* a useful bit mask */
-#define MAX_DRIVES 2 /* per interface; 2 assumed by lots of code */
-#define MAX_HWIFS 4 /* an arbitrary, but realistic limit */
-#define SECTOR_WORDS (512 / 4) /* number of 32bit words per sector */
-
-/*
- * Timeouts for various operations:
- */
-#define WAIT_DRQ (5*HZ/100) /* 50msec - spec allows up to 20ms */
-#define WAIT_READY (3*HZ/100) /* 30msec - should be instantaneous */
-#define WAIT_PIDENTIFY (1*HZ) /* 1sec - should be less than 3ms (?) */
-#define WAIT_WORSTCASE (30*HZ) /* 30sec - worst case when spinning up */
-#define WAIT_CMD (10*HZ) /* 10sec - maximum wait for an IRQ to happen */
-
-#ifdef CONFIG_BLK_DEV_IDETAPE
-#include "ide-tape.h"
-#endif /* CONFIG_BLK_DEV_IDETAPE */
-
-#ifdef CONFIG_BLK_DEV_IDECD
-
-struct atapi_request_sense {
- unsigned char error_code : 7;
- unsigned char valid : 1;
- byte reserved1;
- unsigned char sense_key : 4;
- unsigned char reserved2 : 1;
- unsigned char ili : 1;
- unsigned char reserved3 : 2;
- byte info[4];
- byte sense_len;
- byte command_info[4];
- byte asc;
- byte ascq;
- byte fru;
- byte sense_key_specific[3];
-};
-
-struct packet_command {
- char *buffer;
- int buflen;
- int stat;
- struct atapi_request_sense *sense_data;
- unsigned char c[12];
-};
-
-/* 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;
- unsigned control : 4;
- unsigned adr : 4;
- byte track;
- byte reserved2;
- union {
- unsigned lba;
- struct {
- byte reserved3;
- byte m;
- byte s;
- byte f;
- } 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;
-
- u_char acdsc_adr: 4;
- u_char acdsc_ctrl: 4;
- u_char acdsc_trk;
- u_char acdsc_ind;
- union
- {
- struct
- {
- u_char minute;
- u_char second;
- u_char frame;
- } msf;
- int lba;
- } acdsc_absaddr;
- union
- {
- struct
- {
- u_char minute;
- u_char second;
- u_char frame;
- } msf;
- int lba;
- } acdsc_reladdr;
-};
-
-
-/* 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;
-
- /* Sector buffer. If a read request wants only the first part of a cdrom
- block, we cache the rest of the block here, in the expectation that that
- data is going to be wanted soon. SECTOR_BUFFERED is the number of the
- first buffered sector, and NSECTORS_BUFFERED is the number of sectors
- in the buffer. Before the buffer is allocated, we should have
- SECTOR_BUFFER == NULL and NSECTORS_BUFFERED == 0. */
-
- unsigned long sector_buffered;
- unsigned long nsectors_buffered;
- char *sector_buffer;
-
- /* The result of the last successful request sense command
- on this device. */
- struct atapi_request_sense sense_data;
-};
-
-#endif /* CONFIG_BLK_DEV_IDECD */
-
-/*
- * Now for the data we need to maintain per-drive: ide_drive_t
- */
-
-typedef enum {ide_disk, ide_cdrom, ide_tape} ide_media_t;
-
-typedef union {
- unsigned all : 8; /* all of the bits together */
- struct {
- unsigned set_geometry : 1; /* respecify drive geometry */
- unsigned recalibrate : 1; /* seek to cyl 0 */
- unsigned set_multmode : 1; /* set multmode count */
- unsigned set_pio : 1; /* set pio mode */
- unsigned reserved : 4; /* unused */
- } b;
- } special_t;
-
-typedef union {
- unsigned all : 8; /* all of the bits together */
- struct {
- unsigned head : 4; /* always zeros here */
- unsigned unit : 1; /* drive select number, 0 or 1 */
- unsigned bit5 : 1; /* always 1 */
- unsigned lba : 1; /* using LBA instead of CHS */
- unsigned bit7 : 1; /* always 1 */
- } b;
- } select_t;
-
-typedef struct ide_drive_s {
- special_t special; /* special action flags */
- unsigned present : 1; /* drive is physically present */
- unsigned noprobe : 1; /* from: hdx=noprobe */
- unsigned keep_settings : 1; /* restore settings after drive reset */
- unsigned busy : 1; /* currently doing revalidate_disk() */
- unsigned removeable : 1; /* 1 if need to do check_media_change */
- unsigned using_dma : 1; /* disk is using dma for read/write */
- unsigned forced_geom : 1; /* 1 if hdx=c,h,s was given at boot */
- unsigned unmask : 1; /* flag: okay to unmask other irqs */
- unsigned autotune : 2; /* 1=autotune, 2=noautotune, 0=default */
-#if FAKE_FDISK_FOR_EZDRIVE
- unsigned remap_0_to_1 : 1; /* flag: partitioned with ezdrive */
-#endif /* FAKE_FDISK_FOR_EZDRIVE */
- ide_media_t media; /* disk, cdrom, tape */
- select_t select; /* basic drive/head select reg value */
- byte ctl; /* "normal" value for IDE_CONTROL_REG */
- byte ready_stat; /* min status value for drive ready */
- byte mult_count; /* current multiple sector setting */
- byte mult_req; /* requested multiple sector setting */
- byte pio_req; /* requested multiple sector setting */
- byte io_32bit; /* 0=16-bit, 1=32-bit, 2/3=32bit+sync */
- byte bad_wstat; /* used for ignoring WRERR_STAT */
- byte sect0; /* offset of first sector for DM6:DDO */
- byte usage; /* current "open()" count for drive */
- byte head; /* "real" number of heads */
- byte sect; /* "real" sectors per track */
- byte bios_head; /* BIOS/fdisk/LILO number of heads */
- byte bios_sect; /* BIOS/fdisk/LILO sectors per track */
- unsigned short bios_cyl; /* BIOS/fdisk/LILO number of cyls */
- unsigned short cyl; /* "real" number of cyls */
- void *hwif; /* actually (ide_hwif_t *) */
- struct wait_queue *wqueue; /* used to wait for drive in open() */
- struct hd_driveid *id; /* drive model identification info */
- struct hd_struct *part; /* drive partition table */
- char name[4]; /* drive name, such as "hda" */
-#ifdef CONFIG_BLK_DEV_IDECD
- struct cdrom_info cdrom_info; /* for ide-cd.c */
-#endif /* CONFIG_BLK_DEV_IDECD */
-#ifdef CONFIG_BLK_DEV_IDETAPE
- idetape_tape_t tape; /* for ide-tape.c */
-#endif /* CONFIG_BLK_DEV_IDETAPE */
-
- } ide_drive_t;
-
-/*
- * An ide_dmaproc_t() 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.
- *
- * Returns 0 if all went well.
- * Returns 1 if DMA read/write could not be started, in which case the caller
- * should either try again later, or revert to PIO for the current request.
- */
-typedef enum { ide_dma_read = 0, ide_dma_write = 1,
- ide_dma_abort = 2, ide_dma_check = 3,
- ide_dma_status_bad = 4, ide_dma_transferred = 5,
- ide_dma_begin = 6 }
- ide_dma_action_t;
-
-typedef int (ide_dmaproc_t)(ide_dma_action_t, ide_drive_t *);
-
-
-/*
- * An ide_tuneproc_t() is used to set the speed of an IDE interface
- * to a particular PIO mode. The "byte" parameter is used
- * to select the PIO mode by number (0,1,2,3,4,5), and a value of 255
- * indicates that the interface driver should "auto-tune" the PIO mode
- * according to the drive capabilities in drive->id;
- *
- * Not all interface types support tuning, and not all of those
- * support all possible PIO settings. They may silently ignore
- * or round values as they see fit.
- */
-typedef void (ide_tuneproc_t)(ide_drive_t *, byte);
-
-/*
- * This is used to provide HT6560B interface support.
- * It will probably also be used by the DC4030VL driver.
- */
-typedef void (ide_selectproc_t) (ide_drive_t *);
-
-/*
- * hwif_chipset_t is used to keep track of the specific hardware
- * chipset used by each IDE interface, if known.
- */
-typedef enum { ide_unknown, ide_generic, ide_triton,
- ide_cmd640, ide_dtc2278, ide_ali14xx,
- ide_qd6580, ide_umc8672, ide_ht6560b }
- hwif_chipset_t;
-
-typedef struct hwif_s {
- struct hwif_s *next; /* for linked-list in ide_hwgroup_t */
- void *hwgroup; /* actually (ide_hwgroup_t *) */
- unsigned short io_base; /* base io port addr */
- unsigned short ctl_port; /* usually io_base+0x206 */
- ide_drive_t drives[MAX_DRIVES]; /* drive info */
- struct gendisk *gd; /* gendisk structure */
- ide_tuneproc_t *tuneproc; /* routine to tune PIO mode for drives */
-#ifdef CONFIG_BLK_DEV_HT6560B
- ide_selectproc_t *selectproc; /* tweaks hardware to select drive */
-#endif /* CONFIG_BLK_DEV_HT6560B */
- ide_dmaproc_t *dmaproc; /* dma read/write/abort routine */
- unsigned long *dmatable; /* dma physical region descriptor table */
- unsigned short dma_base; /* base addr for dma ports (triton) */
- byte irq; /* our irq number */
- byte major; /* our major number */
- char name[5]; /* name of interface, eg. "ide0" */
- byte index; /* 0 for ide0; 1 for ide1; ... */
- hwif_chipset_t chipset; /* sub-module for tuning.. */
- unsigned noprobe : 1; /* don't probe for this interface */
- unsigned present : 1; /* this interface exists */
- unsigned serialized : 1; /* valid only for ide_hwifs[0] */
- unsigned no_unmask : 1; /* disallow setting unmask bits */
-#if (DISK_RECOVERY_TIME > 0)
- unsigned long last_time; /* time when previous rq was done */
-#endif
-#ifdef CONFIG_BLK_DEV_IDECD
- struct request request_sense_request; /* from ide-cd.c */
- struct packet_command request_sense_pc; /* from ide-cd.c */
-#endif /* CONFIG_BLK_DEV_IDECD */
-#ifdef CONFIG_BLK_DEV_IDETAPE
- ide_drive_t *tape_drive; /* Pointer to the tape on this interface */
-#endif /* CONFIG_BLK_DEV_IDETAPE */
- } ide_hwif_t;
-
-/*
- * internal ide interrupt handler type
- */
-typedef void (ide_handler_t)(ide_drive_t *);
-
-typedef struct hwgroup_s {
- ide_handler_t *handler;/* irq handler, if active */
- ide_drive_t *drive; /* current drive */
- ide_hwif_t *hwif; /* ptr to current hwif in linked-list */
- struct request *rq; /* current request */
- struct timer_list timer; /* failsafe timer */
- struct request wrq; /* local copy of current write rq */
- unsigned long poll_timeout; /* timeout value during long polls */
- } ide_hwgroup_t;
-
-/*
- * ide_hwifs[] is the master data structure used to keep track
- * of just about everything in ide.c. Whenever possible, routines
- * should be using pointers to a drive (ide_drive_t *) or
- * pointers to a hwif (ide_hwif_t *), rather than indexing this
- * structure directly (the allocation/layout may change!).
- */
-#ifdef _IDE_C
- ide_hwif_t ide_hwifs[MAX_HWIFS]; /* master data repository */
-#else
-extern ide_hwif_t ide_hwifs[];
-#endif
-
-/*
- * One final include file, which references some of the data/defns from above
- */
-#define IDE_DRIVER /* "parameter" for blk.h */
-#include <linux/blk.h>
-
-#if (DISK_RECOVERY_TIME > 0)
-void ide_set_recovery_timer (ide_hwif_t *);
-#define SET_RECOVERY_TIMER(drive) ide_set_recovery_timer (drive)
-#else
-#define SET_RECOVERY_TIMER(drive)
-#endif
-
-/*
- * This is used for (nearly) all data transfers from the IDE interface
- */
-void ide_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount);
-
-/*
- * This is used for (nearly) all data transfers to the IDE interface
- */
-void ide_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount);
-
-/*
- * This is used on exit from the driver, to designate the next irq handler
- * and also to start the safety timer.
- */
-void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, unsigned int timeout);
-
-/*
- * Error reporting, in human readable form (luxurious, but a memory hog).
- */
-byte ide_dump_status (ide_drive_t *drive, const char *msg, byte stat);
-
-/*
- * ide_error() takes action based on the error returned by the controller.
- * The calling function must return afterwards, to restart the request.
- */
-void ide_error (ide_drive_t *drive, const char *msg, byte stat);
-
-/*
- * ide_fixstring() cleans up and (optionally) byte-swaps a text string,
- * removing leading/trailing blanks and compressing internal blanks.
- * It is primarily used to tidy up the model name/number fields as
- * returned by the WIN_[P]IDENTIFY commands.
- */
-void ide_fixstring (byte *s, const int bytecount, const int byteswap);
-
-/*
- * 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 return.
- *
- */
-int ide_wait_stat (ide_drive_t *drive, byte good, byte bad, unsigned long timeout);
-
-/*
- * This routine is called from the partition-table code in genhd.c
- * to "convert" a drive to a logical geometry with fewer than 1024 cyls.
- *
- * The second parameter, "xparm", determines exactly how the translation
- * will be handled:
- * 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.
- * >1 = convert to a CHS geometry with "xparm" 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, int, const char *);
-
-/*
- * Start a reset operation for an IDE interface.
- * The caller should return immediately after invoking this.
- */
-void ide_do_reset (ide_drive_t *);
-
-/*
- * This function is intended to be used prior to invoking ide_do_drive_cmd().
- */
-void ide_init_drive_cmd (struct request *rq);
-
-/*
- * "action" parameter type for ide_do_drive_cmd() below.
- */
-typedef enum
- {ide_wait, /* insert rq at end of list, and wait for it */
- ide_next, /* insert rq immediately after current request */
- ide_preempt, /* insert rq in front of current request */
- ide_end} /* insert rq at end of list, but don't wait for it */
- ide_action_t;
-
-/*
- * This function issues a special IDE device request
- * onto the request queue.
- *
- * If action is ide_wait, then then 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. (Currently used by ide-tape.c,
- * when operating in the pipelined operation mode).
- */
-int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t action);
-
-/*
- * Clean up after success/failure of an explicit drive cmd.
- * stat/err are used only when (HWGROUP(drive)->rq->cmd == IDE_DRIVE_CMD).
- */
-void ide_end_drive_cmd (ide_drive_t *drive, byte stat, byte err);
-
-#ifdef CONFIG_BLK_DEV_IDECD
-/*
- * These are routines in ide-cd.c invoked from ide.c
- */
-void ide_do_rw_cdrom (ide_drive_t *, unsigned long);
-int ide_cdrom_ioctl (ide_drive_t *, struct inode *, struct file *, unsigned int, unsigned long);
-int ide_cdrom_check_media_change (ide_drive_t *);
-int ide_cdrom_open (struct inode *, struct file *, ide_drive_t *);
-void ide_cdrom_release (struct inode *, struct file *, ide_drive_t *);
-void ide_cdrom_setup (ide_drive_t *);
-#endif /* CONFIG_BLK_DEV_IDECD */
-
-#ifdef CONFIG_BLK_DEV_IDETAPE
-
-/*
- * Functions in ide-tape.c which are invoked from ide.c:
- */
-
-/*
- * idetape_identify_device is called during device probing stage to
- * probe for an ide atapi tape drive and to initialize global variables
- * in ide-tape.c which provide the link between the character device
- * and the correspoding block device.
- *
- * Returns 1 if an ide tape was detected and is supported.
- * Returns 0 otherwise.
- */
-
-int idetape_identify_device (ide_drive_t *drive,struct hd_driveid *id);
-
-/*
- * idetape_setup is called a bit later than idetape_identify_device,
- * during the search for disk partitions, to initialize various tape
- * state variables in ide_drive_t *drive.
- */
-
-void idetape_setup (ide_drive_t *drive);
-
-/*
- * idetape_do_request is our request function. It is called by ide.c
- * to process a new request.
- */
-
-void idetape_do_request (ide_drive_t *drive, struct request *rq, unsigned long block);
-
-/*
- * idetape_end_request is used to finish servicing a request, and to
- * insert a pending pipeline request into the main device queue.
- */
-
-void idetape_end_request (byte uptodate, ide_hwgroup_t *hwgroup);
-
-/*
- * Block device interface functions.
- */
-
-int idetape_blkdev_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg);
-int idetape_blkdev_open (struct inode *inode, struct file *filp, ide_drive_t *drive);
-void idetape_blkdev_release (struct inode *inode, struct file *filp, ide_drive_t *drive);
-
-/*
- * idetape_register_chrdev initializes the character device interface to
- * the ide tape drive.
- */
-
-void idetape_register_chrdev (void);
-
-#endif /* CONFIG_BLK_DEV_IDETAPE */
-
-#ifdef CONFIG_BLK_DEV_TRITON
-void ide_init_triton (byte, byte);
-#endif /* CONFIG_BLK_DEV_TRITON */
diff --git a/i386/i386at/gpl/linux/block/ide_modes.h b/i386/i386at/gpl/linux/block/ide_modes.h
deleted file mode 100644
index e174d5d..0000000
--- a/i386/i386at/gpl/linux/block/ide_modes.h
+++ /dev/null
@@ -1,142 +0,0 @@
-#ifndef _IDE_MODES_H
-#define _IDE_MODES_H
-/*
- * linux/drivers/block/ide_modes.h
- *
- * Copyright (C) 1996 Linus Torvalds, Igor Abramov, and Mark Lord
- */
-
-/*
- * 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.
- */
-
-#if defined(CONFIG_BLK_DEV_CMD640) || defined(CONFIG_IDE_CHIPSETS)
-
-#ifndef _IDE_C
-
-int ide_scan_pio_blacklist (char *model);
-unsigned int ide_get_best_pio_mode (ide_drive_t *drive);
-
-#else /* _IDE_C */
-
-/*
- * 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 }, */
-
- { "WDC AC2700", 3 },
- { "WDC AC2540", 3 },
- { "WDC AC2420", 3 },
- { "WDC AC2340", 3 },
- { "WDC AC2250", 0 },
- { "WDC AC2200", 0 },
- { "WDC AC2120", 0 },
- { "WDC AC2850", 3 },
- { "WDC AC1270", 3 },
- { "WDC AC1170", 3 },
- { "WDC AC1210", 1 },
- { "WDC AC280", 0 },
-/* { "WDC AC21000", 4 }, */
- { "WDC AC31000", 3 },
-/* { "WDC AC21200", 4 }, */
- { "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 },
-
- { "QUANTUM ELS127A", 0 },
- { "QUANTUM ELS170A", 0 },
- { "QUANTUM LPS240A", 0 },
- { "QUANTUM LPS210A", 3 },
- { "QUANTUM LPS270A", 3 },
- { "QUANTUM LPS365A", 3 },
- { "QUANTUM LPS540A", 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 mode 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".
- */
-unsigned int ide_get_best_pio_mode (ide_drive_t *drive)
-{
- unsigned int pio = 0;
- struct hd_driveid *id = drive->id;
-
- if (id != NULL) {
- if (HWIF(drive)->chipset != ide_cmd640 && !strcmp("QUANTUM FIREBALL1080A", id->model))
- pio = 4;
- else
- pio = ide_scan_pio_blacklist(id->model);
- if (pio == -1) {
- pio = (id->tPIO < 2) ? id->tPIO : 2;
- if (id->field_valid & 2) {
- byte modes = id->eide_pio_modes;
- if (modes & 4) pio = 5;
- else if (modes & 2) pio = 4;
- else if (modes & 1) pio = 3;
- }
- }
- }
- return pio;
-}
-
-#endif /* _IDE_C */
-#endif /* defined(CONFIG_BLK_DEV_CMD640) || defined(CONFIG_IDE_CHIPSETS) */
-#endif /* _IDE_MODES_H */
diff --git a/i386/i386at/gpl/linux/block/rz1000.c b/i386/i386at/gpl/linux/block/rz1000.c
deleted file mode 100644
index 11f1dbd..0000000
--- a/i386/i386at/gpl/linux/block/rz1000.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * linux/drivers/block/rz1000.c Version 0.02 Feb 08, 1996
- *
- * Copyright (C) 1995-1996 Linus Torvalds & author (see below)
- */
-
-/*
- * Principal Author/Maintainer: mlord@bnr.ca (Mark Lord)
- *
- * This file provides support for disabling the buggy read-ahead
- * mode of the RZ1000 IDE chipset, commonly used on Intel motherboards.
- */
-
-#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 <asm/io.h>
-#include <linux/bios32.h>
-#include <linux/pci.h>
-#include "ide.h"
-
-static void ide_pci_access_error (int rc)
-{
- printk("ide: pcibios access failed - %s\n", pcibios_strerror(rc));
-}
-
-void init_rz1000 (byte bus, byte fn)
-{
- int rc;
- unsigned short reg;
-
- printk("ide: buggy RZ1000 interface: ");
- if ((rc = pcibios_read_config_word (bus, fn, PCI_COMMAND, &reg))) {
- ide_pci_access_error (rc);
- } else if (!(reg & 1)) {
- printk("not enabled\n");
- } else {
- if ((rc = pcibios_read_config_word(bus, fn, 0x40, &reg))
- || (rc = pcibios_write_config_word(bus, fn, 0x40, reg & 0xdfff)))
- {
- ide_hwifs[0].no_unmask = 1;
- ide_hwifs[1].no_unmask = 1;
- ide_hwifs[0].serialized = 1;
- ide_pci_access_error (rc);
- printk("serialized, disabled unmasking\n");
- } else
- printk("disabled read-ahead\n");
- }
-}
diff --git a/i386/i386at/gpl/linux/block/triton.c b/i386/i386at/gpl/linux/block/triton.c
deleted file mode 100644
index 4f825f6..0000000
--- a/i386/i386at/gpl/linux/block/triton.c
+++ /dev/null
@@ -1,467 +0,0 @@
-/*
- * linux/drivers/block/triton.c Version 1.06 Feb 6, 1996
- *
- * Copyright (c) 1995-1996 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 Intel PCI Triton chipset (82371FB).
- *
- * DMA is currently supported only for hard disk drives (not cdroms).
- *
- * Support for cdroms will likely be added at a later date,
- * after broader experience has been obtained with hard disks.
- *
- * Up to four drives may be enabled for DMA, and the Triton chipset will
- * (hopefully) arbitrate the PCI bus among them. Note that the 82371FB chip
- * provides a single "line buffer" for the BM IDE function, so performance of
- * multiple (two) drives doing DMA simultaneously will suffer somewhat,
- * as they contest for that resource bottleneck. This is handled transparently
- * inside the 82371FB chip.
- *
- * By default, DMA support is prepared for use, but is currently enabled only
- * for drives which support multi-word DMA mode2 (mword2), or which are
- * recognized as "good" (see table below). Drives with only mode0 or mode1
- * (single or multi) 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-2.4 (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 was done with an ASUS P55TP4XE/100 system and the following drives:
- *
- * Quantum Fireball 1080A (1Gig w/83kB buffer), DMA mode2, PIO mode4.
- * - DMA mode2 works well (7.4MB/sec), despite the tiny on-drive buffer.
- * - This drive also does PIO mode4, at about the same speed as DMA mode2.
- * An awesome drive for the price!
- *
- * Fujitsu M1606TA (1Gig w/256kB buffer), DMA mode2, PIO mode4.
- * - DMA mode2 gives horrible performance (1.6MB/sec), despite the good
- * size of the on-drive buffer and a boasted 10ms average access time.
- * - PIO mode4 was better, but peaked at a mere 4.5MB/sec.
- *
- * Micropolis MC2112A (1Gig w/508kB buffer), drive pre-dates EIDE and ATA2.
- * - DMA works fine (2.2MB/sec), probably due to the large on-drive buffer.
- * - This older drive can also be tweaked for fastPIO (3.7MB/sec) by using
- * maximum clock settings (5,4) and setting all flags except prefetch.
- *
- * Western Digital AC31000H (1Gig w/128kB buffer), DMA mode1, PIO mode3.
- * - DMA does not work reliably. The drive appears to be somewhat tardy
- * in deasserting DMARQ at the end of a sector. This is evident in
- * the observation that WRITEs work most of the time, depending on
- * cache-buffer occupancy, but multi-sector reads seldom work.
- *
- * Testing was done with a Gigabyte GA-586 ATE system and the following drive:
- * (Uwe Bonnes - bon@elektron.ikp.physik.th-darmstadt.de)
- *
- * Western Digital AC31600H (1.6Gig w/128kB buffer), DMA mode2, PIO mode4.
- * - much better than its 1Gig cousin, this drive is reported to work
- * very well with DMA (7.3MB/sec).
- *
- * Other drives:
- *
- * Maxtor 7540AV (515Meg w/32kB buffer), DMA modes mword0/sword2, PIO mode3.
- * - a budget drive, with budget performance, around 3MB/sec.
- *
- * Western Digital AC2850F (814Meg w/64kB buffer), DMA mode1, PIO mode3.
- * - another "caviar" drive, similar to the AC31000, except that this one
- * worked with DMA in at least one system. Throughput is about 3.8MB/sec
- * for both DMA and PIO.
- *
- * Conner CFS850A (812Meg w/64kB buffer), DMA mode2, PIO mode4.
- * - like most Conner models, this drive proves that even a fast interface
- * cannot improve slow media. Both DMA and PIO peak around 3.5MB/sec.
- *
- * If you have any drive models to add, email your results to: mlord@bnr.ca
- * 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).
- *
- * And, yes, Intel Zappa boards really *do* use the Triton IDE ports.
- */
-#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/bios32.h>
-
-#include <asm/io.h>
-#include <asm/dma.h>
-
-#include "ide.h"
-
-/*
- * good_dma_drives() lists the model names (from "hdparm -i")
- * of drives which do not support mword2 DMA but which are
- * known to work fine with this interface under Linux.
- */
-const char *good_dma_drives[] = {"Micropolis 2112A",
- "CONNER CTMA 4000"};
-
-/*
- * 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 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
- */
-static void dma_intr (ide_drive_t *drive)
-{
- byte stat, dma_stat;
- int i;
- struct request *rq = HWGROUP(drive)->rq;
- unsigned short dma_base = HWIF(drive)->dma_base;
-
- dma_stat = inb(dma_base+2); /* get DMA status */
- outb(inb(dma_base)&~1, dma_base); /* stop DMA operation */
- stat = GET_STAT(); /* get drive status */
- if (OK_STAT(stat,DRIVE_READY,drive->bad_wstat|DRQ_STAT)) {
- if ((dma_stat & 7) == 4) { /* verify good DMA status */
- rq = HWGROUP(drive)->rq;
- for (i = rq->nr_sectors; i > 0;) {
- i -= rq->current_nr_sectors;
- ide_end_request(1, HWGROUP(drive));
- }
- return;
- }
- printk("%s: bad DMA status: 0x%02x\n", drive->name, dma_stat);
- }
- sti();
- ide_error(drive, "dma_intr", stat);
-}
-
-/*
- * build_dmatable() prepares a dma request.
- * Returns 0 if all went okay, returns 1 otherwise.
- */
-static int build_dmatable (ide_drive_t *drive)
-{
- struct request *rq = HWGROUP(drive)->rq;
- struct buffer_head *bh = rq->bh;
- unsigned long size, addr, *table = HWIF(drive)->dmatable;
- unsigned int count = 0;
-
- 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 and tape requests have (rq->bh == NULL) */
- addr = virt_to_bus (rq->buffer);
-#ifdef CONFIG_BLK_DEV_IDETAPE
- if (drive->media == ide_tape)
- size = drive->tape.pc->request_transfer;
- else
-#endif /* CONFIG_BLK_DEV_IDETAPE */
- 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 dma table, without crossing any 64kB boundaries.
- * We assume 16-bit alignment of all blocks.
- */
- while (size) {
- if (++count >= PRD_ENTRIES) {
- printk("%s: DMA table too small\n", drive->name);
- return 1; /* revert to PIO for this request */
- } else {
- unsigned long bcount = 0x10000 - (addr & 0xffff);
- if (bcount > size)
- bcount = size;
- *table++ = addr;
- *table++ = bcount;
- addr += bcount;
- size -= bcount;
- }
- }
- } while (bh != NULL);
- if (count) {
- *--table |= 0x80000000; /* set End-Of-Table (EOT) bit */
- return 0;
- }
- printk("%s: empty DMA table?\n", drive->name);
- return 1; /* let the PIO routines handle this weirdness */
-}
-
-static int config_drive_for_dma (ide_drive_t *drive)
-{
- const char **list;
-
- struct hd_driveid *id = drive->id;
- if (id && (id->capability & 1)) {
- /* Enable DMA on any drive that supports mword2 DMA */
- if ((id->field_valid & 2) && (id->dma_mword & 0x404) == 0x404) {
- drive->using_dma = 1;
- return 0; /* DMA enabled */
- }
- /* Consult the list of known "good" drives */
- list = good_dma_drives;
- while (*list) {
- if (!strcmp(*list++,id->model)) {
- drive->using_dma = 1;
- return 0; /* DMA enabled */
- }
- }
- }
- return 1; /* DMA not enabled */
-}
-
-/*
- * triton_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.
- */
-static int triton_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
-{
- unsigned long dma_base = HWIF(drive)->dma_base;
- unsigned int reading = (1 << 3);
-
- switch (func) {
- case ide_dma_abort:
- outb(inb(dma_base)&~1, dma_base); /* stop DMA */
- return 0;
- case ide_dma_check:
- return config_drive_for_dma (drive);
- case ide_dma_write:
- reading = 0;
- case ide_dma_read:
- break;
- case ide_dma_status_bad:
- return ((inb(dma_base+2) & 7) != 4); /* verify good DMA status */
- case ide_dma_transferred:
-#if 0
- return (number of bytes actually transferred);
-#else
- return (0);
-#endif
- case ide_dma_begin:
- outb(inb(dma_base)|1, dma_base); /* begin DMA */
- return 0;
- default:
- printk("triton_dmaproc: unsupported func: %d\n", func);
- return 1;
- }
- if (build_dmatable (drive))
- return 1;
- outl(virt_to_bus (HWIF(drive)->dmatable), dma_base + 4); /* PRD table */
- outb(reading, dma_base); /* specify r/w */
- outb(0x26, dma_base+2); /* clear status bits */
-#ifdef CONFIG_BLK_DEV_IDEATAPI
- if (drive->media != ide_disk)
- return 0;
-#endif /* CONFIG_BLK_DEV_IDEATAPI */
- ide_set_handler(drive, &dma_intr, WAIT_CMD); /* issue cmd to drive */
- OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG);
- outb(inb(dma_base)|1, dma_base); /* begin DMA */
- return 0;
-}
-
-/*
- * print_triton_drive_flags() displays the currently programmed options
- * in the Triton chipset for a given drive.
- *
- * If fastDMA is "no", then slow ISA timings are used for DMA data xfers.
- * If fastPIO is "no", then slow ISA timings are used for PIO data xfers.
- * If IORDY is "no", then IORDY is assumed to always be asserted.
- * If PreFetch is "no", then data pre-fetch/post are not used.
- *
- * When "fastPIO" and/or "fastDMA" are "yes", then faster PCI timings and
- * back-to-back 16-bit data transfers are enabled, using the sample_CLKs
- * and recovery_CLKs (PCI clock cycles) timing parameters for that interface.
- */
-static void print_triton_drive_flags (unsigned int unit, byte flags)
-{
- printk(" %s ", unit ? "slave :" : "master:");
- printk( "fastDMA=%s", (flags&9) ? "on " : "off");
- printk(" PreFetch=%s", (flags&4) ? "on " : "off");
- printk(" IORDY=%s", (flags&2) ? "on " : "off");
- printk(" fastPIO=%s\n", ((flags&9)==1) ? "on " : "off");
-}
-
-static void init_triton_dma (ide_hwif_t *hwif, unsigned short base)
-{
- static unsigned long dmatable = 0;
-
-#if 0
- printk(" %s: BusMaster DMA at 0x%04x-0x%04x", hwif->name, base, base+7);
-#endif
- if (check_region(base, 8)) {
-#if 0
- printk(" -- ERROR, PORTS ALREADY IN USE");
-#endif
- } else {
- request_region(base, 8, "triton DMA");
- hwif->dma_base = base;
- if (!dmatable) {
- /*
- * Since we know we are on a PCI bus, we could
- * actually use __get_free_pages() here instead
- * of __get_dma_pages() -- no ISA limitations.
- */
- dmatable = __get_dma_pages(GFP_KERNEL, 0);
- }
- if (dmatable) {
- hwif->dmatable = (unsigned long *) dmatable;
- dmatable += (PRD_ENTRIES * PRD_BYTES);
- outl(virt_to_bus(hwif->dmatable), base + 4);
- hwif->dmaproc = &triton_dmaproc;
- }
- }
-#if 0
- printk("\n");
-#endif
-}
-
-/*
- * calc_mode() returns the ATA PIO mode number, based on the number
- * of cycle clks passed in. Assumes 33Mhz bus operation (30ns per clk).
- */
-byte calc_mode (byte clks)
-{
- if (clks == 3) return 5;
- if (clks == 4) return 4;
- if (clks < 6) return 3;
- if (clks < 8) return 2;
- if (clks < 13) return 1;
- return 0;
-}
-
-/*
- * ide_init_triton() prepares the IDE driver for DMA operation.
- * This routine is called once, from ide.c during driver initialization,
- * for each triton chipset which is found (unlikely to be more than one).
- */
-void ide_init_triton (byte bus, byte fn)
-{
- int rc = 0, h;
- int dma_enabled = 0;
- unsigned short bmiba, pcicmd;
- unsigned int timings;
-
- printk("ide: Triton BM-IDE on PCI bus %d function %d\n", bus, fn);
- /*
- * See if IDE and BM-DMA features are enabled:
- */
- if ((rc = pcibios_read_config_word(bus, fn, 0x04, &pcicmd)))
- goto quit;
- if ((pcicmd & 1) == 0) {
- printk("ide: Triton IDE ports are not enabled\n");
- goto quit;
- }
- if ((pcicmd & 4) == 0) {
- printk("ide: Triton BM-DMA feature is not enabled -- upgrade your BIOS\n");
- } else {
- /*
- * Get the bmiba base address
- */
- if ((rc = pcibios_read_config_word(bus, fn, 0x20, &bmiba)))
- goto quit;
- bmiba &= 0xfff0; /* extract port base address */
- dma_enabled = 1;
- }
-
- /*
- * See if ide port(s) are enabled
- */
- if ((rc = pcibios_read_config_dword(bus, fn, 0x40, &timings)))
- goto quit;
- if (!(timings & 0x80008000)) {
- printk("ide: neither Triton IDE port is enabled\n");
- goto quit;
- }
-
- /*
- * Save the dma_base port addr for each interface
- */
- for (h = 0; h < MAX_HWIFS; ++h) {
- byte s_clks, r_clks;
- ide_hwif_t *hwif = &ide_hwifs[h];
- unsigned short time;
- if (hwif->io_base == 0x1f0) {
- time = timings & 0xffff;
- if ((timings & 0x8000) == 0) /* interface enabled? */
- continue;
- hwif->chipset = ide_triton;
- if (dma_enabled)
- init_triton_dma(hwif, bmiba);
- } else if (hwif->io_base == 0x170) {
- time = timings >> 16;
- if ((timings & 0x8000) == 0) /* interface enabled? */
- continue;
- hwif->chipset = ide_triton;
- if (dma_enabled)
- init_triton_dma(hwif, bmiba + 8);
- } else
- continue;
- s_clks = ((~time >> 12) & 3) + 2;
- r_clks = ((~time >> 8) & 3) + 1;
-#if 0
- printk(" %s timing: (0x%04x) sample_CLKs=%d, recovery_CLKs=%d (PIO mode%d)\n",
- hwif->name, time, s_clks, r_clks, calc_mode(s_clks+r_clks));
- print_triton_drive_flags (0, time & 0xf);
- print_triton_drive_flags (1, (time >> 4) & 0xf);
-#endif
- }
-
-quit: if (rc) printk("ide: pcibios access failed - %s\n", pcibios_strerror(rc));
-}
-