diff options
author | Thomas Bushnell <thomas@gnu.org> | 1999-04-26 05:35:47 +0000 |
---|---|---|
committer | Thomas Bushnell <thomas@gnu.org> | 1999-04-26 05:35:47 +0000 |
commit | 3a4e8f5c1c60f87e1c9e0878ddb6cf7dac8c59c0 (patch) | |
tree | 50b56b8570e175dbcff43b5f0d61103b6fea5906 /i386 | |
parent | 002b9c7d51f7fdb0fe222d4a6023655687c6e501 (diff) | |
download | gnumach-3a4e8f5c1c60f87e1c9e0878ddb6cf7dac8c59c0.tar.gz gnumach-3a4e8f5c1c60f87e1c9e0878ddb6cf7dac8c59c0.tar.bz2 gnumach-3a4e8f5c1c60f87e1c9e0878ddb6cf7dac8c59c0.zip |
1998-11-06 OKUJI Yoshinori <okuji@kuicr.kyoto-u.ac.jp>
* i386/i386at/gpl/linux: Moved to ...
* linuxdev: ... here.
* i386/Makefrag: Linux drivers specific code moved to ...
* linuxdev/Makefrag: ... here.
* i386/Files: Recreated.
* i386/Subdirs: Likewise.
* linuxdev/drivers: New directory.
* linuxdev/arch: Likewise.
* linuxdev/arch/i386: Likewise.
* linuxdev/{block,scsi,net,pci}: Moved to ...
* linuxdev/drivers/{block,scsi,net,pci}: ... here.
* i386/{Drivers.in,device-drivers.h.in,driverlist.in}: Moved to ...
* linuxdev/{Drivers.in,device-drivers.h.in,driverlist.in}: ... here.
* linuxdev/{linux_emul.h,linux_*.c}: Moved to ...
* linuxdev/arch/i386/{linux_emul.h,linux_*.c}: ... here.
* linuxdev/arch/i386/linux_block.c: Include <linux_emul.h>, instead
of <i386at/gpl/linux/linux_emul.h>.
* linuxdev/arch/i386/linux_init.c: Likewise.
* linuxdev/arch/i386/linux_kmem.c: Likewise.
* linuxdev/arch/i386/linux_misc.c: Likewise.
* linuxdev/arch/i386/linux_net.c: Likewise.
* linuxdev/arch/i386/linux_sched.c: Likewise.
* device/ds_routines.c: Include <linuxdev/device-drivers.h>, instead
of <i386/device-drivers.h>.
* linuxdev/arch/i386/linux_init.c: Likewise.
* linuxdev/include/linux/autoconf.h: Likewise.
* Makefile.in: Include $(srcdir)/linuxdev/Makefrag.
* linuxdev/Drivers.in (AC_INIT): Use include/linux/autoconf.h,
instead of i386/i386asm.sym.
Diffstat (limited to 'i386')
296 files changed, 0 insertions, 146223 deletions
diff --git a/i386/i386at/gpl/linux/block/cmd640.c b/i386/i386at/gpl/linux/block/cmd640.c deleted file mode 100644 index 99a139dc..00000000 --- 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 ee4a8980..00000000 --- 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 cebc7eaa..00000000 --- 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 6dc93806..00000000 --- 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 4b7c5e95..00000000 --- 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 b1ebc4c3..00000000 --- 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 e174d5dc..00000000 --- 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 11f1dbd5..00000000 --- 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, ®))) { - ide_pci_access_error (rc); - } else if (!(reg & 1)) { - printk("not enabled\n"); - } else { - if ((rc = pcibios_read_config_word(bus, fn, 0x40, ®)) - || (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 4f825f69..00000000 --- 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)); -} - diff --git a/i386/i386at/gpl/linux/include/asm/bitops.h b/i386/i386at/gpl/linux/include/asm/bitops.h deleted file mode 100644 index 5387f31d..00000000 --- a/i386/i386at/gpl/linux/include/asm/bitops.h +++ /dev/null @@ -1,137 +0,0 @@ -#ifndef _I386_BITOPS_H -#define _I386_BITOPS_H - -/* - * Copyright 1992, Linus Torvalds. - */ - -/* - * These have to be done with inline assembly: that way the bit-setting - * is guaranteed to be atomic. All bit operations return 0 if the bit - * was cleared before the operation and != 0 if it was not. - * - * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1). - */ - -#ifdef __SMP__ -#define LOCK_PREFIX "lock ; " -#else -#define LOCK_PREFIX "" -#endif - -/* - * Some hacks to defeat gcc over-optimizations.. - */ -struct __dummy { unsigned long a[100]; }; -#define ADDR (*(struct __dummy *) addr) -#define CONST_ADDR (*(const struct __dummy *) addr) - -extern __inline__ int set_bit(int nr, void * addr) -{ - int oldbit; - - __asm__ __volatile__(LOCK_PREFIX - "btsl %2,%1\n\tsbbl %0,%0" - :"=r" (oldbit),"=m" (ADDR) - :"ir" (nr)); - return oldbit; -} - -extern __inline__ int clear_bit(int nr, void * addr) -{ - int oldbit; - - __asm__ __volatile__(LOCK_PREFIX - "btrl %2,%1\n\tsbbl %0,%0" - :"=r" (oldbit),"=m" (ADDR) - :"ir" (nr)); - return oldbit; -} - -extern __inline__ int change_bit(int nr, void * addr) -{ - int oldbit; - - __asm__ __volatile__(LOCK_PREFIX - "btcl %2,%1\n\tsbbl %0,%0" - :"=r" (oldbit),"=m" (ADDR) - :"ir" (nr)); - return oldbit; -} - -/* - * This routine doesn't need to be atomic. - */ -extern __inline__ int test_bit(int nr, const void * addr) -{ - return 1UL & (((const unsigned int *) addr)[nr >> 5] >> (nr & 31)); -} - -/* - * Find-bit routines.. - */ -extern __inline__ int find_first_zero_bit(void * addr, unsigned size) -{ - int res; - - if (!size) - return 0; - __asm__(" - cld - movl $-1,%%eax - xorl %%edx,%%edx - repe; scasl - je 1f - xorl -4(%%edi),%%eax - subl $4,%%edi - bsfl %%eax,%%edx -1: subl %%ebx,%%edi - shll $3,%%edi - addl %%edi,%%edx" - :"=d" (res) - :"c" ((size + 31) >> 5), "D" (addr), "b" (addr) - :"ax", "cx", "di"); - return res; -} - -extern __inline__ int find_next_zero_bit (void * addr, int size, int offset) -{ - unsigned long * p = ((unsigned long *) addr) + (offset >> 5); - int set = 0, bit = offset & 31, res; - - if (bit) { - /* - * Look for zero in first byte - */ - __asm__(" - bsfl %1,%0 - jne 1f - movl $32, %0 -1: " - : "=r" (set) - : "r" (~(*p >> bit))); - if (set < (32 - bit)) - return set + offset; - set = 32 - bit; - p++; - } - /* - * No zero yet, search remaining full bytes for a zero - */ - res = find_first_zero_bit (p, size - 32 * (p - (unsigned long *) addr)); - return (offset + set + res); -} - -/* - * ffz = Find First Zero in word. Undefined if no zero exists, - * so code should check against ~0UL first.. - */ -extern __inline__ unsigned long ffz(unsigned long word) -{ - __asm__("bsfl %1,%0" - :"=r" (word) - :"r" (~word)); - return word; -} - -#endif /* _I386_BITOPS_H */ diff --git a/i386/i386at/gpl/linux/include/asm/byteorder.h b/i386/i386at/gpl/linux/include/asm/byteorder.h deleted file mode 100644 index 3f40767f..00000000 --- a/i386/i386at/gpl/linux/include/asm/byteorder.h +++ /dev/null @@ -1,90 +0,0 @@ -#ifndef _I386_BYTEORDER_H -#define _I386_BYTEORDER_H - -#undef ntohl -#undef ntohs -#undef htonl -#undef htons - -#ifndef __LITTLE_ENDIAN -#define __LITTLE_ENDIAN 1234 -#endif - -#ifndef __LITTLE_ENDIAN_BITFIELD -#define __LITTLE_ENDIAN_BITFIELD -#endif - -/* For avoiding bswap on i386 */ -#ifdef __KERNEL__ -#include <linux/config.h> -#endif - -extern unsigned long int ntohl(unsigned long int); -extern unsigned short int ntohs(unsigned short int); -extern unsigned long int htonl(unsigned long int); -extern unsigned short int htons(unsigned short int); - -extern __inline__ unsigned long int __ntohl(unsigned long int); -extern __inline__ unsigned short int __ntohs(unsigned short int); -extern __inline__ unsigned long int __constant_ntohl(unsigned long int); -extern __inline__ unsigned short int __constant_ntohs(unsigned short int); - -extern __inline__ unsigned long int -__ntohl(unsigned long int x) -{ -#if defined(__KERNEL__) && !defined(CONFIG_M386) - __asm__("bswap %0" : "=r" (x) : "0" (x)); -#else - __asm__("xchgb %b0,%h0\n\t" /* swap lower bytes */ - "rorl $16,%0\n\t" /* swap words */ - "xchgb %b0,%h0" /* swap higher bytes */ - :"=q" (x) - : "0" (x)); -#endif - return x; -} - -#define __constant_ntohl(x) \ - ((unsigned long int)((((unsigned long int)(x) & 0x000000ffU) << 24) | \ - (((unsigned long int)(x) & 0x0000ff00U) << 8) | \ - (((unsigned long int)(x) & 0x00ff0000U) >> 8) | \ - (((unsigned long int)(x) & 0xff000000U) >> 24))) - -extern __inline__ unsigned short int -__ntohs(unsigned short int x) -{ - __asm__("xchgb %b0,%h0" /* swap bytes */ - : "=q" (x) - : "0" (x)); - return x; -} - -#define __constant_ntohs(x) \ - ((unsigned short int)((((unsigned short int)(x) & 0x00ff) << 8) | \ - (((unsigned short int)(x) & 0xff00) >> 8))) \ - -#define __htonl(x) __ntohl(x) -#define __htons(x) __ntohs(x) -#define __constant_htonl(x) __constant_ntohl(x) -#define __constant_htons(x) __constant_ntohs(x) - -#ifdef __OPTIMIZE__ -# define ntohl(x) \ -(__builtin_constant_p((long)(x)) ? \ - __constant_ntohl((x)) : \ - __ntohl((x))) -# define ntohs(x) \ -(__builtin_constant_p((short)(x)) ? \ - __constant_ntohs((x)) : \ - __ntohs((x))) -# define htonl(x) \ -(__builtin_constant_p((long)(x)) ? \ - __constant_htonl((x)) : \ - __htonl((x))) -# define htons(x) \ -(__builtin_constant_p((short)(x)) ? \ - __constant_htons((x)) : \ - __htons((x))) -#endif - -#endif diff --git a/i386/i386at/gpl/linux/include/asm/delay.h b/i386/i386at/gpl/linux/include/asm/delay.h deleted file mode 100644 index e22e8d6b..00000000 --- a/i386/i386at/gpl/linux/include/asm/delay.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef _I386_DELAY_H -#define _I386_DELAY_H - -/* - * Copyright (C) 1993 Linus Torvalds - * - * Delay routines, using a pre-computed "loops_per_second" value. - */ - -#ifdef __SMP__ -#include <asm/smp.h> -#endif - -extern __inline__ void __delay(int loops) -{ - __asm__ __volatile__( - ".align 2,0x90\n1:\tdecl %0\n\tjns 1b" - :/* no outputs */ - :"a" (loops) - :"ax"); -} - -/* - * division by multiplication: you don't have to worry about - * loss of precision. - * - * Use only for very small delays ( < 1 msec). Should probably use a - * lookup table, really, as the multiplications take much too long with - * short delays. This is a "reasonable" implementation, though (and the - * first constant multiplications gets optimized away if the delay is - * a constant) - */ -extern __inline__ void udelay(unsigned long usecs) -{ - usecs *= 0x000010c6; /* 2**32 / 1000000 */ - __asm__("mull %0" - :"=d" (usecs) -#ifdef __SMP__ - :"a" (usecs),"0" (cpu_data[smp_processor_id()].udelay_val) -#else - :"a" (usecs),"0" (loops_per_sec) -#endif - :"ax"); - - __delay(usecs); -} - -extern __inline__ unsigned long muldiv(unsigned long a, unsigned long b, unsigned long c) -{ - __asm__("mull %1 ; divl %2" - :"=a" (a) - :"d" (b), - "r" (c), - "0" (a) - :"dx"); - return a; -} - -#endif /* defined(_I386_DELAY_H) */ diff --git a/i386/i386at/gpl/linux/include/asm/dma.h b/i386/i386at/gpl/linux/include/asm/dma.h deleted file mode 100644 index b739ed7d..00000000 --- a/i386/i386at/gpl/linux/include/asm/dma.h +++ /dev/null @@ -1,271 +0,0 @@ -/* $Id: dma.h,v 1.1.1.1 1997/02/25 21:27:24 thomas Exp $ - * linux/include/asm/dma.h: Defines for using and allocating dma channels. - * Written by Hennus Bergman, 1992. - * High DMA channel support & info by Hannu Savolainen - * and John Boyd, Nov. 1992. - */ - -#ifndef _ASM_DMA_H -#define _ASM_DMA_H - -#include <asm/io.h> /* need byte IO */ - - -#ifdef HAVE_REALLY_SLOW_DMA_CONTROLLER -#define dma_outb outb_p -#else -#define dma_outb outb -#endif - -#define dma_inb inb - -/* - * NOTES about DMA transfers: - * - * controller 1: channels 0-3, byte operations, ports 00-1F - * controller 2: channels 4-7, word operations, ports C0-DF - * - * - ALL registers are 8 bits only, regardless of transfer size - * - channel 4 is not used - cascades 1 into 2. - * - channels 0-3 are byte - addresses/counts are for physical bytes - * - channels 5-7 are word - addresses/counts are for physical words - * - transfers must not cross physical 64K (0-3) or 128K (5-7) boundaries - * - transfer count loaded to registers is 1 less than actual count - * - controller 2 offsets are all even (2x offsets for controller 1) - * - page registers for 5-7 don't use data bit 0, represent 128K pages - * - page registers for 0-3 use bit 0, represent 64K pages - * - * DMA transfers are limited to the lower 16MB of _physical_ memory. - * Note that addresses loaded into registers must be _physical_ addresses, - * not logical addresses (which may differ if paging is active). - * - * Address mapping for channels 0-3: - * - * A23 ... A16 A15 ... A8 A7 ... A0 (Physical addresses) - * | ... | | ... | | ... | - * | ... | | ... | | ... | - * | ... | | ... | | ... | - * P7 ... P0 A7 ... A0 A7 ... A0 - * | Page | Addr MSB | Addr LSB | (DMA registers) - * - * Address mapping for channels 5-7: - * - * A23 ... A17 A16 A15 ... A9 A8 A7 ... A1 A0 (Physical addresses) - * | ... | \ \ ... \ \ \ ... \ \ - * | ... | \ \ ... \ \ \ ... \ (not used) - * | ... | \ \ ... \ \ \ ... \ - * P7 ... P1 (0) A7 A6 ... A0 A7 A6 ... A0 - * | Page | Addr MSB | Addr LSB | (DMA registers) - * - * Again, channels 5-7 transfer _physical_ words (16 bits), so addresses - * and counts _must_ be word-aligned (the lowest address bit is _ignored_ at - * the hardware level, so odd-byte transfers aren't possible). - * - * Transfer count (_not # bytes_) is limited to 64K, represented as actual - * count - 1 : 64K => 0xFFFF, 1 => 0x0000. Thus, count is always 1 or more, - * and up to 128K bytes may be transferred on channels 5-7 in one operation. - * - */ - -#define MAX_DMA_CHANNELS 8 - -/* The maximum address that we can perform a DMA transfer to on this platform */ -#define MAX_DMA_ADDRESS 0x1000000 - -/* 8237 DMA controllers */ -#define IO_DMA1_BASE 0x00 /* 8 bit slave DMA, channels 0..3 */ -#define IO_DMA2_BASE 0xC0 /* 16 bit master DMA, ch 4(=slave input)..7 */ - -/* DMA controller registers */ -#define DMA1_CMD_REG 0x08 /* command register (w) */ -#define DMA1_STAT_REG 0x08 /* status register (r) */ -#define DMA1_REQ_REG 0x09 /* request register (w) */ -#define DMA1_MASK_REG 0x0A /* single-channel mask (w) */ -#define DMA1_MODE_REG 0x0B /* mode register (w) */ -#define DMA1_CLEAR_FF_REG 0x0C /* clear pointer flip-flop (w) */ -#define DMA1_TEMP_REG 0x0D /* Temporary Register (r) */ -#define DMA1_RESET_REG 0x0D /* Master Clear (w) */ -#define DMA1_CLR_MASK_REG 0x0E /* Clear Mask */ -#define DMA1_MASK_ALL_REG 0x0F /* all-channels mask (w) */ - -#define DMA2_CMD_REG 0xD0 /* command register (w) */ -#define DMA2_STAT_REG 0xD0 /* status register (r) */ -#define DMA2_REQ_REG 0xD2 /* request register (w) */ -#define DMA2_MASK_REG 0xD4 /* single-channel mask (w) */ -#define DMA2_MODE_REG 0xD6 /* mode register (w) */ -#define DMA2_CLEAR_FF_REG 0xD8 /* clear pointer flip-flop (w) */ -#define DMA2_TEMP_REG 0xDA /* Temporary Register (r) */ -#define DMA2_RESET_REG 0xDA /* Master Clear (w) */ -#define DMA2_CLR_MASK_REG 0xDC /* Clear Mask */ -#define DMA2_MASK_ALL_REG 0xDE /* all-channels mask (w) */ - -#define DMA_ADDR_0 0x00 /* DMA address registers */ -#define DMA_ADDR_1 0x02 -#define DMA_ADDR_2 0x04 -#define DMA_ADDR_3 0x06 -#define DMA_ADDR_4 0xC0 -#define DMA_ADDR_5 0xC4 -#define DMA_ADDR_6 0xC8 -#define DMA_ADDR_7 0xCC - -#define DMA_CNT_0 0x01 /* DMA count registers */ -#define DMA_CNT_1 0x03 -#define DMA_CNT_2 0x05 -#define DMA_CNT_3 0x07 -#define DMA_CNT_4 0xC2 -#define DMA_CNT_5 0xC6 -#define DMA_CNT_6 0xCA -#define DMA_CNT_7 0xCE - -#define DMA_PAGE_0 0x87 /* DMA page registers */ -#define DMA_PAGE_1 0x83 -#define DMA_PAGE_2 0x81 -#define DMA_PAGE_3 0x82 -#define DMA_PAGE_5 0x8B -#define DMA_PAGE_6 0x89 -#define DMA_PAGE_7 0x8A - -#define DMA_MODE_READ 0x44 /* I/O to memory, no autoinit, increment, single mode */ -#define DMA_MODE_WRITE 0x48 /* memory to I/O, no autoinit, increment, single mode */ -#define DMA_MODE_CASCADE 0xC0 /* pass thru DREQ->HRQ, DACK<-HLDA only */ - -/* enable/disable a specific DMA channel */ -static __inline__ void enable_dma(unsigned int dmanr) -{ - if (dmanr<=3) - dma_outb(dmanr, DMA1_MASK_REG); - else - dma_outb(dmanr & 3, DMA2_MASK_REG); -} - -static __inline__ void disable_dma(unsigned int dmanr) -{ - if (dmanr<=3) - dma_outb(dmanr | 4, DMA1_MASK_REG); - else - dma_outb((dmanr & 3) | 4, DMA2_MASK_REG); -} - -/* Clear the 'DMA Pointer Flip Flop'. - * Write 0 for LSB/MSB, 1 for MSB/LSB access. - * Use this once to initialize the FF to a known state. - * After that, keep track of it. :-) - * --- In order to do that, the DMA routines below should --- - * --- only be used while interrupts are disabled! --- - */ -static __inline__ void clear_dma_ff(unsigned int dmanr) -{ - if (dmanr<=3) - dma_outb(0, DMA1_CLEAR_FF_REG); - else - dma_outb(0, DMA2_CLEAR_FF_REG); -} - -/* set mode (above) for a specific DMA channel */ -static __inline__ void set_dma_mode(unsigned int dmanr, char mode) -{ - if (dmanr<=3) - dma_outb(mode | dmanr, DMA1_MODE_REG); - else - dma_outb(mode | (dmanr&3), DMA2_MODE_REG); -} - -/* Set only the page register bits of the transfer address. - * This is used for successive transfers when we know the contents of - * the lower 16 bits of the DMA current address register, but a 64k boundary - * may have been crossed. - */ -static __inline__ void set_dma_page(unsigned int dmanr, char pagenr) -{ - switch(dmanr) { - case 0: - dma_outb(pagenr, DMA_PAGE_0); - break; - case 1: - dma_outb(pagenr, DMA_PAGE_1); - break; - case 2: - dma_outb(pagenr, DMA_PAGE_2); - break; - case 3: - dma_outb(pagenr, DMA_PAGE_3); - break; - case 5: - dma_outb(pagenr & 0xfe, DMA_PAGE_5); - break; - case 6: - dma_outb(pagenr & 0xfe, DMA_PAGE_6); - break; - case 7: - dma_outb(pagenr & 0xfe, DMA_PAGE_7); - break; - } -} - - -/* Set transfer address & page bits for specific DMA channel. - * Assumes dma flipflop is clear. - */ -static __inline__ void set_dma_addr(unsigned int dmanr, unsigned int a) -{ - set_dma_page(dmanr, a>>16); - if (dmanr <= 3) { - dma_outb( a & 0xff, ((dmanr&3)<<1) + IO_DMA1_BASE ); - dma_outb( (a>>8) & 0xff, ((dmanr&3)<<1) + IO_DMA1_BASE ); - } else { - dma_outb( (a>>1) & 0xff, ((dmanr&3)<<2) + IO_DMA2_BASE ); - dma_outb( (a>>9) & 0xff, ((dmanr&3)<<2) + IO_DMA2_BASE ); - } -} - - -/* Set transfer size (max 64k for DMA1..3, 128k for DMA5..7) for - * a specific DMA channel. - * You must ensure the parameters are valid. - * NOTE: from a manual: "the number of transfers is one more - * than the initial word count"! This is taken into account. - * Assumes dma flip-flop is clear. - * NOTE 2: "count" represents _bytes_ and must be even for channels 5-7. - */ -static __inline__ void set_dma_count(unsigned int dmanr, unsigned int count) -{ - count--; - if (dmanr <= 3) { - dma_outb( count & 0xff, ((dmanr&3)<<1) + 1 + IO_DMA1_BASE ); - dma_outb( (count>>8) & 0xff, ((dmanr&3)<<1) + 1 + IO_DMA1_BASE ); - } else { - dma_outb( (count>>1) & 0xff, ((dmanr&3)<<2) + 2 + IO_DMA2_BASE ); - dma_outb( (count>>9) & 0xff, ((dmanr&3)<<2) + 2 + IO_DMA2_BASE ); - } -} - - -/* Get DMA residue count. After a DMA transfer, this - * should return zero. Reading this while a DMA transfer is - * still in progress will return unpredictable results. - * If called before the channel has been used, it may return 1. - * Otherwise, it returns the number of _bytes_ left to transfer. - * - * Assumes DMA flip-flop is clear. - */ -static __inline__ int get_dma_residue(unsigned int dmanr) -{ - unsigned int io_port = (dmanr<=3)? ((dmanr&3)<<1) + 1 + IO_DMA1_BASE - : ((dmanr&3)<<2) + 2 + IO_DMA2_BASE; - - /* using short to get 16-bit wrap around */ - unsigned short count; - - count = 1 + dma_inb(io_port); - count += dma_inb(io_port) << 8; - - return (dmanr<=3)? count : (count<<1); -} - - -/* These are in kernel/dma.c: */ -extern int request_dma(unsigned int dmanr, const char * device_id); /* reserve a DMA channel */ -extern void free_dma(unsigned int dmanr); /* release it again */ - - -#endif /* _ASM_DMA_H */ diff --git a/i386/i386at/gpl/linux/include/asm/errno.h b/i386/i386at/gpl/linux/include/asm/errno.h deleted file mode 100644 index f5c37cad..00000000 --- a/i386/i386at/gpl/linux/include/asm/errno.h +++ /dev/null @@ -1,252 +0,0 @@ -#ifndef _I386_ERRNO_H -#define _I386_ERRNO_H - -#ifdef MACH_INCLUDE -#define LINUX_EPERM 1 /* Operation not permitted */ -#define LINUX_ENOENT 2 /* No such file or directory */ -#define LINUX_ESRCH 3 /* No such process */ -#define LINUX_EINTR 4 /* Interrupted system call */ -#define LINUX_EIO 5 /* I/O error */ -#define LINUX_ENXIO 6 /* No such device or address */ -#define LINUX_E2BIG 7 /* Arg list too long */ -#define LINUX_ENOEXEC 8 /* Exec format error */ -#define LINUX_EBADF 9 /* Bad file number */ -#define LINUX_ECHILD 10 /* No child processes */ -#define LINUX_EAGAIN 11 /* Try again */ -#define LINUX_ENOMEM 12 /* Out of memory */ -#define LINUX_EACCES 13 /* Permission denied */ -#define LINUX_EFAULT 14 /* Bad address */ -#define LINUX_ENOTBLK 15 /* Block device required */ -#define LINUX_EBUSY 16 /* Device or resource busy */ -#define LINUX_EEXIST 17 /* File exists */ -#define LINUX_EXDEV 18 /* Cross-device link */ -#define LINUX_ENODEV 19 /* No such device */ -#define LINUX_ENOTDIR 20 /* Not a directory */ -#define LINUX_EISDIR 21 /* Is a directory */ -#define LINUX_EINVAL 22 /* Invalid argument */ -#define LINUX_ENFILE 23 /* File table overflow */ -#define LINUX_EMFILE 24 /* Too many open files */ -#define LINUX_ENOTTY 25 /* Not a typewriter */ -#define LINUX_ETXTBSY 26 /* Text file busy */ -#define LINUX_EFBIG 27 /* File too large */ -#define LINUX_ENOSPC 28 /* No space left on device */ -#define LINUX_ESPIPE 29 /* Illegal seek */ -#define LINUX_EROFS 30 /* Read-only file system */ -#define LINUX_EMLINK 31 /* Too many links */ -#define LINUX_EPIPE 32 /* Broken pipe */ -#define LINUX_EDOM 33 /* Math argument out of domain of func */ -#define LINUX_ERANGE 34 /* Math result not representable */ -#define LINUX_EDEADLK 35 /* Resource deadlock would occur */ -#define LINUX_ENAMETOOLONG 36 /* File name too long */ -#define LINUX_ENOLCK 37 /* No record locks available */ -#define LINUX_ENOSYS 38 /* Function not implemented */ -#define LINUX_ENOTEMPTY 39 /* Directory not empty */ -#define LINUX_ELOOP 40 /* Too many symbolic links encountered */ -#define LINUX_EWOULDBLOCK LINUX_EAGAIN /* Operation would block */ -#define LINUX_ENOMSG 42 /* No message of desired type */ -#define LINUX_EIDRM 43 /* Identifier removed */ -#define LINUX_ECHRNG 44 /* Channel number out of range */ -#define LINUX_EL2NSYNC 45 /* Level 2 not synchronized */ -#define LINUX_EL3HLT 46 /* Level 3 halted */ -#define LINUX_EL3RST 47 /* Level 3 reset */ -#define LINUX_ELNRNG 48 /* Link number out of range */ -#define LINUX_EUNATCH 49 /* Protocol driver not attached */ -#define LINUX_ENOCSI 50 /* No CSI structure available */ -#define LINUX_EL2HLT 51 /* Level 2 halted */ -#define LINUX_EBADE 52 /* Invalid exchange */ -#define LINUX_EBADR 53 /* Invalid request descriptor */ -#define LINUX_EXFULL 54 /* Exchange full */ -#define LINUX_ENOANO 55 /* No anode */ -#define LINUX_EBADRQC 56 /* Invalid request code */ -#define LINUX_EBADSLT 57 /* Invalid slot */ -#define LINUX_EDEADLOCK 58 /* File locking deadlock error */ -#define LINUX_EBFONT 59 /* Bad font file format */ -#define LINUX_ENOSTR 60 /* Device not a stream */ -#define LINUX_ENODATA 61 /* No data available */ -#define LINUX_ETIME 62 /* Timer expired */ -#define LINUX_ENOSR 63 /* Out of streams resources */ -#define LINUX_ENONET 64 /* Machine is not on the network */ -#define LINUX_ENOPKG 65 /* Package not installed */ -#define LINUX_EREMOTE 66 /* Object is remote */ -#define LINUX_ENOLINK 67 /* Link has been severed */ -#define LINUX_EADV 68 /* Advertise error */ -#define LINUX_ESRMNT 69 /* Srmount error */ -#define LINUX_ECOMM 70 /* Communication error on send */ -#define LINUX_EPROTO 71 /* Protocol error */ -#define LINUX_EMULTIHOP 72 /* Multihop attempted */ -#define LINUX_EDOTDOT 73 /* RFS specific error */ -#define LINUX_EBADMSG 74 /* Not a data message */ -#define LINUX_EOVERFLOW 75 /* Value too large for defined data type */ -#define LINUX_ENOTUNIQ 76 /* Name not unique on network */ -#define LINUX_EBADFD 77 /* File descriptor in bad state */ -#define LINUX_EREMCHG 78 /* Remote address changed */ -#define LINUX_ELIBACC 79 /* Can not access a needed shared library */ -#define LINUX_ELIBBAD 80 /* Accessing a corrupted shared library */ -#define LINUX_ELIBSCN 81 /* .lib section in a.out corrupted */ -#define LINUX_ELIBMAX 82 /* Attempting to link in too many shared libraries */ -#define LINUX_ELIBEXEC 83 /* Cannot exec a shared library directly */ -#define LINUX_EILSEQ 84 /* Illegal byte sequence */ -#define LINUX_ERESTART 85 /* Interrupted system call should be restarted */ -#define LINUX_ESTRPIPE 86 /* Streams pipe error */ -#define LINUX_EUSERS 87 /* Too many users */ -#define LINUX_ENOTSOCK 88 /* Socket operation on non-socket */ -#define LINUX_EDESTADDRREQ 89 /* Destination address required */ -#define LINUX_EMSGSIZE 90 /* Message too long */ -#define LINUX_EPROTOTYPE 91 /* Protocol wrong type for socket */ -#define LINUX_ENOPROTOOPT 92 /* Protocol not available */ -#define LINUX_EPROTONOSUPPORT 93 /* Protocol not supported */ -#define LINUX_ESOCKTNOSUPPORT 94 /* Socket type not supported */ -#define LINUX_EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ -#define LINUX_EPFNOSUPPORT 96 /* Protocol family not supported */ -#define LINUX_EAFNOSUPPORT 97 /* Address family not supported by protocol */ -#define LINUX_EADDRINUSE 98 /* Address already in use */ -#define LINUX_EADDRNOTAVAIL 99 /* Cannot assign requested address */ -#define LINUX_ENETDOWN 100 /* Network is down */ -#define LINUX_ENETUNREACH 101 /* Network is unreachable */ -#define LINUX_ENETRESET 102 /* Network dropped connection because of reset */ -#define LINUX_ECONNABORTED 103 /* Software caused connection abort */ -#define LINUX_ECONNRESET 104 /* Connection reset by peer */ -#define LINUX_ENOBUFS 105 /* No buffer space available */ -#define LINUX_EISCONN 106 /* Transport endpoint is already connected */ -#define LINUX_ENOTCONN 107 /* Transport endpoint is not connected */ -#define LINUX_ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ -#define LINUX_ETOOMANYREFS 109 /* Too many references: cannot splice */ -#define LINUX_ETIMEDOUT 110 /* Connection timed out */ -#define LINUX_ECONNREFUSED 111 /* Connection refused */ -#define LINUX_EHOSTDOWN 112 /* Host is down */ -#define LINUX_EHOSTUNREACH 113 /* No route to host */ -#define LINUX_EALREADY 114 /* Operation already in progress */ -#define LINUX_EINPROGRESS 115 /* Operation now in progress */ -#define LINUX_ESTALE 116 /* Stale NFS file handle */ -#define LINUX_EUCLEAN 117 /* Structure needs cleaning */ -#define LINUX_ENOTNAM 118 /* Not a XENIX named type file */ -#define LINUX_ENAVAIL 119 /* No XENIX semaphores available */ -#define LINUX_EISNAM 120 /* Is a named type file */ -#define LINUX_EREMOTEIO 121 /* Remote I/O error */ -#define LINUX_EDQUOT 122 /* Quota exceeded */ -#else /* ! MACH_INCLUDE */ -#define EPERM 1 /* Operation not permitted */ -#define ENOENT 2 /* No such file or directory */ -#define ESRCH 3 /* No such process */ -#define EINTR 4 /* Interrupted system call */ -#define EIO 5 /* I/O error */ -#define ENXIO 6 /* No such device or address */ -#define E2BIG 7 /* Arg list too long */ -#define ENOEXEC 8 /* Exec format error */ -#define EBADF 9 /* Bad file number */ -#define ECHILD 10 /* No child processes */ -#define EAGAIN 11 /* Try again */ -#define ENOMEM 12 /* Out of memory */ -#define EACCES 13 /* Permission denied */ -#define EFAULT 14 /* Bad address */ -#define ENOTBLK 15 /* Block device required */ -#define EBUSY 16 /* Device or resource busy */ -#define EEXIST 17 /* File exists */ -#define EXDEV 18 /* Cross-device link */ -#define ENODEV 19 /* No such device */ -#define ENOTDIR 20 /* Not a directory */ -#define EISDIR 21 /* Is a directory */ -#define EINVAL 22 /* Invalid argument */ -#define ENFILE 23 /* File table overflow */ -#define EMFILE 24 /* Too many open files */ -#define ENOTTY 25 /* Not a typewriter */ -#define ETXTBSY 26 /* Text file busy */ -#define EFBIG 27 /* File too large */ -#define ENOSPC 28 /* No space left on device */ -#define ESPIPE 29 /* Illegal seek */ -#define EROFS 30 /* Read-only file system */ -#define EMLINK 31 /* Too many links */ -#define EPIPE 32 /* Broken pipe */ -#define EDOM 33 /* Math argument out of domain of func */ -#define ERANGE 34 /* Math result not representable */ -#define EDEADLK 35 /* Resource deadlock would occur */ -#define ENAMETOOLONG 36 /* File name too long */ -#define ENOLCK 37 /* No record locks available */ -#define ENOSYS 38 /* Function not implemented */ -#define ENOTEMPTY 39 /* Directory not empty */ -#define ELOOP 40 /* Too many symbolic links encountered */ -#define EWOULDBLOCK EAGAIN /* Operation would block */ -#define ENOMSG 42 /* No message of desired type */ -#define EIDRM 43 /* Identifier removed */ -#define ECHRNG 44 /* Channel number out of range */ -#define EL2NSYNC 45 /* Level 2 not synchronized */ -#define EL3HLT 46 /* Level 3 halted */ -#define EL3RST 47 /* Level 3 reset */ -#define ELNRNG 48 /* Link number out of range */ -#define EUNATCH 49 /* Protocol driver not attached */ -#define ENOCSI 50 /* No CSI structure available */ -#define EL2HLT 51 /* Level 2 halted */ -#define EBADE 52 /* Invalid exchange */ -#define EBADR 53 /* Invalid request descriptor */ -#define EXFULL 54 /* Exchange full */ -#define ENOANO 55 /* No anode */ -#define EBADRQC 56 /* Invalid request code */ -#define EBADSLT 57 /* Invalid slot */ -#define EDEADLOCK 58 /* File locking deadlock error */ -#define EBFONT 59 /* Bad font file format */ -#define ENOSTR 60 /* Device not a stream */ -#define ENODATA 61 /* No data available */ -#define ETIME 62 /* Timer expired */ -#define ENOSR 63 /* Out of streams resources */ -#define ENONET 64 /* Machine is not on the network */ -#define ENOPKG 65 /* Package not installed */ -#define EREMOTE 66 /* Object is remote */ -#define ENOLINK 67 /* Link has been severed */ -#define EADV 68 /* Advertise error */ -#define ESRMNT 69 /* Srmount error */ -#define ECOMM 70 /* Communication error on send */ -#define EPROTO 71 /* Protocol error */ -#define EMULTIHOP 72 /* Multihop attempted */ -#define EDOTDOT 73 /* RFS specific error */ -#define EBADMSG 74 /* Not a data message */ -#define EOVERFLOW 75 /* Value too large for defined data type */ -#define ENOTUNIQ 76 /* Name not unique on network */ -#define EBADFD 77 /* File descriptor in bad state */ -#define EREMCHG 78 /* Remote address changed */ -#define ELIBACC 79 /* Can not access a needed shared library */ -#define ELIBBAD 80 /* Accessing a corrupted shared library */ -#define ELIBSCN 81 /* .lib section in a.out corrupted */ -#define ELIBMAX 82 /* Attempting to link in too many shared libraries */ -#define ELIBEXEC 83 /* Cannot exec a shared library directly */ -#define EILSEQ 84 /* Illegal byte sequence */ -#define ERESTART 85 /* Interrupted system call should be restarted */ -#define ESTRPIPE 86 /* Streams pipe error */ -#define EUSERS 87 /* Too many users */ -#define ENOTSOCK 88 /* Socket operation on non-socket */ -#define EDESTADDRREQ 89 /* Destination address required */ -#define EMSGSIZE 90 /* Message too long */ -#define EPROTOTYPE 91 /* Protocol wrong type for socket */ -#define ENOPROTOOPT 92 /* Protocol not available */ -#define EPROTONOSUPPORT 93 /* Protocol not supported */ -#define ESOCKTNOSUPPORT 94 /* Socket type not supported */ -#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ -#define EPFNOSUPPORT 96 /* Protocol family not supported */ -#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ -#define EADDRINUSE 98 /* Address already in use */ -#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ -#define ENETDOWN 100 /* Network is down */ -#define ENETUNREACH 101 /* Network is unreachable */ -#define ENETRESET 102 /* Network dropped connection because of reset */ -#define ECONNABORTED 103 /* Software caused connection abort */ -#define ECONNRESET 104 /* Connection reset by peer */ -#define ENOBUFS 105 /* No buffer space available */ -#define EISCONN 106 /* Transport endpoint is already connected */ -#define ENOTCONN 107 /* Transport endpoint is not connected */ -#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ -#define ETOOMANYREFS 109 /* Too many references: cannot splice */ -#define ETIMEDOUT 110 /* Connection timed out */ -#define ECONNREFUSED 111 /* Connection refused */ -#define EHOSTDOWN 112 /* Host is down */ -#define EHOSTUNREACH 113 /* No route to host */ -#define EALREADY 114 /* Operation already in progress */ -#define EINPROGRESS 115 /* Operation now in progress */ -#define ESTALE 116 /* Stale NFS file handle */ -#define EUCLEAN 117 /* Structure needs cleaning */ -#define ENOTNAM 118 /* Not a XENIX named type file */ -#define ENAVAIL 119 /* No XENIX semaphores available */ -#define EISNAM 120 /* Is a named type file */ -#define EREMOTEIO 121 /* Remote I/O error */ -#define EDQUOT 122 /* Quota exceeded */ -#endif /* ! MACH_INCLUDE */ - -#endif diff --git a/i386/i386at/gpl/linux/include/asm/fcntl.h b/i386/i386at/gpl/linux/include/asm/fcntl.h deleted file mode 100644 index 0cb8fcdb..00000000 --- a/i386/i386at/gpl/linux/include/asm/fcntl.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef _I386_FCNTL_H -#define _I386_FCNTL_H - -/* open/fcntl - O_SYNC is only implemented on blocks devices and on files - located on an ext2 file system */ -#define O_ACCMODE 0003 -#define O_RDONLY 00 -#define O_WRONLY 01 -#define O_RDWR 02 -#define O_CREAT 0100 /* not fcntl */ -#define O_EXCL 0200 /* not fcntl */ -#define O_NOCTTY 0400 /* not fcntl */ -#define O_TRUNC 01000 /* not fcntl */ -#define O_APPEND 02000 -#define O_NONBLOCK 04000 -#define O_NDELAY O_NONBLOCK -#define O_SYNC 010000 -#define FASYNC 020000 /* fcntl, for BSD compatibility */ - -#define F_DUPFD 0 /* dup */ -#define F_GETFD 1 /* get f_flags */ -#define F_SETFD 2 /* set f_flags */ -#define F_GETFL 3 /* more flags (cloexec) */ -#define F_SETFL 4 -#define F_GETLK 5 -#define F_SETLK 6 -#define F_SETLKW 7 - -#define F_SETOWN 8 /* for sockets. */ -#define F_GETOWN 9 /* for sockets. */ - -/* for F_[GET|SET]FL */ -#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ - -/* for posix fcntl() and lockf() */ -#define F_RDLCK 0 -#define F_WRLCK 1 -#define F_UNLCK 2 - -/* for old implementation of bsd flock () */ -#define F_EXLCK 4 /* or 3 */ -#define F_SHLCK 8 /* or 4 */ - -/* operations for bsd flock(), also used by the kernel implementation */ -#define LOCK_SH 1 /* shared lock */ -#define LOCK_EX 2 /* exclusive lock */ -#define LOCK_NB 4 /* or'd with one of the above to prevent - blocking */ -#define LOCK_UN 8 /* remove lock */ - -#ifdef __KERNEL__ -#define F_POSIX 1 -#define F_FLOCK 2 -#endif /* __KERNEL__ */ - -struct flock { - short l_type; - short l_whence; - off_t l_start; - off_t l_len; - pid_t l_pid; -}; - -#endif diff --git a/i386/i386at/gpl/linux/include/asm/floppy.h b/i386/i386at/gpl/linux/include/asm/floppy.h deleted file mode 100644 index 93c58fea..00000000 --- a/i386/i386at/gpl/linux/include/asm/floppy.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Architecture specific parts of the Floppy driver - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 1995 - */ -#ifndef __ASM_I386_FLOPPY_H -#define __ASM_I386_FLOPPY_H - -#define fd_inb(port) inb_p(port) -#define fd_outb(port,value) outb_p(port,value) - -#define fd_enable_dma() enable_dma(FLOPPY_DMA) -#define fd_disable_dma() disable_dma(FLOPPY_DMA) -#define fd_request_dma() request_dma(FLOPPY_DMA,"floppy") -#define fd_free_dma() free_dma(FLOPPY_DMA) -#define fd_clear_dma_ff() clear_dma_ff(FLOPPY_DMA) -#define fd_set_dma_mode(mode) set_dma_mode(FLOPPY_DMA,mode) -#define fd_set_dma_addr(addr) set_dma_addr(FLOPPY_DMA,addr) -#define fd_set_dma_count(count) set_dma_count(FLOPPY_DMA,count) -#define fd_enable_irq() enable_irq(FLOPPY_IRQ) -#define fd_disable_irq() disable_irq(FLOPPY_IRQ) -#define fd_cacheflush(addr,size) /* nothing */ -#define fd_request_irq() request_irq(FLOPPY_IRQ, floppy_interrupt, \ - SA_INTERRUPT|SA_SAMPLE_RANDOM, \ - "floppy") -#define fd_free_irq() free_irq(FLOPPY_IRQ); - -__inline__ void virtual_dma_init(void) -{ - /* Nothing to do on an i386 */ -} - -static int FDC1 = 0x3f0; -static int FDC2 = -1; - -#define FLOPPY0_TYPE ((CMOS_READ(0x10) >> 4) & 15) -#define FLOPPY1_TYPE (CMOS_READ(0x10) & 15) - -#define N_FDC 2 -#define N_DRIVE 8 - -/* - * The DMA channel used by the floppy controller cannot access data at - * addresses >= 16MB - * - * Went back to the 1MB limit, as some people had problems with the floppy - * driver otherwise. It doesn't matter much for performance anyway, as most - * floppy accesses go through the track buffer. - */ -#define CROSS_64KB(a,s) ((unsigned long)(a)/K_64 != ((unsigned long)(a) + (s) - 1) / K_64) - -#endif /* __ASM_I386_FLOPPY_H */ diff --git a/i386/i386at/gpl/linux/include/asm/io.h b/i386/i386at/gpl/linux/include/asm/io.h deleted file mode 100644 index 98e32ce6..00000000 --- a/i386/i386at/gpl/linux/include/asm/io.h +++ /dev/null @@ -1,213 +0,0 @@ -#ifndef _ASM_IO_H -#define _ASM_IO_H - -/* - * This file contains the definitions for the x86 IO instructions - * inb/inw/inl/outb/outw/outl and the "string versions" of the same - * (insb/insw/insl/outsb/outsw/outsl). You can also use "pausing" - * versions of the single-IO instructions (inb_p/inw_p/..). - * - * This file is not meant to be obfuscating: it's just complicated - * to (a) handle it all in a way that makes gcc able to optimize it - * as well as possible and (b) trying to avoid writing the same thing - * over and over again with slight variations and possibly making a - * mistake somewhere. - */ - -/* - * Thanks to James van Artsdalen for a better timing-fix than - * the two short jumps: using outb's to a nonexistent port seems - * to guarantee better timings even on fast machines. - * - * On the other hand, I'd like to be sure of a non-existent port: - * I feel a bit unsafe about using 0x80 (should be safe, though) - * - * Linus - */ - -#ifdef SLOW_IO_BY_JUMPING -#define __SLOW_DOWN_IO __asm__ __volatile__("jmp 1f\n1:\tjmp 1f\n1:") -#else -#define __SLOW_DOWN_IO __asm__ __volatile__("outb %al,$0x80") -#endif - -#ifdef REALLY_SLOW_IO -#define SLOW_DOWN_IO { __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; } -#else -#define SLOW_DOWN_IO __SLOW_DOWN_IO -#endif - -/* - * Change virtual addresses to physical addresses and vv. - * These are trivial on the 1:1 Linux/i386 mapping (but if we ever - * make the kernel segment mapped at 0, we need to do translation - * on the i386 as well) - */ -extern inline unsigned long virt_to_phys(volatile void * address) -{ - return (unsigned long) address; -} - -extern inline void * phys_to_virt(unsigned long address) -{ - return (void *) address; -} - -/* - * IO bus memory addresses are also 1:1 with the physical address - */ -#define virt_to_bus virt_to_phys -#define bus_to_virt phys_to_virt - -/* - * readX/writeX() are used to access memory mapped devices. On some - * architectures the memory mapped IO stuff needs to be accessed - * differently. On the x86 architecture, we just read/write the - * memory location directly. - */ -#define readb(addr) (*(volatile unsigned char *) (addr)) -#define readw(addr) (*(volatile unsigned short *) (addr)) -#define readl(addr) (*(volatile unsigned int *) (addr)) - -#define writeb(b,addr) ((*(volatile unsigned char *) (addr)) = (b)) -#define writew(b,addr) ((*(volatile unsigned short *) (addr)) = (b)) -#define writel(b,addr) ((*(volatile unsigned int *) (addr)) = (b)) - -#define memset_io(a,b,c) memset((void *)(a),(b),(c)) -#define memcpy_fromio(a,b,c) memcpy((a),(void *)(b),(c)) -#define memcpy_toio(a,b,c) memcpy((void *)(a),(b),(c)) - -/* - * Again, i386 does not require mem IO specific function. - */ - -#define eth_io_copy_and_sum(a,b,c,d) eth_copy_and_sum((a),(void *)(b),(c),(d)) - -/* - * Talk about misusing macros.. - */ - -#define __OUT1(s,x) \ -extern inline void __out##s(unsigned x value, unsigned short port) { - -#define __OUT2(s,s1,s2) \ -__asm__ __volatile__ ("out" #s " %" s1 "0,%" s2 "1" - -#define __OUT(s,s1,x) \ -__OUT1(s,x) __OUT2(s,s1,"w") : : "a" (value), "d" (port)); } \ -__OUT1(s##c,x) __OUT2(s,s1,"") : : "a" (value), "id" (port)); } \ -__OUT1(s##_p,x) __OUT2(s,s1,"w") : : "a" (value), "d" (port)); SLOW_DOWN_IO; } \ -__OUT1(s##c_p,x) __OUT2(s,s1,"") : : "a" (value), "id" (port)); SLOW_DOWN_IO; } - -#define __IN1(s) \ -extern inline RETURN_TYPE __in##s(unsigned short port) { RETURN_TYPE _v; - -#define __IN2(s,s1,s2) \ -__asm__ __volatile__ ("in" #s " %" s2 "1,%" s1 "0" - -#define __IN(s,s1,i...) \ -__IN1(s) __IN2(s,s1,"w") : "=a" (_v) : "d" (port) ,##i ); return _v; } \ -__IN1(s##c) __IN2(s,s1,"") : "=a" (_v) : "id" (port) ,##i ); return _v; } \ -__IN1(s##_p) __IN2(s,s1,"w") : "=a" (_v) : "d" (port) ,##i ); SLOW_DOWN_IO; return _v; } \ -__IN1(s##c_p) __IN2(s,s1,"") : "=a" (_v) : "id" (port) ,##i ); SLOW_DOWN_IO; return _v; } - -#define __INS(s) \ -extern inline void ins##s(unsigned short port, void * addr, unsigned long count) \ -{ __asm__ __volatile__ ("cld ; rep ; ins" #s \ -: "=D" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); } - -#define __OUTS(s) \ -extern inline void outs##s(unsigned short port, const void * addr, unsigned long count) \ -{ __asm__ __volatile__ ("cld ; rep ; outs" #s \ -: "=S" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); } - -#define RETURN_TYPE unsigned char -/* __IN(b,"b","0" (0)) */ -__IN(b,"") -#undef RETURN_TYPE -#define RETURN_TYPE unsigned short -/* __IN(w,"w","0" (0)) */ -__IN(w,"") -#undef RETURN_TYPE -#define RETURN_TYPE unsigned int -__IN(l,"") -#undef RETURN_TYPE - -__OUT(b,"b",char) -__OUT(w,"w",short) -__OUT(l,,int) - -__INS(b) -__INS(w) -__INS(l) - -__OUTS(b) -__OUTS(w) -__OUTS(l) - -/* - * Note that due to the way __builtin_constant_p() works, you - * - can't use it inside a inline function (it will never be true) - * - you don't have to worry about side effects within the __builtin.. - */ -#define outb(val,port) \ -((__builtin_constant_p((port)) && (port) < 256) ? \ - __outbc((val),(port)) : \ - __outb((val),(port))) - -#define inb(port) \ -((__builtin_constant_p((port)) && (port) < 256) ? \ - __inbc(port) : \ - __inb(port)) - -#define outb_p(val,port) \ -((__builtin_constant_p((port)) && (port) < 256) ? \ - __outbc_p((val),(port)) : \ - __outb_p((val),(port))) - -#define inb_p(port) \ -((__builtin_constant_p((port)) && (port) < 256) ? \ - __inbc_p(port) : \ - __inb_p(port)) - -#define outw(val,port) \ -((__builtin_constant_p((port)) && (port) < 256) ? \ - __outwc((val),(port)) : \ - __outw((val),(port))) - -#define inw(port) \ -((__builtin_constant_p((port)) && (port) < 256) ? \ - __inwc(port) : \ - __inw(port)) - -#define outw_p(val,port) \ -((__builtin_constant_p((port)) && (port) < 256) ? \ - __outwc_p((val),(port)) : \ - __outw_p((val),(port))) - -#define inw_p(port) \ -((__builtin_constant_p((port)) && (port) < 256) ? \ - __inwc_p(port) : \ - __inw_p(port)) - -#define outl(val,port) \ -((__builtin_constant_p((port)) && (port) < 256) ? \ - __outlc((val),(port)) : \ - __outl((val),(port))) - -#define inl(port) \ -((__builtin_constant_p((port)) && (port) < 256) ? \ - __inlc(port) : \ - __inl(port)) - -#define outl_p(val,port) \ -((__builtin_constant_p((port)) && (port) < 256) ? \ - __outlc_p((val),(port)) : \ - __outl_p((val),(port))) - -#define inl_p(port) \ -((__builtin_constant_p((port)) && (port) < 256) ? \ - __inlc_p(port) : \ - __inl_p(port)) - -#endif diff --git a/i386/i386at/gpl/linux/include/asm/ioctl.h b/i386/i386at/gpl/linux/include/asm/ioctl.h deleted file mode 100644 index cc94e3b9..00000000 --- a/i386/i386at/gpl/linux/include/asm/ioctl.h +++ /dev/null @@ -1,75 +0,0 @@ -/* $Id: ioctl.h,v 1.1.1.1 1997/02/25 21:27:24 thomas Exp $ - * - * linux/ioctl.h for Linux by H.H. Bergman. - */ - -#ifndef _ASMI386_IOCTL_H -#define _ASMI386_IOCTL_H - -/* ioctl command encoding: 32 bits total, command in lower 16 bits, - * size of the parameter structure in the lower 14 bits of the - * upper 16 bits. - * Encoding the size of the parameter structure in the ioctl request - * is useful for catching programs compiled with old versions - * and to avoid overwriting user space outside the user buffer area. - * The highest 2 bits are reserved for indicating the ``access mode''. - * NOTE: This limits the max parameter size to 16kB -1 ! - */ - -/* - * The following is for compatibility across the various Linux - * platforms. The i386 ioctl numbering scheme doesn't really enforce - * a type field. De facto, however, the top 8 bits of the lower 16 - * bits are indeed used as a type field, so we might just as well make - * this explicit here. Please be sure to use the decoding macros - * below from now on. - */ -#define _IOC_NRBITS 8 -#define _IOC_TYPEBITS 8 -#define _IOC_SIZEBITS 14 -#define _IOC_DIRBITS 2 - -#define _IOC_NRMASK ((1 << _IOC_NRBITS)-1) -#define _IOC_TYPEMASK ((1 << _IOC_TYPEBITS)-1) -#define _IOC_SIZEMASK ((1 << _IOC_SIZEBITS)-1) -#define _IOC_DIRMASK ((1 << _IOC_DIRBITS)-1) - -#define _IOC_NRSHIFT 0 -#define _IOC_TYPESHIFT (_IOC_NRSHIFT+_IOC_NRBITS) -#define _IOC_SIZESHIFT (_IOC_TYPESHIFT+_IOC_TYPEBITS) -#define _IOC_DIRSHIFT (_IOC_SIZESHIFT+_IOC_SIZEBITS) - -/* - * Direction bits. - */ -#define _IOC_NONE 0U -#define _IOC_WRITE 1U -#define _IOC_READ 2U - -#define _IOC(dir,type,nr,size) \ - (((dir) << _IOC_DIRSHIFT) | \ - ((type) << _IOC_TYPESHIFT) | \ - ((nr) << _IOC_NRSHIFT) | \ - ((size) << _IOC_SIZESHIFT)) - -/* used to create numbers */ -#define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0) -#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size)) -#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size)) -#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size)) - -/* used to decode ioctl numbers.. */ -#define _IOC_DIR(nr) (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK) -#define _IOC_TYPE(nr) (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK) -#define _IOC_NR(nr) (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK) -#define _IOC_SIZE(nr) (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK) - -/* ...and for the drivers/sound files... */ - -#define IOC_IN (_IOC_WRITE << _IOC_DIRSHIFT) -#define IOC_OUT (_IOC_READ << _IOC_DIRSHIFT) -#define IOC_INOUT ((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT) -#define IOCSIZE_MASK (_IOC_SIZEMASK << _IOC_SIZESHIFT) -#define IOCSIZE_SHIFT (_IOC_SIZESHIFT) - -#endif /* _ASMI386_IOCTL_H */ diff --git a/i386/i386at/gpl/linux/include/asm/irq.h b/i386/i386at/gpl/linux/include/asm/irq.h deleted file mode 100644 index 8fd44b48..00000000 --- a/i386/i386at/gpl/linux/include/asm/irq.h +++ /dev/null @@ -1,346 +0,0 @@ -#ifndef _ASM_IRQ_H -#define _ASM_IRQ_H - -/* - * linux/include/asm/irq.h - * - * (C) 1992, 1993 Linus Torvalds - * - * IRQ/IPI changes taken from work by Thomas Radke <tomsoft@informatik.tu-chemnitz.de> - */ - -#include <linux/linkage.h> -#include <asm/segment.h> - -#define NR_IRQS 16 - -extern void disable_irq(unsigned int); -extern void enable_irq(unsigned int); - -#define __STR(x) #x -#define STR(x) __STR(x) - -#define SAVE_ALL \ - "cld\n\t" \ - "push %gs\n\t" \ - "push %fs\n\t" \ - "push %es\n\t" \ - "push %ds\n\t" \ - "pushl %eax\n\t" \ - "pushl %ebp\n\t" \ - "pushl %edi\n\t" \ - "pushl %esi\n\t" \ - "pushl %edx\n\t" \ - "pushl %ecx\n\t" \ - "pushl %ebx\n\t" \ - "movl $" STR(KERNEL_DS) ",%edx\n\t" \ - "mov %dx,%ds\n\t" \ - "mov %dx,%es\n\t" \ - "movl $" STR(USER_DS) ",%edx\n\t" \ - "mov %dx,%fs\n\t" \ - "movl $0,%edx\n\t" \ - "movl %edx,%db7\n\t" - -/* - * SAVE_MOST/RESTORE_MOST is used for the faster version of IRQ handlers, - * installed by using the SA_INTERRUPT flag. These kinds of IRQ's don't - * call the routines that do signal handling etc on return, and can have - * more relaxed register-saving etc. They are also atomic, and are thus - * suited for small, fast interrupts like the serial lines or the harddisk - * drivers, which don't actually need signal handling etc. - * - * Also note that we actually save only those registers that are used in - * C subroutines (%eax, %edx and %ecx), so if you do something weird, - * you're on your own. The only segments that are saved (not counting the - * automatic stack and code segment handling) are %ds and %es, and they - * point to kernel space. No messing around with %fs here. - */ -#define SAVE_MOST \ - "cld\n\t" \ - "push %es\n\t" \ - "push %ds\n\t" \ - "pushl %eax\n\t" \ - "pushl %edx\n\t" \ - "pushl %ecx\n\t" \ - "movl $" STR(KERNEL_DS) ",%edx\n\t" \ - "mov %dx,%ds\n\t" \ - "mov %dx,%es\n\t" - -#define RESTORE_MOST \ - "popl %ecx\n\t" \ - "popl %edx\n\t" \ - "popl %eax\n\t" \ - "pop %ds\n\t" \ - "pop %es\n\t" \ - "iret" - -/* - * The "inb" instructions are not needed, but seem to change the timings - * a bit - without them it seems that the harddisk driver won't work on - * all hardware. Arghh. - */ -#define ACK_FIRST(mask) \ - "inb $0x21,%al\n\t" \ - "jmp 1f\n" \ - "1:\tjmp 1f\n" \ - "1:\torb $" #mask ","SYMBOL_NAME_STR(cache_21)"\n\t" \ - "movb "SYMBOL_NAME_STR(cache_21)",%al\n\t" \ - "outb %al,$0x21\n\t" \ - "jmp 1f\n" \ - "1:\tjmp 1f\n" \ - "1:\tmovb $0x20,%al\n\t" \ - "outb %al,$0x20\n\t" - -#define ACK_SECOND(mask) \ - "inb $0xA1,%al\n\t" \ - "jmp 1f\n" \ - "1:\tjmp 1f\n" \ - "1:\torb $" #mask ","SYMBOL_NAME_STR(cache_A1)"\n\t" \ - "movb "SYMBOL_NAME_STR(cache_A1)",%al\n\t" \ - "outb %al,$0xA1\n\t" \ - "jmp 1f\n" \ - "1:\tjmp 1f\n" \ - "1:\tmovb $0x20,%al\n\t" \ - "outb %al,$0xA0\n\t" \ - "jmp 1f\n" \ - "1:\tjmp 1f\n" \ - "1:\toutb %al,$0x20\n\t" - -#define UNBLK_FIRST(mask) \ - "inb $0x21,%al\n\t" \ - "jmp 1f\n" \ - "1:\tjmp 1f\n" \ - "1:\tandb $~(" #mask "),"SYMBOL_NAME_STR(cache_21)"\n\t" \ - "movb "SYMBOL_NAME_STR(cache_21)",%al\n\t" \ - "outb %al,$0x21\n\t" - -#define UNBLK_SECOND(mask) \ - "inb $0xA1,%al\n\t" \ - "jmp 1f\n" \ - "1:\tjmp 1f\n" \ - "1:\tandb $~(" #mask "),"SYMBOL_NAME_STR(cache_A1)"\n\t" \ - "movb "SYMBOL_NAME_STR(cache_A1)",%al\n\t" \ - "outb %al,$0xA1\n\t" - -#define IRQ_NAME2(nr) nr##_interrupt(void) -#define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr) -#define FAST_IRQ_NAME(nr) IRQ_NAME2(fast_IRQ##nr) -#define BAD_IRQ_NAME(nr) IRQ_NAME2(bad_IRQ##nr) - -#ifdef __SMP__ - -#ifndef __SMP_PROF__ -#define SMP_PROF_INT_SPINS -#define SMP_PROF_IPI_CNT -#else -#define SMP_PROF_INT_SPINS "incl "SYMBOL_NAME_STR(smp_spins)"(,%eax,4)\n\t" -#define SMP_PROF_IPI_CNT "incl "SYMBOL_NAME_STR(ipi_count)"\n\t" -#endif - -#define GET_PROCESSOR_ID \ - "movl "SYMBOL_NAME_STR(apic_reg)", %edx\n\t" \ - "movl 32(%edx), %eax\n\t" \ - "shrl $24,%eax\n\t" \ - "andb $0x0F,%al\n" - -#define ENTER_KERNEL \ - "pushl %eax\n\t" \ - "pushl %edx\n\t" \ - "pushfl\n\t" \ - "cli\n\t" \ - GET_PROCESSOR_ID \ - "1: " \ - "lock\n\t" \ - "btsl $0, "SYMBOL_NAME_STR(kernel_flag)"\n\t" \ - "jnc 3f\n\t" \ - "cmpb "SYMBOL_NAME_STR(active_kernel_processor)", %al\n\t" \ - "je 4f\n\t" \ - "2: " \ - SMP_PROF_INT_SPINS \ - "btl %al, "SYMBOL_NAME_STR(smp_invalidate_needed)"\n\t" \ - "jnc 5f\n\t" \ - "lock\n\t" \ - "btrl %al, "SYMBOL_NAME_STR(smp_invalidate_needed)"\n\t" \ - "jnc 5f\n\t" \ - "movl %cr3,%edx\n\t" \ - "movl %edx,%cr3\n" \ - "5: btl $0, "SYMBOL_NAME_STR(kernel_flag)"\n\t" \ - "jc 2b\n\t" \ - "jmp 1b\n\t" \ - "3: " \ - "movb %al, "SYMBOL_NAME_STR(active_kernel_processor)"\n\t" \ - "4: " \ - "incl "SYMBOL_NAME_STR(kernel_counter)"\n\t" \ - "popfl\n\t" \ - "popl %edx\n\t" \ - "popl %eax\n\t" - -#define LEAVE_KERNEL \ - "pushfl\n\t" \ - "cli\n\t" \ - "decl "SYMBOL_NAME_STR(kernel_counter)"\n\t" \ - "jnz 1f\n\t" \ - "movb $" STR (NO_PROC_ID) ", "SYMBOL_NAME_STR(active_kernel_processor)"\n\t" \ - "lock\n\t" \ - "btrl $0, "SYMBOL_NAME_STR(kernel_flag)"\n\t" \ - "1: " \ - "popfl\n\t" - - -/* - * the syscall count inc is a gross hack because ret_from_syscall is used by both irq and - * syscall return paths (urghh). - */ - -#define BUILD_IRQ(chip,nr,mask) \ -asmlinkage void IRQ_NAME(nr); \ -asmlinkage void FAST_IRQ_NAME(nr); \ -asmlinkage void BAD_IRQ_NAME(nr); \ -__asm__( \ -"\n"__ALIGN_STR"\n" \ -SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \ - "pushl $-"#nr"-2\n\t" \ - SAVE_ALL \ - ENTER_KERNEL \ - ACK_##chip(mask) \ - "incl "SYMBOL_NAME_STR(intr_count)"\n\t"\ - "sti\n\t" \ - "movl %esp,%ebx\n\t" \ - "pushl %ebx\n\t" \ - "pushl $" #nr "\n\t" \ - "call "SYMBOL_NAME_STR(do_IRQ)"\n\t" \ - "addl $8,%esp\n\t" \ - "cli\n\t" \ - UNBLK_##chip(mask) \ - "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \ - "incl "SYMBOL_NAME_STR(syscall_count)"\n\t" \ - "jmp ret_from_sys_call\n" \ -"\n"__ALIGN_STR"\n" \ -SYMBOL_NAME_STR(fast_IRQ) #nr "_interrupt:\n\t" \ - SAVE_MOST \ - ENTER_KERNEL \ - ACK_##chip(mask) \ - "incl "SYMBOL_NAME_STR(intr_count)"\n\t" \ - "pushl $" #nr "\n\t" \ - "call "SYMBOL_NAME_STR(do_fast_IRQ)"\n\t" \ - "addl $4,%esp\n\t" \ - "cli\n\t" \ - UNBLK_##chip(mask) \ - "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \ - LEAVE_KERNEL \ - RESTORE_MOST \ -"\n"__ALIGN_STR"\n" \ -SYMBOL_NAME_STR(bad_IRQ) #nr "_interrupt:\n\t" \ - SAVE_MOST \ - ENTER_KERNEL \ - ACK_##chip(mask) \ - LEAVE_KERNEL \ - RESTORE_MOST); - - -/* - * Message pass must be a fast IRQ.. - */ - -#define BUILD_MSGIRQ(chip,nr,mask) \ -asmlinkage void IRQ_NAME(nr); \ -asmlinkage void FAST_IRQ_NAME(nr); \ -asmlinkage void BAD_IRQ_NAME(nr); \ -__asm__( \ -"\n"__ALIGN_STR"\n" \ -SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \ - "pushl $-"#nr"-2\n\t" \ - SAVE_ALL \ - ENTER_KERNEL \ - ACK_##chip(mask) \ - "incl "SYMBOL_NAME_STR(intr_count)"\n\t"\ - "sti\n\t" \ - "movl %esp,%ebx\n\t" \ - "pushl %ebx\n\t" \ - "pushl $" #nr "\n\t" \ - "call "SYMBOL_NAME_STR(do_IRQ)"\n\t" \ - "addl $8,%esp\n\t" \ - "cli\n\t" \ - UNBLK_##chip(mask) \ - "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \ - "incl "SYMBOL_NAME_STR(syscall_count)"\n\t" \ - "jmp ret_from_sys_call\n" \ -"\n"__ALIGN_STR"\n" \ -SYMBOL_NAME_STR(fast_IRQ) #nr "_interrupt:\n\t" \ - SAVE_MOST \ - ACK_##chip(mask) \ - SMP_PROF_IPI_CNT \ - "pushl $" #nr "\n\t" \ - "call "SYMBOL_NAME_STR(do_fast_IRQ)"\n\t" \ - "addl $4,%esp\n\t" \ - "cli\n\t" \ - UNBLK_##chip(mask) \ - RESTORE_MOST \ -"\n"__ALIGN_STR"\n" \ -SYMBOL_NAME_STR(bad_IRQ) #nr "_interrupt:\n\t" \ - SAVE_MOST \ - ACK_##chip(mask) \ - RESTORE_MOST); - -#define BUILD_RESCHEDIRQ(nr) \ -asmlinkage void IRQ_NAME(nr); \ -__asm__( \ -"\n"__ALIGN_STR"\n" \ -SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \ - "pushl $-"#nr"-2\n\t" \ - SAVE_ALL \ - ENTER_KERNEL \ - "incl "SYMBOL_NAME_STR(intr_count)"\n\t"\ - "sti\n\t" \ - "movl %esp,%ebx\n\t" \ - "pushl %ebx\n\t" \ - "pushl $" #nr "\n\t" \ - "call "SYMBOL_NAME_STR(smp_reschedule_irq)"\n\t" \ - "addl $8,%esp\n\t" \ - "cli\n\t" \ - "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \ - "incl "SYMBOL_NAME_STR(syscall_count)"\n\t" \ - "jmp ret_from_sys_call\n"); -#else - -#define BUILD_IRQ(chip,nr,mask) \ -asmlinkage void IRQ_NAME(nr); \ -asmlinkage void FAST_IRQ_NAME(nr); \ -asmlinkage void BAD_IRQ_NAME(nr); \ -__asm__( \ -"\n"__ALIGN_STR"\n" \ -SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \ - "pushl $-"#nr"-2\n\t" \ - SAVE_ALL \ - ACK_##chip(mask) \ - "incl "SYMBOL_NAME_STR(intr_count)"\n\t"\ - "sti\n\t" \ - "movl %esp,%ebx\n\t" \ - "pushl %ebx\n\t" \ - "pushl $" #nr "\n\t" \ - "call "SYMBOL_NAME_STR(do_IRQ)"\n\t" \ - "addl $8,%esp\n\t" \ - "cli\n\t" \ - UNBLK_##chip(mask) \ - "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \ - "jmp ret_from_sys_call\n" \ -"\n"__ALIGN_STR"\n" \ -SYMBOL_NAME_STR(fast_IRQ) #nr "_interrupt:\n\t" \ - SAVE_MOST \ - ACK_##chip(mask) \ - "incl "SYMBOL_NAME_STR(intr_count)"\n\t" \ - "pushl $" #nr "\n\t" \ - "call "SYMBOL_NAME_STR(do_fast_IRQ)"\n\t" \ - "addl $4,%esp\n\t" \ - "cli\n\t" \ - UNBLK_##chip(mask) \ - "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \ - RESTORE_MOST \ -"\n"__ALIGN_STR"\n" \ -SYMBOL_NAME_STR(bad_IRQ) #nr "_interrupt:\n\t" \ - SAVE_MOST \ - ACK_##chip(mask) \ - RESTORE_MOST); - -#endif -#endif diff --git a/i386/i386at/gpl/linux/include/asm/page.h b/i386/i386at/gpl/linux/include/asm/page.h deleted file mode 100644 index 2bb6837e..00000000 --- a/i386/i386at/gpl/linux/include/asm/page.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef _I386_PAGE_H -#define _I386_PAGE_H - -#ifndef MACH_INCLUDE -/* PAGE_SHIFT determines the page size */ -#define PAGE_SHIFT 12 -#define PAGE_SIZE (1UL << PAGE_SHIFT) -#define PAGE_MASK (~(PAGE_SIZE-1)) -#endif - -#ifdef __KERNEL__ - -#define STRICT_MM_TYPECHECKS - -#ifdef STRICT_MM_TYPECHECKS -/* - * These are used to make use of C type-checking.. - */ -typedef struct { unsigned long pte; } pte_t; -typedef struct { unsigned long pmd; } pmd_t; -typedef struct { unsigned long pgd; } pgd_t; -typedef struct { unsigned long pgprot; } pgprot_t; - -#define pte_val(x) ((x).pte) -#define pmd_val(x) ((x).pmd) -#define pgd_val(x) ((x).pgd) -#define pgprot_val(x) ((x).pgprot) - -#define __pte(x) ((pte_t) { (x) } ) -#define __pmd(x) ((pmd_t) { (x) } ) -#define __pgd(x) ((pgd_t) { (x) } ) -#define __pgprot(x) ((pgprot_t) { (x) } ) - -#else -/* - * .. while these make it easier on the compiler - */ -typedef unsigned long pte_t; -typedef unsigned long pmd_t; -typedef unsigned long pgd_t; -typedef unsigned long pgprot_t; - -#define pte_val(x) (x) -#define pmd_val(x) (x) -#define pgd_val(x) (x) -#define pgprot_val(x) (x) - -#define __pte(x) (x) -#define __pmd(x) (x) -#define __pgd(x) (x) -#define __pgprot(x) (x) - -#endif - -/* to align the pointer to the (next) page boundary */ -#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK) - -/* This handles the memory map.. */ -#define PAGE_OFFSET 0 -#define MAP_NR(addr) (((unsigned long)(addr)) >> PAGE_SHIFT) - -#endif /* __KERNEL__ */ - -#endif /* _I386_PAGE_H */ diff --git a/i386/i386at/gpl/linux/include/asm/param.h b/i386/i386at/gpl/linux/include/asm/param.h deleted file mode 100644 index f821b864..00000000 --- a/i386/i386at/gpl/linux/include/asm/param.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef _ASMi386_PARAM_H -#define _ASMi386_PARAM_H - -#ifndef HZ -#define HZ 100 -#endif - -#define EXEC_PAGESIZE 4096 - -#ifndef NGROUPS -#define NGROUPS 32 -#endif - -#ifndef NOGROUP -#define NOGROUP (-1) -#endif - -#define MAXHOSTNAMELEN 64 /* max length of hostname */ - -#endif diff --git a/i386/i386at/gpl/linux/include/asm/processor.h b/i386/i386at/gpl/linux/include/asm/processor.h deleted file mode 100644 index dea7827b..00000000 --- a/i386/i386at/gpl/linux/include/asm/processor.h +++ /dev/null @@ -1,146 +0,0 @@ -/* - * include/asm-i386/processor.h - * - * Copyright (C) 1994 Linus Torvalds - */ - -#ifndef __ASM_I386_PROCESSOR_H -#define __ASM_I386_PROCESSOR_H - -/* - * System setup and hardware bug flags.. - */ -extern char hard_math; -extern char x86; /* lower 4 bits */ -extern char x86_vendor_id[13]; -extern char x86_model; /* lower 4 bits */ -extern char x86_mask; /* lower 4 bits */ -extern int x86_capability; /* field of flags */ -extern int fdiv_bug; -extern char ignore_irq13; -extern char wp_works_ok; /* doesn't work on a 386 */ -extern char hlt_works_ok; /* problems on some 486Dx4's and old 386's */ - -/* - * Bus types (default is ISA, but people can check others with these..) - * MCA_bus hardcoded to 0 for now. - */ -extern int EISA_bus; -#define MCA_bus 0 -#define MCA_bus__is_a_macro /* for versions in ksyms.c */ - -/* - * User space process size: 3GB. This is hardcoded into a few places, - * so don't change it unless you know what you are doing. - */ -#define TASK_SIZE (0xC0000000UL) - -/* - * Size of io_bitmap in longwords: 32 is ports 0-0x3ff. - */ -#define IO_BITMAP_SIZE 32 - -struct i387_hard_struct { - long cwd; - long swd; - long twd; - long fip; - long fcs; - long foo; - long fos; - long st_space[20]; /* 8*10 bytes for each FP-reg = 80 bytes */ -}; - -struct i387_soft_struct { - long cwd; - long swd; - long twd; - long fip; - long fcs; - long foo; - long fos; - long top; - struct fpu_reg regs[8]; /* 8*16 bytes for each FP-reg = 128 bytes */ - unsigned char lookahead; - struct info *info; - unsigned long entry_eip; -}; - -union i387_union { - struct i387_hard_struct hard; - struct i387_soft_struct soft; -}; - -struct thread_struct { - unsigned short back_link,__blh; - unsigned long esp0; - unsigned short ss0,__ss0h; - unsigned long esp1; - unsigned short ss1,__ss1h; - unsigned long esp2; - unsigned short ss2,__ss2h; - unsigned long cr3; - unsigned long eip; - unsigned long eflags; - unsigned long eax,ecx,edx,ebx; - unsigned long esp; - unsigned long ebp; - unsigned long esi; - unsigned long edi; - unsigned short es, __esh; - unsigned short cs, __csh; - unsigned short ss, __ssh; - unsigned short ds, __dsh; - unsigned short fs, __fsh; - unsigned short gs, __gsh; - unsigned short ldt, __ldth; - unsigned short trace, bitmap; - unsigned long io_bitmap[IO_BITMAP_SIZE+1]; - unsigned long tr; - unsigned long cr2, trap_no, error_code; -/* floating point info */ - union i387_union i387; -/* virtual 86 mode info */ - struct vm86_struct * vm86_info; - unsigned long screen_bitmap; - unsigned long v86flags, v86mask, v86mode; -}; - -#define INIT_MMAP { &init_mm, 0, 0x40000000, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC } - -#define INIT_TSS { \ - 0,0, \ - sizeof(init_kernel_stack) + (long) &init_kernel_stack, \ - KERNEL_DS, 0, \ - 0,0,0,0,0,0, \ - (long) &swapper_pg_dir, \ - 0,0,0,0,0,0,0,0,0,0, \ - USER_DS,0,USER_DS,0,USER_DS,0,USER_DS,0,USER_DS,0,USER_DS,0, \ - _LDT(0),0, \ - 0, 0x8000, \ - {~0, }, /* ioperm */ \ - _TSS(0), 0, 0,0, \ - { { 0, }, }, /* 387 state */ \ - NULL, 0, 0, 0, 0 /* vm86_info */ \ -} - -#define alloc_kernel_stack() get_free_page(GFP_KERNEL) -#define free_kernel_stack(page) free_page((page)) - -static inline void start_thread(struct pt_regs * regs, unsigned long eip, unsigned long esp) -{ - regs->cs = USER_CS; - regs->ds = regs->es = regs->ss = regs->fs = regs->gs = USER_DS; - regs->eip = eip; - regs->esp = esp; -} - -/* - * Return saved PC of a blocked thread. - */ -extern inline unsigned long thread_saved_pc(struct thread_struct *t) -{ - return ((unsigned long *)t->esp)[3]; -} - -#endif /* __ASM_I386_PROCESSOR_H */ diff --git a/i386/i386at/gpl/linux/include/asm/ptrace.h b/i386/i386at/gpl/linux/include/asm/ptrace.h deleted file mode 100644 index 8e4aa52f..00000000 --- a/i386/i386at/gpl/linux/include/asm/ptrace.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef _I386_PTRACE_H -#define _I386_PTRACE_H - -#define EBX 0 -#define ECX 1 -#define EDX 2 -#define ESI 3 -#define EDI 4 -#define EBP 5 -#define EAX 6 -#define DS 7 -#define ES 8 -#define FS 9 -#define GS 10 -#define ORIG_EAX 11 -#define EIP 12 -#define CS 13 -#define EFL 14 -#define UESP 15 -#define SS 16 - - -/* this struct defines the way the registers are stored on the - stack during a system call. */ - -struct pt_regs { - long ebx; - long ecx; - long edx; - long esi; - long edi; - long ebp; - long eax; - unsigned short ds, __dsu; - unsigned short es, __esu; - unsigned short fs, __fsu; - unsigned short gs, __gsu; - long orig_eax; - long eip; - unsigned short cs, __csu; - long eflags; - long esp; - unsigned short ss, __ssu; -}; - -#ifdef __KERNEL__ -#define user_mode(regs) ((VM_MASK & (regs)->eflags) || (3 & (regs)->cs)) -#define instruction_pointer(regs) ((regs)->eip) -extern void show_regs(struct pt_regs *); -#endif - -#endif diff --git a/i386/i386at/gpl/linux/include/asm/resource.h b/i386/i386at/gpl/linux/include/asm/resource.h deleted file mode 100644 index 83940d16..00000000 --- a/i386/i386at/gpl/linux/include/asm/resource.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef _I386_RESOURCE_H -#define _I386_RESOURCE_H - -/* - * Resource limits - */ - -#define RLIMIT_CPU 0 /* CPU time in ms */ -#define RLIMIT_FSIZE 1 /* Maximum filesize */ -#define RLIMIT_DATA 2 /* max data size */ -#define RLIMIT_STACK 3 /* max stack size */ -#define RLIMIT_CORE 4 /* max core file size */ -#define RLIMIT_RSS 5 /* max resident set size */ -#define RLIMIT_NPROC 6 /* max number of processes */ -#define RLIMIT_NOFILE 7 /* max number of open files */ -#define RLIMIT_MEMLOCK 8 /* max locked-in-memory address space */ - -#define RLIM_NLIMITS 9 - -#ifdef __KERNEL__ - -#define INIT_RLIMITS \ -{ \ - { LONG_MAX, LONG_MAX }, \ - { LONG_MAX, LONG_MAX }, \ - { LONG_MAX, LONG_MAX }, \ - { _STK_LIM, _STK_LIM }, \ - { 0, LONG_MAX }, \ - { LONG_MAX, LONG_MAX }, \ - { MAX_TASKS_PER_USER, MAX_TASKS_PER_USER }, \ - { NR_OPEN, NR_OPEN }, \ - { LONG_MAX, LONG_MAX }, \ -} - -#endif /* __KERNEL__ */ - -#endif diff --git a/i386/i386at/gpl/linux/include/asm/segment.h b/i386/i386at/gpl/linux/include/asm/segment.h deleted file mode 100644 index 7cfafa4b..00000000 --- a/i386/i386at/gpl/linux/include/asm/segment.h +++ /dev/null @@ -1,347 +0,0 @@ -#ifndef _ASM_SEGMENT_H -#define _ASM_SEGMENT_H - -#ifdef MACH -#define KERNEL_CS 0x08 -#define KERNEL_DS 0x10 - -#define USER_CS 0x17 -#define USER_DS 0x1f -#else -#define KERNEL_CS 0x10 -#define KERNEL_DS 0x18 - -#define USER_CS 0x23 -#define USER_DS 0x2B -#endif - -#ifndef __ASSEMBLY__ - -/* - * Uh, these should become the main single-value transfer routines.. - * They automatically use the right size if we just have the right - * pointer type.. - */ -#define put_user(x,ptr) __put_user((unsigned long)(x),(ptr),sizeof(*(ptr))) -#define get_user(ptr) ((__typeof__(*(ptr)))__get_user((ptr),sizeof(*(ptr)))) - -/* - * This is a silly but good way to make sure that - * the __put_user function is indeed always optimized, - * and that we use the correct sizes.. - */ -extern int bad_user_access_length(void); - -/* - * dummy pointer type structure.. gcc won't try to do something strange - * this way.. - */ -struct __segment_dummy { unsigned long a[100]; }; -#define __sd(x) ((struct __segment_dummy *) (x)) -#define __const_sd(x) ((const struct __segment_dummy *) (x)) - -static inline void __put_user(unsigned long x, void * y, int size) -{ - switch (size) { - case 1: - __asm__ ("movb %b1,%%fs:%0" - :"=m" (*__sd(y)) - :"iq" ((unsigned char) x), "m" (*__sd(y))); - break; - case 2: - __asm__ ("movw %w1,%%fs:%0" - :"=m" (*__sd(y)) - :"ir" ((unsigned short) x), "m" (*__sd(y))); - break; - case 4: - __asm__ ("movl %1,%%fs:%0" - :"=m" (*__sd(y)) - :"ir" (x), "m" (*__sd(y))); - break; - default: - bad_user_access_length(); - } -} - -static inline unsigned long __get_user(const void * y, int size) -{ - unsigned long result; - - switch (size) { - case 1: - __asm__ ("movb %%fs:%1,%b0" - :"=q" (result) - :"m" (*__const_sd(y))); - return (unsigned char) result; - case 2: - __asm__ ("movw %%fs:%1,%w0" - :"=r" (result) - :"m" (*__const_sd(y))); - return (unsigned short) result; - case 4: - __asm__ ("movl %%fs:%1,%0" - :"=r" (result) - :"m" (*__const_sd(y))); - return result; - default: - return bad_user_access_length(); - } -} - -static inline void __generic_memcpy_tofs(void * to, const void * from, unsigned long n) -{ - __asm__ volatile - (" cld - push %%es - movw %%fs,%%cx - movw %%cx,%%es - cmpl $3,%0 - jbe 1f - movl %%edi,%%ecx - negl %%ecx - andl $3,%%ecx - subl %%ecx,%0 - rep; movsb - movl %0,%%ecx - shrl $2,%%ecx - rep; movsl - andl $3,%0 - 1: movl %0,%%ecx - rep; movsb - pop %%es" - :"=abd" (n) - :"0" (n),"D" ((long) to),"S" ((long) from) - :"cx","di","si"); -} - -static inline void __constant_memcpy_tofs(void * to, const void * from, unsigned long n) -{ - switch (n) { - case 0: - return; - case 1: - __put_user(*(const char *) from, (char *) to, 1); - return; - case 2: - __put_user(*(const short *) from, (short *) to, 2); - return; - case 3: - __put_user(*(const short *) from, (short *) to, 2); - __put_user(*(2+(const char *) from), 2+(char *) to, 1); - return; - case 4: - __put_user(*(const int *) from, (int *) to, 4); - return; - case 8: - __put_user(*(const int *) from, (int *) to, 4); - __put_user(*(1+(const int *) from), 1+(int *) to, 4); - return; - case 12: - __put_user(*(const int *) from, (int *) to, 4); - __put_user(*(1+(const int *) from), 1+(int *) to, 4); - __put_user(*(2+(const int *) from), 2+(int *) to, 4); - return; - case 16: - __put_user(*(const int *) from, (int *) to, 4); - __put_user(*(1+(const int *) from), 1+(int *) to, 4); - __put_user(*(2+(const int *) from), 2+(int *) to, 4); - __put_user(*(3+(const int *) from), 3+(int *) to, 4); - return; - } -#define COMMON(x) \ -__asm__("cld\n\t" \ - "push %%es\n\t" \ - "push %%fs\n\t" \ - "pop %%es\n\t" \ - "rep ; movsl\n\t" \ - x \ - "pop %%es" \ - : /* no outputs */ \ - :"c" (n/4),"D" ((long) to),"S" ((long) from) \ - :"cx","di","si") - - switch (n % 4) { - case 0: - COMMON(""); - return; - case 1: - COMMON("movsb\n\t"); - return; - case 2: - COMMON("movsw\n\t"); - return; - case 3: - COMMON("movsw\n\tmovsb\n\t"); - return; - } -#undef COMMON -} - -static inline void __generic_memcpy_fromfs(void * to, const void * from, unsigned long n) -{ - __asm__ volatile - (" cld - cmpl $3,%0 - jbe 1f - movl %%edi,%%ecx - negl %%ecx - andl $3,%%ecx - subl %%ecx,%0 - fs; rep; movsb - movl %0,%%ecx - shrl $2,%%ecx - fs; rep; movsl - andl $3,%0 - 1: movl %0,%%ecx - fs; rep; movsb" - :"=abd" (n) - :"0" (n),"D" ((long) to),"S" ((long) from) - :"cx","di","si", "memory"); -} - -static inline void __constant_memcpy_fromfs(void * to, const void * from, unsigned long n) -{ - switch (n) { - case 0: - return; - case 1: - *(char *)to = __get_user((const char *) from, 1); - return; - case 2: - *(short *)to = __get_user((const short *) from, 2); - return; - case 3: - *(short *) to = __get_user((const short *) from, 2); - *((char *) to + 2) = __get_user(2+(const char *) from, 1); - return; - case 4: - *(int *) to = __get_user((const int *) from, 4); - return; - case 8: - *(int *) to = __get_user((const int *) from, 4); - *(1+(int *) to) = __get_user(1+(const int *) from, 4); - return; - case 12: - *(int *) to = __get_user((const int *) from, 4); - *(1+(int *) to) = __get_user(1+(const int *) from, 4); - *(2+(int *) to) = __get_user(2+(const int *) from, 4); - return; - case 16: - *(int *) to = __get_user((const int *) from, 4); - *(1+(int *) to) = __get_user(1+(const int *) from, 4); - *(2+(int *) to) = __get_user(2+(const int *) from, 4); - *(3+(int *) to) = __get_user(3+(const int *) from, 4); - return; - } -#define COMMON(x) \ -__asm__("cld\n\t" \ - "rep ; fs ; movsl\n\t" \ - x \ - : /* no outputs */ \ - :"c" (n/4),"D" ((long) to),"S" ((long) from) \ - :"cx","di","si","memory") - - switch (n % 4) { - case 0: - COMMON(""); - return; - case 1: - COMMON("fs ; movsb"); - return; - case 2: - COMMON("fs ; movsw"); - return; - case 3: - COMMON("fs ; movsw\n\tfs ; movsb"); - return; - } -#undef COMMON -} - -#define memcpy_fromfs(to, from, n) \ -(__builtin_constant_p(n) ? \ - __constant_memcpy_fromfs((to),(from),(n)) : \ - __generic_memcpy_fromfs((to),(from),(n))) - -#define memcpy_tofs(to, from, n) \ -(__builtin_constant_p(n) ? \ - __constant_memcpy_tofs((to),(from),(n)) : \ - __generic_memcpy_tofs((to),(from),(n))) - -/* - * These are deprecated.. - * - * Use "put_user()" and "get_user()" with the proper pointer types instead. - */ - -#define get_fs_byte(addr) __get_user((const unsigned char *)(addr),1) -#define get_fs_word(addr) __get_user((const unsigned short *)(addr),2) -#define get_fs_long(addr) __get_user((const unsigned int *)(addr),4) - -#define put_fs_byte(x,addr) __put_user((x),(unsigned char *)(addr),1) -#define put_fs_word(x,addr) __put_user((x),(unsigned short *)(addr),2) -#define put_fs_long(x,addr) __put_user((x),(unsigned int *)(addr),4) - -#ifdef WE_REALLY_WANT_TO_USE_A_BROKEN_INTERFACE - -static inline unsigned short get_user_word(const short *addr) -{ - return __get_user(addr, 2); -} - -static inline unsigned char get_user_byte(const char * addr) -{ - return __get_user(addr,1); -} - -static inline unsigned long get_user_long(const int *addr) -{ - return __get_user(addr, 4); -} - -static inline void put_user_byte(char val,char *addr) -{ - __put_user(val, addr, 1); -} - -static inline void put_user_word(short val,short * addr) -{ - __put_user(val, addr, 2); -} - -static inline void put_user_long(unsigned long val,int * addr) -{ - __put_user(val, addr, 4); -} - -#endif - -/* - * Someone who knows GNU asm better than I should double check the following. - * It seems to work, but I don't know if I'm doing something subtly wrong. - * --- TYT, 11/24/91 - * [ nothing wrong here, Linus: I just changed the ax to be any reg ] - */ - -static inline unsigned long get_fs(void) -{ - unsigned long _v; - __asm__("mov %%fs,%w0":"=r" (_v):"0" (0)); - return _v; -} - -static inline unsigned long get_ds(void) -{ - unsigned long _v; - __asm__("mov %%ds,%w0":"=r" (_v):"0" (0)); - return _v; -} - -static inline void set_fs(unsigned long val) -{ - __asm__ __volatile__("mov %w0,%%fs": /* no output */ :"r" (val)); -} - -#endif /* __ASSEMBLY__ */ - -#endif /* _ASM_SEGMENT_H */ diff --git a/i386/i386at/gpl/linux/include/asm/sigcontext.h b/i386/i386at/gpl/linux/include/asm/sigcontext.h deleted file mode 100644 index 5b84694f..00000000 --- a/i386/i386at/gpl/linux/include/asm/sigcontext.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef _ASMi386_SIGCONTEXT_H -#define _ASMi386_SIGCONTEXT_H - -struct sigcontext_struct { - unsigned short gs, __gsh; - unsigned short fs, __fsh; - unsigned short es, __esh; - unsigned short ds, __dsh; - unsigned long edi; - unsigned long esi; - unsigned long ebp; - unsigned long esp; - unsigned long ebx; - unsigned long edx; - unsigned long ecx; - unsigned long eax; - unsigned long trapno; - unsigned long err; - unsigned long eip; - unsigned short cs, __csh; - unsigned long eflags; - unsigned long esp_at_signal; - unsigned short ss, __ssh; - unsigned long i387; - unsigned long oldmask; - unsigned long cr2; -}; - -#endif diff --git a/i386/i386at/gpl/linux/include/asm/signal.h b/i386/i386at/gpl/linux/include/asm/signal.h deleted file mode 100644 index b37613fe..00000000 --- a/i386/i386at/gpl/linux/include/asm/signal.h +++ /dev/null @@ -1,95 +0,0 @@ -#ifndef _ASMi386_SIGNAL_H -#define _ASMi386_SIGNAL_H - -typedef unsigned long sigset_t; /* at least 32 bits */ - -#define _NSIG 32 -#define NSIG _NSIG - -#define SIGHUP 1 -#define SIGINT 2 -#define SIGQUIT 3 -#define SIGILL 4 -#define SIGTRAP 5 -#define SIGABRT 6 -#define SIGIOT 6 -#define SIGBUS 7 -#define SIGFPE 8 -#define SIGKILL 9 -#define SIGUSR1 10 -#define SIGSEGV 11 -#define SIGUSR2 12 -#define SIGPIPE 13 -#define SIGALRM 14 -#define SIGTERM 15 -#define SIGSTKFLT 16 -#define SIGCHLD 17 -#define SIGCONT 18 -#define SIGSTOP 19 -#define SIGTSTP 20 -#define SIGTTIN 21 -#define SIGTTOU 22 -#define SIGURG 23 -#define SIGXCPU 24 -#define SIGXFSZ 25 -#define SIGVTALRM 26 -#define SIGPROF 27 -#define SIGWINCH 28 -#define SIGIO 29 -#define SIGPOLL SIGIO -/* -#define SIGLOST 29 -*/ -#define SIGPWR 30 -#define SIGUNUSED 31 - -/* - * sa_flags values: SA_STACK is not currently supported, but will allow the - * usage of signal stacks by using the (now obsolete) sa_restorer field in - * the sigaction structure as a stack pointer. This is now possible due to - * the changes in signal handling. LBT 010493. - * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the - * SA_RESTART flag to get restarting signals (which were the default long ago) - */ -#define SA_NOCLDSTOP 1 -#define SA_STACK 0x08000000 -#define SA_RESTART 0x10000000 -#define SA_INTERRUPT 0x20000000 -#define SA_NOMASK 0x40000000 -#define SA_ONESHOT 0x80000000 - -#ifdef __KERNEL__ -/* - * These values of sa_flags are used only by the kernel as part of the - * irq handling routines. - * - * SA_INTERRUPT is also used by the irq handling routines. - */ -#define SA_PROBE SA_ONESHOT -#define SA_SAMPLE_RANDOM SA_RESTART -#endif - - -#define SIG_BLOCK 0 /* for blocking signals */ -#define SIG_UNBLOCK 1 /* for unblocking signals */ -#define SIG_SETMASK 2 /* for setting the signal mask */ - -/* Type of a signal handler. */ -typedef void (*__sighandler_t)(int); - -#define SIG_DFL ((__sighandler_t)0) /* default signal handling */ -#define SIG_IGN ((__sighandler_t)1) /* ignore signal */ -#define SIG_ERR ((__sighandler_t)-1) /* error return from signal */ - -struct sigaction { - __sighandler_t sa_handler; - sigset_t sa_mask; - unsigned long sa_flags; - void (*sa_restorer)(void); -}; - -#ifdef __KERNEL__ -#include <asm/sigcontext.h> -#endif - -#endif diff --git a/i386/i386at/gpl/linux/include/asm/socket.h b/i386/i386at/gpl/linux/include/asm/socket.h deleted file mode 100644 index dc923006..00000000 --- a/i386/i386at/gpl/linux/include/asm/socket.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef _ASM_SOCKET_H -#define _ASM_SOCKET_H - -/* Socket-level I/O control calls. */ -#define FIOSETOWN 0x8901 -#define SIOCSPGRP 0x8902 -#define FIOGETOWN 0x8903 -#define SIOCGPGRP 0x8904 -#define SIOCATMARK 0x8905 -#define SIOCGSTAMP 0x8906 /* Get stamp */ - -/* For setsockoptions(2) */ -#define SOL_SOCKET 1 - -#define SO_DEBUG 1 -#define SO_REUSEADDR 2 -#define SO_TYPE 3 -#define SO_ERROR 4 -#define SO_DONTROUTE 5 -#define SO_BROADCAST 6 -#define SO_SNDBUF 7 -#define SO_RCVBUF 8 -#define SO_KEEPALIVE 9 -#define SO_OOBINLINE 10 -#define SO_NO_CHECK 11 -#define SO_PRIORITY 12 -#define SO_LINGER 13 -#define SO_BSDCOMPAT 14 -/* To add :#define SO_REUSEPORT 15 */ - -#endif /* _ASM_SOCKET_H */ diff --git a/i386/i386at/gpl/linux/include/asm/stat.h b/i386/i386at/gpl/linux/include/asm/stat.h deleted file mode 100644 index b4c64869..00000000 --- a/i386/i386at/gpl/linux/include/asm/stat.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef _I386_STAT_H -#define _I386_STAT_H - -struct old_stat { - unsigned short st_dev; - unsigned short st_ino; - unsigned short st_mode; - unsigned short st_nlink; - unsigned short st_uid; - unsigned short st_gid; - unsigned short st_rdev; - unsigned long st_size; - unsigned long st_atime; - unsigned long st_mtime; - unsigned long st_ctime; -}; - -struct new_stat { - unsigned short st_dev; - unsigned short __pad1; - unsigned long st_ino; - unsigned short st_mode; - unsigned short st_nlink; - unsigned short st_uid; - unsigned short st_gid; - unsigned short st_rdev; - unsigned short __pad2; - unsigned long st_size; - unsigned long st_blksize; - unsigned long st_blocks; - unsigned long st_atime; - unsigned long __unused1; - unsigned long st_mtime; - unsigned long __unused2; - unsigned long st_ctime; - unsigned long __unused3; - unsigned long __unused4; - unsigned long __unused5; -}; - -#endif diff --git a/i386/i386at/gpl/linux/include/asm/statfs.h b/i386/i386at/gpl/linux/include/asm/statfs.h deleted file mode 100644 index 6efb7411..00000000 --- a/i386/i386at/gpl/linux/include/asm/statfs.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef _I386_STATFS_H -#define _I386_STATFS_H - -typedef struct { - long val[2]; -} fsid_t; - -struct statfs { - long f_type; - long f_bsize; - long f_blocks; - long f_bfree; - long f_bavail; - long f_files; - long f_ffree; - fsid_t f_fsid; - long f_namelen; - long f_spare[6]; -}; - -#endif diff --git a/i386/i386at/gpl/linux/include/asm/string.h b/i386/i386at/gpl/linux/include/asm/string.h deleted file mode 100644 index d93a2a77..00000000 --- a/i386/i386at/gpl/linux/include/asm/string.h +++ /dev/null @@ -1,593 +0,0 @@ -#ifndef _I386_STRING_H_ -#define _I386_STRING_H_ - -/* - * This string-include defines all string functions as inline - * functions. Use gcc. It also assumes ds=es=data space, this should be - * normal. Most of the string-functions are rather heavily hand-optimized, - * see especially strtok,strstr,str[c]spn. They should work, but are not - * very easy to understand. Everything is done entirely within the register - * set, making the functions fast and clean. String instructions have been - * used through-out, making for "slightly" unclear code :-) - * - * Copyright (C) 1991, 1992 Linus Torvalds - */ - -#define __HAVE_ARCH_STRCPY -extern inline char * strcpy(char * dest,const char *src) -{ -__asm__ __volatile__( - "cld\n" - "1:\tlodsb\n\t" - "stosb\n\t" - "testb %%al,%%al\n\t" - "jne 1b" - : /* no output */ - :"S" (src),"D" (dest):"si","di","ax","memory"); -return dest; -} - -#define __HAVE_ARCH_STRNCPY -extern inline char * strncpy(char * dest,const char *src,size_t count) -{ -__asm__ __volatile__( - "cld\n" - "1:\tdecl %2\n\t" - "js 2f\n\t" - "lodsb\n\t" - "stosb\n\t" - "testb %%al,%%al\n\t" - "jne 1b\n\t" - "rep\n\t" - "stosb\n" - "2:" - : /* no output */ - :"S" (src),"D" (dest),"c" (count):"si","di","ax","cx","memory"); -return dest; -} - -#define __HAVE_ARCH_STRCAT -extern inline char * strcat(char * dest,const char * src) -{ -__asm__ __volatile__( - "cld\n\t" - "repne\n\t" - "scasb\n\t" - "decl %1\n" - "1:\tlodsb\n\t" - "stosb\n\t" - "testb %%al,%%al\n\t" - "jne 1b" - : /* no output */ - :"S" (src),"D" (dest),"a" (0),"c" (0xffffffff):"si","di","ax","cx"); -return dest; -} - -#define __HAVE_ARCH_STRNCAT -extern inline char * strncat(char * dest,const char * src,size_t count) -{ -__asm__ __volatile__( - "cld\n\t" - "repne\n\t" - "scasb\n\t" - "decl %1\n\t" - "movl %4,%3\n" - "1:\tdecl %3\n\t" - "js 2f\n\t" - "lodsb\n\t" - "stosb\n\t" - "testb %%al,%%al\n\t" - "jne 1b\n" - "2:\txorl %2,%2\n\t" - "stosb" - : /* no output */ - :"S" (src),"D" (dest),"a" (0),"c" (0xffffffff),"g" (count) - :"si","di","ax","cx","memory"); -return dest; -} - -#define __HAVE_ARCH_STRCMP -extern inline int strcmp(const char * cs,const char * ct) -{ -register int __res; -__asm__ __volatile__( - "cld\n" - "1:\tlodsb\n\t" - "scasb\n\t" - "jne 2f\n\t" - "testb %%al,%%al\n\t" - "jne 1b\n\t" - "xorl %%eax,%%eax\n\t" - "jmp 3f\n" - "2:\tsbbl %%eax,%%eax\n\t" - "orb $1,%%eax\n" - "3:" - :"=a" (__res):"S" (cs),"D" (ct):"si","di"); -return __res; -} - -#define __HAVE_ARCH_STRNCMP -extern inline int strncmp(const char * cs,const char * ct,size_t count) -{ -register int __res; -__asm__ __volatile__( - "cld\n" - "1:\tdecl %3\n\t" - "js 2f\n\t" - "lodsb\n\t" - "scasb\n\t" - "jne 3f\n\t" - "testb %%al,%%al\n\t" - "jne 1b\n" - "2:\txorl %%eax,%%eax\n\t" - "jmp 4f\n" - "3:\tsbbl %%eax,%%eax\n\t" - "orb $1,%%al\n" - "4:" - :"=a" (__res):"S" (cs),"D" (ct),"c" (count):"si","di","cx"); -return __res; -} - -#define __HAVE_ARCH_STRCHR -extern inline char * strchr(const char * s, int c) -{ -register char * __res; -__asm__ __volatile__( - "cld\n\t" - "movb %%al,%%ah\n" - "1:\tlodsb\n\t" - "cmpb %%ah,%%al\n\t" - "je 2f\n\t" - "testb %%al,%%al\n\t" - "jne 1b\n\t" - "movl $1,%1\n" - "2:\tmovl %1,%0\n\t" - "decl %0" - :"=a" (__res):"S" (s),"0" (c):"si"); -return __res; -} - -#define __HAVE_ARCH_STRRCHR -extern inline char * strrchr(const char * s, int c) -{ -register char * __res; -__asm__ __volatile__( - "cld\n\t" - "movb %%al,%%ah\n" - "1:\tlodsb\n\t" - "cmpb %%ah,%%al\n\t" - "jne 2f\n\t" - "leal -1(%%esi),%0\n" - "2:\ttestb %%al,%%al\n\t" - "jne 1b" - :"=d" (__res):"0" (0),"S" (s),"a" (c):"ax","si"); -return __res; -} - -#define __HAVE_ARCH_STRSPN -extern inline size_t strspn(const char * cs, const char * ct) -{ -register char * __res; -__asm__ __volatile__( - "cld\n\t" - "movl %4,%%edi\n\t" - "repne\n\t" - "scasb\n\t" - "notl %%ecx\n\t" - "decl %%ecx\n\t" - "movl %%ecx,%%edx\n" - "1:\tlodsb\n\t" - "testb %%al,%%al\n\t" - "je 2f\n\t" - "movl %4,%%edi\n\t" - "movl %%edx,%%ecx\n\t" - "repne\n\t" - "scasb\n\t" - "je 1b\n" - "2:\tdecl %0" - :"=S" (__res):"a" (0),"c" (0xffffffff),"0" (cs),"g" (ct) - :"ax","cx","dx","di"); -return __res-cs; -} - -#define __HAVE_ARCH_STRCSPN -extern inline size_t strcspn(const char * cs, const char * ct) -{ -register char * __res; -__asm__ __volatile__( - "cld\n\t" - "movl %4,%%edi\n\t" - "repne\n\t" - "scasb\n\t" - "notl %%ecx\n\t" - "decl %%ecx\n\t" - "movl %%ecx,%%edx\n" - "1:\tlodsb\n\t" - "testb %%al,%%al\n\t" - "je 2f\n\t" - "movl %4,%%edi\n\t" - "movl %%edx,%%ecx\n\t" - "repne\n\t" - "scasb\n\t" - "jne 1b\n" - "2:\tdecl %0" - :"=S" (__res):"a" (0),"c" (0xffffffff),"0" (cs),"g" (ct) - :"ax","cx","dx","di"); -return __res-cs; -} - -#define __HAVE_ARCH_STRPBRK -extern inline char * strpbrk(const char * cs,const char * ct) -{ -register char * __res; -__asm__ __volatile__( - "cld\n\t" - "movl %4,%%edi\n\t" - "repne\n\t" - "scasb\n\t" - "notl %%ecx\n\t" - "decl %%ecx\n\t" - "movl %%ecx,%%edx\n" - "1:\tlodsb\n\t" - "testb %%al,%%al\n\t" - "je 2f\n\t" - "movl %4,%%edi\n\t" - "movl %%edx,%%ecx\n\t" - "repne\n\t" - "scasb\n\t" - "jne 1b\n\t" - "decl %0\n\t" - "jmp 3f\n" - "2:\txorl %0,%0\n" - "3:" - :"=S" (__res):"a" (0),"c" (0xffffffff),"0" (cs),"g" (ct) - :"ax","cx","dx","di"); -return __res; -} - -#define __HAVE_ARCH_STRSTR -extern inline char * strstr(const char * cs,const char * ct) -{ -register char * __res; -__asm__ __volatile__( - "cld\n\t" \ - "movl %4,%%edi\n\t" - "repne\n\t" - "scasb\n\t" - "notl %%ecx\n\t" - "decl %%ecx\n\t" /* NOTE! This also sets Z if searchstring='' */ - "movl %%ecx,%%edx\n" - "1:\tmovl %4,%%edi\n\t" - "movl %%esi,%%eax\n\t" - "movl %%edx,%%ecx\n\t" - "repe\n\t" - "cmpsb\n\t" - "je 2f\n\t" /* also works for empty string, see above */ - "xchgl %%eax,%%esi\n\t" - "incl %%esi\n\t" - "cmpb $0,-1(%%eax)\n\t" - "jne 1b\n\t" - "xorl %%eax,%%eax\n\t" - "2:" - :"=a" (__res):"0" (0),"c" (0xffffffff),"S" (cs),"g" (ct) - :"cx","dx","di","si"); -return __res; -} - -#define __HAVE_ARCH_STRLEN -extern inline size_t strlen(const char * s) -{ -register int __res; -__asm__ __volatile__( - "cld\n\t" - "repne\n\t" - "scasb\n\t" - "notl %0\n\t" - "decl %0" - :"=c" (__res):"D" (s),"a" (0),"0" (0xffffffff):"di"); -return __res; -} - -#define __HAVE_ARCH_STRTOK -extern inline char * strtok(char * s,const char * ct) -{ -register char * __res; -__asm__ __volatile__( - "testl %1,%1\n\t" - "jne 1f\n\t" - "testl %0,%0\n\t" - "je 8f\n\t" - "movl %0,%1\n" - "1:\txorl %0,%0\n\t" - "movl $-1,%%ecx\n\t" - "xorl %%eax,%%eax\n\t" - "cld\n\t" - "movl %4,%%edi\n\t" - "repne\n\t" - "scasb\n\t" - "notl %%ecx\n\t" - "decl %%ecx\n\t" - "je 7f\n\t" /* empty delimiter-string */ - "movl %%ecx,%%edx\n" - "2:\tlodsb\n\t" - "testb %%al,%%al\n\t" - "je 7f\n\t" - "movl %4,%%edi\n\t" - "movl %%edx,%%ecx\n\t" - "repne\n\t" - "scasb\n\t" - "je 2b\n\t" - "decl %1\n\t" - "cmpb $0,(%1)\n\t" - "je 7f\n\t" - "movl %1,%0\n" - "3:\tlodsb\n\t" - "testb %%al,%%al\n\t" - "je 5f\n\t" - "movl %4,%%edi\n\t" - "movl %%edx,%%ecx\n\t" - "repne\n\t" - "scasb\n\t" - "jne 3b\n\t" - "decl %1\n\t" - "cmpb $0,(%1)\n\t" - "je 5f\n\t" - "movb $0,(%1)\n\t" - "incl %1\n\t" - "jmp 6f\n" - "5:\txorl %1,%1\n" - "6:\tcmpb $0,(%0)\n\t" - "jne 7f\n\t" - "xorl %0,%0\n" - "7:\ttestl %0,%0\n\t" - "jne 8f\n\t" - "movl %0,%1\n" - "8:" - :"=b" (__res),"=S" (___strtok) - :"0" (___strtok),"1" (s),"g" (ct) - :"ax","cx","dx","di","memory"); -return __res; -} - -extern inline void * __memcpy(void * to, const void * from, size_t n) -{ -__asm__ __volatile__( - "cld\n\t" - "rep ; movsl\n\t" - "testb $2,%b1\n\t" - "je 1f\n\t" - "movsw\n" - "1:\ttestb $1,%b1\n\t" - "je 2f\n\t" - "movsb\n" - "2:" - : /* no output */ - :"c" (n/4), "q" (n),"D" ((long) to),"S" ((long) from) - : "cx","di","si","memory"); -return (to); -} - -/* - * This looks horribly ugly, but the compiler can optimize it totally, - * as the count is constant. - */ -extern inline void * __constant_memcpy(void * to, const void * from, size_t n) -{ - switch (n) { - case 0: - return to; - case 1: - *(unsigned char *)to = *(const unsigned char *)from; - return to; - case 2: - *(unsigned short *)to = *(const unsigned short *)from; - return to; - case 3: - *(unsigned short *)to = *(const unsigned short *)from; - *(2+(unsigned char *)to) = *(2+(const unsigned char *)from); - return to; - case 4: - *(unsigned long *)to = *(const unsigned long *)from; - return to; - } -#define COMMON(x) \ -__asm__("cld\n\t" \ - "rep ; movsl" \ - x \ - : /* no outputs */ \ - : "c" (n/4),"D" ((long) to),"S" ((long) from) \ - : "cx","di","si","memory"); - - switch (n % 4) { - case 0: COMMON(""); return to; - case 1: COMMON("\n\tmovsb"); return to; - case 2: COMMON("\n\tmovsw"); return to; - case 3: COMMON("\n\tmovsw\n\tmovsb"); return to; - } -#undef COMMON -} - -#define __HAVE_ARCH_MEMCPY -#define memcpy(t, f, n) \ -(__builtin_constant_p(n) ? \ - __constant_memcpy((t),(f),(n)) : \ - __memcpy((t),(f),(n))) - -#define __HAVE_ARCH_MEMMOVE -extern inline void * memmove(void * dest,const void * src, size_t n) -{ -if (dest<src) -__asm__ __volatile__( - "cld\n\t" - "rep\n\t" - "movsb" - : /* no output */ - :"c" (n),"S" (src),"D" (dest) - :"cx","si","di"); -else -__asm__ __volatile__( - "std\n\t" - "rep\n\t" - "movsb\n\t" - "cld" - : /* no output */ - :"c" (n), - "S" (n-1+(const char *)src), - "D" (n-1+(char *)dest) - :"cx","si","di","memory"); -return dest; -} - -#define memcmp __builtin_memcmp - -#define __HAVE_ARCH_MEMCHR -extern inline void * memchr(const void * cs,int c,size_t count) -{ -register void * __res; -if (!count) - return NULL; -__asm__ __volatile__( - "cld\n\t" - "repne\n\t" - "scasb\n\t" - "je 1f\n\t" - "movl $1,%0\n" - "1:\tdecl %0" - :"=D" (__res):"a" (c),"D" (cs),"c" (count) - :"cx"); -return __res; -} - -extern inline void * __memset_generic(void * s, char c,size_t count) -{ -__asm__ __volatile__( - "cld\n\t" - "rep\n\t" - "stosb" - : /* no output */ - :"a" (c),"D" (s),"c" (count) - :"cx","di","memory"); -return s; -} - -/* we might want to write optimized versions of these later */ -#define __constant_count_memset(s,c,count) __memset_generic((s),(c),(count)) - -/* - * memset(x,0,y) is a reasonably common thing to do, so we want to fill - * things 32 bits at a time even when we don't know the size of the - * area at compile-time.. - */ -extern inline void * __constant_c_memset(void * s, unsigned long c, size_t count) -{ -__asm__ __volatile__( - "cld\n\t" - "rep ; stosl\n\t" - "testb $2,%b1\n\t" - "je 1f\n\t" - "stosw\n" - "1:\ttestb $1,%b1\n\t" - "je 2f\n\t" - "stosb\n" - "2:" - : /* no output */ - :"a" (c), "q" (count), "c" (count/4), "D" ((long) s) - :"cx","di","memory"); -return (s); -} - -/* Added by Gertjan van Wingerde to make minix and sysv module work */ -#define __HAVE_ARCH_STRNLEN -extern inline size_t strnlen(const char * s, size_t count) -{ -register int __res; -__asm__ __volatile__( - "movl %1,%0\n\t" - "jmp 2f\n" - "1:\tcmpb $0,(%0)\n\t" - "je 3f\n\t" - "incl %0\n" - "2:\tdecl %2\n\t" - "cmpl $-1,%2\n\t" - "jne 1b\n" - "3:\tsubl %1,%0" - :"=a" (__res):"c" (s),"d" (count)); -return __res; -} -/* end of additional stuff */ - -/* - * This looks horribly ugly, but the compiler can optimize it totally, - * as we by now know that both pattern and count is constant.. - */ -extern inline void * __constant_c_and_count_memset(void * s, unsigned long pattern, size_t count) -{ - switch (count) { - case 0: - return s; - case 1: - *(unsigned char *)s = pattern; - return s; - case 2: - *(unsigned short *)s = pattern; - return s; - case 3: - *(unsigned short *)s = pattern; - *(2+(unsigned char *)s) = pattern; - return s; - case 4: - *(unsigned long *)s = pattern; - return s; - } -#define COMMON(x) \ -__asm__("cld\n\t" \ - "rep ; stosl" \ - x \ - : /* no outputs */ \ - : "a" (pattern),"c" (count/4),"D" ((long) s) \ - : "cx","di","memory") - - switch (count % 4) { - case 0: COMMON(""); return s; - case 1: COMMON("\n\tstosb"); return s; - case 2: COMMON("\n\tstosw"); return s; - case 3: COMMON("\n\tstosw\n\tstosb"); return s; - } -#undef COMMON -} - -#define __constant_c_x_memset(s, c, count) \ -(__builtin_constant_p(count) ? \ - __constant_c_and_count_memset((s),(c),(count)) : \ - __constant_c_memset((s),(c),(count))) - -#define __memset(s, c, count) \ -(__builtin_constant_p(count) ? \ - __constant_count_memset((s),(c),(count)) : \ - __memset_generic((s),(c),(count))) - -#define __HAVE_ARCH_MEMSET -#define memset(s, c, count) \ -(__builtin_constant_p(c) ? \ - __constant_c_x_memset((s),(0x01010101UL*(unsigned char)c),(count)) : \ - __memset((s),(c),(count))) - -/* - * find the first occurrence of byte 'c', or 1 past the area if none - */ -#define __HAVE_ARCH_MEMSCAN -extern inline void * memscan(void * addr, int c, size_t size) -{ - if (!size) - return addr; - __asm__("cld - repnz; scasb - jnz 1f - dec %%edi -1: " - : "=D" (addr), "=c" (size) - : "0" (addr), "1" (size), "a" (c)); - return addr; -} - -#endif diff --git a/i386/i386at/gpl/linux/include/asm/system.h b/i386/i386at/gpl/linux/include/asm/system.h deleted file mode 100644 index 9c6f862a..00000000 --- a/i386/i386at/gpl/linux/include/asm/system.h +++ /dev/null @@ -1,301 +0,0 @@ -#ifndef __ASM_SYSTEM_H -#define __ASM_SYSTEM_H - -#include <asm/segment.h> - -/* - * Entry into gdt where to find first TSS. GDT layout: - * 0 - nul - * 1 - kernel code segment - * 2 - kernel data segment - * 3 - user code segment - * 4 - user data segment - * ... - * 8 - TSS #0 - * 9 - LDT #0 - * 10 - TSS #1 - * 11 - LDT #1 - */ -#define FIRST_TSS_ENTRY 8 -#define FIRST_LDT_ENTRY (FIRST_TSS_ENTRY+1) -#define _TSS(n) ((((unsigned long) n)<<4)+(FIRST_TSS_ENTRY<<3)) -#define _LDT(n) ((((unsigned long) n)<<4)+(FIRST_LDT_ENTRY<<3)) -#define load_TR(n) __asm__("ltr %%ax": /* no output */ :"a" (_TSS(n))) -#define load_ldt(n) __asm__("lldt %%ax": /* no output */ :"a" (_LDT(n))) -#define store_TR(n) \ -__asm__("str %%ax\n\t" \ - "subl %2,%%eax\n\t" \ - "shrl $4,%%eax" \ - :"=a" (n) \ - :"0" (0),"i" (FIRST_TSS_ENTRY<<3)) - -/* This special macro can be used to load a debugging register */ - -#define loaddebug(register) \ - __asm__("movl %0,%%edx\n\t" \ - "movl %%edx,%%db" #register "\n\t" \ - : /* no output */ \ - :"m" (current->debugreg[register]) \ - :"dx"); - - -/* - * switch_to(n) should switch tasks to task nr n, first - * checking that n isn't the current task, in which case it does nothing. - * This also clears the TS-flag if the task we switched to has used - * the math co-processor latest. - * - * It also reloads the debug regs if necessary.. - */ - - -#ifdef __SMP__ - /* - * Keep the lock depth straight. If we switch on an interrupt from - * kernel->user task we need to lose a depth, and if we switch the - * other way we need to gain a depth. Same layer switches come out - * the same. - * - * We spot a switch in user mode because the kernel counter is the - * same as the interrupt counter depth. (We never switch during the - * message/invalidate IPI). - * - * We fsave/fwait so that an exception goes off at the right time - * (as a call from the fsave or fwait in effect) rather than to - * the wrong process. - */ - -#define switch_to(tsk) do { \ - cli();\ - if(current->flags&PF_USEDFPU) \ - { \ - __asm__ __volatile__("fnsave %0":"=m" (current->tss.i387.hard)); \ - __asm__ __volatile__("fwait"); \ - current->flags&=~PF_USEDFPU; \ - } \ - current->lock_depth=syscall_count; \ - kernel_counter+=next->lock_depth-current->lock_depth; \ - syscall_count=next->lock_depth; \ -__asm__("pushl %%edx\n\t" \ - "movl "SYMBOL_NAME_STR(apic_reg)",%%edx\n\t" \ - "movl 0x20(%%edx), %%edx\n\t" \ - "shrl $22,%%edx\n\t" \ - "and $0x3C,%%edx\n\t" \ - "xchgl %%ecx,"SYMBOL_NAME_STR(current_set)"(,%%edx)\n\t" \ - "popl %%edx\n\t" \ - "ljmp %0\n\t" \ - "sti\n\t" \ - : /* no output */ \ - :"m" (*(((char *)&tsk->tss.tr)-4)), \ - "c" (tsk) \ - :"cx"); \ - /* Now maybe reload the debug registers */ \ - if(current->debugreg[7]){ \ - loaddebug(0); \ - loaddebug(1); \ - loaddebug(2); \ - loaddebug(3); \ - loaddebug(6); \ - } \ -} while (0) - -#else -#define switch_to(tsk) do { \ -__asm__("cli\n\t" \ - "xchgl %%ecx,"SYMBOL_NAME_STR(current_set)"\n\t" \ - "ljmp %0\n\t" \ - "sti\n\t" \ - "cmpl %%ecx,"SYMBOL_NAME_STR(last_task_used_math)"\n\t" \ - "jne 1f\n\t" \ - "clts\n" \ - "1:" \ - : /* no output */ \ - :"m" (*(((char *)&tsk->tss.tr)-4)), \ - "c" (tsk) \ - :"cx"); \ - /* Now maybe reload the debug registers */ \ - if(current->debugreg[7]){ \ - loaddebug(0); \ - loaddebug(1); \ - loaddebug(2); \ - loaddebug(3); \ - loaddebug(6); \ - } \ -} while (0) -#endif - -#define _set_base(addr,base) \ -__asm__("movw %%dx,%0\n\t" \ - "rorl $16,%%edx\n\t" \ - "movb %%dl,%1\n\t" \ - "movb %%dh,%2" \ - : /* no output */ \ - :"m" (*((addr)+2)), \ - "m" (*((addr)+4)), \ - "m" (*((addr)+7)), \ - "d" (base) \ - :"dx") - -#define _set_limit(addr,limit) \ -__asm__("movw %%dx,%0\n\t" \ - "rorl $16,%%edx\n\t" \ - "movb %1,%%dh\n\t" \ - "andb $0xf0,%%dh\n\t" \ - "orb %%dh,%%dl\n\t" \ - "movb %%dl,%1" \ - : /* no output */ \ - :"m" (*(addr)), \ - "m" (*((addr)+6)), \ - "d" (limit) \ - :"dx") - -#define set_base(ldt,base) _set_base( ((char *)&(ldt)) , base ) -#define set_limit(ldt,limit) _set_limit( ((char *)&(ldt)) , (limit-1)>>12 ) - -static inline unsigned long _get_base(char * addr) -{ - unsigned long __base; - __asm__("movb %3,%%dh\n\t" - "movb %2,%%dl\n\t" - "shll $16,%%edx\n\t" - "movw %1,%%dx" - :"=&d" (__base) - :"m" (*((addr)+2)), - "m" (*((addr)+4)), - "m" (*((addr)+7))); - return __base; -} - -#define get_base(ldt) _get_base( ((char *)&(ldt)) ) - -static inline unsigned long get_limit(unsigned long segment) -{ - unsigned long __limit; - __asm__("lsll %1,%0" - :"=r" (__limit):"r" (segment)); - return __limit+1; -} - -#define nop() __asm__ __volatile__ ("nop") - -/* - * Clear and set 'TS' bit respectively - */ -#define clts() __asm__ __volatile__ ("clts") -#define stts() \ -__asm__ __volatile__ ( \ - "movl %%cr0,%%eax\n\t" \ - "orl $8,%%eax\n\t" \ - "movl %%eax,%%cr0" \ - : /* no outputs */ \ - : /* no inputs */ \ - :"ax") - - -#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr)))) -#define tas(ptr) (xchg((ptr),1)) - -struct __xchg_dummy { unsigned long a[100]; }; -#define __xg(x) ((volatile struct __xchg_dummy *)(x)) - -static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size) -{ - switch (size) { - case 1: - __asm__("xchgb %b0,%1" - :"=q" (x), "=m" (*__xg(ptr)) - :"0" (x), "m" (*__xg(ptr))); - break; - case 2: - __asm__("xchgw %w0,%1" - :"=r" (x), "=m" (*__xg(ptr)) - :"0" (x), "m" (*__xg(ptr))); - break; - case 4: - __asm__("xchgl %0,%1" - :"=r" (x), "=m" (*__xg(ptr)) - :"0" (x), "m" (*__xg(ptr))); - break; - } - return x; -} - -#define mb() __asm__ __volatile__ ("" : : :"memory") -#define sti() __asm__ __volatile__ ("sti": : :"memory") -#define cli() __asm__ __volatile__ ("cli": : :"memory") - -#define save_flags(x) \ -__asm__ __volatile__("pushfl ; popl %0":"=r" (x): /* no input */ :"memory") - -#define restore_flags(x) \ -__asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"r" (x):"memory") - -#define iret() __asm__ __volatile__ ("iret": : :"memory") - -#define _set_gate(gate_addr,type,dpl,addr) \ -__asm__ __volatile__ ("movw %%dx,%%ax\n\t" \ - "movw %2,%%dx\n\t" \ - "movl %%eax,%0\n\t" \ - "movl %%edx,%1" \ - :"=m" (*((long *) (gate_addr))), \ - "=m" (*(1+(long *) (gate_addr))) \ - :"i" ((short) (0x8000+(dpl<<13)+(type<<8))), \ - "d" ((char *) (addr)),"a" (KERNEL_CS << 16) \ - :"ax","dx") - -#define set_intr_gate(n,addr) \ - _set_gate(&idt[n],14,0,addr) - -#define set_trap_gate(n,addr) \ - _set_gate(&idt[n],15,0,addr) - -#define set_system_gate(n,addr) \ - _set_gate(&idt[n],15,3,addr) - -#define set_call_gate(a,addr) \ - _set_gate(a,12,3,addr) - -#define _set_seg_desc(gate_addr,type,dpl,base,limit) {\ - *((gate_addr)+1) = ((base) & 0xff000000) | \ - (((base) & 0x00ff0000)>>16) | \ - ((limit) & 0xf0000) | \ - ((dpl)<<13) | \ - (0x00408000) | \ - ((type)<<8); \ - *(gate_addr) = (((base) & 0x0000ffff)<<16) | \ - ((limit) & 0x0ffff); } - -#define _set_tssldt_desc(n,addr,limit,type) \ -__asm__ __volatile__ ("movw $" #limit ",%1\n\t" \ - "movw %%ax,%2\n\t" \ - "rorl $16,%%eax\n\t" \ - "movb %%al,%3\n\t" \ - "movb $" type ",%4\n\t" \ - "movb $0x00,%5\n\t" \ - "movb %%ah,%6\n\t" \ - "rorl $16,%%eax" \ - : /* no output */ \ - :"a" (addr+0xc0000000), "m" (*(n)), "m" (*(n+2)), "m" (*(n+4)), \ - "m" (*(n+5)), "m" (*(n+6)), "m" (*(n+7)) \ - ) - -#define set_tss_desc(n,addr) _set_tssldt_desc(((char *) (n)),((int)(addr)),235,"0x89") -#define set_ldt_desc(n,addr,size) \ - _set_tssldt_desc(((char *) (n)),((int)(addr)),((size << 3) - 1),"0x82") - -/* - * This is the ldt that every process will get unless we need - * something other than this. - */ -extern struct desc_struct default_ldt; - -/* - * disable hlt during certain critical i/o operations - */ -#ifndef MACH -#define HAVE_DISABLE_HLT -#endif -void disable_hlt(void); -void enable_hlt(void); - -#endif diff --git a/i386/i386at/gpl/linux/include/asm/termios.h b/i386/i386at/gpl/linux/include/asm/termios.h deleted file mode 100644 index e9cbf14e..00000000 --- a/i386/i386at/gpl/linux/include/asm/termios.h +++ /dev/null @@ -1,304 +0,0 @@ -#ifndef _I386_TERMIOS_H -#define _I386_TERMIOS_H - -/* 0x54 is just a magic number to make these relatively unique ('T') */ - -#define TCGETS 0x5401 -#define TCSETS 0x5402 -#define TCSETSW 0x5403 -#define TCSETSF 0x5404 -#define TCGETA 0x5405 -#define TCSETA 0x5406 -#define TCSETAW 0x5407 -#define TCSETAF 0x5408 -#define TCSBRK 0x5409 -#define TCXONC 0x540A -#define TCFLSH 0x540B -#define TIOCEXCL 0x540C -#define TIOCNXCL 0x540D -#define TIOCSCTTY 0x540E -#define TIOCGPGRP 0x540F -#define TIOCSPGRP 0x5410 -#define TIOCOUTQ 0x5411 -#define TIOCSTI 0x5412 -#define TIOCGWINSZ 0x5413 -#define TIOCSWINSZ 0x5414 -#define TIOCMGET 0x5415 -#define TIOCMBIS 0x5416 -#define TIOCMBIC 0x5417 -#define TIOCMSET 0x5418 -#define TIOCGSOFTCAR 0x5419 -#define TIOCSSOFTCAR 0x541A -#define FIONREAD 0x541B -#define TIOCINQ FIONREAD -#define TIOCLINUX 0x541C -#define TIOCCONS 0x541D -#define TIOCGSERIAL 0x541E -#define TIOCSSERIAL 0x541F -#define TIOCPKT 0x5420 -#define FIONBIO 0x5421 -#define TIOCNOTTY 0x5422 -#define TIOCSETD 0x5423 -#define TIOCGETD 0x5424 -#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */ -#define TIOCTTYGSTRUCT 0x5426 /* For debugging only */ -#define FIONCLEX 0x5450 /* these numbers need to be adjusted. */ -#define FIOCLEX 0x5451 -#define FIOASYNC 0x5452 -#define TIOCSERCONFIG 0x5453 -#define TIOCSERGWILD 0x5454 -#define TIOCSERSWILD 0x5455 -#define TIOCGLCKTRMIOS 0x5456 -#define TIOCSLCKTRMIOS 0x5457 -#define TIOCSERGSTRUCT 0x5458 /* For debugging only */ -#define TIOCSERGETLSR 0x5459 /* Get line status register */ -#define TIOCSERGETMULTI 0x545A /* Get multiport config */ -#define TIOCSERSETMULTI 0x545B /* Set multiport config */ - -#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ -#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ - -/* Used for packet mode */ -#define TIOCPKT_DATA 0 -#define TIOCPKT_FLUSHREAD 1 -#define TIOCPKT_FLUSHWRITE 2 -#define TIOCPKT_STOP 4 -#define TIOCPKT_START 8 -#define TIOCPKT_NOSTOP 16 -#define TIOCPKT_DOSTOP 32 - -struct winsize { - unsigned short ws_row; - unsigned short ws_col; - unsigned short ws_xpixel; - unsigned short ws_ypixel; -}; - -#define NCC 8 -struct termio { - unsigned short c_iflag; /* input mode flags */ - unsigned short c_oflag; /* output mode flags */ - unsigned short c_cflag; /* control mode flags */ - unsigned short c_lflag; /* local mode flags */ - unsigned char c_line; /* line discipline */ - unsigned char c_cc[NCC]; /* control characters */ -}; - -#define NCCS 19 -struct termios { - tcflag_t c_iflag; /* input mode flags */ - tcflag_t c_oflag; /* output mode flags */ - tcflag_t c_cflag; /* control mode flags */ - tcflag_t c_lflag; /* local mode flags */ - cc_t c_line; /* line discipline */ - cc_t c_cc[NCCS]; /* control characters */ -}; - -/* c_cc characters */ -#define VINTR 0 -#define VQUIT 1 -#define VERASE 2 -#define VKILL 3 -#define VEOF 4 -#define VTIME 5 -#define VMIN 6 -#define VSWTC 7 -#define VSTART 8 -#define VSTOP 9 -#define VSUSP 10 -#define VEOL 11 -#define VREPRINT 12 -#define VDISCARD 13 -#define VWERASE 14 -#define VLNEXT 15 -#define VEOL2 16 - -#ifdef __KERNEL__ -/* intr=^C quit=^| erase=del kill=^U - eof=^D vtime=\0 vmin=\1 sxtc=\0 - start=^Q stop=^S susp=^Z eol=\0 - reprint=^R discard=^U werase=^W lnext=^V - eol2=\0 -*/ -#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0" -#endif - -/* c_iflag bits */ -#define IGNBRK 0000001 -#define BRKINT 0000002 -#define IGNPAR 0000004 -#define PARMRK 0000010 -#define INPCK 0000020 -#define ISTRIP 0000040 -#define INLCR 0000100 -#define IGNCR 0000200 -#define ICRNL 0000400 -#define IUCLC 0001000 -#define IXON 0002000 -#define IXANY 0004000 -#define IXOFF 0010000 -#define IMAXBEL 0020000 - -/* c_oflag bits */ -#define OPOST 0000001 -#define OLCUC 0000002 -#define ONLCR 0000004 -#define OCRNL 0000010 -#define ONOCR 0000020 -#define ONLRET 0000040 -#define OFILL 0000100 -#define OFDEL 0000200 -#define NLDLY 0000400 -#define NL0 0000000 -#define NL1 0000400 -#define CRDLY 0003000 -#define CR0 0000000 -#define CR1 0001000 -#define CR2 0002000 -#define CR3 0003000 -#define TABDLY 0014000 -#define TAB0 0000000 -#define TAB1 0004000 -#define TAB2 0010000 -#define TAB3 0014000 -#define XTABS 0014000 -#define BSDLY 0020000 -#define BS0 0000000 -#define BS1 0020000 -#define VTDLY 0040000 -#define VT0 0000000 -#define VT1 0040000 -#define FFDLY 0100000 -#define FF0 0000000 -#define FF1 0100000 - -/* c_cflag bit meaning */ -#define CBAUD 0010017 -#define B0 0000000 /* hang up */ -#define B50 0000001 -#define B75 0000002 -#define B110 0000003 -#define B134 0000004 -#define B150 0000005 -#define B200 0000006 -#define B300 0000007 -#define B600 0000010 -#define B1200 0000011 -#define B1800 0000012 -#define B2400 0000013 -#define B4800 0000014 -#define B9600 0000015 -#define B19200 0000016 -#define B38400 0000017 -#define EXTA B19200 -#define EXTB B38400 -#define CSIZE 0000060 -#define CS5 0000000 -#define CS6 0000020 -#define CS7 0000040 -#define CS8 0000060 -#define CSTOPB 0000100 -#define CREAD 0000200 -#define PARENB 0000400 -#define PARODD 0001000 -#define HUPCL 0002000 -#define CLOCAL 0004000 -#define CBAUDEX 0010000 -#define B57600 0010001 -#define B115200 0010002 -#define B230400 0010003 -#define CIBAUD 002003600000 /* input baud rate (not used) */ -#define CRTSCTS 020000000000 /* flow control */ - -/* c_lflag bits */ -#define ISIG 0000001 -#define ICANON 0000002 -#define XCASE 0000004 -#define ECHO 0000010 -#define ECHOE 0000020 -#define ECHOK 0000040 -#define ECHONL 0000100 -#define NOFLSH 0000200 -#define TOSTOP 0000400 -#define ECHOCTL 0001000 -#define ECHOPRT 0002000 -#define ECHOKE 0004000 -#define FLUSHO 0010000 -#define PENDIN 0040000 -#define IEXTEN 0100000 - -/* modem lines */ -#define TIOCM_LE 0x001 -#define TIOCM_DTR 0x002 -#define TIOCM_RTS 0x004 -#define TIOCM_ST 0x008 -#define TIOCM_SR 0x010 -#define TIOCM_CTS 0x020 -#define TIOCM_CAR 0x040 -#define TIOCM_RNG 0x080 -#define TIOCM_DSR 0x100 -#define TIOCM_CD TIOCM_CAR -#define TIOCM_RI TIOCM_RNG - -/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ -#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ - - -/* tcflow() and TCXONC use these */ -#define TCOOFF 0 -#define TCOON 1 -#define TCIOFF 2 -#define TCION 3 - -/* tcflush() and TCFLSH use these */ -#define TCIFLUSH 0 -#define TCOFLUSH 1 -#define TCIOFLUSH 2 - -/* tcsetattr uses these */ -#define TCSANOW 0 -#define TCSADRAIN 1 -#define TCSAFLUSH 2 - -/* line disciplines */ -#define N_TTY 0 -#define N_SLIP 1 -#define N_MOUSE 2 -#define N_PPP 3 - -#ifdef __KERNEL__ - -#include <linux/string.h> - -/* - * Translate a "termio" structure into a "termios". Ugh. - */ -extern inline void trans_from_termio(struct termio * termio, - struct termios * termios) -{ -#define SET_LOW_BITS(x,y) ((x) = (0xffff0000 & (x)) | (y)) - SET_LOW_BITS(termios->c_iflag, termio->c_iflag); - SET_LOW_BITS(termios->c_oflag, termio->c_oflag); - SET_LOW_BITS(termios->c_cflag, termio->c_cflag); - SET_LOW_BITS(termios->c_lflag, termio->c_lflag); -#undef SET_LOW_BITS - memcpy(termios->c_cc, termio->c_cc, NCC); -} - -/* - * Translate a "termios" structure into a "termio". Ugh. - */ -extern inline void trans_to_termio(struct termios * termios, - struct termio * termio) -{ - termio->c_iflag = termios->c_iflag; - termio->c_oflag = termios->c_oflag; - termio->c_cflag = termios->c_cflag; - termio->c_lflag = termios->c_lflag; - termio->c_line = termios->c_line; - memcpy(termio->c_cc, termios->c_cc, NCC); -} - -#endif /* __KERNEL__ */ - -#endif /* _I386_TERMIOS_H */ diff --git a/i386/i386at/gpl/linux/include/asm/types.h b/i386/i386at/gpl/linux/include/asm/types.h deleted file mode 100644 index 1b82bef4..00000000 --- a/i386/i386at/gpl/linux/include/asm/types.h +++ /dev/null @@ -1,109 +0,0 @@ -#ifndef _I386_TYPES_H -#define _I386_TYPES_H - -#ifndef MACH_INCLUDE -#ifndef _SIZE_T -#define _SIZE_T -typedef unsigned int size_t; -#endif - -#ifndef _SSIZE_T -#define _SSIZE_T -typedef int ssize_t; -#endif - -#ifndef _PTRDIFF_T -#define _PTRDIFF_T -typedef int ptrdiff_t; -#endif - -#ifndef _TIME_T -#define _TIME_T -typedef long time_t; -#endif - -#ifndef _CLOCK_T -#define _CLOCK_T -typedef long clock_t; -#endif -#endif /* ! MACH_INCLUDE */ - -typedef int pid_t; -#ifndef MACH_INCLUDE -typedef unsigned short uid_t; -typedef unsigned short gid_t; -typedef unsigned short dev_t; -typedef unsigned long ino_t; -typedef unsigned short mode_t; -#endif -typedef unsigned short umode_t; -#ifndef MACH_INCLUDE -typedef unsigned short nlink_t; -typedef int daddr_t; -typedef long off_t; -#endif - -/* - * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the - * header files exported to user space - */ - -typedef __signed__ char __s8; -typedef unsigned char __u8; - -typedef __signed__ short __s16; -typedef unsigned short __u16; - -typedef __signed__ int __s32; -typedef unsigned int __u32; - -#if defined(__GNUC__) && !defined(__STRICT_ANSI__) -typedef __signed__ long long __s64; -typedef unsigned long long __u64; -#endif - -/* - * These aren't exported outside the kernel to avoid name space clashes - */ -#ifdef __KERNEL__ - -typedef signed char s8; -typedef unsigned char u8; - -typedef signed short s16; -typedef unsigned short u16; - -typedef signed int s32; -typedef unsigned int u32; - -typedef signed long long s64; -typedef unsigned long long u64; - -#endif /* __KERNEL__ */ - -#undef __FD_SET -#define __FD_SET(fd,fdsetp) \ - __asm__ __volatile__("btsl %1,%0": \ - "=m" (*(fd_set *) (fdsetp)):"r" ((int) (fd))) - -#undef __FD_CLR -#define __FD_CLR(fd,fdsetp) \ - __asm__ __volatile__("btrl %1,%0": \ - "=m" (*(fd_set *) (fdsetp)):"r" ((int) (fd))) - -#undef __FD_ISSET -#define __FD_ISSET(fd,fdsetp) (__extension__ ({ \ - unsigned char __result; \ - __asm__ __volatile__("btl %1,%2 ; setb %0" \ - :"=q" (__result) :"r" ((int) (fd)), \ - "m" (*(fd_set *) (fdsetp))); \ - __result; })) - -#undef __FD_ZERO -#define __FD_ZERO(fdsetp) \ - __asm__ __volatile__("cld ; rep ; stosl" \ - :"=m" (*(fd_set *) (fdsetp)) \ - :"a" (0), "c" (__FDSET_INTS), \ - "D" ((fd_set *) (fdsetp)) :"cx","di") - -#endif diff --git a/i386/i386at/gpl/linux/include/asm/unistd.h b/i386/i386at/gpl/linux/include/asm/unistd.h deleted file mode 100644 index 1837f210..00000000 --- a/i386/i386at/gpl/linux/include/asm/unistd.h +++ /dev/null @@ -1,322 +0,0 @@ -#ifndef _ASM_I386_UNISTD_H_ -#define _ASM_I386_UNISTD_H_ - -/* - * This file contains the system call numbers. - */ - -#define __NR_setup 0 /* used only by init, to get system going */ -#define __NR_exit 1 -#define __NR_fork 2 -#define __NR_read 3 -#define __NR_write 4 -#define __NR_open 5 -#define __NR_close 6 -#define __NR_waitpid 7 -#define __NR_creat 8 -#define __NR_link 9 -#define __NR_unlink 10 -#define __NR_execve 11 -#define __NR_chdir 12 -#define __NR_time 13 -#define __NR_mknod 14 -#define __NR_chmod 15 -#define __NR_chown 16 -#define __NR_break 17 -#define __NR_oldstat 18 -#define __NR_lseek 19 -#define __NR_getpid 20 -#define __NR_mount 21 -#define __NR_umount 22 -#define __NR_setuid 23 -#define __NR_getuid 24 -#define __NR_stime 25 -#define __NR_ptrace 26 -#define __NR_alarm 27 -#define __NR_oldfstat 28 -#define __NR_pause 29 -#define __NR_utime 30 -#define __NR_stty 31 -#define __NR_gtty 32 -#define __NR_access 33 -#define __NR_nice 34 -#define __NR_ftime 35 -#define __NR_sync 36 -#define __NR_kill 37 -#define __NR_rename 38 -#define __NR_mkdir 39 -#define __NR_rmdir 40 -#define __NR_dup 41 -#define __NR_pipe 42 -#define __NR_times 43 -#define __NR_prof 44 -#define __NR_brk 45 -#define __NR_setgid 46 -#define __NR_getgid 47 -#define __NR_signal 48 -#define __NR_geteuid 49 -#define __NR_getegid 50 -#define __NR_acct 51 -#define __NR_phys 52 -#define __NR_lock 53 -#define __NR_ioctl 54 -#define __NR_fcntl 55 -#define __NR_mpx 56 -#define __NR_setpgid 57 -#define __NR_ulimit 58 -#define __NR_oldolduname 59 -#define __NR_umask 60 -#define __NR_chroot 61 -#define __NR_ustat 62 -#define __NR_dup2 63 -#define __NR_getppid 64 -#define __NR_getpgrp 65 -#define __NR_setsid 66 -#define __NR_sigaction 67 -#define __NR_sgetmask 68 -#define __NR_ssetmask 69 -#define __NR_setreuid 70 -#define __NR_setregid 71 -#define __NR_sigsuspend 72 -#define __NR_sigpending 73 -#define __NR_sethostname 74 -#define __NR_setrlimit 75 -#define __NR_getrlimit 76 -#define __NR_getrusage 77 -#define __NR_gettimeofday 78 -#define __NR_settimeofday 79 -#define __NR_getgroups 80 -#define __NR_setgroups 81 -#define __NR_select 82 -#define __NR_symlink 83 -#define __NR_oldlstat 84 -#define __NR_readlink 85 -#define __NR_uselib 86 -#define __NR_swapon 87 -#define __NR_reboot 88 -#define __NR_readdir 89 -#define __NR_mmap 90 -#define __NR_munmap 91 -#define __NR_truncate 92 -#define __NR_ftruncate 93 -#define __NR_fchmod 94 -#define __NR_fchown 95 -#define __NR_getpriority 96 -#define __NR_setpriority 97 -#define __NR_profil 98 -#define __NR_statfs 99 -#define __NR_fstatfs 100 -#define __NR_ioperm 101 -#define __NR_socketcall 102 -#define __NR_syslog 103 -#define __NR_setitimer 104 -#define __NR_getitimer 105 -#define __NR_stat 106 -#define __NR_lstat 107 -#define __NR_fstat 108 -#define __NR_olduname 109 -#define __NR_iopl 110 -#define __NR_vhangup 111 -#define __NR_idle 112 -#define __NR_vm86 113 -#define __NR_wait4 114 -#define __NR_swapoff 115 -#define __NR_sysinfo 116 -#define __NR_ipc 117 -#define __NR_fsync 118 -#define __NR_sigreturn 119 -#define __NR_clone 120 -#define __NR_setdomainname 121 -#define __NR_uname 122 -#define __NR_modify_ldt 123 -#define __NR_adjtimex 124 -#define __NR_mprotect 125 -#define __NR_sigprocmask 126 -#define __NR_create_module 127 -#define __NR_init_module 128 -#define __NR_delete_module 129 -#define __NR_get_kernel_syms 130 -#define __NR_quotactl 131 -#define __NR_getpgid 132 -#define __NR_fchdir 133 -#define __NR_bdflush 134 -#define __NR_sysfs 135 -#define __NR_personality 136 -#define __NR_afs_syscall 137 /* Syscall for Andrew File System */ -#define __NR_setfsuid 138 -#define __NR_setfsgid 139 -#define __NR__llseek 140 -#define __NR_getdents 141 -#define __NR__newselect 142 -#define __NR_flock 143 -#define __NR_msync 144 -#define __NR_readv 145 -#define __NR_writev 146 -#define __NR_getsid 147 -#define __NR_fdatasync 148 -#define __NR__sysctl 149 -#define __NR_mlock 150 -#define __NR_munlock 151 -#define __NR_mlockall 152 -#define __NR_munlockall 153 -#define __NR_sched_setparam 154 -#define __NR_sched_getparam 155 -#define __NR_sched_setscheduler 156 -#define __NR_sched_getscheduler 157 -#define __NR_sched_yield 158 -#define __NR_sched_get_priority_max 159 -#define __NR_sched_get_priority_min 160 -#define __NR_sched_rr_get_interval 161 -#define __NR_nanosleep 162 - -/* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */ -#define _syscall0(type,name) \ -type name(void) \ -{ \ -long __res; \ -__asm__ volatile ("int $0x80" \ - : "=a" (__res) \ - : "0" (__NR_##name)); \ -if (__res >= 0) \ - return (type) __res; \ -errno = -__res; \ -return -1; \ -} - -#define _syscall1(type,name,type1,arg1) \ -type name(type1 arg1) \ -{ \ -long __res; \ -__asm__ volatile ("int $0x80" \ - : "=a" (__res) \ - : "0" (__NR_##name),"b" ((long)(arg1))); \ -if (__res >= 0) \ - return (type) __res; \ -errno = -__res; \ -return -1; \ -} - -#define _syscall2(type,name,type1,arg1,type2,arg2) \ -type name(type1 arg1,type2 arg2) \ -{ \ -long __res; \ -__asm__ volatile ("int $0x80" \ - : "=a" (__res) \ - : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2))); \ -if (__res >= 0) \ - return (type) __res; \ -errno = -__res; \ -return -1; \ -} - -#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ -type name(type1 arg1,type2 arg2,type3 arg3) \ -{ \ -long __res; \ -__asm__ volatile ("int $0x80" \ - : "=a" (__res) \ - : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \ - "d" ((long)(arg3))); \ -if (__res>=0) \ - return (type) __res; \ -errno=-__res; \ -return -1; \ -} - -#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ -type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ -{ \ -long __res; \ -__asm__ volatile ("int $0x80" \ - : "=a" (__res) \ - : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \ - "d" ((long)(arg3)),"S" ((long)(arg4))); \ -if (__res>=0) \ - return (type) __res; \ -errno=-__res; \ -return -1; \ -} - -#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ - type5,arg5) \ -type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \ -{ \ -long __res; \ -__asm__ volatile ("int $0x80" \ - : "=a" (__res) \ - : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \ - "d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5))); \ -if (__res>=0) \ - return (type) __res; \ -errno=-__res; \ -return -1; \ -} - -#ifdef __KERNEL_SYSCALLS__ - -/* - * we need this inline - forking from kernel space will result - * in NO COPY ON WRITE (!!!), until an execve is executed. This - * is no problem, but for the stack. This is handled by not letting - * main() use the stack at all after fork(). Thus, no function - * calls - which means inline code for fork too, as otherwise we - * would use the stack upon exit from 'fork()'. - * - * Actually only pause and fork are needed inline, so that there - * won't be any messing with the stack from main(), but we define - * some others too. - */ -#define __NR__exit __NR_exit -static inline _syscall0(int,idle) -static inline _syscall0(int,fork) -static inline _syscall2(int,clone,unsigned long,flags,char *,esp) -static inline _syscall0(int,pause) -static inline _syscall0(int,setup) -static inline _syscall0(int,sync) -static inline _syscall0(pid_t,setsid) -static inline _syscall3(int,write,int,fd,const char *,buf,off_t,count) -static inline _syscall1(int,dup,int,fd) -static inline _syscall3(int,execve,const char *,file,char **,argv,char **,envp) -static inline _syscall3(int,open,const char *,file,int,flag,int,mode) -static inline _syscall1(int,close,int,fd) -static inline _syscall1(int,_exit,int,exitcode) -static inline _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options) - -static inline pid_t wait(int * wait_stat) -{ - return waitpid(-1,wait_stat,0); -} - -/* - * This is the mechanism for creating a new kernel thread. - * - * NOTE! Only a kernel-only process(ie the swapper or direct descendants - * who haven't done an "execve()") should use this: it will work within - * a system call from a "real" process, but the process memory space will - * not be free'd until both the parent and the child have exited. - */ -static inline pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) -{ - long retval; - - __asm__ __volatile__( - "movl %%esp,%%esi\n\t" - "int $0x80\n\t" /* Linux/i386 system call */ - "cmpl %%esp,%%esi\n\t" /* child or parent? */ - "je 1f\n\t" /* parent - jump */ - "pushl %3\n\t" /* push argument */ - "call *%4\n\t" /* call fn */ - "movl %2,%0\n\t" /* exit */ - "int $0x80\n" - "1:\t" - :"=a" (retval) - :"0" (__NR_clone), "i" (__NR_exit), - "r" (arg), "r" (fn), - "b" (flags | CLONE_VM) - :"si"); - return retval; -} - -#endif - -#endif /* _ASM_I386_UNISTD_H_ */ diff --git a/i386/i386at/gpl/linux/include/linux/autoconf.h b/i386/i386at/gpl/linux/include/linux/autoconf.h deleted file mode 100644 index 0d565aed..00000000 --- a/i386/i386at/gpl/linux/include/linux/autoconf.h +++ /dev/null @@ -1,221 +0,0 @@ -/* - * Loadable module support - */ -#undef CONFIG_MODULES -#undef CONFIG_MODVERSIONS -#undef CONFIG_KERNELD - -/* - * General setup - */ -#undef CONFIG_MATH_EMULATION -#undef CONFIG_NET -#undef CONFIG_MAX_16M -#define CONFIG_PCI -#define CONFIG_SYSVIPC 1 -#define CONFIG_BINFMT_AOUT 1 -#define CONFIG_BINFMT_ELF 1 -#undef CONFIG_KERNEL_ELF -#undef CONFIG_M386 -#define CONFIG_M486 1 -#undef CONFIG_M586 -#undef CONFIG_M686 - -/* Fetch GNUmach driver config file */ -#include <i386/device-drivers.h> - -#if 0 /* these are now in device-drivers.h */ -/* - * Floppy, IDE, and other block devices - */ -#define CONFIG_BLK_DEV_FD 1 -#define CONFIG_BLK_DEV_IDE 1 -#endif - -/* - * Please see drivers/block/README.ide for help/info on IDE drives - */ -#define CONFIG_BLK_DEV_HD_IDE 1 -#define CONFIG_BLK_DEV_IDEATAPI 1 -#define CONFIG_BLK_DEV_IDECD 1 -#undef CONFIG_BLK_DEV_IDETAPE -#define CONFIG_BLK_DEV_CMD640 1 -#define CONFIG_BLK_DEV_RZ1000 1 -#define CONFIG_BLK_DEV_TRITON 1 -#define CONFIG_IDE_CHIPSETS 1 -#undef CONFIG_BLK_DEV_RAM -#undef CONFIG_BLK_DEV_LOOP -#undef CONFIG_BLK_DEV_XD - -#if 0 /* now in device-drivers.h */ -/* - * Networking options - */ -#undef CONFIG_FIREWALL -#undef CONFIG_NET_ALIAS -#define CONFIG_INET 1 -#undef CONFIG_IP_FORWARD -#undef CONFIG_IP_MULTICAST -#undef CONFIG_IP_ACCT -#endif - -/* - * (it is safe to leave these untouched) - */ -#undef CONFIG_INET_PCTCP -#undef CONFIG_INET_RARP -#undef CONFIG_NO_PATH_MTU_DISCOVERY -#undef CONFIG_TCP_NAGLE_OFF -#define CONFIG_IP_NOSR 1 -#define CONFIG_SKB_LARGE 1 - -/* - * - */ -#undef CONFIG_IPX -#undef CONFIG_ATALK -#undef CONFIG_AX25 -#undef CONFIG_NETLINK - -#if 0 -/* - * SCSI support - */ -#define CONFIG_SCSI 1 -#endif - -/* - * SCSI support type (disk, tape, CDrom) - */ -#define CONFIG_BLK_DEV_SD 1 -#undef CONFIG_CHR_DEV_ST -#define CONFIG_BLK_DEV_SR 1 -#undef CONFIG_CHR_DEV_SG - -#if 0 /* now in device-drivers.h */ -/* - * Some SCSI devices (e.g. CD jukebox) support multiple LUNs - */ -#undef CONFIG_SCSI_MULTI_LUN -#undef CONFIG_SCSI_CONSTANTS - -/* - * SCSI low-level drivers - */ -#undef CONFIG_SCSI_ADVANSYS -#define CONFIG_SCSI_AHA152X 1 -#define CONFIG_SCSI_AHA1542 1 -#define CONFIG_SCSI_AHA1740 1 -#define CONFIG_SCSI_AIC7XXX 1 -#undef CONFIG_SCSI_BUSLOGIC -#undef CONFIG_SCSI_EATA_DMA -#undef CONFIG_SCSI_EATA_PIO -#define CONFIG_SCSI_U14_34F 1 -#undef CONFIG_SCSI_FUTURE_DOMAIN -#undef CONFIG_SCSI_GENERIC_NCR5380 -#undef CONFIG_SCSI_IN2000 -#undef CONFIG_SCSI_PAS16 -#undef CONFIG_SCSI_QLOGIC -#define CONFIG_SCSI_SEAGATE 1 -#undef CONFIG_SCSI_T128 -#undef CONFIG_SCSI_ULTRASTOR -#undef CONFIG_SCSI_7000FASST -#undef CONFIG_SCSI_EATA -#undef CONFIG_SCSI_NCR53C406A -#undef CONFIG_SCSI_AM53C974 -#define CONFIG_SCSI_NCR53C7xx 1 -#endif - -/* - * Network device support - */ -#undef CONFIG_NETDEVICES -#undef CONFIG_DUMMY -#undef CONFIG_SLIP -#undef CONFIG_SLIP_COMPRESSED -#undef CONFIG_SLIP_SMART -#undef CONFIG_PPP - -#if 0 -/* - * CCP compressors for PPP are only built as modules. - */ -#undef CONFIG_SCC -#undef CONFIG_PLIP -#undef CONFIG_EQUALIZER -#undef CONFIG_NET_ALPHA -#define CONFIG_NET_VENDOR_SMC 1 -#undef CONFIG_LANCE -#undef CONFIG_NET_VENDOR_3COM -#undef CONFIG_EL1 -#undef CONFIG_EL2 -#define CONFIG_EL3 1 -#undef CONFIG_VORTEX -#define CONFIG_NET_ISA 1 -#undef CONFIG_E2100 -#undef CONFIG_DEPCA -#undef CONFIG_EWRK3 -#define CONFIG_HPLAN_PLUS 1 -#undef CONFIG_HPLAN -#undef CONFIG_HP100 -#define CONFIG_NE2000 1 -#undef CONFIG_SK_G16 -#undef CONFIG_NET_EISA -#undef CONFIG_NET_POCKET -#undef CONFIG_TR -#undef CONFIG_ARCNET -#define CONFIG_DE4X5 1 -#define CONFIG_ULTRA 1 -#define CONFIG_WD80x3 1 - -/* - * CD-ROM drivers (not for SCSI or IDE/ATAPI drives) - */ -#undef CONFIG_CD_NO_IDESCSI -#endif - -/* - * Filesystems - */ -#undef CONFIG_QUOTA -#define CONFIG_MINIX_FS 1 -#undef CONFIG_EXT_FS -#define CONFIG_EXT2_FS 1 -#undef CONFIG_XIA_FS -#define CONFIG_FAT_FS 1 -#define CONFIG_MSDOS_FS 1 -#undef CONFIG_VFAT_FS -#undef CONFIG_UMSDOS_FS -#define CONFIG_PROC_FS 1 -#define CONFIG_NFS_FS 1 -#undef CONFIG_ROOT_NFS -#undef CONFIG_SMB_FS -#define CONFIG_ISO9660_FS 1 -#undef CONFIG_HPFS_FS -#undef CONFIG_SYSV_FS - -#if 0 -/* - * Character devices - */ -#undef CONFIG_CYCLADES -#undef CONFIG_STALDRV -#define CONFIG_PRINTER 1 -#undef CONFIG_BUSMOUSE -#undef CONFIG_PSMOUSE -#undef CONFIG_MS_BUSMOUSE -#undef CONFIG_ATIXL_BUSMOUSE -#undef CONFIG_QIC02_TAPE -#undef CONFIG_APM -#undef CONFIG_WATCHDOG - -/* - * Sound - */ -#undef CONFIG_SOUND - -/* - * Kernel hacking - */ -#undef CONFIG_PROFILE -#endif diff --git a/i386/i386at/gpl/linux/include/linux/binfmts.h b/i386/i386at/gpl/linux/include/linux/binfmts.h deleted file mode 100644 index 0d1c403a..00000000 --- a/i386/i386at/gpl/linux/include/linux/binfmts.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef _LINUX_BINFMTS_H -#define _LINUX_BINFMTS_H - -#include <linux/ptrace.h> - -/* - * MAX_ARG_PAGES defines the number of pages allocated for arguments - * and envelope for the new program. 32 should suffice, this gives - * a maximum env+arg of 128kB w/4KB pages! - */ -#define MAX_ARG_PAGES 32 - -/* - * This structure is used to hold the arguments that are used when loading binaries. - */ -struct linux_binprm{ - char buf[128]; - unsigned long page[MAX_ARG_PAGES]; - unsigned long p; - int sh_bang; - struct inode * inode; - int e_uid, e_gid; - int argc, envc; - char * filename; /* Name of binary */ - unsigned long loader, exec; -}; - -/* - * This structure defines the functions that are used to load the binary formats that - * linux accepts. - */ -struct linux_binfmt { - struct linux_binfmt * next; - int *use_count; - int (*load_binary)(struct linux_binprm *, struct pt_regs * regs); - int (*load_shlib)(int fd); - int (*core_dump)(long signr, struct pt_regs * regs); -}; - -extern int register_binfmt(struct linux_binfmt *); -extern int unregister_binfmt(struct linux_binfmt *); - -extern int read_exec(struct inode *inode, unsigned long offset, - char * addr, unsigned long count, int to_kmem); - -extern int open_inode(struct inode * inode, int mode); - -extern int init_elf_binfmt(void); -extern int init_aout_binfmt(void); - -extern void flush_old_exec(struct linux_binprm * bprm); -extern unsigned long setup_arg_pages(unsigned long text_size,unsigned long * page); -extern unsigned long * create_tables(char * p,struct linux_binprm * bprm,int ibcs); -extern unsigned long copy_strings(int argc,char ** argv,unsigned long *page, - unsigned long p, int from_kmem); - -/* this eventually goes away */ -#define change_ldt(a,b) setup_arg_pages(a,b) - -#endif diff --git a/i386/i386at/gpl/linux/include/linux/bios32.h b/i386/i386at/gpl/linux/include/linux/bios32.h deleted file mode 100644 index f57398e5..00000000 --- a/i386/i386at/gpl/linux/include/linux/bios32.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * BIOS32, PCI BIOS functions and defines - * Copyright 1994, Drew Eckhardt - * - * For more information, please consult - * - * PCI BIOS Specification Revision - * PCI Local Bus Specification - * PCI System Design Guide - * - * PCI Special Interest Group - * M/S HF3-15A - * 5200 N.E. Elam Young Parkway - * Hillsboro, Oregon 97124-6497 - * +1 (503) 696-2000 - * +1 (800) 433-5177 - * - * Manuals are $25 each or $50 for all three, plus $7 shipping - * within the United States, $35 abroad. - */ - -#ifndef BIOS32_H -#define BIOS32_H - -/* - * Error values that may be returned by the PCI bios. Use - * pcibios_strerror() to convert to a printable string. - */ -#define PCIBIOS_SUCCESSFUL 0x00 -#define PCIBIOS_FUNC_NOT_SUPPORTED 0x81 -#define PCIBIOS_BAD_VENDOR_ID 0x83 -#define PCIBIOS_DEVICE_NOT_FOUND 0x86 -#define PCIBIOS_BAD_REGISTER_NUMBER 0x87 -#define PCIBIOS_SET_FAILED 0x88 -#define PCIBIOS_BUFFER_TOO_SMALL 0x89 - -extern int pcibios_present (void); -extern unsigned long pcibios_init (unsigned long memory_start, - unsigned long memory_end); -extern unsigned long pcibios_fixup (unsigned long memory_start, - unsigned long memory_end); -extern int pcibios_find_class (unsigned int class_code, unsigned short index, - unsigned char *bus, unsigned char *dev_fn); -extern int pcibios_find_device (unsigned short vendor, unsigned short dev_id, - unsigned short index, unsigned char *bus, - unsigned char *dev_fn); -extern int pcibios_read_config_byte (unsigned char bus, unsigned char dev_fn, - unsigned char where, unsigned char *val); -extern int pcibios_read_config_word (unsigned char bus, unsigned char dev_fn, - unsigned char where, unsigned short *val); -extern int pcibios_read_config_dword (unsigned char bus, unsigned char dev_fn, - unsigned char where, unsigned int *val); -extern int pcibios_write_config_byte (unsigned char bus, unsigned char dev_fn, - unsigned char where, unsigned char val); -extern int pcibios_write_config_word (unsigned char bus, unsigned char dev_fn, - unsigned char where, unsigned short val); -extern pcibios_write_config_dword (unsigned char bus, unsigned char dev_fn, - unsigned char where, unsigned int val); -extern const char *pcibios_strerror (int error); - -#endif /* BIOS32_H */ diff --git a/i386/i386at/gpl/linux/include/linux/blk.h b/i386/i386at/gpl/linux/include/linux/blk.h deleted file mode 100644 index cf236a61..00000000 --- a/i386/i386at/gpl/linux/include/linux/blk.h +++ /dev/null @@ -1,408 +0,0 @@ -#ifndef _BLK_H -#define _BLK_H - -#include <linux/blkdev.h> -#include <linux/locks.h> -#include <linux/config.h> - -/* - * This is used in the elevator algorithm. We don't prioritise reads - * over writes any more --- although reads are more time-critical than - * writes, by treating them equally we increase filesystem throughput. - * This turns out to give better overall performance. -- sct - */ -#define IN_ORDER(s1,s2) \ -((s1)->rq_dev < (s2)->rq_dev || (((s1)->rq_dev == (s2)->rq_dev && \ -(s1)->sector < (s2)->sector))) - -/* - * These will have to be changed to be aware of different buffer - * sizes etc.. It actually needs a major cleanup. - */ -#ifdef IDE_DRIVER -#define SECTOR_MASK ((BLOCK_SIZE >> 9) - 1) -#else -#define SECTOR_MASK (blksize_size[MAJOR_NR] && \ - blksize_size[MAJOR_NR][MINOR(CURRENT->rq_dev)] ? \ - ((blksize_size[MAJOR_NR][MINOR(CURRENT->rq_dev)] >> 9) - 1) : \ - ((BLOCK_SIZE >> 9) - 1)) -#endif /* IDE_DRIVER */ - -#define SUBSECTOR(block) (CURRENT->current_nr_sectors > 0) - -#ifdef CONFIG_CDU31A -extern int cdu31a_init(void); -#endif CONFIG_CDU31A -#ifdef CONFIG_MCD -extern int mcd_init(void); -#endif CONFIG_MCD -#ifdef CONFIG_MCDX -extern int mcdx_init(void); -#endif CONFIG_MCDX -#ifdef CONFIG_SBPCD -extern int sbpcd_init(void); -#endif CONFIG_SBPCD -#ifdef CONFIG_AZTCD -extern int aztcd_init(void); -#endif CONFIG_AZTCD -#ifdef CONFIG_CDU535 -extern int sony535_init(void); -#endif CONFIG_CDU535 -#ifdef CONFIG_GSCD -extern int gscd_init(void); -#endif CONFIG_GSCD -#ifdef CONFIG_CM206 -extern int cm206_init(void); -#endif CONFIG_CM206 -#ifdef CONFIG_OPTCD -extern int optcd_init(void); -#endif CONFIG_OPTCD -#ifdef CONFIG_SJCD -extern int sjcd_init(void); -#endif CONFIG_SJCD -#ifdef CONFIG_CDI_INIT -extern int cdi_init(void); -#endif CONFIG_CDI_INIT -#ifdef CONFIG_BLK_DEV_HD -extern int hd_init(void); -#endif -#ifdef CONFIG_BLK_DEV_IDE -extern int ide_init(void); -#endif -#ifdef CONFIG_BLK_DEV_XD -extern int xd_init(void); -#endif - -extern void set_device_ro(kdev_t dev,int flag); -void add_blkdev_randomness(int major); - -extern int floppy_init(void); -extern void rd_load(void); -extern int rd_init(void); -extern int rd_doload; /* 1 = load ramdisk, 0 = don't load */ -extern int rd_prompt; /* 1 = prompt for ramdisk, 0 = don't prompt */ -extern int rd_image_start; /* starting block # of image */ - -#define RO_IOCTLS(dev,where) \ - case BLKROSET: if (!suser()) return -EACCES; \ - set_device_ro((dev),get_fs_long((long *) (where))); return 0; \ - case BLKROGET: { int __err = verify_area(VERIFY_WRITE, (void *) (where), sizeof(long)); \ - if (!__err) put_fs_long(0!=is_read_only(dev),(long *) (where)); return __err; } - -#if defined(MAJOR_NR) || defined(IDE_DRIVER) - -/* - * Add entries as needed. - */ - -#ifdef IDE_DRIVER - -#define DEVICE_NR(device) (MINOR(device) >> PARTN_BITS) -#define DEVICE_ON(device) /* nothing */ -#define DEVICE_OFF(device) /* nothing */ - -#elif (MAJOR_NR == RAMDISK_MAJOR) - -/* ram disk */ -#define DEVICE_NAME "ramdisk" -#define DEVICE_REQUEST rd_request -#define DEVICE_NR(device) (MINOR(device)) -#define DEVICE_ON(device) -#define DEVICE_OFF(device) -#define DEVICE_NO_RANDOM - -#elif (MAJOR_NR == FLOPPY_MAJOR) - -static void floppy_off(unsigned int nr); - -#define DEVICE_NAME "floppy" -#define DEVICE_INTR do_floppy -#define DEVICE_REQUEST do_fd_request -#define DEVICE_NR(device) ( (MINOR(device) & 3) | ((MINOR(device) & 0x80 ) >> 5 )) -#define DEVICE_ON(device) -#define DEVICE_OFF(device) floppy_off(DEVICE_NR(device)) - -#elif (MAJOR_NR == HD_MAJOR) - -/* harddisk: timeout is 6 seconds.. */ -#define DEVICE_NAME "harddisk" -#define DEVICE_INTR do_hd -#define DEVICE_TIMEOUT HD_TIMER -#define TIMEOUT_VALUE (6*HZ) -#define DEVICE_REQUEST do_hd_request -#define DEVICE_NR(device) (MINOR(device)>>6) -#define DEVICE_ON(device) -#define DEVICE_OFF(device) - -#elif (MAJOR_NR == SCSI_DISK_MAJOR) - -#define DEVICE_NAME "scsidisk" -#define DEVICE_INTR do_sd -#define TIMEOUT_VALUE (2*HZ) -#define DEVICE_REQUEST do_sd_request -#define DEVICE_NR(device) (MINOR(device) >> 4) -#define DEVICE_ON(device) -#define DEVICE_OFF(device) - -#elif (MAJOR_NR == SCSI_TAPE_MAJOR) - -#define DEVICE_NAME "scsitape" -#define DEVICE_INTR do_st -#define DEVICE_NR(device) (MINOR(device) & 0x7f) -#define DEVICE_ON(device) -#define DEVICE_OFF(device) - -#elif (MAJOR_NR == SCSI_CDROM_MAJOR) - -#define DEVICE_NAME "CD-ROM" -#define DEVICE_INTR do_sr -#define DEVICE_REQUEST do_sr_request -#define DEVICE_NR(device) (MINOR(device)) -#define DEVICE_ON(device) -#define DEVICE_OFF(device) - -#elif (MAJOR_NR == XT_DISK_MAJOR) - -#define DEVICE_NAME "xt disk" -#define DEVICE_REQUEST do_xd_request -#define DEVICE_NR(device) (MINOR(device) >> 6) -#define DEVICE_ON(device) -#define DEVICE_OFF(device) - -#elif (MAJOR_NR == CDU31A_CDROM_MAJOR) - -#define DEVICE_NAME "CDU31A" -#define DEVICE_REQUEST do_cdu31a_request -#define DEVICE_NR(device) (MINOR(device)) -#define DEVICE_ON(device) -#define DEVICE_OFF(device) - -#elif (MAJOR_NR == MITSUMI_CDROM_MAJOR) - -#define DEVICE_NAME "Mitsumi CD-ROM" -/* #define DEVICE_INTR do_mcd */ -#define DEVICE_REQUEST do_mcd_request -#define DEVICE_NR(device) (MINOR(device)) -#define DEVICE_ON(device) -#define DEVICE_OFF(device) - -#elif (MAJOR_NR == MITSUMI_X_CDROM_MAJOR) - -#define DEVICE_NAME "Mitsumi CD-ROM" -/* #define DEVICE_INTR do_mcdx */ -#define DEVICE_REQUEST do_mcdx_request -#define DEVICE_NR(device) (MINOR(device)) -#define DEVICE_ON(device) -#define DEVICE_OFF(device) - -#elif (MAJOR_NR == MATSUSHITA_CDROM_MAJOR) - -#define DEVICE_NAME "Matsushita CD-ROM controller #1" -#define DEVICE_REQUEST do_sbpcd_request -#define DEVICE_NR(device) (MINOR(device)) -#define DEVICE_ON(device) -#define DEVICE_OFF(device) - -#elif (MAJOR_NR == MATSUSHITA_CDROM2_MAJOR) - -#define DEVICE_NAME "Matsushita CD-ROM controller #2" -#define DEVICE_REQUEST do_sbpcd2_request -#define DEVICE_NR(device) (MINOR(device)) -#define DEVICE_ON(device) -#define DEVICE_OFF(device) - -#elif (MAJOR_NR == MATSUSHITA_CDROM3_MAJOR) - -#define DEVICE_NAME "Matsushita CD-ROM controller #3" -#define DEVICE_REQUEST do_sbpcd3_request -#define DEVICE_NR(device) (MINOR(device)) -#define DEVICE_ON(device) -#define DEVICE_OFF(device) - -#elif (MAJOR_NR == MATSUSHITA_CDROM4_MAJOR) - -#define DEVICE_NAME "Matsushita CD-ROM controller #4" -#define DEVICE_REQUEST do_sbpcd4_request -#define DEVICE_NR(device) (MINOR(device)) -#define DEVICE_ON(device) -#define DEVICE_OFF(device) - -#elif (MAJOR_NR == AZTECH_CDROM_MAJOR) - -#define DEVICE_NAME "Aztech CD-ROM" -#define DEVICE_REQUEST do_aztcd_request -#define DEVICE_NR(device) (MINOR(device)) -#define DEVICE_ON(device) -#define DEVICE_OFF(device) - -#elif (MAJOR_NR == CDU535_CDROM_MAJOR) - -#define DEVICE_NAME "SONY-CDU535" -#define DEVICE_INTR do_cdu535 -#define DEVICE_REQUEST do_cdu535_request -#define DEVICE_NR(device) (MINOR(device)) -#define DEVICE_ON(device) -#define DEVICE_OFF(device) - -#elif (MAJOR_NR == GOLDSTAR_CDROM_MAJOR) - -#define DEVICE_NAME "Goldstar R420" -#define DEVICE_REQUEST do_gscd_request -#define DEVICE_NR(device) (MINOR(device)) -#define DEVICE_ON(device) -#define DEVICE_OFF(device) - -#elif (MAJOR_NR == CM206_CDROM_MAJOR) -#define DEVICE_NAME "Philips/LMS cd-rom cm206" -#define DEVICE_REQUEST do_cm206_request -#define DEVICE_NR(device) (MINOR(device)) -#define DEVICE_ON(device) -#define DEVICE_OFF(device) - -#elif (MAJOR_NR == OPTICS_CDROM_MAJOR) - -#define DEVICE_NAME "DOLPHIN 8000AT CD-ROM" -#define DEVICE_REQUEST do_optcd_request -#define DEVICE_NR(device) (MINOR(device)) -#define DEVICE_ON(device) -#define DEVICE_OFF(device) - -#elif (MAJOR_NR == SANYO_CDROM_MAJOR) - -#define DEVICE_NAME "Sanyo H94A CD-ROM" -#define DEVICE_REQUEST do_sjcd_request -#define DEVICE_NR(device) (MINOR(device)) -#define DEVICE_ON(device) -#define DEVICE_OFF(device) - -#endif /* MAJOR_NR == whatever */ - -#if (MAJOR_NR != SCSI_TAPE_MAJOR) && !defined(IDE_DRIVER) - -#ifndef CURRENT -#define CURRENT (blk_dev[MAJOR_NR].current_request) -#endif - -#define CURRENT_DEV DEVICE_NR(CURRENT->rq_dev) - -#ifdef DEVICE_INTR -void (*DEVICE_INTR)(void) = NULL; -#endif -#ifdef DEVICE_TIMEOUT - -#define SET_TIMER \ -((timer_table[DEVICE_TIMEOUT].expires = jiffies + TIMEOUT_VALUE), \ -(timer_active |= 1<<DEVICE_TIMEOUT)) - -#define CLEAR_TIMER \ -timer_active &= ~(1<<DEVICE_TIMEOUT) - -#define SET_INTR(x) \ -if ((DEVICE_INTR = (x)) != NULL) \ - SET_TIMER; \ -else \ - CLEAR_TIMER; - -#else - -#define SET_INTR(x) (DEVICE_INTR = (x)) - -#endif /* DEVICE_TIMEOUT */ - -static void (DEVICE_REQUEST)(void); - -#ifdef DEVICE_INTR -#define CLEAR_INTR SET_INTR(NULL) -#else -#define CLEAR_INTR -#endif - -#define INIT_REQUEST \ - if (!CURRENT) {\ - CLEAR_INTR; \ - return; \ - } \ - if (MAJOR(CURRENT->rq_dev) != MAJOR_NR) \ - panic(DEVICE_NAME ": request list destroyed"); \ - if (CURRENT->bh) { \ - if (!buffer_locked(CURRENT->bh)) \ - panic(DEVICE_NAME ": block not locked"); \ - } - -#endif /* (MAJOR_NR != SCSI_TAPE_MAJOR) && !defined(IDE_DRIVER) */ - -/* end_request() - SCSI devices have their own version */ -/* - IDE drivers have their own copy too */ - -#if ! SCSI_MAJOR(MAJOR_NR) - -#if defined(IDE_DRIVER) && !defined(_IDE_C) /* shared copy for IDE modules */ -void ide_end_request(byte uptodate, ide_hwgroup_t *hwgroup); -#else - -#ifdef IDE_DRIVER -void ide_end_request(byte uptodate, ide_hwgroup_t *hwgroup) { - struct request *req = hwgroup->rq; -#else -static void end_request(int uptodate) { - struct request *req = CURRENT; -#endif /* IDE_DRIVER */ - struct buffer_head * bh; - - req->errors = 0; - if (!uptodate) { - printk("end_request: I/O error, dev %s, sector %lu\n", - kdevname(req->rq_dev), req->sector); -#ifdef MACH - for (bh = req->bh; bh; ) { - struct buffer_head *next = bh->b_reqnext; - bh->b_reqnext = NULL; - mark_buffer_uptodate(bh, 0); - unlock_buffer(bh); - bh = next; - } - req->bh = NULL; -#else - req->nr_sectors--; - req->nr_sectors &= ~SECTOR_MASK; - req->sector += (BLOCK_SIZE / 512); - req->sector &= ~SECTOR_MASK; -#endif - } - - if ((bh = req->bh) != NULL) { - req->bh = bh->b_reqnext; - bh->b_reqnext = NULL; - mark_buffer_uptodate(bh, uptodate); - unlock_buffer(bh); - if ((bh = req->bh) != NULL) { - req->current_nr_sectors = bh->b_size >> 9; - if (req->nr_sectors < req->current_nr_sectors) { - req->nr_sectors = req->current_nr_sectors; - printk("end_request: buffer-list destroyed\n"); - } - req->buffer = bh->b_data; - return; - } - } -#ifndef DEVICE_NO_RANDOM - add_blkdev_randomness(MAJOR(req->rq_dev)); -#endif -#ifdef IDE_DRIVER - blk_dev[MAJOR(req->rq_dev)].current_request = req->next; - hwgroup->rq = NULL; -#else - DEVICE_OFF(req->rq_dev); - CURRENT = req->next; -#endif /* IDE_DRIVER */ - if (req->sem != NULL) - up(req->sem); - req->rq_status = RQ_INACTIVE; - wake_up(&wait_for_request); -} -#endif /* defined(IDE_DRIVER) && !defined(_IDE_C) */ -#endif /* ! SCSI_MAJOR(MAJOR_NR) */ - -#endif /* defined(MAJOR_NR) || defined(IDE_DRIVER) */ - -#endif /* _BLK_H */ diff --git a/i386/i386at/gpl/linux/include/linux/blkdev.h b/i386/i386at/gpl/linux/include/linux/blkdev.h deleted file mode 100644 index ba4d08af..00000000 --- a/i386/i386at/gpl/linux/include/linux/blkdev.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef _LINUX_BLKDEV_H -#define _LINUX_BLKDEV_H - -#include <linux/major.h> -#include <linux/sched.h> -#include <linux/genhd.h> - -/* - * Ok, this is an expanded form so that we can use the same - * request for paging requests when that is implemented. In - * paging, 'bh' is NULL, and the semaphore is used to wait - * for read/write completion. - */ -struct request { - volatile int rq_status; /* should split this into a few status bits */ -#define RQ_INACTIVE (-1) -#define RQ_ACTIVE 1 -#define RQ_SCSI_BUSY 0xffff -#define RQ_SCSI_DONE 0xfffe -#define RQ_SCSI_DISCONNECTING 0xffe0 - - kdev_t rq_dev; - int cmd; /* READ or WRITE */ - int errors; - unsigned long sector; - unsigned long nr_sectors; - unsigned long current_nr_sectors; - char * buffer; - struct semaphore * sem; - struct buffer_head * bh; - struct buffer_head * bhtail; - struct request * next; -}; - -struct blk_dev_struct { - void (*request_fn)(void); - struct request * current_request; -}; - -struct sec_size { - unsigned block_size; - unsigned block_size_bits; -}; - -extern struct sec_size * blk_sec[MAX_BLKDEV]; -extern struct blk_dev_struct blk_dev[MAX_BLKDEV]; -extern struct wait_queue * wait_for_request; -extern void resetup_one_dev(struct gendisk *dev, int drive); - -extern int * blk_size[MAX_BLKDEV]; - -extern int * blksize_size[MAX_BLKDEV]; - -extern int * hardsect_size[MAX_BLKDEV]; - -#endif diff --git a/i386/i386at/gpl/linux/include/linux/cdrom.h b/i386/i386at/gpl/linux/include/linux/cdrom.h deleted file mode 100644 index 5811ff0f..00000000 --- a/i386/i386at/gpl/linux/include/linux/cdrom.h +++ /dev/null @@ -1,465 +0,0 @@ -/* - * -- <linux/cdrom.h> - * general (not only SCSI) header library for linux CDROM drivers - * (C) 1992 David Giller rafetmad@oxy.edu - * 1994, 1995 Eberhard Moenkeberg emoenke@gwdg.de - * - */ - -#ifndef _LINUX_CDROM_H -#define _LINUX_CDROM_H - -/* - * some fix numbers - */ -#define CD_MINS 74 /* max. minutes per CD, not really a limit */ -#define CD_SECS 60 /* seconds per minute */ -#define CD_FRAMES 75 /* frames per second */ - -#define CD_SYNC_SIZE 12 /* 12 sync bytes per raw data frame, not transfered by the drive */ -#define CD_HEAD_SIZE 4 /* header (address) bytes per raw data frame */ -#define CD_SUBHEAD_SIZE 8 /* subheader bytes per raw XA data frame */ -#define CD_XA_HEAD (CD_HEAD_SIZE+CD_SUBHEAD_SIZE) /* "before data" part of raw XA frame */ -#define CD_XA_SYNC_HEAD (CD_SYNC_SIZE+CD_XA_HEAD)/* sync bytes + header of XA frame */ - -#define CD_FRAMESIZE 2048 /* bytes per frame, "cooked" mode */ -#define CD_FRAMESIZE_RAW 2352 /* bytes per frame, "raw" mode */ -/* most drives don't deliver everything: */ -#define CD_FRAMESIZE_RAW1 (CD_FRAMESIZE_RAW-CD_SYNC_SIZE) /* 2340 */ -#define CD_FRAMESIZE_RAW0 (CD_FRAMESIZE_RAW-CD_SYNC_SIZE-CD_HEAD_SIZE) /* 2336 */ - -#define CD_EDC_SIZE 4 /* bytes EDC per most raw data frame types */ -#define CD_ZERO_SIZE 8 /* bytes zero per yellow book mode 1 frame */ -#define CD_ECC_SIZE 276 /* bytes ECC per most raw data frame types */ -#define CD_XA_TAIL (CD_EDC_SIZE+CD_ECC_SIZE) /* "after data" part of raw XA frame */ - -#define CD_FRAMESIZE_SUB 96 /* subchannel data "frame" size */ -#define CD_MSF_OFFSET 150 /* MSF numbering offset of first frame */ - -#define CD_CHUNK_SIZE 24 /* lowest-level "data bytes piece" */ -#define CD_NUM_OF_CHUNKS 98 /* chunks per frame */ - -#define CD_FRAMESIZE_XA CD_FRAMESIZE_RAW1 /* obsolete name */ -#define CD_BLOCK_OFFSET CD_MSF_OFFSET /* obsolete name */ - -/* - * the raw frame layout: - * - * - audio (red): | audio_sample_bytes | - * | 2352 | - * - * - data (yellow, mode1): | sync - head - data - EDC - zero - ECC | - * | 12 - 4 - 2048 - 4 - 8 - 276 | - * - * - data (yellow, mode2): | sync - head - data | - * | 12 - 4 - 2336 | - * - * - XA data (green, mode2 form1): | sync - head - sub - data - EDC - ECC | - * | 12 - 4 - 8 - 2048 - 4 - 276 | - * - * - XA data (green, mode2 form2): | sync - head - sub - data - EDC | - * | 12 - 4 - 8 - 2324 - 4 | - */ - -/* - * CDROM IOCTL structures - */ - -struct cdrom_blk -{ - unsigned from; - unsigned short len; -}; - - -struct cdrom_msf -{ - u_char cdmsf_min0; /* start minute */ - u_char cdmsf_sec0; /* start second */ - u_char cdmsf_frame0; /* start frame */ - u_char cdmsf_min1; /* end minute */ - u_char cdmsf_sec1; /* end second */ - u_char cdmsf_frame1; /* end frame */ -}; - -struct cdrom_ti -{ - u_char cdti_trk0; /* start track */ - u_char cdti_ind0; /* start index */ - u_char cdti_trk1; /* end track */ - u_char cdti_ind1; /* end index */ -}; - -struct cdrom_tochdr -{ - u_char cdth_trk0; /* start track */ - u_char cdth_trk1; /* end track */ -}; - -struct cdrom_tocentry -{ - u_char cdte_track; - u_char cdte_adr :4; - u_char cdte_ctrl :4; - u_char cdte_format; - union - { - struct - { - u_char minute; - u_char second; - u_char frame; - } msf; - int lba; - } cdte_addr; - u_char cdte_datamode; -}; - -/* - * CD-ROM address types (cdrom_tocentry.cdte_format) - */ -#define CDROM_LBA 0x01 /* "logical block": first frame is #0 */ -#define CDROM_MSF 0x02 /* "minute-second-frame": binary, not bcd here! */ - -/* - * bit to tell whether track is data or audio (cdrom_tocentry.cdte_ctrl) - */ -#define CDROM_DATA_TRACK 0x04 - -/* - * The leadout track is always 0xAA, regardless of # of tracks on disc - */ -#define CDROM_LEADOUT 0xAA - -struct cdrom_subchnl -{ - u_char cdsc_format; - u_char cdsc_audiostatus; - u_char cdsc_adr: 4; - u_char cdsc_ctrl: 4; - u_char cdsc_trk; - u_char cdsc_ind; - union - { - struct - { - u_char minute; - u_char second; - u_char frame; - } msf; - int lba; - } cdsc_absaddr; - union - { - struct - { - u_char minute; - u_char second; - u_char frame; - } msf; - int lba; - } cdsc_reladdr; -}; - -/* - * audio states (from SCSI-2, but seen with other drives, too) - */ -#define CDROM_AUDIO_INVALID 0x00 /* audio status not supported */ -#define CDROM_AUDIO_PLAY 0x11 /* audio play operation in progress */ -#define CDROM_AUDIO_PAUSED 0x12 /* audio play operation paused */ -#define CDROM_AUDIO_COMPLETED 0x13 /* audio play successfully completed */ -#define CDROM_AUDIO_ERROR 0x14 /* audio play stopped due to error */ -#define CDROM_AUDIO_NO_STATUS 0x15 /* no current audio status to return */ - -struct cdrom_volctrl -{ - u_char channel0; - u_char channel1; - u_char channel2; - u_char channel3; -}; - -struct cdrom_read -{ - int cdread_lba; - caddr_t cdread_bufaddr; - int cdread_buflen; -}; - -/* - * extensions for transfering audio frames - * currently used by sbpcd.c, cdu31a.c, ide-cd.c - */ -struct cdrom_read_audio -{ - union - { - struct - { - u_char minute; - u_char second; - u_char frame; - } msf; - int lba; - } addr; /* frame address */ - u_char addr_format; /* CDROM_LBA or CDROM_MSF */ - int nframes; /* number of 2352-byte-frames to read at once, limited by the drivers */ - u_char *buf; /* frame buffer (size: nframes*2352 bytes) */ -}; - -/* - * this has to be the "arg" of the CDROMMULTISESSION ioctl - * for obtaining multi session info. - * The returned "addr" is valid only if "xa_flag" is true. - */ -struct cdrom_multisession -{ - union - { - struct - { - u_char minute; - u_char second; - u_char frame; - } msf; - int lba; - } addr; /* frame address: start-of-last-session (not the new "frame 16"!)*/ - u_char xa_flag; /* 1: "is XA disk" */ - u_char addr_format; /* CDROM_LBA or CDROM_MSF */ -}; - -#ifdef FIVETWELVE -#define CDROM_MODE1_SIZE 512 -#else -#define CDROM_MODE1_SIZE 2048 -#endif FIVETWELVE -#define CDROM_MODE2_SIZE 2336 - -/* - * CD-ROM IOCTL commands - * For IOCTL calls, we will commandeer byte 0x53, or 'S'. - */ - -#define CDROMPAUSE 0x5301 -#define CDROMRESUME 0x5302 -#define CDROMPLAYMSF 0x5303 /* (struct cdrom_msf) */ -#define CDROMPLAYTRKIND 0x5304 /* (struct cdrom_ti) */ - -#define CDROMREADTOCHDR 0x5305 /* (struct cdrom_tochdr) */ -#define CDROMREADTOCENTRY 0x5306 /* (struct cdrom_tocentry) */ - -#define CDROMSTOP 0x5307 /* stop the drive motor */ -#define CDROMSTART 0x5308 /* turn the motor on */ - -#define CDROMEJECT 0x5309 /* eject CD-ROM media */ - -#define CDROMVOLCTRL 0x530a /* (struct cdrom_volctrl) */ - -#define CDROMSUBCHNL 0x530b /* (struct cdrom_subchnl) */ - -#define CDROMREADMODE2 0x530c /* (struct cdrom_read) */ - /* read type-2 data */ - -#define CDROMREADMODE1 0x530d /* (struct cdrom_read) */ - /* read type-1 data */ - -#define CDROMREADAUDIO 0x530e /* (struct cdrom_read_audio) */ - -/* - * enable (1) / disable (0) auto-ejecting - */ -#define CDROMEJECT_SW 0x530f /* arg: 0 or 1 */ - -/* - * obtain the start-of-last-session address of multi session disks - */ -#define CDROMMULTISESSION 0x5310 /* (struct cdrom_multisession) */ - -/* - * obtain the "universal product code" number - * (only some data disks have it coded) - */ -#define CDROM_GET_UPC 0x5311 /* 8 bytes returned */ - -#define CDROMRESET 0x5312 /* hard-reset the drive */ -#define CDROMVOLREAD 0x5313 /* let the drive tell its volume setting */ - /* (struct cdrom_volctrl) */ - -/* - * these ioctls are used in aztcd.c - */ -#define CDROMREADRAW 0x5314 /* read data in raw mode */ -#define CDROMREADCOOKED 0x5315 /* read data in cooked mode */ -#define CDROMSEEK 0x5316 /* seek msf address */ - -/* - * for playing audio in logical block addressing mode - */ -#define CDROMPLAYBLK 0x5317 /* (struct cdrom_blk) */ - - -/* - * CD-ROM-specific SCSI command opcodes - */ - -/* - * Group 2 (10-byte). All of these are called 'optional' by SCSI-II. - */ -#define SCMD_READ_TOC 0x43 /* read table of contents */ -#define SCMD_PLAYAUDIO_MSF 0x47 /* play data at time offset */ -#define SCMD_PLAYAUDIO_TI 0x48 /* play data at track/index */ -#define SCMD_PAUSE_RESUME 0x4B /* pause/resume audio */ -#define SCMD_READ_SUBCHANNEL 0x42 /* read SC info on playing disc */ -#define SCMD_PLAYAUDIO10 0x45 /* play data at logical block */ -#define SCMD_READ_HEADER 0x44 /* read TOC header */ - -/* - * Group 5 - */ -#define SCMD_PLAYAUDIO12 0xA5 /* play data at logical block */ -#define SCMD_PLAYTRACK_REL12 0xA9 /* play track at relative offset */ - -/* - * Group 6 Commands - */ -#define SCMD_CD_PLAYBACK_CONTROL 0xC9 /* Sony vendor-specific audio */ -#define SCMD_CD_PLAYBACK_STATUS 0xC4 /* control opcodes */ - -/* - * CD-ROM capacity structure. - */ -struct scsi_capacity -{ - u_long capacity; - u_long lbasize; -}; - -/* - * CD-ROM MODE_SENSE/MODE_SELECT parameters - */ -#define ERR_RECOVERY_PARMS 0x01 -#define DISCO_RECO_PARMS 0x02 -#define FORMAT_PARMS 0x03 -#define GEOMETRY_PARMS 0x04 -#define CERTIFICATION_PARMS 0x06 -#define CACHE_PARMS 0x38 - -/* - * standard mode-select header prepended to all mode-select commands - */ -struct ccs_modesel_head -{ - u_char _r1; /* reserved */ - u_char medium; /* device-specific medium type */ - u_char _r2; /* reserved */ - u_char block_desc_length; /* block descriptor length */ - u_char density; /* device-specific density code */ - u_char number_blocks_hi; /* number of blocks in this block desc */ - u_char number_blocks_med; - u_char number_blocks_lo; - u_char _r3; - u_char block_length_hi; /* block length for blocks in this desc */ - u_short block_length; -}; - -/* - * error recovery parameters - */ -struct ccs_err_recovery -{ - u_char _r1 : 2; /* reserved */ - u_char page_code : 6; /* page code */ - u_char page_length; /* page length */ - u_char awre : 1; /* auto write realloc enabled */ - u_char arre : 1; /* auto read realloc enabled */ - u_char tb : 1; /* transfer block */ - u_char rc : 1; /* read continuous */ - u_char eec : 1; /* enable early correction */ - u_char per : 1; /* post error */ - u_char dte : 1; /* disable transfer on error */ - u_char dcr : 1; /* disable correction */ - u_char retry_count; /* error retry count */ - u_char correction_span; /* largest recov. to be attempted, bits */ - u_char head_offset_count; /* head offset (2's C) for each retry */ - u_char strobe_offset_count; /* data strobe */ - u_char recovery_time_limit; /* time limit on recovery attempts */ -}; - -/* - * disco/reco parameters - */ -struct ccs_disco_reco -{ - u_char _r1 : 2; /* reserved */ - u_char page_code : 6; /* page code */ - u_char page_length; /* page length */ - u_char buffer_full_ratio; /* write buffer reconnect threshold */ - u_char buffer_empty_ratio; /* read */ - u_short bus_inactivity_limit; /* limit on bus inactivity time */ - u_short disconnect_time_limit; /* minimum disconnect time */ - u_short connect_time_limit; /* minimum connect time */ - u_short _r2; /* reserved */ -}; - -/* - * drive geometry parameters - */ -struct ccs_geometry -{ - u_char _r1 : 2; /* reserved */ - u_char page_code : 6; /* page code */ - u_char page_length; /* page length */ - u_char cyl_ub; /* #cyls */ - u_char cyl_mb; - u_char cyl_lb; - u_char heads; /* #heads */ - u_char precomp_cyl_ub; /* precomp start */ - u_char precomp_cyl_mb; - u_char precomp_cyl_lb; - u_char current_cyl_ub; /* reduced current start */ - u_char current_cyl_mb; - u_char current_cyl_lb; - u_short step_rate; /* stepping motor rate */ - u_char landing_cyl_ub; /* landing zone */ - u_char landing_cyl_mb; - u_char landing_cyl_lb; - u_char _r2; - u_char _r3; - u_char _r4; -}; - -/* - * cache parameters - */ -struct ccs_cache -{ - u_char _r1 : 2; /* reserved */ - u_char page_code : 6; /* page code */ - u_char page_length; /* page length */ - u_char mode; /* cache control byte */ - u_char threshold; /* prefetch threshold */ - u_char max_prefetch; /* maximum prefetch size */ - u_char max_multiplier; /* maximum prefetch multiplier */ - u_char min_prefetch; /* minimum prefetch size */ - u_char min_multiplier; /* minimum prefetch multiplier */ - u_char _r2[8]; -}; - -#endif _LINUX_CDROM_H -/*==========================================================================*/ -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ diff --git a/i386/i386at/gpl/linux/include/linux/config.h b/i386/i386at/gpl/linux/include/linux/config.h deleted file mode 100644 index a54cdff2..00000000 --- a/i386/i386at/gpl/linux/include/linux/config.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef _LINUX_CONFIG_H -#define _LINUX_CONFIG_H - -#include <linux/autoconf.h> - -/* - * Defines for what uname() should return - */ -#ifndef UTS_SYSNAME -#define UTS_SYSNAME "Linux" -#endif - -#ifndef UTS_MACHINE -#define UTS_MACHINE "unknown" -#endif - -#ifndef UTS_NODENAME -#define UTS_NODENAME "(none)" /* set by sethostname() */ -#endif - -#ifndef UTS_DOMAINNAME -#define UTS_DOMAINNAME "(none)" /* set by setdomainname() */ -#endif - -/* - * The definitions for UTS_RELEASE and UTS_VERSION are now defined - * in linux/version.h, and should only be used by linux/version.c - */ - -/* Don't touch these, unless you really know what your doing. */ -#define DEF_INITSEG 0x9000 -#define DEF_SYSSEG 0x1000 -#define DEF_SETUPSEG 0x9020 -#define DEF_SYSSIZE 0x7F00 - -/* internal svga startup constants */ -#define NORMAL_VGA 0xffff /* 80x25 mode */ -#define EXTENDED_VGA 0xfffe /* 80x50 mode */ -#define ASK_VGA 0xfffd /* ask for it at bootup */ - -#endif diff --git a/i386/i386at/gpl/linux/include/linux/delay.h b/i386/i386at/gpl/linux/include/linux/delay.h deleted file mode 100644 index 50b5d0b1..00000000 --- a/i386/i386at/gpl/linux/include/linux/delay.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef _LINUX_DELAY_H -#define _LINUX_DELAY_H - -/* - * Copyright (C) 1993 Linus Torvalds - * - * Delay routines, using a pre-computed "loops_per_second" value. - */ - -extern unsigned long loops_per_sec; - -#include <asm/delay.h> - -#endif /* defined(_LINUX_DELAY_H) */ diff --git a/i386/i386at/gpl/linux/include/linux/errno.h b/i386/i386at/gpl/linux/include/linux/errno.h deleted file mode 100644 index ac212844..00000000 --- a/i386/i386at/gpl/linux/include/linux/errno.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef _LINUX_ERRNO_H -#define _LINUX_ERRNO_H - -#include <asm/errno.h> - -#ifdef __KERNEL__ - -/* Should never be seen by user programs */ -#define ERESTARTSYS 512 -#define ERESTARTNOINTR 513 -#define ERESTARTNOHAND 514 /* restart if no handler.. */ -#define ENOIOCTLCMD 515 /* No ioctl command */ - -#endif - -#endif diff --git a/i386/i386at/gpl/linux/include/linux/etherdevice.h b/i386/i386at/gpl/linux/include/linux/etherdevice.h deleted file mode 100644 index b29b76b9..00000000 --- a/i386/i386at/gpl/linux/include/linux/etherdevice.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * INET An implementation of the TCP/IP protocol suite for the LINUX - * operating system. NET is implemented using the BSD Socket - * interface as the means of communication with the user level. - * - * Definitions for the Ethernet handlers. - * - * Version: @(#)eth.h 1.0.4 05/13/93 - * - * Authors: Ross Biro, <bir7@leland.Stanford.Edu> - * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> - * - * Relocated to include/linux where it belongs by Alan Cox - * <gw4pts@gw4pts.ampr.org> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * WARNING: This move may well be temporary. This file will get merged with others RSN. - * - */ -#ifndef _LINUX_ETHERDEVICE_H -#define _LINUX_ETHERDEVICE_H - - -#include <linux/if_ether.h> - -#ifdef __KERNEL__ -extern int eth_header(struct sk_buff *skb, struct device *dev, - unsigned short type, void *daddr, - void *saddr, unsigned len); -extern int eth_rebuild_header(void *buff, struct device *dev, - unsigned long dst, struct sk_buff *skb); -#ifdef MACH -#define eth_type_trans(skb, dev) 0 -#else -extern unsigned short eth_type_trans(struct sk_buff *skb, struct device *dev); -#endif -extern void eth_header_cache_bind(struct hh_cache ** hhp, struct device *dev, - unsigned short htype, __u32 daddr); -extern void eth_header_cache_update(struct hh_cache *hh, struct device *dev, unsigned char * haddr); -#ifdef MACH -#define eth_copy_and_sum(skb, src, length, base) \ - memcpy ((skb)->data, src, length) -#else -extern void eth_copy_and_sum(struct sk_buff *dest, - unsigned char *src, int length, int base); -#endif -extern struct device * init_etherdev(struct device *, int); - -#endif - -#endif /* _LINUX_ETHERDEVICE_H */ diff --git a/i386/i386at/gpl/linux/include/linux/fcntl.h b/i386/i386at/gpl/linux/include/linux/fcntl.h deleted file mode 100644 index 9de3512e..00000000 --- a/i386/i386at/gpl/linux/include/linux/fcntl.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _LINUX_FCNTL_H -#define _LINUX_FCNTL_H - -#include <asm/fcntl.h> - -#endif diff --git a/i386/i386at/gpl/linux/include/linux/fd.h b/i386/i386at/gpl/linux/include/linux/fd.h deleted file mode 100644 index 87a837b6..00000000 --- a/i386/i386at/gpl/linux/include/linux/fd.h +++ /dev/null @@ -1,368 +0,0 @@ -#ifndef _LINUX_FD_H -#define _LINUX_FD_H - -#include <linux/ioctl.h> - -/* New file layout: Now the ioctl definitions immediately follow the - * definitions of the structures that they use */ - -/* - * Geometry - */ -struct floppy_struct { - unsigned int size, /* nr of sectors total */ - sect, /* sectors per track */ - head, /* nr of heads */ - track, /* nr of tracks */ - stretch; /* !=0 means double track steps */ -#define FD_STRETCH 1 -#define FD_SWAPSIDES 2 - - unsigned char gap, /* gap1 size */ - - rate, /* data rate. |= 0x40 for perpendicular */ -#define FD_2M 0x4 -#define FD_SIZECODEMASK 0x38 -#define FD_SIZECODE(floppy) (((((floppy)->rate&FD_SIZECODEMASK)>> 3)+ 2) %8) -#define FD_SECTSIZE(floppy) ( (floppy)->rate & FD_2M ? \ - 512 : 128 << FD_SIZECODE(floppy) ) -#define FD_PERP 0x40 - - spec1, /* stepping rate, head unload time */ - fmt_gap; /* gap2 size */ - const char * name; /* used only for predefined formats */ -}; - - -/* commands needing write access have 0x40 set */ -/* commands needing super user access have 0x80 set */ - -#define FDCLRPRM _IO(2, 0x41) -/* clear user-defined parameters */ - -#define FDSETPRM _IOW(2, 0x42, struct floppy_struct) -#define FDSETMEDIAPRM FDSETPRM -/* set user-defined parameters for current media */ - -#define FDDEFPRM _IOW(2, 0x43, struct floppy_struct) -#define FDGETPRM _IOR(2, 0x04, struct floppy_struct) -#define FDDEFMEDIAPRM FDDEFPRM -#define FDGETMEDIAPRM FDGETPRM -/* set/get disk parameters */ - - -#define FDMSGON _IO(2,0x45) -#define FDMSGOFF _IO(2,0x46) -/* issue/don't issue kernel messages on media type change */ - - -/* - * Formatting (obsolete) - */ -#define FD_FILL_BYTE 0xF6 /* format fill byte. */ - -struct format_descr { - unsigned int device,head,track; -}; - -#define FDFMTBEG _IO(2,0x47) -/* begin formatting a disk */ -#define FDFMTTRK _IOW(2,0x48, struct format_descr) -/* format the specified track */ -#define FDFMTEND _IO(2,0x49) -/* end formatting a disk */ - - -/* - * Error thresholds - */ -struct floppy_max_errors { - unsigned int - abort, /* number of errors to be reached before aborting */ - read_track, /* maximal number of errors permitted to read an - * entire track at once */ - reset, /* maximal number of errors before a reset is tried */ - recal, /* maximal number of errors before a recalibrate is - * tried */ - - /* - * Threshold for reporting FDC errors to the console. - * Setting this to zero may flood your screen when using - * ultra cheap floppies ;-) - */ - reporting; - -}; - -#define FDSETEMSGTRESH _IO(2,0x4a) -/* set fdc error reporting threshold */ - -#define FDFLUSH _IO(2,0x4b) -/* flush buffers for media; either for verifying media, or for - * handling a media change without closing the file descriptor */ - -#define FDSETMAXERRS _IOW(2, 0x4c, struct floppy_max_errors) -#define FDGETMAXERRS _IOR(2, 0x0e, struct floppy_max_errors) -/* set/get abortion and read_track threshold. See also floppy_drive_params - * structure */ - - -typedef char floppy_drive_name[16]; -#define FDGETDRVTYP _IOR(2, 0x0f, floppy_drive_name) -/* get drive type: 5 1/4 or 3 1/2 */ - - -/* - * Drive parameters (user modifyable) - */ -struct floppy_drive_params { - char cmos; /* cmos type */ - - /* Spec2 is (HLD<<1 | ND), where HLD is head load time (1=2ms, 2=4 ms - * etc) and ND is set means no DMA. Hardcoded to 6 (HLD=6ms, use DMA). - */ - unsigned long max_dtr; /* Step rate, usec */ - unsigned long hlt; /* Head load/settle time, msec */ - unsigned long hut; /* Head unload time (remnant of - * 8" drives) */ - unsigned long srt; /* Step rate, usec */ - - unsigned long spinup; /* time needed for spinup (expressed - * in jiffies) */ - unsigned long spindown; /* timeout needed for spindown */ - unsigned char spindown_offset; /* decides in which position the disk - * will stop */ - unsigned char select_delay; /* delay to wait after select */ - unsigned char rps; /* rotations per second */ - unsigned char tracks; /* maximum number of tracks */ - unsigned long timeout; /* timeout for interrupt requests */ - - unsigned char interleave_sect; /* if there are more sectors, use - * interleave */ - - struct floppy_max_errors max_errors; - - char flags; /* various flags, including ftd_msg */ -/* - * Announce successful media type detection and media information loss after - * disk changes. - * Also used to enable/disable printing of overrun warnings. - */ - -#define FTD_MSG 0x10 -#define FD_BROKEN_DCL 0x20 -#define FD_DEBUG 0x02 -#define FD_SILENT_DCL_CLEAR 0x4 -#define FD_INVERTED_DCL 0x80 - - char read_track; /* use readtrack during probing? */ - -/* - * Auto-detection. Each drive type has eight formats which are - * used in succession to try to read the disk. If the FDC cannot lock onto - * the disk, the next format is tried. This uses the variable 'probing'. - */ - short autodetect[8]; /* autodetected formats */ - - int checkfreq; /* how often should the drive be checked for disk - * changes */ - int native_format; /* native format of this drive */ -}; - -enum { - FD_NEED_TWADDLE_BIT, /* more magic */ - FD_VERIFY_BIT, /* inquire for write protection */ - FD_DISK_NEWCHANGE_BIT, /* change detected, and no action undertaken yet - * to clear media change status */ - FD_UNUSED_BIT, - FD_DISK_CHANGED_BIT, /* disk has been changed since last i/o */ - FD_DISK_WRITABLE_BIT /* disk is writable */ -}; - -#define FDSETDRVPRM _IOW(2, 0x90, struct floppy_drive_params) -#define FDGETDRVPRM _IOR(2, 0x11, struct floppy_drive_params) -/* set/get drive parameters */ - - -/* - * Current drive state (not directly modifyable by user, readonly) - */ -struct floppy_drive_struct { - signed char flags; -/* values for these flags */ -#define FD_NEED_TWADDLE (1 << FD_NEED_TWADDLE_BIT) -#define FD_VERIFY (1 << FD_VERIFY_BIT) -#define FD_DISK_NEWCHANGE (1 << FD_DISK_NEWCHANGE_BIT) -#define FD_DISK_CHANGED (1 << FD_DISK_CHANGED_BIT) -#define FD_DISK_WRITABLE (1 << FD_DISK_WRITABLE_BIT) - - unsigned long spinup_date; - unsigned long select_date; - unsigned long first_read_date; - short probed_format; - short track; /* current track */ - short maxblock; /* id of highest block read */ - short maxtrack; /* id of highest half track read */ - int generation; /* how many diskchanges? */ - -/* - * (User-provided) media information is _not_ discarded after a media change - * if the corresponding keep_data flag is non-zero. Positive values are - * decremented after each probe. - */ - int keep_data; - - /* Prevent "aliased" accesses. */ - int fd_ref; - int fd_device; - int last_checked; /* when was the drive last checked for a disk - * change? */ - - char *dmabuf; - int bufblocks; -}; - -#define FDGETDRVSTAT _IOR(2, 0x12, struct floppy_drive_struct) -#define FDPOLLDRVSTAT _IOR(2, 0x13, struct floppy_drive_struct) -/* get drive state: GET returns the cached state, POLL polls for new state */ - - -/* - * reset FDC - */ -enum reset_mode { - FD_RESET_IF_NEEDED, /* reset only if the reset flags is set */ - FD_RESET_IF_RAWCMD, /* obsolete */ - FD_RESET_ALWAYS /* reset always */ -}; -#define FDRESET _IO(2, 0x54) - - -/* - * FDC state - */ -struct floppy_fdc_state { - int spec1; /* spec1 value last used */ - int spec2; /* spec2 value last used */ - int dtr; - unsigned char version; /* FDC version code */ - unsigned char dor; - int address; /* io address */ - unsigned int rawcmd:2; - unsigned int reset:1; - unsigned int need_configure:1; - unsigned int perp_mode:2; - unsigned int has_fifo:1; - unsigned int driver_version; /* version code for floppy driver */ -#define FD_DRIVER_VERSION 0x100 -/* user programs using the floppy API should use floppy_fdc_state to - * get the version number of the floppy driver that they are running - * on. If this version number is bigger than the one compiled into the - * user program (the FD_DRIVER_VERSION define), it should be prepared - * to bigger structures - */ - - unsigned char track[4]; - /* Position of the heads of the 4 units attached to this FDC, - * as stored on the FDC. In the future, the position as stored - * on the FDC might not agree with the actual physical - * position of these drive heads. By allowing such - * disagreement, it will be possible to reset the FDC without - * incurring the expensive cost of repositioning all heads. - * Right now, these positions are hard wired to 0. */ - -}; - -#define FDGETFDCSTAT _IOR(2, 0x15, struct floppy_fdc_state) - - -/* - * Asynchronous Write error tracking - */ -struct floppy_write_errors { - /* Write error logging. - * - * These fields can be cleared with the FDWERRORCLR ioctl. - * Only writes that were attempted but failed due to a physical media - * error are logged. write(2) calls that fail and return an error code - * to the user process are not counted. - */ - - unsigned int write_errors; /* number of physical write errors - * encountered */ - - /* position of first and last write errors */ - unsigned long first_error_sector; - int first_error_generation; - unsigned long last_error_sector; - int last_error_generation; - - unsigned int badness; /* highest retry count for a read or write - * operation */ -}; - -#define FDWERRORCLR _IO(2, 0x56) -/* clear write error and badness information */ -#define FDWERRORGET _IOR(2, 0x17, struct floppy_write_errors) -/* get write error and badness information */ - - -/* - * Raw commands - */ -/* new interface flag: now we can do them in batches */ -#define FDHAVEBATCHEDRAWCMD - -struct floppy_raw_cmd { - unsigned int flags; -#define FD_RAW_READ 1 -#define FD_RAW_WRITE 2 -#define FD_RAW_NO_MOTOR 4 -#define FD_RAW_DISK_CHANGE 4 /* out: disk change flag was set */ -#define FD_RAW_INTR 8 /* wait for an interrupt */ -#define FD_RAW_SPIN 0x10 /* spin up the disk for this command */ -#define FD_RAW_NO_MOTOR_AFTER 0x20 /* switch the motor off after command - * completion */ -#define FD_RAW_NEED_DISK 0x40 /* this command needs a disk to be present */ -#define FD_RAW_NEED_SEEK 0x80 /* this command uses an implied seek (soft) */ - -/* more "in" flags */ -#define FD_RAW_MORE 0x100 /* more records follow */ -#define FD_RAW_STOP_IF_FAILURE 0x200 /* stop if we encounter a failure */ -#define FD_RAW_STOP_IF_SUCCESS 0x400 /* stop if command successful */ -#define FD_RAW_SOFTFAILURE 0x800 /* consider the return value for failure - * detection too */ - -/* more "out" flags */ -#define FD_RAW_FAILURE 0x10000 /* command sent to fdc, fdc returned error */ -#define FD_RAW_HARDFAILURE 0x20000 /* fdc had to be reset, or timed out */ - - void *data; - char *kernel_data; /* location of data buffer in the kernel */ - struct floppy_raw_cmd *next; /* used for chaining of raw cmd's - * withing the kernel */ - long length; /* in: length of dma transfer. out: remaining bytes */ - long phys_length; /* physical length, if different from dma length */ - int buffer_length; /* length of allocated buffer */ - - unsigned char rate; - unsigned char cmd_count; - unsigned char cmd[16]; - unsigned char reply_count; - unsigned char reply[16]; - int track; - int resultcode; - - int reserved1; - int reserved2; -}; - -#define FDRAWCMD _IO(2, 0x58) -/* send a raw command to the fdc. Structure size not included, because of - * batches */ - -#define FDTWADDLE _IO(2, 0x59) -/* flicker motor-on bit before reading a sector. Experimental */ - - -#endif diff --git a/i386/i386at/gpl/linux/include/linux/fdreg.h b/i386/i386at/gpl/linux/include/linux/fdreg.h deleted file mode 100644 index 03d8893d..00000000 --- a/i386/i386at/gpl/linux/include/linux/fdreg.h +++ /dev/null @@ -1,127 +0,0 @@ -#ifndef _LINUX_FDREG_H -#define _LINUX_FDREG_H -/* - * This file contains some defines for the floppy disk controller. - * Various sources. Mostly "IBM Microcomputers: A Programmers - * Handbook", Sanches and Canton. - */ - -#ifdef FDPATCHES - -#define FD_IOPORT fdc_state[fdc].address - -/* Fd controller regs. S&C, about page 340 */ -#define FD_STATUS (4 + FD_IOPORT ) -#define FD_DATA (5 + FD_IOPORT ) - -/* Digital Output Register */ -#define FD_DOR (2 + FD_IOPORT ) - -/* Digital Input Register (read) */ -#define FD_DIR (7 + FD_IOPORT ) - -/* Diskette Control Register (write)*/ -#define FD_DCR (7 + FD_IOPORT ) - -#else - -#define FD_STATUS 0x3f4 -#define FD_DATA 0x3f5 -#define FD_DOR 0x3f2 /* Digital Output Register */ -#define FD_DIR 0x3f7 /* Digital Input Register (read) */ -#define FD_DCR 0x3f7 /* Diskette Control Register (write)*/ - -#endif - -/* Bits of main status register */ -#define STATUS_BUSYMASK 0x0F /* drive busy mask */ -#define STATUS_BUSY 0x10 /* FDC busy */ -#define STATUS_DMA 0x20 /* 0- DMA mode */ -#define STATUS_DIR 0x40 /* 0- cpu->fdc */ -#define STATUS_READY 0x80 /* Data reg ready */ - -/* Bits of FD_ST0 */ -#define ST0_DS 0x03 /* drive select mask */ -#define ST0_HA 0x04 /* Head (Address) */ -#define ST0_NR 0x08 /* Not Ready */ -#define ST0_ECE 0x10 /* Equipment check error */ -#define ST0_SE 0x20 /* Seek end */ -#define ST0_INTR 0xC0 /* Interrupt code mask */ - -/* Bits of FD_ST1 */ -#define ST1_MAM 0x01 /* Missing Address Mark */ -#define ST1_WP 0x02 /* Write Protect */ -#define ST1_ND 0x04 /* No Data - unreadable */ -#define ST1_OR 0x10 /* OverRun */ -#define ST1_CRC 0x20 /* CRC error in data or addr */ -#define ST1_EOC 0x80 /* End Of Cylinder */ - -/* Bits of FD_ST2 */ -#define ST2_MAM 0x01 /* Missing Address Mark (again) */ -#define ST2_BC 0x02 /* Bad Cylinder */ -#define ST2_SNS 0x04 /* Scan Not Satisfied */ -#define ST2_SEH 0x08 /* Scan Equal Hit */ -#define ST2_WC 0x10 /* Wrong Cylinder */ -#define ST2_CRC 0x20 /* CRC error in data field */ -#define ST2_CM 0x40 /* Control Mark = deleted */ - -/* Bits of FD_ST3 */ -#define ST3_HA 0x04 /* Head (Address) */ -#define ST3_DS 0x08 /* drive is double-sided */ -#define ST3_TZ 0x10 /* Track Zero signal (1=track 0) */ -#define ST3_RY 0x20 /* drive is ready */ -#define ST3_WP 0x40 /* Write Protect */ -#define ST3_FT 0x80 /* Drive Fault */ - -/* Values for FD_COMMAND */ -#define FD_RECALIBRATE 0x07 /* move to track 0 */ -#define FD_SEEK 0x0F /* seek track */ -#define FD_READ 0xE6 /* read with MT, MFM, SKip deleted */ -#define FD_WRITE 0xC5 /* write with MT, MFM */ -#define FD_SENSEI 0x08 /* Sense Interrupt Status */ -#define FD_SPECIFY 0x03 /* specify HUT etc */ -#define FD_FORMAT 0x4D /* format one track */ -#define FD_VERSION 0x10 /* get version code */ -#define FD_CONFIGURE 0x13 /* configure FIFO operation */ -#define FD_PERPENDICULAR 0x12 /* perpendicular r/w mode */ -#define FD_GETSTATUS 0x04 /* read ST3 */ -#define FD_DUMPREGS 0x0E /* dump the contents of the fdc regs */ -#define FD_READID 0xEA /* prints the header of a sector */ -#define FD_UNLOCK 0x14 /* Fifo config unlock */ -#define FD_LOCK 0x94 /* Fifo config lock */ -#define FD_RSEEK_OUT 0x8f /* seek out (i.e. to lower tracks) */ -#define FD_RSEEK_IN 0xcf /* seek in (i.e. to higher tracks) */ -#define FD_PARTID 0x18 /* part id ("extended" version cmd) */ -#define FD_SAVE 0x2e /* save fdc regs for later restore */ - -/* DMA commands */ -#define DMA_READ 0x46 -#define DMA_WRITE 0x4A - -/* FDC version return types */ -#define FDC_NONE 0x00 -#define FDC_UNKNOWN 0x10 /* DO NOT USE THIS TYPE EXCEPT IF IDENTIFICATION - FAILS EARLY */ -#define FDC_8272A 0x20 /* Intel 8272a, NEC 765 */ -#define FDC_765ED 0x30 /* Non-Intel 1MB-compatible FDC, can't detect */ -#define FDC_82072 0x40 /* Intel 82072; 8272a + FIFO + DUMPREGS */ -#define FDC_82077_ORIG 0x50 /* Original version of 82077AA, sans LOCK */ -#define FDC_82077 0x52 /* 82077AA-1 */ -#define FDC_82077_UNKN 0x53 /* Unknown 82077 variant */ -#define FDC_82078 0x60 /* 44pin 82078 or 64pin 82078SL */ -#define FDC_82078_1 0x61 /* 82078-1 (2Mbps fdc) */ -#define FDC_S82078B 0x62 /* S82078B (first seen on Adaptec AVA-2825 VLB - * SCSI/EIDE/Floppy controller) */ -#define FDC_87306 0x63 /* National Semiconductor PC 87306 */ - -/* - * Beware: the fdc type list is roughly sorted by increasing features. - * Presence of features is tested by comparing the FDC version id with the - * "oldest" version that has the needed feature. - * If during FDC detection, an obscure test fails late in the sequence, don't - * assign FDC_UNKNOWN. Else the FDC will be treated as a dumb 8272a, or worse. - * This is especially true if the tests are unneeded. - */ - -#define FD_RESET_DELAY 20 -#endif diff --git a/i386/i386at/gpl/linux/include/linux/fs.h b/i386/i386at/gpl/linux/include/linux/fs.h deleted file mode 100644 index 278aa361..00000000 --- a/i386/i386at/gpl/linux/include/linux/fs.h +++ /dev/null @@ -1,698 +0,0 @@ -#ifndef _LINUX_FS_H -#define _LINUX_FS_H - -/* - * This file has definitions for some important file table - * structures etc. - */ - -#include <linux/linkage.h> -#include <linux/limits.h> -#include <linux/wait.h> -#include <linux/types.h> -#include <linux/vfs.h> -#include <linux/net.h> -#include <linux/kdev_t.h> -#include <linux/ioctl.h> - -/* - * It's silly to have NR_OPEN bigger than NR_FILE, but I'll fix - * that later. Anyway, now the file code is no longer dependent - * on bitmaps in unsigned longs, but uses the new fd_set structure.. - * - * Some programs (notably those using select()) may have to be - * recompiled to take full advantage of the new limits.. - */ - -/* Fixed constants first: */ -#undef NR_OPEN -#define NR_OPEN 256 - -#define NR_SUPER 64 -#define NR_IHASH 131 -#define BLOCK_SIZE 1024 -#define BLOCK_SIZE_BITS 10 - -/* And dynamically-tunable limits and defaults: */ -extern int max_inodes, nr_inodes; -extern int max_files, nr_files; -#define NR_INODE 2048 /* this should be bigger than NR_FILE */ -#define NR_FILE 1024 /* this can well be larger on a larger system */ - -#define MAY_EXEC 1 -#define MAY_WRITE 2 -#define MAY_READ 4 - -#define FMODE_READ 1 -#define FMODE_WRITE 2 - -#define READ 0 -#define WRITE 1 -#define READA 2 /* read-ahead - don't pause */ -#define WRITEA 3 /* "write-ahead" - silly, but somewhat useful */ - -#ifndef NULL -#define NULL ((void *) 0) -#endif - -#define NIL_FILP ((struct file *)0) -#define SEL_IN 1 -#define SEL_OUT 2 -#define SEL_EX 4 - -/* - * These are the fs-independent mount-flags: up to 16 flags are supported - */ -#define MS_RDONLY 1 /* Mount read-only */ -#define MS_NOSUID 2 /* Ignore suid and sgid bits */ -#define MS_NODEV 4 /* Disallow access to device special files */ -#define MS_NOEXEC 8 /* Disallow program execution */ -#define MS_SYNCHRONOUS 16 /* Writes are synced at once */ -#define MS_REMOUNT 32 /* Alter flags of a mounted FS */ -#define S_WRITE 128 /* Write on file/directory/symlink */ -#define S_APPEND 256 /* Append-only file */ -#define S_IMMUTABLE 512 /* Immutable file */ - -/* - * Flags that can be altered by MS_REMOUNT - */ -#define MS_RMT_MASK (MS_RDONLY) - -/* - * Magic mount flag number. Has to be or-ed to the flag values. - */ -#define MS_MGC_VAL 0xC0ED0000 /* magic flag number to indicate "new" flags */ -#define MS_MGC_MSK 0xffff0000 /* magic flag number mask */ - -/* - * Note that read-only etc flags are inode-specific: setting some file-system - * flags just means all the inodes inherit those flags by default. It might be - * possible to override it selectively if you really wanted to with some - * ioctl() that is not currently implemented. - * - * Exception: MS_RDONLY is always applied to the entire file system. - */ -#define IS_RDONLY(inode) (((inode)->i_sb) && ((inode)->i_sb->s_flags & MS_RDONLY)) -#define IS_NOSUID(inode) ((inode)->i_flags & MS_NOSUID) -#define IS_NODEV(inode) ((inode)->i_flags & MS_NODEV) -#define IS_NOEXEC(inode) ((inode)->i_flags & MS_NOEXEC) -#define IS_SYNC(inode) ((inode)->i_flags & MS_SYNCHRONOUS) - -#define IS_WRITABLE(inode) ((inode)->i_flags & S_WRITE) -#define IS_APPEND(inode) ((inode)->i_flags & S_APPEND) -#define IS_IMMUTABLE(inode) ((inode)->i_flags & S_IMMUTABLE) - -/* the read-only stuff doesn't really belong here, but any other place is - probably as bad and I don't want to create yet another include file. */ - -#define BLKROSET _IO(0x12,93) /* set device read-only (0 = read-write) */ -#define BLKROGET _IO(0x12,94) /* get read-only status (0 = read_write) */ -#define BLKRRPART _IO(0x12,95) /* re-read partition table */ -#define BLKGETSIZE _IO(0x12,96) /* return device size */ -#define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */ -#define BLKRASET _IO(0x12,98) /* Set read ahead for block device */ -#define BLKRAGET _IO(0x12,99) /* get current read ahead setting */ - -#define BMAP_IOCTL 1 /* obsolete - kept for compatibility */ -#define FIBMAP _IO(0x00,1) /* bmap access */ -#define FIGETBSZ _IO(0x00,2) /* get the block size used for bmap */ - -#ifdef __KERNEL__ - -#include <asm/bitops.h> - -extern void buffer_init(void); -extern unsigned long inode_init(unsigned long start, unsigned long end); -extern unsigned long file_table_init(unsigned long start, unsigned long end); -extern unsigned long name_cache_init(unsigned long start, unsigned long end); - -typedef char buffer_block[BLOCK_SIZE]; - -/* bh state bits */ -#define BH_Uptodate 0 /* 1 if the buffer contains valid data */ -#define BH_Dirty 1 /* 1 if the buffer is dirty */ -#define BH_Lock 2 /* 1 if the buffer is locked */ -#define BH_Req 3 /* 0 if the buffer has been invalidated */ -#define BH_Touched 4 /* 1 if the buffer has been touched (aging) */ -#define BH_Has_aged 5 /* 1 if the buffer has been aged (aging) */ -#define BH_Protected 6 /* 1 if the buffer is protected */ -#define BH_FreeOnIO 7 /* 1 to discard the buffer_head after IO */ - -/* - * Try to keep the most commonly used fields in single cache lines (16 - * bytes) to improve performance. This ordering should be - * particularly beneficial on 32-bit processors. - * - * We use the first 16 bytes for the data which is used in searches - * over the block hash lists (ie. getblk(), find_buffer() and - * friends). - * - * The second 16 bytes we use for lru buffer scans, as used by - * sync_buffers() and refill_freelist(). -- sct - */ -struct buffer_head { - /* First cache line: */ - unsigned long b_blocknr; /* block number */ - kdev_t b_dev; /* device (B_FREE = free) */ - struct buffer_head * b_next; /* Hash queue list */ - struct buffer_head * b_this_page; /* circular list of buffers in one page */ - - /* Second cache line: */ - unsigned long b_state; /* buffer state bitmap (see above) */ - struct buffer_head * b_next_free; - unsigned int b_count; /* users using this block */ - unsigned long b_size; /* block size */ - - /* Non-performance-critical data follows. */ - char * b_data; /* pointer to data block (1024 bytes) */ - unsigned int b_list; /* List that this buffer appears */ - unsigned long b_flushtime; /* Time when this (dirty) buffer - * should be written */ - unsigned long b_lru_time; /* Time when this buffer was - * last used. */ - struct wait_queue * b_wait; - struct buffer_head * b_prev; /* doubly linked list of hash-queue */ - struct buffer_head * b_prev_free; /* doubly linked list of buffers */ - struct buffer_head * b_reqnext; /* request queue */ -}; - -static inline int buffer_uptodate(struct buffer_head * bh) -{ - return test_bit(BH_Uptodate, &bh->b_state); -} - -static inline int buffer_dirty(struct buffer_head * bh) -{ - return test_bit(BH_Dirty, &bh->b_state); -} - -static inline int buffer_locked(struct buffer_head * bh) -{ - return test_bit(BH_Lock, &bh->b_state); -} - -static inline int buffer_req(struct buffer_head * bh) -{ - return test_bit(BH_Req, &bh->b_state); -} - -static inline int buffer_touched(struct buffer_head * bh) -{ - return test_bit(BH_Touched, &bh->b_state); -} - -static inline int buffer_has_aged(struct buffer_head * bh) -{ - return test_bit(BH_Has_aged, &bh->b_state); -} - -static inline int buffer_protected(struct buffer_head * bh) -{ - return test_bit(BH_Protected, &bh->b_state); -} - -#ifndef MACH -#include <linux/pipe_fs_i.h> -#include <linux/minix_fs_i.h> -#include <linux/ext_fs_i.h> -#include <linux/ext2_fs_i.h> -#include <linux/hpfs_fs_i.h> -#include <linux/msdos_fs_i.h> -#include <linux/umsdos_fs_i.h> -#include <linux/iso_fs_i.h> -#include <linux/nfs_fs_i.h> -#include <linux/xia_fs_i.h> -#include <linux/sysv_fs_i.h> -#endif - -/* - * Attribute flags. These should be or-ed together to figure out what - * has been changed! - */ -#define ATTR_MODE 1 -#define ATTR_UID 2 -#define ATTR_GID 4 -#define ATTR_SIZE 8 -#define ATTR_ATIME 16 -#define ATTR_MTIME 32 -#define ATTR_CTIME 64 -#define ATTR_ATIME_SET 128 -#define ATTR_MTIME_SET 256 -#define ATTR_FORCE 512 /* Not a change, but a change it */ - -/* - * This is the Inode Attributes structure, used for notify_change(). It - * uses the above definitions as flags, to know which values have changed. - * Also, in this manner, a Filesystem can look at only the values it cares - * about. Basically, these are the attributes that the VFS layer can - * request to change from the FS layer. - * - * Derek Atkins <warlord@MIT.EDU> 94-10-20 - */ -struct iattr { - unsigned int ia_valid; - umode_t ia_mode; - uid_t ia_uid; - gid_t ia_gid; - off_t ia_size; - time_t ia_atime; - time_t ia_mtime; - time_t ia_ctime; -}; - -#include <linux/quota.h> - -#ifdef MACH -struct inode -{ - umode_t i_mode; - kdev_t i_rdev; -}; - -struct file -{ - mode_t f_mode; - loff_t f_pos; - unsigned short f_flags; - int f_resid; - void *f_object; - void *f_np; -}; - -struct vm_area_struct; -struct page; -#else /* ! MACH */ -struct inode { - kdev_t i_dev; - unsigned long i_ino; - umode_t i_mode; - nlink_t i_nlink; - uid_t i_uid; - gid_t i_gid; - kdev_t i_rdev; - off_t i_size; - time_t i_atime; - time_t i_mtime; - time_t i_ctime; - unsigned long i_blksize; - unsigned long i_blocks; - unsigned long i_version; - unsigned long i_nrpages; - struct semaphore i_sem; - struct inode_operations *i_op; - struct super_block *i_sb; - struct wait_queue *i_wait; - struct file_lock *i_flock; - struct vm_area_struct *i_mmap; - struct page *i_pages; - struct dquot *i_dquot[MAXQUOTAS]; - struct inode *i_next, *i_prev; - struct inode *i_hash_next, *i_hash_prev; - struct inode *i_bound_to, *i_bound_by; - struct inode *i_mount; - unsigned short i_count; - unsigned short i_flags; - unsigned char i_lock; - unsigned char i_dirt; - unsigned char i_pipe; - unsigned char i_sock; - unsigned char i_seek; - unsigned char i_update; - unsigned short i_writecount; - union { - struct pipe_inode_info pipe_i; - struct minix_inode_info minix_i; - struct ext_inode_info ext_i; - struct ext2_inode_info ext2_i; - struct hpfs_inode_info hpfs_i; - struct msdos_inode_info msdos_i; - struct umsdos_inode_info umsdos_i; - struct iso_inode_info isofs_i; - struct nfs_inode_info nfs_i; - struct xiafs_inode_info xiafs_i; - struct sysv_inode_info sysv_i; - struct socket socket_i; - void * generic_ip; - } u; -}; - -struct file { - mode_t f_mode; - loff_t f_pos; - unsigned short f_flags; - unsigned short f_count; - off_t f_reada; - struct file *f_next, *f_prev; - int f_owner; /* pid or -pgrp where SIGIO should be sent */ - struct inode * f_inode; - struct file_operations * f_op; - unsigned long f_version; - void *private_data; /* needed for tty driver, and maybe others */ -}; -#endif /* ! MACH */ - -struct file_lock { - struct file_lock *fl_next; /* singly linked list for this inode */ - struct file_lock *fl_nextlink; /* doubly linked list of all locks */ - struct file_lock *fl_prevlink; /* used to simplify lock removal */ - struct file_lock *fl_block; - struct task_struct *fl_owner; - struct wait_queue *fl_wait; - struct file *fl_file; - char fl_flags; - char fl_type; - off_t fl_start; - off_t fl_end; -}; - -struct fasync_struct { - int magic; - struct fasync_struct *fa_next; /* singly linked list */ - struct file *fa_file; -}; - -#define FASYNC_MAGIC 0x4601 - -extern int fasync_helper(struct inode *, struct file *, int, struct fasync_struct **); - -#ifndef MACH -#include <linux/minix_fs_sb.h> -#include <linux/ext_fs_sb.h> -#include <linux/ext2_fs_sb.h> -#include <linux/hpfs_fs_sb.h> -#include <linux/msdos_fs_sb.h> -#include <linux/iso_fs_sb.h> -#include <linux/nfs_fs_sb.h> -#include <linux/xia_fs_sb.h> -#include <linux/sysv_fs_sb.h> - -struct super_block { - kdev_t s_dev; - unsigned long s_blocksize; - unsigned char s_blocksize_bits; - unsigned char s_lock; - unsigned char s_rd_only; - unsigned char s_dirt; - struct file_system_type *s_type; - struct super_operations *s_op; - struct dquot_operations *dq_op; - unsigned long s_flags; - unsigned long s_magic; - unsigned long s_time; - struct inode * s_covered; - struct inode * s_mounted; - struct wait_queue * s_wait; - union { - struct minix_sb_info minix_sb; - struct ext_sb_info ext_sb; - struct ext2_sb_info ext2_sb; - struct hpfs_sb_info hpfs_sb; - struct msdos_sb_info msdos_sb; - struct isofs_sb_info isofs_sb; - struct nfs_sb_info nfs_sb; - struct xiafs_sb_info xiafs_sb; - struct sysv_sb_info sysv_sb; - void *generic_sbp; - } u; -}; -#endif /* ! MACH */ - -/* - * This is the "filldir" function type, used by readdir() to let - * the kernel specify what kind of dirent layout it wants to have. - * This allows the kernel to read directories into kernel space or - * to have different dirent layouts depending on the binary type. - */ -typedef int (*filldir_t)(void *, const char *, int, off_t, ino_t); - -struct file_operations { - int (*lseek) (struct inode *, struct file *, off_t, int); - int (*read) (struct inode *, struct file *, char *, int); - int (*write) (struct inode *, struct file *, const char *, int); - int (*readdir) (struct inode *, struct file *, void *, filldir_t); - int (*select) (struct inode *, struct file *, int, select_table *); - int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long); - int (*mmap) (struct inode *, struct file *, struct vm_area_struct *); - int (*open) (struct inode *, struct file *); - void (*release) (struct inode *, struct file *); - int (*fsync) (struct inode *, struct file *); - int (*fasync) (struct inode *, struct file *, int); - int (*check_media_change) (kdev_t dev); - int (*revalidate) (kdev_t dev); -}; - -struct inode_operations { - struct file_operations * default_file_ops; - int (*create) (struct inode *,const char *,int,int,struct inode **); - int (*lookup) (struct inode *,const char *,int,struct inode **); - int (*link) (struct inode *,struct inode *,const char *,int); - int (*unlink) (struct inode *,const char *,int); - int (*symlink) (struct inode *,const char *,int,const char *); - int (*mkdir) (struct inode *,const char *,int,int); - int (*rmdir) (struct inode *,const char *,int); - int (*mknod) (struct inode *,const char *,int,int,int); - int (*rename) (struct inode *,const char *,int,struct inode *,const char *,int); - int (*readlink) (struct inode *,char *,int); - int (*follow_link) (struct inode *,struct inode *,int,int,struct inode **); - int (*readpage) (struct inode *, struct page *); - int (*writepage) (struct inode *, struct page *); - int (*bmap) (struct inode *,int); - void (*truncate) (struct inode *); - int (*permission) (struct inode *, int); - int (*smap) (struct inode *,int); -}; - -struct super_operations { - void (*read_inode) (struct inode *); - int (*notify_change) (struct inode *, struct iattr *); - void (*write_inode) (struct inode *); - void (*put_inode) (struct inode *); - void (*put_super) (struct super_block *); - void (*write_super) (struct super_block *); - void (*statfs) (struct super_block *, struct statfs *, int); - int (*remount_fs) (struct super_block *, int *, char *); -}; - -struct dquot_operations { - void (*initialize) (struct inode *, short); - void (*drop) (struct inode *); - int (*alloc_block) (const struct inode *, unsigned long); - int (*alloc_inode) (const struct inode *, unsigned long); - void (*free_block) (const struct inode *, unsigned long); - void (*free_inode) (const struct inode *, unsigned long); - int (*transfer) (struct inode *, struct iattr *, char); -}; - -struct file_system_type { - struct super_block *(*read_super) (struct super_block *, void *, int); - const char *name; - int requires_dev; - struct file_system_type * next; -}; - -extern int register_filesystem(struct file_system_type *); -extern int unregister_filesystem(struct file_system_type *); - -asmlinkage int sys_open(const char *, int, int); -asmlinkage int sys_close(unsigned int); /* yes, it's really unsigned */ - -extern void kill_fasync(struct fasync_struct *fa, int sig); - -extern int getname(const char * filename, char **result); -extern void putname(char * name); -extern int do_truncate(struct inode *, unsigned long); -extern int register_blkdev(unsigned int, const char *, struct file_operations *); -extern int unregister_blkdev(unsigned int major, const char * name); -extern int blkdev_open(struct inode * inode, struct file * filp); -extern struct file_operations def_blk_fops; -extern struct inode_operations blkdev_inode_operations; - -extern int register_chrdev(unsigned int, const char *, struct file_operations *); -extern int unregister_chrdev(unsigned int major, const char * name); -extern int chrdev_open(struct inode * inode, struct file * filp); -extern struct file_operations def_chr_fops; -extern struct inode_operations chrdev_inode_operations; - -extern void init_fifo(struct inode * inode); - -extern struct file_operations connecting_fifo_fops; -extern struct file_operations read_fifo_fops; -extern struct file_operations write_fifo_fops; -extern struct file_operations rdwr_fifo_fops; -extern struct file_operations read_pipe_fops; -extern struct file_operations write_pipe_fops; -extern struct file_operations rdwr_pipe_fops; - -extern struct file_system_type *get_fs_type(const char *name); - -extern int fs_may_mount(kdev_t dev); -extern int fs_may_umount(kdev_t dev, struct inode * mount_root); -extern int fs_may_remount_ro(kdev_t dev); - -extern struct file *first_file; -extern struct super_block super_blocks[NR_SUPER]; - -extern void refile_buffer(struct buffer_head * buf); -extern void set_writetime(struct buffer_head * buf, int flag); -extern void refill_freelist(int size); -extern int try_to_free_buffer(struct buffer_head*, struct buffer_head**, int); - -extern struct buffer_head ** buffer_pages; -extern int nr_buffers; -extern int buffermem; -extern int nr_buffer_heads; - -#define BUF_CLEAN 0 -#define BUF_UNSHARED 1 /* Buffers that were shared but are not any more */ -#define BUF_LOCKED 2 /* Buffers scheduled for write */ -#define BUF_LOCKED1 3 /* Supers, inodes */ -#define BUF_DIRTY 4 /* Dirty buffers, not yet scheduled for write */ -#define BUF_SHARED 5 /* Buffers shared */ -#define NR_LIST 6 - -#ifdef MACH -extern inline void -mark_buffer_uptodate (struct buffer_head *bh, int on) -{ - if (on) - set_bit (BH_Uptodate, &bh->b_state); - else - clear_bit (BH_Uptodate, &bh->b_state); -} -#else -void mark_buffer_uptodate(struct buffer_head * bh, int on); -#endif - -extern inline void mark_buffer_clean(struct buffer_head * bh) -{ -#ifdef MACH - clear_bit(BH_Dirty, &bh->b_state); -#else - if (clear_bit(BH_Dirty, &bh->b_state)) { - if (bh->b_list == BUF_DIRTY) - refile_buffer(bh); - } -#endif -} - -extern inline void mark_buffer_dirty(struct buffer_head * bh, int flag) -{ -#ifdef MACH - set_bit(BH_Dirty, &bh->b_state); -#else - if (!set_bit(BH_Dirty, &bh->b_state)) { - set_writetime(bh, flag); - if (bh->b_list != BUF_DIRTY) - refile_buffer(bh); - } -#endif -} - -extern int check_disk_change(kdev_t dev); -#ifdef MACH -#define invalidate_inodes(dev) -#else -extern void invalidate_inodes(kdev_t dev); -#endif -extern void invalidate_inode_pages(struct inode *, unsigned long); -#ifdef MACH -#define invalidate_buffers(dev) -#else -extern void invalidate_buffers(kdev_t dev); -#endif -extern int floppy_is_wp(int minor); -extern void sync_inodes(kdev_t dev); -#ifdef MACH -#define sync_dev(dev) -#define fsync_dev(dev) -#else -extern void sync_dev(kdev_t dev); -extern int fsync_dev(kdev_t dev); -#endif -extern void sync_supers(kdev_t dev); -extern int bmap(struct inode * inode,int block); -extern int notify_change(struct inode *, struct iattr *); -extern int namei(const char * pathname, struct inode ** res_inode); -extern int lnamei(const char * pathname, struct inode ** res_inode); -#ifdef MACH -#define permission(i, m) 0 -#else -extern int permission(struct inode * inode,int mask); -#endif -extern int get_write_access(struct inode *inode); -extern void put_write_access(struct inode *inode); -extern int open_namei(const char * pathname, int flag, int mode, - struct inode ** res_inode, struct inode * base); -extern int do_mknod(const char * filename, int mode, dev_t dev); -extern int do_pipe(int *); -extern void iput(struct inode * inode); -extern struct inode * __iget(struct super_block * sb,int nr,int crsmnt); -extern struct inode * get_empty_inode(void); -extern void insert_inode_hash(struct inode *); -extern void clear_inode(struct inode *); -extern struct inode * get_pipe_inode(void); -extern struct file * get_empty_filp(void); -extern int close_fp(struct file *filp); -extern struct buffer_head * get_hash_table(kdev_t dev, int block, int size); -extern struct buffer_head * getblk(kdev_t dev, int block, int size); -extern void ll_rw_block(int rw, int nr, struct buffer_head * bh[]); -extern void ll_rw_page(int rw, kdev_t dev, unsigned long nr, char * buffer); -extern void ll_rw_swap_file(int rw, kdev_t dev, unsigned int *b, int nb, char *buffer); -extern int is_read_only(kdev_t dev); -extern void __brelse(struct buffer_head *buf); -extern inline void brelse(struct buffer_head *buf) -{ - if (buf) - __brelse(buf); -} -extern void __bforget(struct buffer_head *buf); -extern inline void bforget(struct buffer_head *buf) -{ - if (buf) - __bforget(buf); -} -extern void set_blocksize(kdev_t dev, int size); -extern struct buffer_head * bread(kdev_t dev, int block, int size); -extern struct buffer_head * breada(kdev_t dev,int block, int size, - unsigned int pos, unsigned int filesize); - -extern int generic_readpage(struct inode *, struct page *); -extern int generic_file_read(struct inode *, struct file *, char *, int); -extern int generic_mmap(struct inode *, struct file *, struct vm_area_struct *); -extern int brw_page(int, unsigned long, kdev_t, int [], int, int); - -extern void put_super(kdev_t dev); -unsigned long generate_cluster(kdev_t dev, int b[], int size); -extern kdev_t ROOT_DEV; - -extern void show_buffers(void); -extern void mount_root(void); - -extern int char_read(struct inode *, struct file *, char *, int); -extern int block_read(struct inode *, struct file *, char *, int); -extern int read_ahead[]; - -extern int char_write(struct inode *, struct file *, const char *, int); -extern int block_write(struct inode *, struct file *, const char *, int); - -extern int block_fsync(struct inode *, struct file *); -extern int file_fsync(struct inode *, struct file *); - -extern void dcache_add(struct inode *, const char *, int, unsigned long); -extern int dcache_lookup(struct inode *, const char *, int, unsigned long *); - -extern int inode_change_ok(struct inode *, struct iattr *); -extern void inode_setattr(struct inode *, struct iattr *); - -extern inline struct inode * iget(struct super_block * sb,int nr) -{ - return __iget(sb, nr, 1); -} - -/* kludge to get SCSI modules working */ -#include <linux/minix_fs.h> -#include <linux/minix_fs_sb.h> - -#endif /* __KERNEL__ */ - -#endif diff --git a/i386/i386at/gpl/linux/include/linux/genhd.h b/i386/i386at/gpl/linux/include/linux/genhd.h deleted file mode 100644 index e1c5888d..00000000 --- a/i386/i386at/gpl/linux/include/linux/genhd.h +++ /dev/null @@ -1,73 +0,0 @@ -#ifndef _LINUX_GENHD_H -#define _LINUX_GENHD_H - -/* - * genhd.h Copyright (C) 1992 Drew Eckhardt - * Generic hard disk header file by - * Drew Eckhardt - * - * <drew@colorado.edu> - */ - -#define CONFIG_MSDOS_PARTITION 1 - -#ifdef __alpha__ -#define CONFIG_OSF_PARTITION 1 -#endif - -#ifdef __sparc__ -#define CONFIG_SUN_PARTITION 1 -#endif - -/* These two have identical behaviour; use the second one if DOS fdisk gets - confused about extended/logical partitions starting past cylinder 1023. */ -#define DOS_EXTENDED_PARTITION 5 -#define LINUX_EXTENDED_PARTITION 0x85 - -#define DM6_PARTITION 0x54 /* has DDO: use xlated geom & offset */ -#define EZD_PARTITION 0x55 /* EZ-DRIVE: same as DM6 (we think) */ -#define DM6_AUX1PARTITION 0x51 /* no DDO: use xlated geom */ -#define DM6_AUX3PARTITION 0x53 /* no DDO: use xlated geom */ - -#ifdef MACH_INCLUDE -struct linux_partition { -#else -struct partition { -#endif - unsigned char boot_ind; /* 0x80 - active */ - unsigned char head; /* starting head */ - unsigned char sector; /* starting sector */ - unsigned char cyl; /* starting cylinder */ - unsigned char sys_ind; /* What partition type */ - unsigned char end_head; /* end head */ - unsigned char end_sector; /* end sector */ - unsigned char end_cyl; /* end cylinder */ - unsigned int start_sect; /* starting sector counting from 0 */ - unsigned int nr_sects; /* nr of sectors in partition */ -}; - -struct hd_struct { - long start_sect; - long nr_sects; -}; - -struct gendisk { - int major; /* major number of driver */ - const char *major_name; /* name of major driver */ - int minor_shift; /* number of times minor is shifted to - get real minor */ - int max_p; /* maximum partitions per device */ - int max_nr; /* maximum number of real devices */ - - void (*init)(struct gendisk *); /* Initialization called before we do our thing */ - struct hd_struct *part; /* partition table */ - int *sizes; /* device size in blocks, copied to blk_size[] */ - int nr_real; /* number of real devices */ - - void *real_devices; /* internal use */ - struct gendisk *next; -}; - -extern struct gendisk *gendisk_head; /* linked list of disks */ - -#endif diff --git a/i386/i386at/gpl/linux/include/linux/hdreg.h b/i386/i386at/gpl/linux/include/linux/hdreg.h deleted file mode 100644 index 58a9a5df..00000000 --- a/i386/i386at/gpl/linux/include/linux/hdreg.h +++ /dev/null @@ -1,171 +0,0 @@ -#ifndef _LINUX_HDREG_H -#define _LINUX_HDREG_H - -/* - * This file contains some defines for the AT-hd-controller. - * Various sources. - */ - -#define HD_IRQ 14 /* the standard disk interrupt */ - -/* ide.c has it's own port definitions in "ide.h" */ - -/* Hd controller regs. Ref: IBM AT Bios-listing */ -#define HD_DATA 0x1f0 /* _CTL when writing */ -#define HD_ERROR 0x1f1 /* see err-bits */ -#define HD_NSECTOR 0x1f2 /* nr of sectors to read/write */ -#define HD_SECTOR 0x1f3 /* starting sector */ -#define HD_LCYL 0x1f4 /* starting cylinder */ -#define HD_HCYL 0x1f5 /* high byte of starting cyl */ -#define HD_CURRENT 0x1f6 /* 101dhhhh , d=drive, hhhh=head */ -#define HD_STATUS 0x1f7 /* see status-bits */ -#define HD_FEATURE HD_ERROR /* same io address, read=error, write=feature */ -#define HD_PRECOMP HD_FEATURE /* obsolete use of this port - predates IDE */ -#define HD_COMMAND HD_STATUS /* same io address, read=status, write=cmd */ - -#define HD_CMD 0x3f6 /* used for resets */ -#define HD_ALTSTATUS 0x3f6 /* same as HD_STATUS but doesn't clear irq */ - -/* remainder is shared between hd.c, ide.c, ide-cd.c, and the hdparm utility */ - -/* Bits of HD_STATUS */ -#define ERR_STAT 0x01 -#define INDEX_STAT 0x02 -#define ECC_STAT 0x04 /* Corrected error */ -#define DRQ_STAT 0x08 -#define SEEK_STAT 0x10 -#define WRERR_STAT 0x20 -#define READY_STAT 0x40 -#define BUSY_STAT 0x80 - -/* Values for HD_COMMAND */ -#define WIN_RESTORE 0x10 -#define WIN_READ 0x20 -#define WIN_WRITE 0x30 -#define WIN_VERIFY 0x40 -#define WIN_FORMAT 0x50 -#define WIN_INIT 0x60 -#define WIN_SEEK 0x70 -#define WIN_DIAGNOSE 0x90 -#define WIN_SPECIFY 0x91 /* set drive geometry translation */ -#define WIN_SETIDLE1 0xE3 -#define WIN_SETIDLE2 0x97 - -#define WIN_DOORLOCK 0xde /* lock door on removeable drives */ -#define WIN_DOORUNLOCK 0xdf /* unlock door on removeable drives */ - -#define WIN_MULTREAD 0xC4 /* read sectors using multiple mode */ -#define WIN_MULTWRITE 0xC5 /* write sectors using multiple mode */ -#define WIN_SETMULT 0xC6 /* enable/disable multiple mode */ -#define WIN_IDENTIFY 0xEC /* ask drive to identify itself */ -#define WIN_SETFEATURES 0xEF /* set special drive features */ -#define WIN_READDMA 0xc8 /* read sectors using DMA transfers */ -#define WIN_WRITEDMA 0xca /* write sectors using DMA transfers */ - -/* Additional drive command codes used by ATAPI devices. */ -#define WIN_PIDENTIFY 0xA1 /* identify ATAPI device */ -#define WIN_SRST 0x08 /* ATAPI soft reset command */ -#define WIN_PACKETCMD 0xa0 /* Send a packet command. */ - -/* Bits for HD_ERROR */ -#define MARK_ERR 0x01 /* Bad address mark */ -#define TRK0_ERR 0x02 /* couldn't find track 0 */ -#define ABRT_ERR 0x04 /* Command aborted */ -#define ID_ERR 0x10 /* ID field not found */ -#define ECC_ERR 0x40 /* Uncorrectable ECC error */ -#define BBD_ERR 0x80 /* block marked bad */ - -struct hd_geometry { - unsigned char heads; - unsigned char sectors; - unsigned short cylinders; - unsigned long start; -}; - -/* hd/ide ctl's that pass (arg) ptrs to user space are numbered 0x030n/0x031n */ -#define HDIO_GETGEO 0x0301 /* get device geometry */ -#define HDIO_GET_UNMASKINTR 0x0302 /* get current unmask setting */ -#define HDIO_GET_MULTCOUNT 0x0304 /* get current IDE blockmode setting */ -#define HDIO_GET_IDENTITY 0x0307 /* get IDE identification info */ -#define HDIO_GET_KEEPSETTINGS 0x0308 /* get keep-settings-on-reset flag */ -#define HDIO_GET_32BIT 0x0309 /* get current io_32bit setting */ -#define HDIO_GET_NOWERR 0x030a /* get ignore-write-error flag */ -#define HDIO_GET_DMA 0x030b /* get use-dma flag */ -#define HDIO_DRIVE_CMD 0x031f /* execute a special drive command */ - -/* hd/ide ctl's that pass (arg) non-ptr values are numbered 0x032n/0x033n */ -#define HDIO_SET_MULTCOUNT 0x0321 /* change IDE blockmode */ -#define HDIO_SET_UNMASKINTR 0x0322 /* permit other irqs during I/O */ -#define HDIO_SET_KEEPSETTINGS 0x0323 /* keep ioctl settings on reset */ -#define HDIO_SET_32BIT 0x0324 /* change io_32bit flags */ -#define HDIO_SET_NOWERR 0x0325 /* change ignore-write-error flag */ -#define HDIO_SET_DMA 0x0326 /* change use-dma flag */ -#define HDIO_SET_PIO_MODE 0x0327 /* reconfig interface to new speed */ - -/* structure returned by HDIO_GET_IDENTITY, as per ANSI ATA2 rev.2f spec */ -struct hd_driveid { - unsigned short config; /* lots of obsolete bit flags */ - unsigned short cyls; /* "physical" cyls */ - unsigned short reserved2; /* reserved (word 2) */ - unsigned short heads; /* "physical" heads */ - unsigned short track_bytes; /* unformatted bytes per track */ - unsigned short sector_bytes; /* unformatted bytes per sector */ - unsigned short sectors; /* "physical" sectors per track */ - unsigned short vendor0; /* vendor unique */ - unsigned short vendor1; /* vendor unique */ - unsigned short vendor2; /* vendor unique */ - unsigned char serial_no[20]; /* 0 = not_specified */ - unsigned short buf_type; - unsigned short buf_size; /* 512 byte increments; 0 = not_specified */ - unsigned short ecc_bytes; /* for r/w long cmds; 0 = not_specified */ - unsigned char fw_rev[8]; /* 0 = not_specified */ - unsigned char model[40]; /* 0 = not_specified */ - unsigned char max_multsect; /* 0=not_implemented */ - unsigned char vendor3; /* vendor unique */ - unsigned short dword_io; /* 0=not_implemented; 1=implemented */ - unsigned char vendor4; /* vendor unique */ - unsigned char capability; /* bits 0:DMA 1:LBA 2:IORDYsw 3:IORDYsup*/ - unsigned short reserved50; /* reserved (word 50) */ - unsigned char vendor5; /* vendor unique */ - unsigned char tPIO; /* 0=slow, 1=medium, 2=fast */ - unsigned char vendor6; /* vendor unique */ - unsigned char tDMA; /* 0=slow, 1=medium, 2=fast */ - unsigned short field_valid; /* bits 0:cur_ok 1:eide_ok */ - unsigned short cur_cyls; /* logical cylinders */ - unsigned short cur_heads; /* logical heads */ - unsigned short cur_sectors; /* logical sectors per track */ - unsigned short cur_capacity0; /* logical total sectors on drive */ - unsigned short cur_capacity1; /* (2 words, misaligned int) */ - unsigned char multsect; /* current multiple sector count */ - unsigned char multsect_valid; /* when (bit0==1) multsect is ok */ - unsigned int lba_capacity; /* total number of sectors */ - unsigned short dma_1word; /* single-word dma info */ - unsigned short dma_mword; /* multiple-word dma info */ - unsigned short eide_pio_modes; /* bits 0:mode3 1:mode4 */ - unsigned short eide_dma_min; /* min mword dma cycle time (ns) */ - unsigned short eide_dma_time; /* recommended mword dma cycle time (ns) */ - unsigned short eide_pio; /* min cycle time (ns), no IORDY */ - unsigned short eide_pio_iordy; /* min cycle time (ns), with IORDY */ - unsigned short reserved69; /* reserved (word 69) */ - unsigned short reserved70; /* reserved (word 70) */ - /* unsigned short reservedxx[57];*/ /* reserved (words 71-127) */ - /* unsigned short vendor7 [32];*/ /* vendor unique (words 128-159) */ - /* unsigned short reservedyy[96];*/ /* reserved (words 160-255) */ -}; - -#ifdef __KERNEL__ -/* - * These routines are used for kernel command line parameters from main.c: - */ -#include <linux/config.h> - -#ifdef CONFIG_BLK_DEV_HD -void hd_setup(char *, int *); -#endif /* CONFIG_BLK_DEV_HD */ -#ifdef CONFIG_BLK_DEV_IDE -void ide_setup(char *); -#endif /* CONFIG_BLK_DEV_IDE */ - -#endif /* __KERNEL__ */ - -#endif /* _LINUX_HDREG_H */ diff --git a/i386/i386at/gpl/linux/include/linux/head.h b/i386/i386at/gpl/linux/include/linux/head.h deleted file mode 100644 index 3829b1c3..00000000 --- a/i386/i386at/gpl/linux/include/linux/head.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef _LINUX_HEAD_H -#define _LINUX_HEAD_H - -typedef struct desc_struct { - unsigned long a,b; -} desc_table[256]; - -extern desc_table idt,gdt; - -#define GDT_NUL 0 -#define GDT_CODE 1 -#define GDT_DATA 2 -#define GDT_TMP 3 - -#define LDT_NUL 0 -#define LDT_CODE 1 -#define LDT_DATA 2 - -#endif diff --git a/i386/i386at/gpl/linux/include/linux/if.h b/i386/i386at/gpl/linux/include/linux/if.h deleted file mode 100644 index 73ef7feb..00000000 --- a/i386/i386at/gpl/linux/include/linux/if.h +++ /dev/null @@ -1,167 +0,0 @@ -/* - * INET An implementation of the TCP/IP protocol suite for the LINUX - * operating system. INET is implemented using the BSD Socket - * interface as the means of communication with the user level. - * - * Global definitions for the INET interface module. - * - * Version: @(#)if.h 1.0.2 04/18/93 - * - * Authors: Original taken from Berkeley UNIX 4.3, (c) UCB 1982-1988 - * Ross Biro, <bir7@leland.Stanford.Edu> - * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ -#ifndef _LINUX_IF_H -#define _LINUX_IF_H - -#include <linux/types.h> /* for "caddr_t" et al */ -#include <linux/socket.h> /* for "struct sockaddr" et al */ - -/* Standard interface flags. */ -#define LINUX_IFF_UP 0x1 /* interface is up */ -#define LINUX_IFF_BROADCAST 0x2 /* broadcast address valid */ -#define LINUX_IFF_DEBUG 0x4 /* turn on debugging */ -#define LINUX_IFF_LOOPBACK 0x8 /* is a loopback net */ -#define LINUX_IFF_POINTOPOINT 0x10 /* interface is has p-p link */ -#define LINUX_IFF_NOTRAILERS 0x20 /* avoid use of trailers */ -#define LINUX_IFF_RUNNING 0x40 /* resources allocated */ -#define LINUX_IFF_NOARP 0x80 /* no ARP protocol */ -#define LINUX_IFF_PROMISC 0x100 /* receive all packets */ -/* Not supported */ -#define LINUX_IFF_ALLMULTI 0x200 /* receive all multicast packets*/ - -#define LINUX_IFF_MASTER 0x400 /* master of a load balancer */ -#define LINUX_IFF_SLAVE 0x800 /* slave of a load balancer */ - -#define LINUX_IFF_MULTICAST 0x1000 /* Supports multicast */ - -#ifdef MACH -#ifndef MACH_INCLUDE -#define IFF_UP LINUX_IFF_UP -#define IFF_BROADCAST LINUX_IFF_BROADCAST -#define IFF_DEBUG LINUX_IFF_DEBUG -#define IFF_LOOPBACK LINUX_IFF_LOOPBACK -#define IFF_POINTOPOINT LINUX_IFF_POINTOPOINT -#define IFF_NOTRAILERS LINUX_IFF_NOTRAILERS -#define IFF_RUNNING LINUX_IFF_RUNNING -#define IFF_NOARP LINUX_IFF_NOARP -#define IFF_PROMISC LINUX_IFF_PROMISC -#define IFF_ALLMULTI LINUX_IFF_ALLMULTI -#define IFF_MASTER LINUX_IFF_MASTER -#define IFF_SLAVE LINUX_IFF_SLAVE -#define IFF_MULTICAST LINUX_IFF_MULTICAST -#endif -#endif - -/* - * The ifaddr structure contains information about one address - * of an interface. They are maintained by the different address - * families, are allocated and attached when an address is set, - * and are linked together so all addresses for an interface can - * be located. - */ - -struct ifaddr -{ - struct sockaddr ifa_addr; /* address of interface */ - union { - struct sockaddr ifu_broadaddr; - struct sockaddr ifu_dstaddr; - } ifa_ifu; - struct iface *ifa_ifp; /* back-pointer to interface */ - struct ifaddr *ifa_next; /* next address for interface */ -}; - -#define ifa_broadaddr ifa_ifu.ifu_broadaddr /* broadcast address */ -#define ifa_dstaddr ifa_ifu.ifu_dstaddr /* other end of link */ - -/* - * Device mapping structure. I'd just gone off and designed a - * beautiful scheme using only loadable modules with arguments - * for driver options and along come the PCMCIA people 8) - * - * Ah well. The get() side of this is good for WDSETUP, and it'll - * be handy for debugging things. The set side is fine for now and - * being very small might be worth keeping for clean configuration. - */ - -struct ifmap -{ - unsigned long mem_start; - unsigned long mem_end; - unsigned short base_addr; - unsigned char irq; - unsigned char dma; - unsigned char port; - /* 3 bytes spare */ -}; - -/* - * Interface request structure used for socket - * ioctl's. All interface ioctl's must have parameter - * definitions which begin with ifr_name. The - * remainder may be interface specific. - */ - -struct ifreq -{ -#define IFHWADDRLEN 6 -#define IFNAMSIZ 16 - union - { - char ifrn_name[IFNAMSIZ]; /* if name, e.g. "en0" */ - } ifr_ifrn; - - union { - struct sockaddr ifru_addr; - struct sockaddr ifru_dstaddr; - struct sockaddr ifru_broadaddr; - struct sockaddr ifru_netmask; - struct sockaddr ifru_hwaddr; - short ifru_flags; - int ifru_metric; - int ifru_mtu; - struct ifmap ifru_map; - char ifru_slave[IFNAMSIZ]; /* Just fits the size */ - caddr_t ifru_data; - } ifr_ifru; -}; - -#define ifr_name ifr_ifrn.ifrn_name /* interface name */ -#define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */ -#define ifr_addr ifr_ifru.ifru_addr /* address */ -#define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-p lnk */ -#define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */ -#define ifr_netmask ifr_ifru.ifru_netmask /* interface net mask */ -#define ifr_flags ifr_ifru.ifru_flags /* flags */ -#define ifr_metric ifr_ifru.ifru_metric /* metric */ -#define ifr_mtu ifr_ifru.ifru_mtu /* mtu */ -#define ifr_map ifr_ifru.ifru_map /* device map */ -#define ifr_slave ifr_ifru.ifru_slave /* slave device */ -#define ifr_data ifr_ifru.ifru_data /* for use by interface */ - -/* - * Structure used in SIOCGIFCONF request. - * Used to retrieve interface configuration - * for machine (useful for programs which - * must know all networks accessible). - */ - -struct ifconf -{ - int ifc_len; /* size of buffer */ - union - { - caddr_t ifcu_buf; - struct ifreq *ifcu_req; - } ifc_ifcu; -}; -#define ifc_buf ifc_ifcu.ifcu_buf /* buffer address */ -#define ifc_req ifc_ifcu.ifcu_req /* array of structures */ - -#endif /* _LINUX_IF_H */ diff --git a/i386/i386at/gpl/linux/include/linux/if_arp.h b/i386/i386at/gpl/linux/include/linux/if_arp.h deleted file mode 100644 index fa350688..00000000 --- a/i386/i386at/gpl/linux/include/linux/if_arp.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * INET An implementation of the TCP/IP protocol suite for the LINUX - * operating system. INET is implemented using the BSD Socket - * interface as the means of communication with the user level. - * - * Global definitions for the ARP (RFC 826) protocol. - * - * Version: @(#)if_arp.h 1.0.1 04/16/93 - * - * Authors: Original taken from Berkeley UNIX 4.3, (c) UCB 1986-1988 - * Portions taken from the KA9Q/NOS (v2.00m PA0GRI) source. - * Ross Biro, <bir7@leland.Stanford.Edu> - * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> - * Florian La Roche. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ -#ifndef _LINUX_IF_ARP_H -#define _LINUX_IF_ARP_H - -/* ARP protocol HARDWARE identifiers. */ -#define ARPHRD_NETROM 0 /* from KA9Q: NET/ROM pseudo */ -#define ARPHRD_ETHER 1 /* Ethernet 10Mbps */ -#define ARPHRD_EETHER 2 /* Experimental Ethernet */ -#define ARPHRD_AX25 3 /* AX.25 Level 2 */ -#define ARPHRD_PRONET 4 /* PROnet token ring */ -#define ARPHRD_CHAOS 5 /* Chaosnet */ -#define ARPHRD_IEEE802 6 /* IEEE 802.2 Ethernet/TR/TB */ -#define ARPHRD_ARCNET 7 /* ARCnet */ -#define ARPHRD_APPLETLK 8 /* APPLEtalk */ -/* Dummy types for non ARP hardware */ -#define ARPHRD_SLIP 256 -#define ARPHRD_CSLIP 257 -#define ARPHRD_SLIP6 258 -#define ARPHRD_CSLIP6 259 -#define ARPHRD_RSRVD 260 /* Notional KISS type */ -#define ARPHRD_ADAPT 264 -#define ARPHRD_PPP 512 -#define ARPHRD_TUNNEL 768 /* IPIP tunnel */ -#define ARPHRD_TUNNEL6 769 /* IPIP6 tunnel */ -#define ARPHRD_FRAD 770 /* Frame Relay */ -#define ARPHRD_SKIP 771 /* SKIP vif */ -#define ARPHRD_LOOPBACK 772 /* Loopback device */ - -/* ARP protocol opcodes. */ -#define ARPOP_REQUEST 1 /* ARP request */ -#define ARPOP_REPLY 2 /* ARP reply */ -#define ARPOP_RREQUEST 3 /* RARP request */ -#define ARPOP_RREPLY 4 /* RARP reply */ - - -/* ARP ioctl request. */ -struct arpreq { - struct sockaddr arp_pa; /* protocol address */ - struct sockaddr arp_ha; /* hardware address */ - int arp_flags; /* flags */ - struct sockaddr arp_netmask; /* netmask (only for proxy arps) */ - char arp_dev[16]; -}; - -struct arpreq_old { - struct sockaddr arp_pa; /* protocol address */ - struct sockaddr arp_ha; /* hardware address */ - int arp_flags; /* flags */ - struct sockaddr arp_netmask; /* netmask (only for proxy arps) */ -}; - -/* ARP Flag values. */ -#define ATF_COM 0x02 /* completed entry (ha valid) */ -#define ATF_PERM 0x04 /* permanent entry */ -#define ATF_PUBL 0x08 /* publish entry */ -#define ATF_USETRAILERS 0x10 /* has requested trailers */ -#define ATF_NETMASK 0x20 /* want to use a netmask (only - for proxy entries) */ - -/* - * This structure defines an ethernet arp header. - */ - -struct arphdr -{ - unsigned short ar_hrd; /* format of hardware address */ - unsigned short ar_pro; /* format of protocol address */ - unsigned char ar_hln; /* length of hardware address */ - unsigned char ar_pln; /* length of protocol address */ - unsigned short ar_op; /* ARP opcode (command) */ - -#if 0 - /* - * Ethernet looks like this : This bit is variable sized however... - */ - unsigned char ar_sha[ETH_ALEN]; /* sender hardware address */ - unsigned char ar_sip[4]; /* sender IP address */ - unsigned char ar_tha[ETH_ALEN]; /* target hardware address */ - unsigned char ar_tip[4]; /* target IP address */ -#endif - -}; - -#endif /* _LINUX_IF_ARP_H */ diff --git a/i386/i386at/gpl/linux/include/linux/if_ether.h b/i386/i386at/gpl/linux/include/linux/if_ether.h deleted file mode 100644 index 14078472..00000000 --- a/i386/i386at/gpl/linux/include/linux/if_ether.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * INET An implementation of the TCP/IP protocol suite for the LINUX - * operating system. INET is implemented using the BSD Socket - * interface as the means of communication with the user level. - * - * Global definitions for the Ethernet IEEE 802.3 interface. - * - * Version: @(#)if_ether.h 1.0.1a 02/08/94 - * - * Author: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> - * Donald Becker, <becker@super.org> - * Alan Cox, <alan@cymru.net> - * Steve Whitehouse, <gw7rrm@eeshack3.swan.ac.uk> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ -#ifndef _LINUX_IF_ETHER_H -#define _LINUX_IF_ETHER_H - -/* IEEE 802.3 Ethernet magic constants. The frame sizes omit the preamble - and FCS/CRC (frame check sequence). */ -#define ETH_ALEN 6 /* Octets in one ethernet addr */ -#define ETH_HLEN 14 /* Total octets in header. */ -#define ETH_ZLEN 60 /* Min. octets in frame sans FCS */ -#define ETH_DATA_LEN 1500 /* Max. octets in payload */ -#define ETH_FRAME_LEN 1514 /* Max. octets in frame sans FCS */ - - -/* These are the defined Ethernet Protocol ID's. */ -#define ETH_P_LOOP 0x0060 /* Ethernet Loopback packet */ -#define ETH_P_ECHO 0x0200 /* Ethernet Echo packet */ -#define ETH_P_PUP 0x0400 /* Xerox PUP packet */ -#define ETH_P_IP 0x0800 /* Internet Protocol packet */ -#define ETH_P_X25 0x0805 /* CCITT X.25 */ -#define ETH_P_ARP 0x0806 /* Address Resolution packet */ -#define ETH_P_BPQ 0x08FF /* G8BPQ AX.25 Ethernet Packet [ NOT AN OFFICIALLY REGISTERED ID ] */ -#define ETH_P_DEC 0x6000 /* DEC Assigned proto */ -#define ETH_P_DNA_DL 0x6001 /* DEC DNA Dump/Load */ -#define ETH_P_DNA_RC 0x6002 /* DEC DNA Remote Console */ -#define ETH_P_DNA_RT 0x6003 /* DEC DNA Routing */ -#define ETH_P_LAT 0x6004 /* DEC LAT */ -#define ETH_P_DIAG 0x6005 /* DEC Diagnostics */ -#define ETH_P_CUST 0x6006 /* DEC Customer use */ -#define ETH_P_SCA 0x6007 /* DEC Systems Comms Arch */ -#define ETH_P_RARP 0x8035 /* Reverse Addr Res packet */ -#define ETH_P_ATALK 0x809B /* Appletalk DDP */ -#define ETH_P_AARP 0x80F3 /* Appletalk AARP */ -#define ETH_P_IPX 0x8137 /* IPX over DIX */ -#define ETH_P_IPV6 0x86DD /* IPv6 over bluebook */ -#define ETH_P_802_3 0x0001 /* Dummy type for 802.3 frames */ -#define ETH_P_AX25 0x0002 /* Dummy protocol id for AX.25 */ -#define ETH_P_ALL 0x0003 /* Every packet (be careful!!!) */ -#define ETH_P_802_2 0x0004 /* 802.2 frames */ -#define ETH_P_SNAP 0x0005 /* Internal only */ -#define ETH_P_DDCMP 0x0006 /* DEC DDCMP: Internal only */ -#define ETH_P_WAN_PPP 0x0007 /* Dummy type for WAN PPP frames*/ -#define ETH_P_PPP_MP 0x0008 /* Dummy type for PPP MP frames */ - -/* This is an Ethernet frame header. */ -struct ethhdr { - unsigned char h_dest[ETH_ALEN]; /* destination eth addr */ - unsigned char h_source[ETH_ALEN]; /* source ether addr */ - unsigned short h_proto; /* packet type ID field */ -}; - -/* Ethernet statistics collection data. */ -struct enet_statistics{ - int rx_packets; /* total packets received */ - int tx_packets; /* total packets transmitted */ - int rx_errors; /* bad packets received */ - int tx_errors; /* packet transmit problems */ - int rx_dropped; /* no space in linux buffers */ - int tx_dropped; /* no space available in linux */ - int multicast; /* multicast packets received */ - int collisions; - - /* detailed rx_errors: */ - int rx_length_errors; - int rx_over_errors; /* receiver ring buff overflow */ - int rx_crc_errors; /* recved pkt with crc error */ - int rx_frame_errors; /* recv'd frame alignment error */ - int rx_fifo_errors; /* recv'r fifo overrun */ - int rx_missed_errors; /* receiver missed packet */ - - /* detailed tx_errors */ - int tx_aborted_errors; - int tx_carrier_errors; - int tx_fifo_errors; - int tx_heartbeat_errors; - int tx_window_errors; -}; - -#endif /* _LINUX_IF_ETHER_H */ diff --git a/i386/i386at/gpl/linux/include/linux/if_tr.h b/i386/i386at/gpl/linux/include/linux/if_tr.h deleted file mode 100644 index 61629332..00000000 --- a/i386/i386at/gpl/linux/include/linux/if_tr.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * INET An implementation of the TCP/IP protocol suite for the LINUX - * operating system. INET is implemented using the BSD Socket - * interface as the means of communication with the user level. - * - * Global definitions for the Token-Ring IEEE 802.5 interface. - * - * Version: @(#)if_tr.h 0.0 07/11/94 - * - * Author: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> - * Donald Becker, <becker@super.org> - * Peter De Schrijver, <stud11@cc4.kuleuven.ac.be> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ -#ifndef _LINUX_IF_TR_H -#define _LINUX_IF_TR_H - - -/* IEEE 802.5 Token-Ring magic constants. The frame sizes omit the preamble - and FCS/CRC (frame check sequence). */ -#define TR_ALEN 6 /* Octets in one ethernet addr */ -#define TR_HLEN (sizeof(struct trh_hdr)+sizeof(struct trllc)) -#define AC 0x10 -#define LLC_FRAME 0x40 -#if 0 -#define ETH_HLEN 14 /* Total octets in header. */ -#define ETH_ZLEN 60 /* Min. octets in frame sans FCS */ -#define ETH_DATA_LEN 1500 /* Max. octets in payload */ -#define ETH_FRAME_LEN 1514 /* Max. octets in frame sans FCS */ -#endif - - -/* These are some defined Ethernet Protocol ID's. */ -#define ETH_P_IP 0x0800 /* Internet Protocol packet */ -#define ETH_P_ARP 0x0806 /* Address Resolution packet */ -#define ETH_P_RARP 0x8035 /* Reverse Addr Res packet */ - -/* LLC and SNAP constants */ -#define EXTENDED_SAP 0xAA -#define UI_CMD 0x03 - -/* This is an Token-Ring frame header. */ -struct trh_hdr { - unsigned char ac; /* access control field */ - unsigned char fc; /* frame control field */ - unsigned char daddr[TR_ALEN]; /* destination address */ - unsigned char saddr[TR_ALEN]; /* source address */ - unsigned short rcf; /* route control field */ - unsigned short rseg[8];/* routing registers */ -}; - -/* This is an Token-Ring LLC structure */ -struct trllc { - unsigned char dsap; /* destination SAP */ - unsigned char ssap; /* source SAP */ - unsigned char llc; /* LLC control field */ - unsigned char protid[3]; /* protocol id */ - unsigned short ethertype; /* ether type field */ -}; - - -/* Token-Ring statistics collection data. */ -struct tr_statistics{ - int rx_packets; /* total packets received */ - int tx_packets; /* total packets transmitted */ - int rx_errors; /* bad packets received */ - int tx_errors; /* packet transmit problems */ - int rx_dropped; /* no space in linux buffers */ - int tx_dropped; /* no space available in linux */ - int multicast; /* multicast packets received */ - int transmit_collision; - - /* detailed Token-Ring errors. See IBM Token-Ring Network Architecture - for more info */ - - int line_errors; - int internal_errors; - int burst_errors; - int A_C_errors; - int abort_delimiters; - int lost_frames; - int recv_congest_count; - int frame_copied_errors; - int frequency_errors; - int token_errors; - int dummy1; - -}; - -/* source routing stuff */ - -#define TR_RII 0x80 -#define TR_RCF_DIR_BIT 0x80 -#define TR_RCF_LEN_MASK 0x1f00 -#define TR_RCF_BROADCAST 0x8000 -#define TR_RCF_LIMITED_BROADCAST 0xA000 -#define TR_RCF_FRAME2K 0x20 -#define TR_RCF_BROADCAST_MASK 0xC000 - -#endif /* _LINUX_IF_TR_H */ diff --git a/i386/i386at/gpl/linux/include/linux/igmp.h b/i386/i386at/gpl/linux/include/linux/igmp.h deleted file mode 100644 index 161528f1..00000000 --- a/i386/i386at/gpl/linux/include/linux/igmp.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Linux NET3: Internet Gateway Management Protocol [IGMP] - * - * Authors: - * Alan Cox <Alan.Cox@linux.org> - * - * Extended to talk the BSD extended IGMP protocol of mrouted 3.6 - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#ifndef _LINUX_IGMP_H -#define _LINUX_IGMP_H - -/* - * IGMP protocol structures - */ - -/* - * Header in on cable format - */ - -struct igmphdr -{ - __u8 type; - __u8 code; /* For newer IGMP */ - __u16 csum; - __u32 group; -}; - -#define IGMP_HOST_MEMBERSHIP_QUERY 0x11 /* From RFC1112 */ -#define IGMP_HOST_MEMBERSHIP_REPORT 0x12 /* Ditto */ -#define IGMP_DVMRP 0x13 /* DVMRP routing */ -#define IGMP_PIM 0x14 /* PIM routing */ -#define IGMP_HOST_NEW_MEMBERSHIP_REPORT 0x16 /* New version of 0x11 */ -#define IGMP_HOST_LEAVE_MESSAGE 0x17 /* An extra BSD seems to send */ - -#define IGMP_MTRACE_RESP 0x1e -#define IGMP_MTRACE 0x1f - - -/* - * Use the BSD names for these for compatibility - */ - -#define IGMP_DELAYING_MEMBER 0x01 -#define IGMP_IDLE_MEMBER 0x02 -#define IGMP_LAZY_MEMBER 0x03 -#define IGMP_SLEEPING_MEMBER 0x04 -#define IGMP_AWAKENING_MEMBER 0x05 - -#define IGMP_OLD_ROUTER 0x00 -#define IGMP_NEW_ROUTER 0x01 - -#define IGMP_MINLEN 8 - -#define IGMP_MAX_HOST_REPORT_DELAY 10 /* max delay for response to */ - /* query (in seconds) */ - -#define IGMP_TIMER_SCALE 10 /* denotes that the igmphdr->timer field */ - /* specifies time in 10th of seconds */ - -#define IGMP_AGE_THRESHOLD 540 /* If this host don't hear any IGMP V1 */ - /* message in this period of time, */ - /* revert to IGMP v2 router. */ - -#define IGMP_ALL_HOSTS htonl(0xE0000001L) -#define IGMP_ALL_ROUTER htonl(0xE0000002L) -#define IGMP_LOCAL_GROUP htonl(0xE0000000L) -#define IGMP_LOCAL_GROUP_MASK htonl(0xFFFFFF00L) - -/* - * struct for keeping the multicast list in - */ - -#ifdef __KERNEL__ -struct ip_mc_socklist -{ - unsigned long multiaddr[IP_MAX_MEMBERSHIPS]; /* This is a speed trade off */ - struct device *multidev[IP_MAX_MEMBERSHIPS]; -}; - -struct ip_mc_list -{ - struct device *interface; - unsigned long multiaddr; - struct ip_mc_list *next; - struct timer_list timer; - int tm_running; - int users; -}; - -struct ip_router_info -{ - struct device *dev; - int type; /* type of router which is querier on this interface */ - int time; /* # of slow timeouts since last old query */ - struct timer_list timer; - struct ip_router_info *next; -}; - -extern struct ip_mc_list *ip_mc_head; - - -extern int igmp_rcv(struct sk_buff *, struct device *, struct options *, __u32, unsigned short, - __u32, int , struct inet_protocol *); -extern void ip_mc_drop_device(struct device *dev); -extern int ip_mc_join_group(struct sock *sk, struct device *dev, unsigned long addr); -extern int ip_mc_leave_group(struct sock *sk, struct device *dev,unsigned long addr); -extern void ip_mc_drop_socket(struct sock *sk); -extern void ip_mr_init(void); -#endif -#endif diff --git a/i386/i386at/gpl/linux/include/linux/in.h b/i386/i386at/gpl/linux/include/linux/in.h deleted file mode 100644 index c8e156e8..00000000 --- a/i386/i386at/gpl/linux/include/linux/in.h +++ /dev/null @@ -1,149 +0,0 @@ -/* - * INET An implementation of the TCP/IP protocol suite for the LINUX - * operating system. INET is implemented using the BSD Socket - * interface as the means of communication with the user level. - * - * Definitions of the Internet Protocol. - * - * Version: @(#)in.h 1.0.1 04/21/93 - * - * Authors: Original taken from the GNU Project <netinet/in.h> file. - * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ -#ifndef _LINUX_IN_H -#define _LINUX_IN_H - -#include <linux/types.h> - -/* Standard well-defined IP protocols. */ -enum { - IPPROTO_IP = 0, /* Dummy protocol for TCP */ - IPPROTO_ICMP = 1, /* Internet Control Message Protocol */ - IPPROTO_IGMP = 2, /* Internet Gateway Management Protocol */ - IPPROTO_IPIP = 4, /* IPIP tunnels (older KA9Q tunnels use 94) */ - IPPROTO_TCP = 6, /* Transmission Control Protocol */ - IPPROTO_EGP = 8, /* Exterior Gateway Protocol */ - IPPROTO_PUP = 12, /* PUP protocol */ - IPPROTO_UDP = 17, /* User Datagram Protocol */ - IPPROTO_IDP = 22, /* XNS IDP protocol */ - - IPPROTO_RAW = 255, /* Raw IP packets */ - IPPROTO_MAX -}; - - -/* Internet address. */ -struct in_addr { - __u32 s_addr; -}; - -/* Request struct for multicast socket ops */ - -struct ip_mreq -{ - struct in_addr imr_multiaddr; /* IP multicast address of group */ - struct in_addr imr_interface; /* local IP address of interface */ -}; - - -/* Structure describing an Internet (IP) socket address. */ -#define __SOCK_SIZE__ 16 /* sizeof(struct sockaddr) */ -struct sockaddr_in { - short int sin_family; /* Address family */ - unsigned short int sin_port; /* Port number */ - struct in_addr sin_addr; /* Internet address */ - - /* Pad to size of `struct sockaddr'. */ - unsigned char __pad[__SOCK_SIZE__ - sizeof(short int) - - sizeof(unsigned short int) - sizeof(struct in_addr)]; -}; -#define sin_zero __pad /* for BSD UNIX comp. -FvK */ - - -/* - * Definitions of the bits in an Internet address integer. - * On subnets, host and network parts are found according - * to the subnet mask, not these masks. - */ -#define IN_CLASSA(a) ((((long int) (a)) & 0x80000000) == 0) -#define IN_CLASSA_NET 0xff000000 -#define IN_CLASSA_NSHIFT 24 -#define IN_CLASSA_HOST (0xffffffff & ~IN_CLASSA_NET) -#define IN_CLASSA_MAX 128 - -#define IN_CLASSB(a) ((((long int) (a)) & 0xc0000000) == 0x80000000) -#define IN_CLASSB_NET 0xffff0000 -#define IN_CLASSB_NSHIFT 16 -#define IN_CLASSB_HOST (0xffffffff & ~IN_CLASSB_NET) -#define IN_CLASSB_MAX 65536 - -#define IN_CLASSC(a) ((((long int) (a)) & 0xe0000000) == 0xc0000000) -#define IN_CLASSC_NET 0xffffff00 -#define IN_CLASSC_NSHIFT 8 -#define IN_CLASSC_HOST (0xffffffff & ~IN_CLASSC_NET) - -#define IN_CLASSD(a) ((((long int) (a)) & 0xf0000000) == 0xe0000000) -#define IN_MULTICAST(a) IN_CLASSD(a) -#define IN_MULTICAST_NET 0xF0000000 - -#define IN_EXPERIMENTAL(a) ((((long int) (a)) & 0xe0000000) == 0xe0000000) -#define IN_BADCLASS(a) ((((long int) (a)) & 0xf0000000) == 0xf0000000) - -/* Address to accept any incoming messages. */ -#define INADDR_ANY ((unsigned long int) 0x00000000) - -/* Address to send to all hosts. */ -#define INADDR_BROADCAST ((unsigned long int) 0xffffffff) - -/* Address indicating an error return. */ -#define INADDR_NONE 0xffffffff - -/* Network number for local host loopback. */ -#define IN_LOOPBACKNET 127 - -/* Address to loopback in software to local host. */ -#define INADDR_LOOPBACK 0x7f000001 /* 127.0.0.1 */ -#define IN_LOOPBACK(a) ((((long int) (a)) & 0xff000000) == 0x7f000000) - -/* Defines for Multicast INADDR */ -#define INADDR_UNSPEC_GROUP 0xe0000000 /* 224.0.0.0 */ -#define INADDR_ALLHOSTS_GROUP 0xe0000001 /* 224.0.0.1 */ -#define INADDR_MAX_LOCAL_GROUP 0xe00000ff /* 224.0.0.255 */ - -/* <asm/byteorder.h> contains the htonl type stuff.. */ - -#include <asm/byteorder.h> - -/* Some random defines to make it easier in the kernel.. */ -#ifdef __KERNEL__ - -#define LOOPBACK(x) (((x) & htonl(0xff000000)) == htonl(0x7f000000)) -#define MULTICAST(x) (((x) & htonl(0xf0000000)) == htonl(0xe0000000)) - -#endif - -/* - * IPv6 definitions as we start to include them. This is just - * a beginning dont get excited 8) - */ - -struct in_addr6 -{ - unsigned char s6_addr[16]; -}; - -struct sockaddr_in6 -{ - unsigned short sin6_family; - unsigned short sin6_port; - unsigned long sin6_flowinfo; - struct in_addr6 sin6_addr; -}; - - -#endif /* _LINUX_IN_H */ diff --git a/i386/i386at/gpl/linux/include/linux/inet.h b/i386/i386at/gpl/linux/include/linux/inet.h deleted file mode 100644 index 9ecc9cb3..00000000 --- a/i386/i386at/gpl/linux/include/linux/inet.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Swansea University Computer Society NET3 - * - * This work is derived from NET2Debugged, which is in turn derived - * from NET2D which was written by: - * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> - * - * This work was derived from Ross Biro's inspirational work - * for the LINUX operating system. His version numbers were: - * - * $Id: inet.h,v 1.1.1.1 1997/02/25 21:27:28 thomas Exp $ - * $Id: inet.h,v 1.1.1.1 1997/02/25 21:27:28 thomas Exp $ - * $Id: inet.h,v 1.1.1.1 1997/02/25 21:27:28 thomas Exp $ - * $Id: inet.h,v 1.1.1.1 1997/02/25 21:27:28 thomas Exp $ - * $Id: inet.h,v 1.1.1.1 1997/02/25 21:27:28 thomas Exp $ - * $Id: inet.h,v 1.1.1.1 1997/02/25 21:27:28 thomas Exp $ - * $Id: inet.h,v 1.1.1.1 1997/02/25 21:27:28 thomas Exp $ - * $Id: inet.h,v 1.1.1.1 1997/02/25 21:27:28 thomas Exp $ - * $Id: inet.h,v 1.1.1.1 1997/02/25 21:27:28 thomas Exp $ - * $Id: inet.h,v 1.1.1.1 1997/02/25 21:27:28 thomas Exp $ - * $Id: inet.h,v 1.1.1.1 1997/02/25 21:27:28 thomas Exp $ - * $Id: inet.h,v 1.1.1.1 1997/02/25 21:27:28 thomas Exp $ - * $Id: inet.h,v 1.1.1.1 1997/02/25 21:27:28 thomas Exp $ - * $Id: inet.h,v 1.1.1.1 1997/02/25 21:27:28 thomas Exp $ - * $Id: inet.h,v 1.1.1.1 1997/02/25 21:27:28 thomas Exp $ - * $Id: inet.h,v 1.1.1.1 1997/02/25 21:27:28 thomas Exp $ - * $Id: inet.h,v 1.1.1.1 1997/02/25 21:27:28 thomas Exp $ - * $Id: inet.h,v 1.1.1.1 1997/02/25 21:27:28 thomas Exp $ - * $Id: inet.h,v 1.1.1.1 1997/02/25 21:27:28 thomas Exp $ - * $Id: inet.h,v 1.1.1.1 1997/02/25 21:27:28 thomas Exp $ - * $Id: inet.h,v 1.1.1.1 1997/02/25 21:27:28 thomas Exp $ - * $Id: inet.h,v 1.1.1.1 1997/02/25 21:27:28 thomas Exp $ - * $Id: inet.h,v 1.1.1.1 1997/02/25 21:27:28 thomas Exp $ - * $Id: inet.h,v 1.1.1.1 1997/02/25 21:27:28 thomas Exp $ - * $Id: inet.h,v 1.1.1.1 1997/02/25 21:27:28 thomas Exp $ - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ -#ifndef _LINUX_INET_H -#define _LINUX_INET_H - -#ifdef __KERNEL__ - -extern void inet_proto_init(struct net_proto *pro); -extern char *in_ntoa(unsigned long in); -extern unsigned long in_aton(const char *str); - -#endif -#endif /* _LINUX_INET_H */ diff --git a/i386/i386at/gpl/linux/include/linux/interrupt.h b/i386/i386at/gpl/linux/include/linux/interrupt.h deleted file mode 100644 index a20cbe8e..00000000 --- a/i386/i386at/gpl/linux/include/linux/interrupt.h +++ /dev/null @@ -1,91 +0,0 @@ -/* interrupt.h */ -#ifndef _LINUX_INTERRUPT_H -#define _LINUX_INTERRUPT_H - -#include <linux/kernel.h> -#include <asm/bitops.h> - -struct bh_struct { - void (*routine)(void *); - void *data; -}; - -extern unsigned long bh_active; -extern unsigned long bh_mask; -extern struct bh_struct bh_base[32]; - -asmlinkage void do_bottom_half(void); - -/* Who gets which entry in bh_base. Things which will occur most often - should come first - in which case NET should be up the top with SERIAL/TQUEUE! */ - -enum { - TIMER_BH = 0, - CONSOLE_BH, - TQUEUE_BH, - SERIAL_BH, - NET_BH, - IMMEDIATE_BH, - KEYBOARD_BH, - CYCLADES_BH, - CM206_BH -}; - -extern inline void mark_bh(int nr) -{ - set_bit(nr, &bh_active); -} - -extern inline void disable_bh(int nr) -{ - clear_bit(nr, &bh_mask); -} - -extern inline void enable_bh(int nr) -{ - set_bit(nr, &bh_mask); -} - -extern inline void start_bh_atomic(void) -{ - intr_count++; - barrier(); -} - -extern inline void end_bh_atomic(void) -{ - barrier(); - intr_count--; -} - -/* - * Autoprobing for irqs: - * - * probe_irq_on() and probe_irq_off() provide robust primitives - * for accurate IRQ probing during kernel initialization. They are - * reasonably simple to use, are not "fooled" by spurious interrupts, - * and, unlike other attempts at IRQ probing, they do not get hung on - * stuck interrupts (such as unused PS2 mouse interfaces on ASUS boards). - * - * For reasonably foolproof probing, use them as follows: - * - * 1. clear and/or mask the device's internal interrupt. - * 2. sti(); - * 3. irqs = probe_irq_on(); // "take over" all unassigned idle IRQs - * 4. enable the device and cause it to trigger an interrupt. - * 5. wait for the device to interrupt, using non-intrusive polling or a delay. - * 6. irq = probe_irq_off(irqs); // get IRQ number, 0=none, negative=multiple - * 7. service the device to clear its pending interrupt. - * 8. loop again if paranoia is required. - * - * probe_irq_on() returns a mask of allocated irq's. - * - * probe_irq_off() takes the mask as a parameter, - * and returns the irq number which occurred, - * or zero if none occurred, or a negative irq number - * if more than one irq occurred. - */ -extern unsigned long probe_irq_on(void); /* returns 0 on failure */ -extern int probe_irq_off(unsigned long); /* returns 0 or negative on failure */ - -#endif diff --git a/i386/i386at/gpl/linux/include/linux/ioctl.h b/i386/i386at/gpl/linux/include/linux/ioctl.h deleted file mode 100644 index aa91eb39..00000000 --- a/i386/i386at/gpl/linux/include/linux/ioctl.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef _LINUX_IOCTL_H -#define _LINUX_IOCTL_H - -#include <asm/ioctl.h> - -#endif /* _LINUX_IOCTL_H */ - diff --git a/i386/i386at/gpl/linux/include/linux/ioport.h b/i386/i386at/gpl/linux/include/linux/ioport.h deleted file mode 100644 index 335e3b65..00000000 --- a/i386/i386at/gpl/linux/include/linux/ioport.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * portio.h Definitions of routines for detecting, reserving and - * allocating system resources. - * - * Version: 0.01 8/30/93 - * - * Author: Donald Becker (becker@super.org) - */ - -#ifndef _LINUX_PORTIO_H -#define _LINUX_PORTIO_H - -#define HAVE_PORTRESERVE -/* - * Call check_region() before probing for your hardware. - * Once you have found you hardware, register it with request_region(). - * If you unload the driver, use release_region to free ports. - */ -extern void reserve_setup(char *str, int *ints); -extern int check_region(unsigned int from, unsigned int extent); -extern void request_region(unsigned int from, unsigned int extent,const char *name); -extern void release_region(unsigned int from, unsigned int extent); -extern int get_ioport_list(char *); - - -#define HAVE_AUTOIRQ -extern void *irq2dev_map[16]; /* Use only if you own the IRQ. */ -extern int autoirq_setup(int waittime); -extern int autoirq_report(int waittime); - -#endif /* _LINUX_PORTIO_H */ diff --git a/i386/i386at/gpl/linux/include/linux/ip.h b/i386/i386at/gpl/linux/include/linux/ip.h deleted file mode 100644 index 4d5d70c1..00000000 --- a/i386/i386at/gpl/linux/include/linux/ip.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - * INET An implementation of the TCP/IP protocol suite for the LINUX - * operating system. INET is implemented using the BSD Socket - * interface as the means of communication with the user level. - * - * Definitions for the IP protocol. - * - * Version: @(#)ip.h 1.0.2 04/28/93 - * - * Authors: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ -#ifndef _LINUX_IP_H -#define _LINUX_IP_H -#include <asm/byteorder.h> - -#define IPOPT_END 0 -#define IPOPT_NOOP 1 -#define IPOPT_SEC 130 -#define IPOPT_LSRR 131 -#define IPOPT_SSRR 137 -#define IPOPT_RR 7 -#define IPOPT_SID 136 -#define IPOPT_TIMESTAMP 68 - - -#define MAXTTL 255 - -struct timestamp { - __u8 len; - __u8 ptr; -#if defined(__LITTLE_ENDIAN_BITFIELD) - __u8 flags:4, - overflow:4; -#elif defined(__BIG_ENDIAN_BITFIELD) - __u8 overflow:4, - flags:4; -#else -#error "Please fix <asm/byteorder.h>" -#endif - __u32 data[9]; -}; - - -#define MAX_ROUTE 16 - -struct route { - char route_size; - char pointer; - unsigned long route[MAX_ROUTE]; -}; - -#define IPOPT_OPTVAL 0 -#define IPOPT_OLEN 1 -#define IPOPT_OFFSET 2 -#define IPOPT_MINOFF 4 -#define MAX_IPOPTLEN 40 -#define IPOPT_NOP IPOPT_NOOP -#define IPOPT_EOL IPOPT_END -#define IPOPT_TS IPOPT_TIMESTAMP - -#define IPOPT_TS_TSONLY 0 /* timestamps only */ -#define IPOPT_TS_TSANDADDR 1 /* timestamps and addresses */ -#define IPOPT_TS_PRESPEC 2 /* specified modules only */ - -struct options { - __u32 faddr; /* Saved first hop address */ - unsigned char optlen; - unsigned char srr; - unsigned char rr; - unsigned char ts; - unsigned char is_setbyuser:1, /* Set by setsockopt? */ - is_data:1, /* Options in __data, rather than skb */ - is_strictroute:1, /* Strict source route */ - srr_is_hit:1, /* Packet destination addr was our one */ - is_changed:1, /* IP checksum more not valid */ - rr_needaddr:1, /* Need to record addr of outgoing dev */ - ts_needtime:1, /* Need to record timestamp */ - ts_needaddr:1; /* Need to record addr of outgoing dev */ - unsigned char __pad1; - unsigned char __pad2; - unsigned char __pad3; - unsigned char __data[0]; -}; - -struct iphdr { -#if defined(__LITTLE_ENDIAN_BITFIELD) - __u8 ihl:4, - version:4; -#elif defined (__BIG_ENDIAN_BITFIELD) - __u8 version:4, - ihl:4; -#else -#error "Please fix <asm/byteorder.h>" -#endif - __u8 tos; - __u16 tot_len; - __u16 id; - __u16 frag_off; - __u8 ttl; - __u8 protocol; - __u16 check; - __u32 saddr; - __u32 daddr; - /*The options start here. */ -}; - - -#endif /* _LINUX_IP_H */ diff --git a/i386/i386at/gpl/linux/include/linux/ipc.h b/i386/i386at/gpl/linux/include/linux/ipc.h deleted file mode 100644 index 3878e020..00000000 --- a/i386/i386at/gpl/linux/include/linux/ipc.h +++ /dev/null @@ -1,67 +0,0 @@ -#ifndef _LINUX_IPC_H -#define _LINUX_IPC_H -#include <linux/types.h> - -typedef int key_t; /* should go in <types.h> type for IPC key */ -#define IPC_PRIVATE ((key_t) 0) - -struct ipc_perm -{ - key_t key; - ushort uid; /* owner euid and egid */ - ushort gid; - ushort cuid; /* creator euid and egid */ - ushort cgid; - ushort mode; /* access modes see mode flags below */ - ushort seq; /* sequence number */ -}; - - -/* resource get request flags */ -#define IPC_CREAT 00001000 /* create if key is nonexistent */ -#define IPC_EXCL 00002000 /* fail if key exists */ -#define IPC_NOWAIT 00004000 /* return error on wait */ - - -/* - * Control commands used with semctl, msgctl and shmctl - * see also specific commands in sem.h, msg.h and shm.h - */ -#define IPC_RMID 0 /* remove resource */ -#define IPC_SET 1 /* set ipc_perm options */ -#define IPC_STAT 2 /* get ipc_perm options */ -#define IPC_INFO 3 /* see ipcs */ - -#ifdef __KERNEL__ - -/* special shmsegs[id], msgque[id] or semary[id] values */ -#define IPC_UNUSED ((void *) -1) -#define IPC_NOID ((void *) -2) /* being allocated/destroyed */ - -/* - * These are used to wrap system calls. See ipc/util.c. - */ -struct ipc_kludge { - struct msgbuf *msgp; - long msgtyp; -}; - -#define SEMOP 1 -#define SEMGET 2 -#define SEMCTL 3 -#define MSGSND 11 -#define MSGRCV 12 -#define MSGGET 13 -#define MSGCTL 14 -#define SHMAT 21 -#define SHMDT 22 -#define SHMGET 23 -#define SHMCTL 24 - -#define IPCCALL(version,op) ((version)<<16 | (op)) - -#endif /* __KERNEL__ */ - -#endif /* _LINUX_IPC_H */ - - diff --git a/i386/i386at/gpl/linux/include/linux/kdev_t.h b/i386/i386at/gpl/linux/include/linux/kdev_t.h deleted file mode 100644 index 0497ea8c..00000000 --- a/i386/i386at/gpl/linux/include/linux/kdev_t.h +++ /dev/null @@ -1,114 +0,0 @@ -#ifndef _LINUX_KDEV_T_H -#define _LINUX_KDEV_T_H -#ifdef __KERNEL__ -/* -As a preparation for the introduction of larger device numbers, -we introduce a type kdev_t to hold them. No information about -this type is known outside of this include file. - -Objects of type kdev_t designate a device. Outside of the kernel -the corresponding things are objects of type dev_t - usually an -integral type with the device major and minor in the high and low -bits, respectively. Conversion is done by - -extern kdev_t to_kdev_t(int); - -It is up to the various file systems to decide how objects of type -dev_t are stored on disk. -The only other point of contact between kernel and outside world -are the system calls stat and mknod, new versions of which will -eventually have to be used in libc. - -[Unfortunately, the floppy control ioctls fail to hide the internal -kernel structures, and the fd_device field of a struct floppy_drive_struct -is user-visible. So, it remains a dev_t for the moment, with some ugly -conversions in floppy.c.] - -Inside the kernel, we aim for a kdev_t type that is a pointer -to a structure with information about the device (like major, -minor, size, blocksize, sectorsize, name, read-only flag, -struct file_operations etc.). - -However, for the time being we let kdev_t be almost the same as dev_t: - -typedef struct { unsigned short major, minor; } kdev_t; - -Admissible operations on an object of type kdev_t: -- passing it along -- comparing it for equality with another such object -- storing it in ROOT_DEV, inode->i_dev, inode->i_rdev, sb->s_dev, - bh->b_dev, req->rq_dev, de->dc_dev, tty->device -- using its bit pattern as argument in a hash function -- finding its major and minor -- complaining about it - -An object of type kdev_t is created only by the function MKDEV(), -with the single exception of the constant 0 (no device). - -Right now the other information mentioned above is usually found -in static arrays indexed by major or major,minor. - -An obstacle to immediately using - typedef struct { ... (* lots of information *) } *kdev_t -is the case of mknod used to create a block device that the -kernel doesn't know about at present (but first learns about -when some module is inserted). - -aeb - 950811 -*/ - -/* Since MINOR(dev) is used as index in static arrays, - the kernel is not quite ready yet for larger minors. - However, everything runs fine with an arbitrary kdev_t type. */ - -#define MINORBITS 8 -#define MINORMASK ((1<<MINORBITS) - 1) - -typedef unsigned short kdev_t; - -#define MAJOR(dev) ((dev) >> MINORBITS) -#define MINOR(dev) ((dev) & MINORMASK) -#define HASHDEV(dev) (dev) -#define NODEV 0 -#define MKDEV(ma,mi) (((ma) << MINORBITS) | (mi)) -#define B_FREE 0xffff /* yuk */ - -extern char * kdevname(kdev_t); /* note: returns pointer to static data! */ - -/* -As long as device numbers in the outside world have 16 bits only, -we use these conversions. -*/ - -static inline unsigned int kdev_t_to_nr(kdev_t dev) { - return (MAJOR(dev)<<8) | MINOR(dev); -} - -static inline kdev_t to_kdev_t(int dev) -{ - int major, minor; -#if 0 - major = (dev >> 16); - if (!major) { - major = (dev >> 8); - minor = (dev & 0xff); - } else - minor = (dev & 0xffff); -#else - major = (dev >> 8); - minor = (dev & 0xff); -#endif - return MKDEV(major, minor); -} - -#else /* __KERNEL__ */ - -/* -Some programs want their definitions of MAJOR and MINOR and MKDEV -from the kernel sources. These must be the externally visible ones. -*/ -#define MAJOR(dev) ((dev)>>8) -#define MINOR(dev) ((dev) & 0xff) -#define MKDEV(ma,mi) ((ma)<<8 | (mi)) -#endif /* __KERNEL__ */ -#endif diff --git a/i386/i386at/gpl/linux/include/linux/kernel.h b/i386/i386at/gpl/linux/include/linux/kernel.h deleted file mode 100644 index d4985576..00000000 --- a/i386/i386at/gpl/linux/include/linux/kernel.h +++ /dev/null @@ -1,94 +0,0 @@ -#ifndef _LINUX_KERNEL_H -#define _LINUX_KERNEL_H - -/* - * 'kernel.h' contains some often-used function prototypes etc - */ - -#ifdef __KERNEL__ - -#include <stdarg.h> -#include <linux/linkage.h> - -#define INT_MAX ((int)(~0U>>1)) -#define UINT_MAX (~0U) -#define LONG_MAX ((long)(~0UL>>1)) -#define ULONG_MAX (~0UL) - -#define STACK_MAGIC 0xdeadbeef - -#define KERN_EMERG "<0>" /* system is unusable */ -#define KERN_ALERT "<1>" /* action must be taken immediately */ -#define KERN_CRIT "<2>" /* critical conditions */ -#define KERN_ERR "<3>" /* error conditions */ -#define KERN_WARNING "<4>" /* warning conditions */ -#define KERN_NOTICE "<5>" /* normal but significant condition */ -#define KERN_INFO "<6>" /* informational */ -#define KERN_DEBUG "<7>" /* debug-level messages */ - -#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) -# define NORET_TYPE __volatile__ -# define ATTRIB_NORET /**/ -# define NORET_AND /**/ -#else -# define NORET_TYPE /**/ -# define ATTRIB_NORET __attribute__((noreturn)) -# define NORET_AND noreturn, -#endif - -extern void math_error(void); -NORET_TYPE void panic(const char * fmt, ...) - __attribute__ ((NORET_AND format (printf, 1, 2))); -NORET_TYPE void do_exit(long error_code) - ATTRIB_NORET; -extern unsigned long simple_strtoul(const char *,char **,unsigned int); -extern int linux_sprintf(char * buf, const char * fmt, ...); -extern int linux_vsprintf(char *buf, const char *, va_list); -#ifndef MACH_INCLUDE -#define sprintf linux_sprintf -#define vsprintf linux_vsprintf -#endif - -extern int session_of_pgrp(int pgrp); - -extern int kill_proc(int pid, int sig, int priv); -extern int kill_pg(int pgrp, int sig, int priv); -extern int kill_sl(int sess, int sig, int priv); - -asmlinkage int printk(const char * fmt, ...) - __attribute__ ((format (printf, 1, 2))); - -/* - * This is defined as a macro, but at some point this might become a - * real subroutine that sets a flag if it returns true (to do - * BSD-style accounting where the process is flagged if it uses root - * privs). The implication of this is that you should do normal - * permissions checks first, and check suser() last. - * - * "suser()" checks against the effective user id, while "fsuser()" - * is used for file permission checking and checks against the fsuid.. - */ -#ifdef MACH -#define suser() 1 -#else -#define suser() (current->euid == 0) -#endif -#define fsuser() (current->fsuid == 0) - -#endif /* __KERNEL__ */ - -#define SI_LOAD_SHIFT 16 -struct sysinfo { - long uptime; /* Seconds since boot */ - unsigned long loads[3]; /* 1, 5, and 15 minute load averages */ - unsigned long totalram; /* Total usable main memory size */ - unsigned long freeram; /* Available memory size */ - unsigned long sharedram; /* Amount of shared memory */ - unsigned long bufferram; /* Memory used by buffers */ - unsigned long totalswap; /* Total swap space size */ - unsigned long freeswap; /* swap space still available */ - unsigned short procs; /* Number of current processes */ - char _f[22]; /* Pads structure to 64 bytes */ -}; - -#endif diff --git a/i386/i386at/gpl/linux/include/linux/kernel_stat.h b/i386/i386at/gpl/linux/include/linux/kernel_stat.h deleted file mode 100644 index 1966490a..00000000 --- a/i386/i386at/gpl/linux/include/linux/kernel_stat.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef _LINUX_KERNEL_STAT_H -#define _LINUX_KERNEL_STAT_H - -#include <asm/irq.h> - -/* - * 'kernel_stat.h' contains the definitions needed for doing - * some kernel statistics (cpu usage, context switches ...), - * used by rstatd/perfmeter - */ - -#define DK_NDRIVE 4 - -struct kernel_stat { - unsigned int cpu_user, cpu_nice, cpu_system; - unsigned int dk_drive[DK_NDRIVE]; - unsigned int dk_drive_rio[DK_NDRIVE]; - unsigned int dk_drive_wio[DK_NDRIVE]; - unsigned int dk_drive_rblk[DK_NDRIVE]; - unsigned int dk_drive_wblk[DK_NDRIVE]; - unsigned int pgpgin, pgpgout; - unsigned int pswpin, pswpout; - unsigned int interrupts[NR_IRQS]; - unsigned int ipackets, opackets; - unsigned int ierrors, oerrors; - unsigned int collisions; - unsigned int context_swtch; -}; - -extern struct kernel_stat kstat; - -#endif /* _LINUX_KERNEL_STAT_H */ diff --git a/i386/i386at/gpl/linux/include/linux/limits.h b/i386/i386at/gpl/linux/include/linux/limits.h deleted file mode 100644 index d0f300c4..00000000 --- a/i386/i386at/gpl/linux/include/linux/limits.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef _LINUX_LIMITS_H -#define _LINUX_LIMITS_H - -#define NR_OPEN 256 - -#define NGROUPS_MAX 32 /* supplemental group IDs are available */ -#define ARG_MAX 131072 /* # bytes of args + environ for exec() */ -#define CHILD_MAX 999 /* no limit :-) */ -#define OPEN_MAX 256 /* # open files a process may have */ -#define LINK_MAX 127 /* # links a file may have */ -#define MAX_CANON 255 /* size of the canonical input queue */ -#define MAX_INPUT 255 /* size of the type-ahead buffer */ -#define NAME_MAX 255 /* # chars in a file name */ -#define PATH_MAX 1024 /* # chars in a path name */ -#define PIPE_BUF 4096 /* # bytes in atomic write to a pipe */ - -#endif diff --git a/i386/i386at/gpl/linux/include/linux/linkage.h b/i386/i386at/gpl/linux/include/linux/linkage.h deleted file mode 100644 index c8a7a491..00000000 --- a/i386/i386at/gpl/linux/include/linux/linkage.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef _LINUX_LINKAGE_H -#define _LINUX_LINKAGE_H - -#ifdef __cplusplus -#define asmlinkage extern "C" -#else -#define asmlinkage -#endif - -#ifdef __ELF__ -#define SYMBOL_NAME_STR(X) #X -#define SYMBOL_NAME(X) X -#ifdef __STDC__ -#define SYMBOL_NAME_LABEL(X) X##: -#else -#define SYMBOL_NAME_LABEL(X) X/**/: -#endif -#else -#define SYMBOL_NAME_STR(X) "_"#X -#ifdef __STDC__ -#define SYMBOL_NAME(X) _##X -#define SYMBOL_NAME_LABEL(X) _##X##: -#else -#define SYMBOL_NAME(X) _/**/X -#define SYMBOL_NAME_LABEL(X) _/**/X/**/: -#endif -#endif - -#if !defined(__i486__) && !defined(__i586__) -#ifdef __ELF__ -#define __ALIGN .align 4,0x90 -#define __ALIGN_STR ".align 4,0x90" -#else /* __ELF__ */ -#define __ALIGN .align 2,0x90 -#define __ALIGN_STR ".align 2,0x90" -#endif /* __ELF__ */ -#else /* __i486__/__i586__ */ -#ifdef __ELF__ -#define __ALIGN .align 16,0x90 -#define __ALIGN_STR ".align 16,0x90" -#else /* __ELF__ */ -#define __ALIGN .align 4,0x90 -#define __ALIGN_STR ".align 4,0x90" -#endif /* __ELF__ */ -#endif /* __i486__/__i586__ */ - -#ifdef __ASSEMBLY__ - -#define ALIGN __ALIGN -#define ALIGN_STRING __ALIGN_STRING - -#define ENTRY(name) \ - .globl SYMBOL_NAME(name); \ - ALIGN; \ - SYMBOL_NAME_LABEL(name) - -#endif - -#endif diff --git a/i386/i386at/gpl/linux/include/linux/locks.h b/i386/i386at/gpl/linux/include/linux/locks.h deleted file mode 100644 index c3202b08..00000000 --- a/i386/i386at/gpl/linux/include/linux/locks.h +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef _LINUX_LOCKS_H -#define _LINUX_LOCKS_H - -#ifndef _LINUX_MM_H -#include <linux/mm.h> -#endif -#ifndef _LINUX_PAGEMAP_H -#include <linux/pagemap.h> -#endif - -/* - * Unlocked, temporary IO buffer_heads gets moved to the reuse_list - * once their page becomes unlocked. - */ -extern struct buffer_head *reuse_list; - -/* - * Buffer cache locking - note that interrupts may only unlock, not - * lock buffers. - */ -extern void __wait_on_buffer(struct buffer_head *); - -extern inline void wait_on_buffer(struct buffer_head * bh) -{ - if (test_bit(BH_Lock, &bh->b_state)) - __wait_on_buffer(bh); -} - -extern inline void lock_buffer(struct buffer_head * bh) -{ - if (set_bit(BH_Lock, &bh->b_state)) - __wait_on_buffer(bh); -} - -void unlock_buffer(struct buffer_head *); - -#ifndef MACH -/* - * super-block locking. Again, interrupts may only unlock - * a super-block (although even this isn't done right now. - * nfs may need it). - */ -extern void __wait_on_super(struct super_block *); - -extern inline void wait_on_super(struct super_block * sb) -{ - if (sb->s_lock) - __wait_on_super(sb); -} - -extern inline void lock_super(struct super_block * sb) -{ - if (sb->s_lock) - __wait_on_super(sb); - sb->s_lock = 1; -} - -extern inline void unlock_super(struct super_block * sb) -{ - sb->s_lock = 0; - wake_up(&sb->s_wait); -} -#endif /* ! MACH */ - -#endif /* _LINUX_LOCKS_H */ - diff --git a/i386/i386at/gpl/linux/include/linux/major.h b/i386/i386at/gpl/linux/include/linux/major.h deleted file mode 100644 index c1b2dcf0..00000000 --- a/i386/i386at/gpl/linux/include/linux/major.h +++ /dev/null @@ -1,119 +0,0 @@ -#ifndef _LINUX_MAJOR_H -#define _LINUX_MAJOR_H - -/* - * This file has definitions for major device numbers - */ - -/* limits */ - -#define MAX_CHRDEV 64 -#define MAX_BLKDEV 64 - -/* - * assignments - * - * devices are as follows (same as minix, so we can use the minix fs): - * - * character block comments - * -------------------- -------------------- -------------------- - * 0 - unnamed unnamed minor 0 = true nodev - * 1 - /dev/mem ramdisk - * 2 - /dev/ptyp* floppy - * 3 - /dev/ttyp* ide0 or hd - * 4 - /dev/tty* - * 5 - /dev/tty; /dev/cua* - * 6 - lp - * 7 - /dev/vcs* - * 8 - scsi disk - * 9 - scsi tape - * 10 - mice - * 11 - scsi cdrom - * 12 - qic02 tape - * 13 - xt disk - * 14 - sound card - * 15 - cdu31a cdrom - * 16 - sockets goldstar cdrom - * 17 - af_unix optics cdrom - * 18 - af_inet sanyo cdrom - * 19 - cyclades /dev/ttyC* - * 20 - cyclades /dev/cub* mitsumi (mcdx) cdrom - * 21 - scsi generic - * 22 - ide1 - * 23 - mitsumi cdrom - * 24 - sony535 cdrom - * 25 - matsushita cdrom minors 0..3 - * 26 - matsushita cdrom 2 minors 0..3 - * 27 - qic117 tape matsushita cdrom 3 minors 0..3 - * 28 - matsushita cdrom 4 minors 0..3 - * 29 - aztech/orchid/okano/wearnes cdrom - * 32 - philips/lms cm206 cdrom - * 33 - ide2 - * 34 - z8530 driver ide3 - * 36 - netlink - */ - -#define UNNAMED_MAJOR 0 -#define MEM_MAJOR 1 -#define RAMDISK_MAJOR 1 -#define FLOPPY_MAJOR 2 -#define PTY_MASTER_MAJOR 2 -#define IDE0_MAJOR 3 -#define PTY_SLAVE_MAJOR 3 -#define HD_MAJOR IDE0_MAJOR -#define TTY_MAJOR 4 -#define TTYAUX_MAJOR 5 -#define LP_MAJOR 6 -#define VCS_MAJOR 7 -#define SCSI_DISK_MAJOR 8 -#define SCSI_TAPE_MAJOR 9 -#define MOUSE_MAJOR 10 -#define SCSI_CDROM_MAJOR 11 -#define QIC02_TAPE_MAJOR 12 -#define XT_DISK_MAJOR 13 -#define SOUND_MAJOR 14 -#define CDU31A_CDROM_MAJOR 15 -#define SOCKET_MAJOR 16 -#define GOLDSTAR_CDROM_MAJOR 16 -#define AF_UNIX_MAJOR 17 -#define OPTICS_CDROM_MAJOR 17 -#define AF_INET_MAJOR 18 -#define SANYO_CDROM_MAJOR 18 -#define CYCLADES_MAJOR 19 -#define CYCLADESAUX_MAJOR 20 -#define MITSUMI_X_CDROM_MAJOR 20 -#define SCSI_GENERIC_MAJOR 21 -#define Z8530_MAJOR 34 -#define IDE1_MAJOR 22 -#define MITSUMI_CDROM_MAJOR 23 -#define CDU535_CDROM_MAJOR 24 -#define STL_SERIALMAJOR 24 -#define MATSUSHITA_CDROM_MAJOR 25 -#define STL_CALLOUTMAJOR 25 -#define MATSUSHITA_CDROM2_MAJOR 26 -#define QIC117_TAPE_MAJOR 27 -#define MATSUSHITA_CDROM3_MAJOR 27 -#define MATSUSHITA_CDROM4_MAJOR 28 -#define STL_SIOMEMMAJOR 28 -#define AZTECH_CDROM_MAJOR 29 -#define CM206_CDROM_MAJOR 32 -#define IDE2_MAJOR 33 -#define IDE3_MAJOR 34 -#define NETLINK_MAJOR 36 -#define IDETAPE_MAJOR 37 - -/* - * Tests for SCSI devices. - */ - -#define SCSI_MAJOR(M) \ - ((M) == SCSI_DISK_MAJOR \ - || (M) == SCSI_TAPE_MAJOR \ - || (M) == SCSI_CDROM_MAJOR \ - || (M) == SCSI_GENERIC_MAJOR) - -static inline int scsi_major(int m) { - return SCSI_MAJOR(m); -} - -#endif diff --git a/i386/i386at/gpl/linux/include/linux/malloc.h b/i386/i386at/gpl/linux/include/linux/malloc.h deleted file mode 100644 index 847383ad..00000000 --- a/i386/i386at/gpl/linux/include/linux/malloc.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef _LINUX_MALLOC_H -#define _LINUX_MALLOC_H - -#include <linux/mm.h> - -#ifndef MACH_INCLUDE -#define kmalloc linux_kmalloc -#define kfree linux_kfree -#endif - -void *linux_kmalloc(unsigned int size, int priority); -void linux_kfree(void * obj); - -#define kfree_s(a,b) linux_kfree(a) - -#endif /* _LINUX_MALLOC_H */ diff --git a/i386/i386at/gpl/linux/include/linux/math_emu.h b/i386/i386at/gpl/linux/include/linux/math_emu.h deleted file mode 100644 index 0d9606d9..00000000 --- a/i386/i386at/gpl/linux/include/linux/math_emu.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef _LINUX_MATH_EMU_H -#define _LINUX_MATH_EMU_H - -struct fpu_reg { - char sign; - char tag; - long exp; - unsigned sigl; - unsigned sigh; -}; - - -/* This structure matches the layout of the data saved to the stack - following a device-not-present interrupt, part of it saved - automatically by the 80386/80486. - */ -struct info { - long ___orig_eip; - long ___ret_from_system_call; - long ___ebx; - long ___ecx; - long ___edx; - long ___esi; - long ___edi; - long ___ebp; - long ___eax; - long ___ds; - long ___es; - long ___fs; - long ___gs; - long ___orig_eax; - long ___eip; - long ___cs; - long ___eflags; - long ___esp; - long ___ss; - long ___vm86_es; /* This and the following only in vm86 mode */ - long ___vm86_ds; - long ___vm86_fs; - long ___vm86_gs; -}; - -#endif diff --git a/i386/i386at/gpl/linux/include/linux/mc146818rtc.h b/i386/i386at/gpl/linux/include/linux/mc146818rtc.h deleted file mode 100644 index d2e709a1..00000000 --- a/i386/i386at/gpl/linux/include/linux/mc146818rtc.h +++ /dev/null @@ -1,109 +0,0 @@ -/* mc146818rtc.h - register definitions for the Real-Time-Clock / CMOS RAM - * Copyright Torsten Duwe <duwe@informatik.uni-erlangen.de> 1993 - * derived from Data Sheet, Copyright Motorola 1984 (!). - * It was written to be part of the Linux operating system. - */ -/* permission is hereby granted to copy, modify and redistribute this code - * in terms of the GNU Library General Public License, Version 2 or later, - * at your option. - */ - -#ifndef _MC146818RTC_H -#define _MC146818RTC_H -#include <asm/io.h> - -#ifndef RTC_PORT -#define RTC_PORT(x) (0x70 + (x)) -#define RTC_ALWAYS_BCD 1 -#endif - -#define CMOS_READ(addr) ({ \ -outb_p((addr),RTC_PORT(0)); \ -inb_p(RTC_PORT(1)); \ -}) -#define CMOS_WRITE(val, addr) ({ \ -outb_p((addr),RTC_PORT(0)); \ -outb_p((val),RTC_PORT(1)); \ -}) - -/********************************************************************** - * register summary - **********************************************************************/ -#define RTC_SECONDS 0 -#define RTC_SECONDS_ALARM 1 -#define RTC_MINUTES 2 -#define RTC_MINUTES_ALARM 3 -#define RTC_HOURS 4 -#define RTC_HOURS_ALARM 5 -/* RTC_*_alarm is always true if 2 MSBs are set */ -# define RTC_ALARM_DONT_CARE 0xC0 - -#define RTC_DAY_OF_WEEK 6 -#define RTC_DAY_OF_MONTH 7 -#define RTC_MONTH 8 -#define RTC_YEAR 9 - -/* control registers - Moto names - */ -#define RTC_REG_A 10 -#define RTC_REG_B 11 -#define RTC_REG_C 12 -#define RTC_REG_D 13 - -/********************************************************************** - * register details - **********************************************************************/ -#define RTC_FREQ_SELECT RTC_REG_A - -/* update-in-progress - set to "1" 244 microsecs before RTC goes off the bus, - * reset after update (may take 1.984ms @ 32768Hz RefClock) is complete, - * totalling to a max high interval of 2.228 ms. - */ -# define RTC_UIP 0x80 -# define RTC_DIV_CTL 0x70 - /* divider control: refclock values 4.194 / 1.049 MHz / 32.768 kHz */ -# define RTC_REF_CLCK_4MHZ 0x00 -# define RTC_REF_CLCK_1MHZ 0x10 -# define RTC_REF_CLCK_32KHZ 0x20 - /* 2 values for divider stage reset, others for "testing purposes only" */ -# define RTC_DIV_RESET1 0x60 -# define RTC_DIV_RESET2 0x70 - /* Periodic intr. / Square wave rate select. 0=none, 1=32.8kHz,... 15=2Hz */ -# define RTC_RATE_SELECT 0x0F - -/**********************************************************************/ -#define RTC_CONTROL RTC_REG_B -# define RTC_SET 0x80 /* disable updates for clock setting */ -# define RTC_PIE 0x40 /* periodic interrupt enable */ -# define RTC_AIE 0x20 /* alarm interrupt enable */ -# define RTC_UIE 0x10 /* update-finished interrupt enable */ -# define RTC_SQWE 0x08 /* enable square-wave output */ -# define RTC_DM_BINARY 0x04 /* all time/date values are BCD if clear */ -# define RTC_24H 0x02 /* 24 hour mode - else hours bit 7 means pm */ -# define RTC_DST_EN 0x01 /* auto switch DST - works f. USA only */ - -/**********************************************************************/ -#define RTC_INTR_FLAGS RTC_REG_C -/* caution - cleared by read */ -# define RTC_IRQF 0x80 /* any of the following 3 is active */ -# define RTC_PF 0x40 -# define RTC_AF 0x20 -# define RTC_UF 0x10 - -/**********************************************************************/ -#define RTC_VALID RTC_REG_D -# define RTC_VRT 0x80 /* valid RAM and time */ -/**********************************************************************/ - -/* example: !(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) - * determines if the following two #defines are needed - */ -#ifndef BCD_TO_BIN -#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10) -#endif - -#ifndef BIN_TO_BCD -#define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10) -#endif - -#endif /* _MC146818RTC_H */ diff --git a/i386/i386at/gpl/linux/include/linux/minix_fs.h b/i386/i386at/gpl/linux/include/linux/minix_fs.h deleted file mode 100644 index f0ecdea0..00000000 --- a/i386/i386at/gpl/linux/include/linux/minix_fs.h +++ /dev/null @@ -1,135 +0,0 @@ -#ifndef _LINUX_MINIX_FS_H -#define _LINUX_MINIX_FS_H - -/* - * The minix filesystem constants/structures - */ - -/* - * Thanks to Kees J Bot for sending me the definitions of the new - * minix filesystem (aka V2) with bigger inodes and 32-bit block - * pointers. - */ - -#define MINIX_ROOT_INO 1 - -/* Not the same as the bogus LINK_MAX in <linux/limits.h>. Oh well. */ -#define MINIX_LINK_MAX 250 - -#define MINIX_I_MAP_SLOTS 8 -#define MINIX_Z_MAP_SLOTS 64 -#define MINIX_SUPER_MAGIC 0x137F /* original minix fs */ -#define MINIX_SUPER_MAGIC2 0x138F /* minix fs, 30 char names */ -#define MINIX2_SUPER_MAGIC 0x2468 /* minix V2 fs */ -#define MINIX2_SUPER_MAGIC2 0x2478 /* minix V2 fs, 30 char names */ -#define MINIX_VALID_FS 0x0001 /* Clean fs. */ -#define MINIX_ERROR_FS 0x0002 /* fs has errors. */ - -#define MINIX_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix_inode))) -#define MINIX2_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix2_inode))) - -#define MINIX_V1 0x0001 /* original minix fs */ -#define MINIX_V2 0x0002 /* minix V2 fs */ - -#define INODE_VERSION(inode) inode->i_sb->u.minix_sb.s_version - -/* - * This is the original minix inode layout on disk. - * Note the 8-bit gid and atime and ctime. - */ -struct minix_inode { - __u16 i_mode; - __u16 i_uid; - __u32 i_size; - __u32 i_time; - __u8 i_gid; - __u8 i_nlinks; - __u16 i_zone[9]; -}; - -/* - * The new minix inode has all the time entries, as well as - * long block numbers and a third indirect block (7+1+1+1 - * instead of 7+1+1). Also, some previously 8-bit values are - * now 16-bit. The inode is now 64 bytes instead of 32. - */ -struct minix2_inode { - __u16 i_mode; - __u16 i_nlinks; - __u16 i_uid; - __u16 i_gid; - __u32 i_size; - __u32 i_atime; - __u32 i_mtime; - __u32 i_ctime; - __u32 i_zone[10]; -}; - -/* - * minix super-block data on disk - */ -struct minix_super_block { - __u16 s_ninodes; - __u16 s_nzones; - __u16 s_imap_blocks; - __u16 s_zmap_blocks; - __u16 s_firstdatazone; - __u16 s_log_zone_size; - __u32 s_max_size; - __u16 s_magic; - __u16 s_state; - __u32 s_zones; -}; - -struct minix_dir_entry { - __u16 inode; - char name[0]; -}; - -#ifdef __KERNEL__ - -extern int minix_lookup(struct inode * dir,const char * name, int len, - struct inode ** result); -extern int minix_create(struct inode * dir,const char * name, int len, int mode, - struct inode ** result); -extern int minix_mkdir(struct inode * dir, const char * name, int len, int mode); -extern int minix_rmdir(struct inode * dir, const char * name, int len); -extern int minix_unlink(struct inode * dir, const char * name, int len); -extern int minix_symlink(struct inode * inode, const char * name, int len, - const char * symname); -extern int minix_link(struct inode * oldinode, struct inode * dir, const char * name, int len); -extern int minix_mknod(struct inode * dir, const char * name, int len, int mode, int rdev); -extern int minix_rename(struct inode * old_dir, const char * old_name, int old_len, - struct inode * new_dir, const char * new_name, int new_len); -extern struct inode * minix_new_inode(const struct inode * dir); -extern void minix_free_inode(struct inode * inode); -extern unsigned long minix_count_free_inodes(struct super_block *sb); -extern int minix_new_block(struct super_block * sb); -extern void minix_free_block(struct super_block * sb, int block); -extern unsigned long minix_count_free_blocks(struct super_block *sb); - -extern int minix_bmap(struct inode *,int); - -extern struct buffer_head * minix_getblk(struct inode *, int, int); -extern struct buffer_head * minix_bread(struct inode *, int, int); - -extern void minix_truncate(struct inode *); -extern void minix_put_super(struct super_block *); -extern struct super_block *minix_read_super(struct super_block *,void *,int); -extern int init_minix_fs(void); -extern void minix_write_super(struct super_block *); -extern int minix_remount (struct super_block * sb, int * flags, char * data); -extern void minix_read_inode(struct inode *); -extern void minix_write_inode(struct inode *); -extern void minix_put_inode(struct inode *); -extern void minix_statfs(struct super_block *, struct statfs *, int); -extern int minix_sync_inode(struct inode *); -extern int minix_sync_file(struct inode *, struct file *); - -extern struct inode_operations minix_file_inode_operations; -extern struct inode_operations minix_dir_inode_operations; -extern struct inode_operations minix_symlink_inode_operations; - -#endif /* __KERNEL__ */ - -#endif diff --git a/i386/i386at/gpl/linux/include/linux/minix_fs_sb.h b/i386/i386at/gpl/linux/include/linux/minix_fs_sb.h deleted file mode 100644 index e77b4efc..00000000 --- a/i386/i386at/gpl/linux/include/linux/minix_fs_sb.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef _MINIX_FS_SB -#define _MINIX_FS_SB - -/* - * minix super-block data in memory - */ -struct minix_sb_info { - unsigned long s_ninodes; - unsigned long s_nzones; - unsigned long s_imap_blocks; - unsigned long s_zmap_blocks; - unsigned long s_firstdatazone; - unsigned long s_log_zone_size; - unsigned long s_max_size; - struct buffer_head * s_imap[8]; - struct buffer_head * s_zmap[64]; - unsigned long s_dirsize; - unsigned long s_namelen; - struct buffer_head * s_sbh; - struct minix_super_block * s_ms; - unsigned short s_mount_state; - unsigned short s_version; -}; - -#endif diff --git a/i386/i386at/gpl/linux/include/linux/mm.h b/i386/i386at/gpl/linux/include/linux/mm.h deleted file mode 100644 index f8bbb9ba..00000000 --- a/i386/i386at/gpl/linux/include/linux/mm.h +++ /dev/null @@ -1,297 +0,0 @@ -#ifndef _LINUX_MM_H -#define _LINUX_MM_H - -#include <linux/sched.h> -#include <linux/errno.h> -#include <linux/kernel.h> -#include <linux/string.h> - -extern unsigned long high_memory; - -#include <asm/page.h> - -#ifdef __KERNEL__ - -#define VERIFY_READ 0 -#define VERIFY_WRITE 1 - -extern int verify_area(int, const void *, unsigned long); - -/* - * Linux kernel virtual memory manager primitives. - * The idea being to have a "virtual" mm in the same way - * we have a virtual fs - giving a cleaner interface to the - * mm details, and allowing different kinds of memory mappings - * (from shared memory to executable loading to arbitrary - * mmap() functions). - */ - -/* - * This struct defines a memory VMM memory area. There is one of these - * per VM-area/task. A VM area is any part of the process virtual memory - * space that has a special rule for the page-fault handlers (ie a shared - * library, the executable area etc). - */ -struct vm_area_struct { - struct mm_struct * vm_mm; /* VM area parameters */ - unsigned long vm_start; - unsigned long vm_end; - pgprot_t vm_page_prot; - unsigned short vm_flags; -/* AVL tree of VM areas per task, sorted by address */ - short vm_avl_height; - struct vm_area_struct * vm_avl_left; - struct vm_area_struct * vm_avl_right; -/* linked list of VM areas per task, sorted by address */ - struct vm_area_struct * vm_next; -/* for areas with inode, the circular list inode->i_mmap */ -/* for shm areas, the circular list of attaches */ -/* otherwise unused */ - struct vm_area_struct * vm_next_share; - struct vm_area_struct * vm_prev_share; -/* more */ - struct vm_operations_struct * vm_ops; - unsigned long vm_offset; - struct inode * vm_inode; - unsigned long vm_pte; /* shared mem */ -}; - -/* - * vm_flags.. - */ -#define VM_READ 0x0001 /* currently active flags */ -#define VM_WRITE 0x0002 -#define VM_EXEC 0x0004 -#define VM_SHARED 0x0008 - -#define VM_MAYREAD 0x0010 /* limits for mprotect() etc */ -#define VM_MAYWRITE 0x0020 -#define VM_MAYEXEC 0x0040 -#define VM_MAYSHARE 0x0080 - -#define VM_GROWSDOWN 0x0100 /* general info on the segment */ -#define VM_GROWSUP 0x0200 -#define VM_SHM 0x0400 /* shared memory area, don't swap out */ -#define VM_DENYWRITE 0x0800 /* ETXTBSY on write attempts.. */ - -#define VM_EXECUTABLE 0x1000 -#define VM_LOCKED 0x2000 - -#define VM_STACK_FLAGS 0x0177 - -/* - * mapping from the currently active vm_flags protection bits (the - * low four bits) to a page protection mask.. - */ -extern pgprot_t protection_map[16]; - - -/* - * These are the virtual MM functions - opening of an area, closing and - * unmapping it (needed to keep files on disk up-to-date etc), pointer - * to the functions called when a no-page or a wp-page exception occurs. - */ -struct vm_operations_struct { - void (*open)(struct vm_area_struct * area); - void (*close)(struct vm_area_struct * area); - void (*unmap)(struct vm_area_struct *area, unsigned long, size_t); - void (*protect)(struct vm_area_struct *area, unsigned long, size_t, unsigned int newprot); - int (*sync)(struct vm_area_struct *area, unsigned long, size_t, unsigned int flags); - void (*advise)(struct vm_area_struct *area, unsigned long, size_t, unsigned int advise); - unsigned long (*nopage)(struct vm_area_struct * area, unsigned long address, int write_access); - unsigned long (*wppage)(struct vm_area_struct * area, unsigned long address, - unsigned long page); - int (*swapout)(struct vm_area_struct *, unsigned long, pte_t *); - pte_t (*swapin)(struct vm_area_struct *, unsigned long, unsigned long); -}; - -/* - * Try to keep the most commonly accessed fields in single cache lines - * here (16 bytes or greater). This ordering should be particularly - * beneficial on 32-bit processors. - * - * The first line is data used in linear searches (eg. clock algorithm - * scans). The second line is data used in page searches through the - * page-cache. -- sct - */ -typedef struct page { - unsigned int count; - unsigned dirty:16, - age:8, - uptodate:1, - error:1, - referenced:1, - locked:1, - free_after:1, - unused:2, - reserved:1; - struct wait_queue *wait; - struct page *next; - - struct page *next_hash; - unsigned long offset; - struct inode *inode; - struct page *write_list; - - struct page *prev; - struct page *prev_hash; -} mem_map_t; - -extern mem_map_t * mem_map; - -/* - * Free area management - */ - -#define NR_MEM_LISTS 6 - -struct mem_list { - struct mem_list * next; - struct mem_list * prev; -}; - -extern struct mem_list free_area_list[NR_MEM_LISTS]; -extern unsigned int * free_area_map[NR_MEM_LISTS]; - -/* - * This is timing-critical - most of the time in getting a new page - * goes to clearing the page. If you want a page without the clearing - * overhead, just use __get_free_page() directly.. - */ -#define __get_free_page(priority) __get_free_pages((priority),0,~0UL) -#define __get_dma_pages(priority, order) __get_free_pages((priority),(order),MAX_DMA_ADDRESS) -extern unsigned long __get_free_pages(int priority, unsigned long gfporder, unsigned long max_addr); - -extern inline unsigned long get_free_page(int priority) -{ - unsigned long page; - - page = __get_free_page(priority); - if (page) - memset((void *) page, 0, PAGE_SIZE); - return page; -} - -/* memory.c & swap.c*/ - -#define free_page(addr) free_pages((addr),0) -extern void free_pages(unsigned long addr, unsigned long order); - -extern void show_free_areas(void); -extern unsigned long put_dirty_page(struct task_struct * tsk,unsigned long page, - unsigned long address); - -extern void free_page_tables(struct task_struct * tsk); -extern void clear_page_tables(struct task_struct * tsk); -extern int new_page_tables(struct task_struct * tsk); -extern int copy_page_tables(struct task_struct * to); - -extern int zap_page_range(struct mm_struct *mm, unsigned long address, unsigned long size); -extern int copy_page_range(struct mm_struct *dst, struct mm_struct *src, struct vm_area_struct *vma); -extern int remap_page_range(unsigned long from, unsigned long to, unsigned long size, pgprot_t prot); -extern int zeromap_page_range(unsigned long from, unsigned long size, pgprot_t prot); - -extern void vmtruncate(struct inode * inode, unsigned long offset); -extern void handle_mm_fault(struct vm_area_struct *vma, unsigned long address, int write_access); -extern void do_wp_page(struct task_struct * tsk, struct vm_area_struct * vma, unsigned long address, int write_access); -extern void do_no_page(struct task_struct * tsk, struct vm_area_struct * vma, unsigned long address, int write_access); - -extern unsigned long paging_init(unsigned long start_mem, unsigned long end_mem); -extern void mem_init(unsigned long start_mem, unsigned long end_mem); -extern void show_mem(void); -extern void oom(struct task_struct * tsk); -extern void si_meminfo(struct sysinfo * val); - -/* vmalloc.c */ - -extern void * vmalloc(unsigned long size); -extern void * vremap(unsigned long offset, unsigned long size); -extern void vfree(void * addr); -extern int vread(char *buf, char *addr, int count); - -/* mmap.c */ -extern unsigned long do_mmap(struct file * file, unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, unsigned long off); -extern void merge_segments(struct task_struct *, unsigned long, unsigned long); -extern void insert_vm_struct(struct task_struct *, struct vm_area_struct *); -extern void remove_shared_vm_struct(struct vm_area_struct *); -extern void build_mmap_avl(struct mm_struct *); -extern void exit_mmap(struct mm_struct *); -extern int do_munmap(unsigned long, size_t); -extern unsigned long get_unmapped_area(unsigned long, unsigned long); - -/* filemap.c */ -extern unsigned long page_unuse(unsigned long); -extern int shrink_mmap(int, unsigned long); -extern void truncate_inode_pages(struct inode *, unsigned long); - -#define GFP_BUFFER 0x00 -#define GFP_ATOMIC 0x01 -#define GFP_USER 0x02 -#define GFP_KERNEL 0x03 -#define GFP_NOBUFFER 0x04 -#define GFP_NFS 0x05 - -/* Flag - indicates that the buffer will be suitable for DMA. Ignored on some - platforms, used as appropriate on others */ - -#define GFP_DMA 0x80 - -#define GFP_LEVEL_MASK 0xf - -#define avl_empty (struct vm_area_struct *) NULL - -#ifndef MACH -static inline int expand_stack(struct vm_area_struct * vma, unsigned long address) -{ - unsigned long grow; - - address &= PAGE_MASK; - if (vma->vm_end - address > current->rlim[RLIMIT_STACK].rlim_cur) - return -ENOMEM; - grow = vma->vm_start - address; - vma->vm_start = address; - vma->vm_offset -= grow; - vma->vm_mm->total_vm += grow >> PAGE_SHIFT; - if (vma->vm_flags & VM_LOCKED) - vma->vm_mm->locked_vm += grow >> PAGE_SHIFT; - return 0; -} - -/* Look up the first VMA which satisfies addr < vm_end, NULL if none. */ -static inline struct vm_area_struct * find_vma (struct task_struct * task, unsigned long addr) -{ - struct vm_area_struct * result = NULL; - struct vm_area_struct * tree; - - if (!task->mm) - return NULL; - for (tree = task->mm->mmap_avl ; ; ) { - if (tree == avl_empty) - return result; - if (tree->vm_end > addr) { - if (tree->vm_start <= addr) - return tree; - result = tree; - tree = tree->vm_avl_left; - } else - tree = tree->vm_avl_right; - } -} - -/* Look up the first VMA which intersects the interval start_addr..end_addr-1, - NULL if none. Assume start_addr < end_addr. */ -static inline struct vm_area_struct * find_vma_intersection (struct task_struct * task, unsigned long start_addr, unsigned long end_addr) -{ - struct vm_area_struct * vma; - - vma = find_vma(task,start_addr); - if (!vma || end_addr <= vma->vm_start) - return NULL; - return vma; -} -#endif /* ! MACH */ - -#endif /* __KERNEL__ */ - -#endif diff --git a/i386/i386at/gpl/linux/include/linux/module.h b/i386/i386at/gpl/linux/include/linux/module.h deleted file mode 100644 index a91ad19b..00000000 --- a/i386/i386at/gpl/linux/include/linux/module.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Dynamic loading of modules into the kernel. - * - * Modified by Bjorn Ekwall <bj0rn@blox.se> - */ - -#ifndef _LINUX_MODULE_H -#define _LINUX_MODULE_H - -#ifdef __GENKSYMS__ -# define _set_ver(sym,vers) sym -# undef MODVERSIONS -# define MODVERSIONS -#else /* ! __GENKSYMS__ */ -# if defined(MODVERSIONS) && !defined(MODULE) && defined(EXPORT_SYMTAB) -# define _set_ver(sym,vers) sym -# include <linux/modversions.h> -# endif -#endif /* __GENKSYMS__ */ - -/* values of module.state */ -#define MOD_UNINITIALIZED 0 -#define MOD_RUNNING 1 -#define MOD_DELETED 2 - -/* maximum length of module name */ -#define MOD_MAX_NAME 64 - -/* magic marker for modules inserted from kerneld, to be auto-reaped */ -#define MOD_AUTOCLEAN 0x40000000 /* big enough, but no sign problems... */ - -/* maximum length of symbol name */ -#define SYM_MAX_NAME 60 - -struct kernel_sym { /* sent to "insmod" */ - unsigned long value; /* value of symbol */ - char name[SYM_MAX_NAME]; /* name of symbol */ -}; - -struct module_ref { - struct module *module; - struct module_ref *next; -}; - -struct internal_symbol { - void *addr; - const char *name; - }; - -struct symbol_table { /* received from "insmod" */ - int size; /* total, including string table!!! */ - int n_symbols; - int n_refs; - struct internal_symbol symbol[0]; /* actual size defined by n_symbols */ - struct module_ref ref[0]; /* actual size defined by n_refs */ -}; -/* - * Note: The string table follows immediately after the symbol table in memory! - */ - -struct module { - struct module *next; - struct module_ref *ref; /* the list of modules that refer to me */ - struct symbol_table *symtab; - const char *name; - int size; /* size of module in pages */ - void* addr; /* address of module */ - int state; - void (*cleanup)(void); /* cleanup routine */ -}; - -struct mod_routines { - int (*init)(void); /* initialization routine */ - void (*cleanup)(void); /* cleanup routine */ -}; - -/* rename_module_symbol(old_name, new_name) WOW! */ -extern int rename_module_symbol(char *, char *); - -/* insert new symbol table */ -extern int register_symtab(struct symbol_table *); - -/* - * The first word of the module contains the use count. - */ -#define GET_USE_COUNT(module) (* (long *) (module)->addr) -/* - * define the count variable, and usage macros. - */ - -#ifdef MODULE - -extern long mod_use_count_; -#define MOD_INC_USE_COUNT mod_use_count_++ -#define MOD_DEC_USE_COUNT mod_use_count_-- -#define MOD_IN_USE ((mod_use_count_ & ~MOD_AUTOCLEAN) != 0) - -#ifndef __NO_VERSION__ -#include <linux/version.h> -char kernel_version[]=UTS_RELEASE; -#endif - -#if defined(MODVERSIONS) && !defined(__GENKSYMS__) -int Using_Versions; /* gcc will handle this global (used as a flag) correctly */ -#endif - -#else - -#define MOD_INC_USE_COUNT do { } while (0) -#define MOD_DEC_USE_COUNT do { } while (0) -#define MOD_IN_USE 1 - -#endif - -#endif diff --git a/i386/i386at/gpl/linux/include/linux/mount.h b/i386/i386at/gpl/linux/include/linux/mount.h deleted file mode 100644 index 357c7ae6..00000000 --- a/i386/i386at/gpl/linux/include/linux/mount.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * - * Definitions for mount interface. This describes the in the kernel build - * linkedlist with mounted filesystems. - * - * Author: Marco van Wieringen <mvw@mcs.ow.nl> <mvw@tnix.net> <mvw@cistron.nl> - * - * Version: $Id: mount.h,v 1.1.1.1 1997/02/25 21:27:29 thomas Exp $ - * - */ -#ifndef _LINUX_MOUNT_H -#define _LINUX_MOUNT_H - -struct vfsmount -{ - kdev_t mnt_dev; /* Device this applies to */ - char *mnt_devname; /* Name of device e.g. /dev/dsk/hda1 */ - char *mnt_dirname; /* Name of directory mounted on */ - unsigned int mnt_flags; /* Flags of this device */ - struct semaphore mnt_sem; /* lock device while I/O in progress */ - struct super_block *mnt_sb; /* pointer to superblock */ - struct file *mnt_quotas[MAXQUOTAS]; /* fp's to quotafiles */ - time_t mnt_iexp[MAXQUOTAS]; /* expiretime for inodes */ - time_t mnt_bexp[MAXQUOTAS]; /* expiretime for blocks */ - struct vfsmount *mnt_next; /* pointer to next in linkedlist */ -}; - -struct vfsmount *lookup_vfsmnt(kdev_t dev); - -#endif /* _LINUX_MOUNT_H */ diff --git a/i386/i386at/gpl/linux/include/linux/net.h b/i386/i386at/gpl/linux/include/linux/net.h deleted file mode 100644 index 1fbe98a0..00000000 --- a/i386/i386at/gpl/linux/include/linux/net.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - * NET An implementation of the SOCKET network access protocol. - * This is the master header file for the Linux NET layer, - * or, in plain English: the networking handling part of the - * kernel. - * - * Version: @(#)net.h 1.0.3 05/25/93 - * - * Authors: Orest Zborowski, <obz@Kodak.COM> - * Ross Biro, <bir7@leland.Stanford.Edu> - * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ -#ifndef _LINUX_NET_H -#define _LINUX_NET_H - - -#include <linux/wait.h> -#include <linux/socket.h> - - -#define NSOCKETS 2000 /* Dynamic, this is MAX LIMIT */ -#define NSOCKETS_UNIX 128 /* unix domain static limit */ -#define NPROTO 16 /* should be enough for now.. */ - - -#define SYS_SOCKET 1 /* sys_socket(2) */ -#define SYS_BIND 2 /* sys_bind(2) */ -#define SYS_CONNECT 3 /* sys_connect(2) */ -#define SYS_LISTEN 4 /* sys_listen(2) */ -#define SYS_ACCEPT 5 /* sys_accept(2) */ -#define SYS_GETSOCKNAME 6 /* sys_getsockname(2) */ -#define SYS_GETPEERNAME 7 /* sys_getpeername(2) */ -#define SYS_SOCKETPAIR 8 /* sys_socketpair(2) */ -#define SYS_SEND 9 /* sys_send(2) */ -#define SYS_RECV 10 /* sys_recv(2) */ -#define SYS_SENDTO 11 /* sys_sendto(2) */ -#define SYS_RECVFROM 12 /* sys_recvfrom(2) */ -#define SYS_SHUTDOWN 13 /* sys_shutdown(2) */ -#define SYS_SETSOCKOPT 14 /* sys_setsockopt(2) */ -#define SYS_GETSOCKOPT 15 /* sys_getsockopt(2) */ -#define SYS_SENDMSG 16 /* sys_sendmsg(2) */ -#define SYS_RECVMSG 17 /* sys_recvmsg(2) */ - - -typedef enum { - SS_FREE = 0, /* not allocated */ - SS_UNCONNECTED, /* unconnected to any socket */ - SS_CONNECTING, /* in process of connecting */ - SS_CONNECTED, /* connected to socket */ - SS_DISCONNECTING /* in process of disconnecting */ -} socket_state; - -#define SO_ACCEPTCON (1<<16) /* performed a listen */ -#define SO_WAITDATA (1<<17) /* wait data to read */ -#define SO_NOSPACE (1<<18) /* no space to write */ - -#ifdef __KERNEL__ -/* - * Internal representation of a socket. not all the fields are used by - * all configurations: - * - * server client - * conn client connected to server connected to - * iconn list of clients -unused- - * awaiting connections - * wait sleep for clients, sleep for connection, - * sleep for i/o sleep for i/o - */ -struct socket { - short type; /* SOCK_STREAM, ... */ - socket_state state; - long flags; - struct proto_ops *ops; /* protocols do most everything */ - void *data; /* protocol data */ - struct socket *conn; /* server socket connected to */ - struct socket *iconn; /* incomplete client conn.s */ - struct socket *next; - struct wait_queue **wait; /* ptr to place to wait on */ - struct inode *inode; - struct fasync_struct *fasync_list; /* Asynchronous wake up list */ -}; - -#define SOCK_INODE(S) ((S)->inode) - -struct proto_ops { - int family; - - int (*create) (struct socket *sock, int protocol); - int (*dup) (struct socket *newsock, struct socket *oldsock); - int (*release) (struct socket *sock, struct socket *peer); - int (*bind) (struct socket *sock, struct sockaddr *umyaddr, - int sockaddr_len); - int (*connect) (struct socket *sock, struct sockaddr *uservaddr, - int sockaddr_len, int flags); - int (*socketpair) (struct socket *sock1, struct socket *sock2); - int (*accept) (struct socket *sock, struct socket *newsock, - int flags); - int (*getname) (struct socket *sock, struct sockaddr *uaddr, - int *usockaddr_len, int peer); - int (*select) (struct socket *sock, int sel_type, - select_table *wait); - int (*ioctl) (struct socket *sock, unsigned int cmd, - unsigned long arg); - int (*listen) (struct socket *sock, int len); - int (*shutdown) (struct socket *sock, int flags); - int (*setsockopt) (struct socket *sock, int level, int optname, - char *optval, int optlen); - int (*getsockopt) (struct socket *sock, int level, int optname, - char *optval, int *optlen); - int (*fcntl) (struct socket *sock, unsigned int cmd, - unsigned long arg); - int (*sendmsg) (struct socket *sock, struct msghdr *m, int total_len, int nonblock, int flags); - int (*recvmsg) (struct socket *sock, struct msghdr *m, int total_len, int nonblock, int flags, int *addr_len); -}; - -struct net_proto { - const char *name; /* Protocol name */ - void (*init_func)(struct net_proto *); /* Bootstrap */ -}; - -extern int sock_wake_async(struct socket *sock, int how); -extern int sock_register(int family, struct proto_ops *ops); -extern int sock_unregister(int family); -extern struct socket *sock_alloc(void); -extern void sock_release(struct socket *sock); -#endif /* __KERNEL__ */ -#endif /* _LINUX_NET_H */ diff --git a/i386/i386at/gpl/linux/include/linux/netdevice.h b/i386/i386at/gpl/linux/include/linux/netdevice.h deleted file mode 100644 index 9e1143be..00000000 --- a/i386/i386at/gpl/linux/include/linux/netdevice.h +++ /dev/null @@ -1,332 +0,0 @@ -/* - * INET An implementation of the TCP/IP protocol suite for the LINUX - * operating system. INET is implemented using the BSD Socket - * interface as the means of communication with the user level. - * - * Definitions for the Interfaces handler. - * - * Version: @(#)dev.h 1.0.10 08/12/93 - * - * Authors: Ross Biro, <bir7@leland.Stanford.Edu> - * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> - * Corey Minyard <wf-rch!minyard@relay.EU.net> - * Donald J. Becker, <becker@super.org> - * Alan Cox, <A.Cox@swansea.ac.uk> - * Bjorn Ekwall. <bj0rn@blox.se> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * Moved to /usr/include/linux for NET3 - */ -#ifndef _LINUX_NETDEVICE_H -#define _LINUX_NETDEVICE_H - -#include <linux/config.h> -#include <linux/if.h> -#include <linux/if_ether.h> -#include <linux/skbuff.h> - -/* for future expansion when we will have different priorities. */ -#define DEV_NUMBUFFS 3 -#define MAX_ADDR_LEN 7 -#ifndef CONFIG_AX25 -#ifndef CONFIG_TR -#ifndef CONFIG_NET_IPIP -#define MAX_HEADER 32 /* We really need about 18 worst case .. so 32 is aligned */ -#else -#define MAX_HEADER 48 /* We need to allow for having tunnel headers */ -#endif /* IPIP */ -#else -#define MAX_HEADER 48 /* Token Ring header needs 40 bytes ... 48 is aligned */ -#endif /* TR */ -#else -#define MAX_HEADER 96 /* AX.25 + NetROM */ -#endif /* AX25 */ - -#define IS_MYADDR 1 /* address is (one of) our own */ -#define IS_LOOPBACK 2 /* address is for LOOPBACK */ -#define IS_BROADCAST 3 /* address is a valid broadcast */ -#define IS_INVBCAST 4 /* Wrong netmask bcast not for us (unused)*/ -#define IS_MULTICAST 5 /* Multicast IP address */ - -/* - * We tag multicasts with these structures. - */ - -struct dev_mc_list -{ - struct dev_mc_list *next; - char dmi_addr[MAX_ADDR_LEN]; - unsigned short dmi_addrlen; - unsigned short dmi_users; -}; - -struct hh_cache -{ - struct hh_cache *hh_next; - void *hh_arp; /* Opaque pointer, used by - * any address resolution module, - * not only ARP. - */ - unsigned int hh_refcnt; /* number of users */ - unsigned short hh_type; /* protocol identifier, f.e ETH_P_IP */ - char hh_uptodate; /* hh_data is valid */ - char hh_data[16]; /* cached hardware header */ -}; - -/* - * The DEVICE structure. - * Actually, this whole structure is a big mistake. It mixes I/O - * data with strictly "high-level" data, and it has to know about - * almost every data structure used in the INET module. - */ -#ifdef MACH -#ifndef MACH_INCLUDE -#define device linux_device -#endif -struct linux_device -#else -struct device -#endif -{ - - /* - * This is the first field of the "visible" part of this structure - * (i.e. as seen by users in the "Space.c" file). It is the name - * the interface. - */ - char *name; - - /* I/O specific fields - FIXME: Merge these and struct ifmap into one */ - unsigned long rmem_end; /* shmem "recv" end */ - unsigned long rmem_start; /* shmem "recv" start */ - unsigned long mem_end; /* shared mem end */ - unsigned long mem_start; /* shared mem start */ - unsigned long base_addr; /* device I/O address */ - unsigned char irq; /* device IRQ number */ - - /* Low-level status flags. */ - volatile unsigned char start, /* start an operation */ - interrupt; /* interrupt arrived */ - unsigned long tbusy; /* transmitter busy must be long for bitops */ - - struct linux_device *next; - - /* The device initialization function. Called only once. */ - int (*init)(struct linux_device *dev); - - /* Some hardware also needs these fields, but they are not part of the - usual set specified in Space.c. */ - unsigned char if_port; /* Selectable AUI, TP,..*/ - unsigned char dma; /* DMA channel */ - - struct enet_statistics* (*get_stats)(struct linux_device *dev); - - /* - * This marks the end of the "visible" part of the structure. All - * fields hereafter are internal to the system, and may change at - * will (read: may be cleaned up at will). - */ - - /* These may be needed for future network-power-down code. */ - unsigned long trans_start; /* Time (in jiffies) of last Tx */ - unsigned long last_rx; /* Time of last Rx */ - - unsigned short flags; /* interface flags (a la BSD) */ - unsigned short family; /* address family ID (AF_INET) */ - unsigned short metric; /* routing metric (not used) */ - unsigned short mtu; /* interface MTU value */ - unsigned short type; /* interface hardware type */ - unsigned short hard_header_len; /* hardware hdr length */ - void *priv; /* pointer to private data */ - - /* Interface address info. */ - unsigned char broadcast[MAX_ADDR_LEN]; /* hw bcast add */ - unsigned char pad; /* make dev_addr aligned to 8 bytes */ - unsigned char dev_addr[MAX_ADDR_LEN]; /* hw address */ - unsigned char addr_len; /* hardware address length */ - unsigned long pa_addr; /* protocol address */ - unsigned long pa_brdaddr; /* protocol broadcast addr */ - unsigned long pa_dstaddr; /* protocol P-P other side addr */ - unsigned long pa_mask; /* protocol netmask */ - unsigned short pa_alen; /* protocol address length */ - - struct dev_mc_list *mc_list; /* Multicast mac addresses */ - int mc_count; /* Number of installed mcasts */ - - struct ip_mc_list *ip_mc_list; /* IP multicast filter chain */ - __u32 tx_queue_len; /* Max frames per queue allowed */ - - /* For load balancing driver pair support */ - - unsigned long pkt_queue; /* Packets queued */ - struct linux_device *slave; /* Slave device */ - struct net_alias_info *alias_info; /* main dev alias info */ - struct net_alias *my_alias; /* alias devs */ - - /* Pointer to the interface buffers. */ - struct sk_buff_head buffs[DEV_NUMBUFFS]; - - /* Pointers to interface service routines. */ - int (*open)(struct linux_device *dev); - int (*stop)(struct linux_device *dev); - int (*hard_start_xmit) (struct sk_buff *skb, - struct linux_device *dev); - int (*hard_header) (struct sk_buff *skb, - struct linux_device *dev, - unsigned short type, - void *daddr, - void *saddr, - unsigned len); - int (*rebuild_header)(void *eth, - struct linux_device *dev, - unsigned long raddr, struct sk_buff *skb); -#define HAVE_MULTICAST - void (*set_multicast_list)(struct linux_device *dev); -#define HAVE_SET_MAC_ADDR - int (*set_mac_address)(struct linux_device *dev, - void *addr); -#define HAVE_PRIVATE_IOCTL - int (*do_ioctl)(struct linux_device *dev, - struct ifreq *ifr, int cmd); -#define HAVE_SET_CONFIG - int (*set_config)(struct linux_device *dev, - struct ifmap *map); -#define HAVE_HEADER_CACHE - void (*header_cache_bind)(struct hh_cache **hhp, - struct linux_device *dev, - unsigned short htype, - __u32 daddr); - void (*header_cache_update)(struct hh_cache *hh, - struct linux_device *dev, - unsigned char * haddr); -#ifdef MACH -#ifdef MACH_INCLUDE - struct net_data *net_data; -#else - void *net_data; -#endif -#endif -}; - - -struct packet_type { - unsigned short type; /* This is really htons(ether_type). */ - struct linux_device * dev; - int (*func) (struct sk_buff *, struct linux_device *, - struct packet_type *); - void *data; - struct packet_type *next; -}; - - -#ifdef __KERNEL__ - -#include <linux/notifier.h> - -/* Used by dev_rint */ -#define IN_SKBUFF 1 - -extern volatile unsigned long in_bh; - -extern struct linux_device loopback_dev; -extern struct linux_device *dev_base; -extern struct packet_type *ptype_base[16]; - - -extern int ip_addr_match(unsigned long addr1, unsigned long addr2); -extern int ip_chk_addr(unsigned long addr); -extern struct linux_device *ip_dev_check(unsigned long daddr); -extern unsigned long ip_my_addr(void); -extern unsigned long ip_get_mask(unsigned long addr); -extern struct linux_device *ip_dev_find(unsigned long addr); -extern struct linux_device *dev_getbytype(unsigned short type); - -extern void dev_add_pack(struct packet_type *pt); -extern void dev_remove_pack(struct packet_type *pt); -extern struct linux_device *dev_get(const char *name); -extern int dev_open(struct linux_device *dev); -extern int dev_close(struct linux_device *dev); -extern void dev_queue_xmit(struct sk_buff *skb, - struct linux_device *dev, - int pri); -#define HAVE_NETIF_RX 1 -extern void netif_rx(struct sk_buff *skb); -extern void dev_transmit(void); -extern int in_net_bh(void); -extern void net_bh(void *tmp); -#ifdef MACH -#define dev_tint(dev) -#else -extern void dev_tint(struct linux_device *dev); -#endif -extern int dev_get_info(char *buffer, char **start, off_t offset, int length, int dummy); -extern int dev_ioctl(unsigned int cmd, void *); - -extern void dev_init(void); - -/* Locking protection for page faults during outputs to devices unloaded during the fault */ - -extern int dev_lockct; - -/* - * These two dont currently need to be interrupt safe - * but they may do soon. Do it properly anyway. - */ - -extern __inline__ void dev_lock_list(void) -{ - unsigned long flags; - save_flags(flags); - cli(); - dev_lockct++; - restore_flags(flags); -} - -extern __inline__ void dev_unlock_list(void) -{ - unsigned long flags; - save_flags(flags); - cli(); - dev_lockct--; - restore_flags(flags); -} - -/* - * This almost never occurs, isnt in performance critical paths - * and we can thus be relaxed about it - */ - -extern __inline__ void dev_lock_wait(void) -{ - while(dev_lockct) - schedule(); -} - - -/* These functions live elsewhere (drivers/net/net_init.c, but related) */ - -extern void ether_setup(struct linux_device *dev); -extern void tr_setup(struct linux_device *dev); -extern int ether_config(struct linux_device *dev, - struct ifmap *map); -/* Support for loadable net-drivers */ -extern int register_netdev(struct linux_device *dev); -extern void unregister_netdev(struct linux_device *dev); -extern int register_netdevice_notifier(struct notifier_block *nb); -extern int unregister_netdevice_notifier(struct notifier_block *nb); -/* Functions used for multicast support */ -extern void dev_mc_upload(struct linux_device *dev); -extern void dev_mc_delete(struct linux_device *dev, - void *addr, int alen, int all); -extern void dev_mc_add(struct linux_device *dev, - void *addr, int alen, int newonly); -extern void dev_mc_discard(struct linux_device *dev); -/* This is the wrong place but it'll do for the moment */ -extern void ip_mc_allhost(struct linux_device *dev); -#endif /* __KERNEL__ */ - -#endif /* _LINUX_DEV_H */ diff --git a/i386/i386at/gpl/linux/include/linux/nfs.h b/i386/i386at/gpl/linux/include/linux/nfs.h deleted file mode 100644 index ceb0cd1b..00000000 --- a/i386/i386at/gpl/linux/include/linux/nfs.h +++ /dev/null @@ -1,172 +0,0 @@ -#ifndef _LINUX_NFS_H -#define _LINUX_NFS_H - -#ifndef MACH_INCLUDE -#define NFS_PORT 2049 -#define NFS_MAXDATA 8192 -#define NFS_MAXPATHLEN 1024 -#define NFS_MAXNAMLEN 255 -#define NFS_MAXGROUPS 16 -#define NFS_FHSIZE 32 -#define NFS_COOKIESIZE 4 -#define NFS_FIFO_DEV (-1) -#define NFSMODE_FMT 0170000 -#define NFSMODE_DIR 0040000 -#define NFSMODE_CHR 0020000 -#define NFSMODE_BLK 0060000 -#define NFSMODE_REG 0100000 -#define NFSMODE_LNK 0120000 -#define NFSMODE_SOCK 0140000 -#define NFSMODE_FIFO 0010000 - -#ifdef __KERNEL__ /* user programs should get these from the rpc header files */ - -#define RPC_VERSION 2 - -enum rpc_auth_flavor { - RPC_AUTH_NULL = 0, - RPC_AUTH_UNIX = 1, - RPC_AUTH_SHORT = 2 -}; - -enum rpc_msg_type { - RPC_CALL = 0, - RPC_REPLY = 1 -}; - -enum rpc_reply_stat { - RPC_MSG_ACCEPTED = 0, - RPC_MSG_DENIED = 1 -}; - -enum rpc_accept_stat { - RPC_SUCCESS = 0, - RPC_PROG_UNAVAIL = 1, - RPC_PROG_MISMATCH = 2, - RPC_PROC_UNAVAIL = 3, - RPC_GARBAGE_ARGS = 4 -}; - -enum rpc_reject_stat { - RPC_MISMATCH = 0, - RPC_AUTH_ERROR = 1 -}; - -enum rpc_auth_stat { - RPC_AUTH_BADCRED = 1, - RPC_AUTH_REJECTEDCRED = 2, - RPC_AUTH_BADVERF = 3, - RPC_AUTH_REJECTEDVERF = 4, - RPC_AUTH_TOOWEAK = 5 -}; - -#endif /* __KERNEL__ */ - -enum nfs_stat { - NFS_OK = 0, - NFSERR_PERM = 1, - NFSERR_NOENT = 2, - NFSERR_IO = 5, - NFSERR_NXIO = 6, - NFSERR_EAGAIN = 11, - NFSERR_ACCES = 13, - NFSERR_EXIST = 17, - NFSERR_NODEV = 19, - NFSERR_NOTDIR = 20, - NFSERR_ISDIR = 21, - NFSERR_INVAL = 22, /* that Sun forgot */ - NFSERR_FBIG = 27, - NFSERR_NOSPC = 28, - NFSERR_ROFS = 30, - NFSERR_NAMETOOLONG = 63, - NFSERR_NOTEMPTY = 66, - NFSERR_DQUOT = 69, - NFSERR_STALE = 70, - NFSERR_WFLUSH = 99 -}; - -enum nfs_ftype { - NFNON = 0, - NFREG = 1, - NFDIR = 2, - NFBLK = 3, - NFCHR = 4, - NFLNK = 5, - NFSOCK = 6, - NFBAD = 7, - NFFIFO = 8 -}; - -#define NFS_PROGRAM 100003 -#define NFS_VERSION 2 -#define NFSPROC_NULL 0 -#define NFSPROC_GETATTR 1 -#define NFSPROC_SETATTR 2 -#define NFSPROC_ROOT 3 -#define NFSPROC_LOOKUP 4 -#define NFSPROC_READLINK 5 -#define NFSPROC_READ 6 -#define NFSPROC_WRITECACHE 7 -#define NFSPROC_WRITE 8 -#define NFSPROC_CREATE 9 -#define NFSPROC_REMOVE 10 -#define NFSPROC_RENAME 11 -#define NFSPROC_LINK 12 -#define NFSPROC_SYMLINK 13 -#define NFSPROC_MKDIR 14 -#define NFSPROC_RMDIR 15 -#define NFSPROC_READDIR 16 -#define NFSPROC_STATFS 17 - -struct nfs_fh { - char data[NFS_FHSIZE]; -}; - -struct nfs_time { - u_int seconds; - u_int useconds; -}; - -struct nfs_fattr { - enum nfs_ftype type; - u_int mode; - u_int nlink; - u_int uid; - u_int gid; - u_int size; - u_int blocksize; - u_int rdev; - u_int blocks; - u_int fsid; - u_int fileid; - struct nfs_time atime; - struct nfs_time mtime; - struct nfs_time ctime; -}; - -struct nfs_sattr { - u_int mode; - u_int uid; - u_int gid; - u_int size; - struct nfs_time atime; - struct nfs_time mtime; -}; - -struct nfs_entry { - u_int fileid; - char *name; - int cookie; - int eof; -}; - -struct nfs_fsinfo { - u_int tsize; - u_int bsize; - u_int blocks; - u_int bfree; - u_int bavail; -}; - -#endif /* ! MACH_INCLUDE */ -#endif diff --git a/i386/i386at/gpl/linux/include/linux/notifier.h b/i386/i386at/gpl/linux/include/linux/notifier.h deleted file mode 100644 index 3de4d976..00000000 --- a/i386/i386at/gpl/linux/include/linux/notifier.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Routines to manage notifier chains for passing status changes to any - * interested routines. We need this instead of hard coded call lists so - * that modules can poke their nose into the innards. The network devices - * needed them so here they are for the rest of you. - * - * Alan Cox <Alan.Cox@linux.org> - */ - -#ifndef _LINUX_NOTIFIER_H -#define _LINUX_NOTIFIER_H -#include <linux/errno.h> - -struct notifier_block -{ - int (*notifier_call)(struct notifier_block *this, unsigned long, void *); - struct notifier_block *next; - int priority; -}; - - -#ifdef __KERNEL__ - -#define NOTIFY_DONE 0x0000 /* Don't care */ -#define NOTIFY_OK 0x0001 /* Suits me */ -#define NOTIFY_STOP_MASK 0x8000 /* Don't call further */ -#define NOTIFY_BAD (NOTIFY_STOP_MASK|0x0002) /* Bad/Veto action */ - -extern __inline__ int notifier_chain_register(struct notifier_block **list, struct notifier_block *n) -{ - while(*list) - { - if(n->priority > (*list)->priority) - break; - list= &((*list)->next); - } - n->next = *list; - *list=n; - return 0; -} - -/* - * Warning to any non GPL module writers out there.. these functions are - * GPL'd - */ - -extern __inline__ int notifier_chain_unregister(struct notifier_block **nl, struct notifier_block *n) -{ - while((*nl)!=NULL) - { - if((*nl)==n) - { - *nl=n->next; - return 0; - } - nl=&((*nl)->next); - } -#ifdef MACH_INCLUDE - return -LINUX_ENOENT; -#else - return -ENOENT; -#endif -} - -/* - * This is one of these things that is generally shorter inline - */ - -extern __inline__ int notifier_call_chain(struct notifier_block **n, unsigned long val, void *v) -{ - int ret=NOTIFY_DONE; - struct notifier_block *nb = *n; - while(nb) - { - ret=nb->notifier_call(nb,val,v); - if(ret&NOTIFY_STOP_MASK) - return ret; - nb=nb->next; - } - return ret; -} - - -/* - * Declared notifiers so far. I can imagine quite a few more chains - * over time (eg laptop power reset chains, reboot chain (to clean - * device units up), device [un]mount chain, module load/unload chain, - * low memory chain, screenblank chain (for plug in modular screenblankers) - * VC switch chains (for loadable kernel svgalib VC switch helpers) etc... - */ - -/* netdevice notifier chain */ -#define NETDEV_UP 0x0001 /* For now you can't veto a device up/down */ -#define NETDEV_DOWN 0x0002 -#define NETDEV_REBOOT 0x0003 /* Tell a protocol stack a network interface - detected a hardware crash and restarted - - we can use this eg to kick tcp sessions - once done */ -#endif -#endif diff --git a/i386/i386at/gpl/linux/include/linux/pagemap.h b/i386/i386at/gpl/linux/include/linux/pagemap.h deleted file mode 100644 index 6de993b3..00000000 --- a/i386/i386at/gpl/linux/include/linux/pagemap.h +++ /dev/null @@ -1,131 +0,0 @@ -#ifndef _LINUX_PAGEMAP_H -#define _LINUX_PAGEMAP_H - -#include <asm/system.h> - -/* - * Page-mapping primitive inline functions - * - * Copyright 1995 Linus Torvalds - */ - -#ifndef MACH -static inline unsigned long page_address(struct page * page) -{ - return PAGE_OFFSET + PAGE_SIZE*(page - mem_map); -} - -#define PAGE_HASH_BITS 10 -#define PAGE_HASH_SIZE (1 << PAGE_HASH_BITS) - -#define PAGE_AGE_VALUE 16 - -extern unsigned long page_cache_size; -extern struct page * page_hash_table[PAGE_HASH_SIZE]; - -/* - * We use a power-of-two hash table to avoid a modulus, - * and get a reasonable hash by knowing roughly how the - * inode pointer and offsets are distributed (ie, we - * roughly know which bits are "significant") - */ -static inline unsigned long _page_hashfn(struct inode * inode, unsigned long offset) -{ -#define i (((unsigned long) inode)/sizeof(unsigned long)) -#define o (offset >> PAGE_SHIFT) -#define s(x) ((x)+((x)>>PAGE_HASH_BITS)) - return s(i+o) & (PAGE_HASH_SIZE-1); -#undef i -#undef o -#undef s -} - -#define page_hash(inode,offset) page_hash_table[_page_hashfn(inode,offset)] - -static inline struct page * find_page(struct inode * inode, unsigned long offset) -{ - struct page *page; - unsigned long flags; - - for (page = page_hash(inode, offset); page ; page = page->next_hash) { - if (page->inode != inode) - continue; - if (page->offset != offset) - continue; - save_flags(flags); - cli(); - page->referenced = 1; - page->count++; - restore_flags(flags); - break; - } - return page; -} - -static inline void remove_page_from_hash_queue(struct page * page) -{ - struct page **p = &page_hash(page->inode,page->offset); - - page_cache_size--; - if (page->next_hash) - page->next_hash->prev_hash = page->prev_hash; - if (page->prev_hash) - page->prev_hash->next_hash = page->next_hash; - if (*p == page) - *p = page->next_hash; - page->next_hash = page->prev_hash = NULL; -} - -static inline void add_page_to_hash_queue(struct inode * inode, struct page * page) -{ - struct page **p = &page_hash(inode,page->offset); - - page_cache_size++; - page->referenced = 1; - page->age = PAGE_AGE_VALUE; - page->prev_hash = NULL; - if ((page->next_hash = *p) != NULL) - page->next_hash->prev_hash = page; - *p = page; -} - -static inline void remove_page_from_inode_queue(struct page * page) -{ - struct inode * inode = page->inode; - - page->inode = NULL; - inode->i_nrpages--; - if (inode->i_pages == page) - inode->i_pages = page->next; - if (page->next) - page->next->prev = page->prev; - if (page->prev) - page->prev->next = page->next; - page->next = NULL; - page->prev = NULL; -} - -static inline void add_page_to_inode_queue(struct inode * inode, struct page * page) -{ - struct page **p = &inode->i_pages; - - inode->i_nrpages++; - page->inode = inode; - page->prev = NULL; - if ((page->next = *p) != NULL) - page->next->prev = page; - *p = page; -} - -extern void __wait_on_page(struct page *); -static inline void wait_on_page(struct page * page) -{ - if (page->locked) - __wait_on_page(page); -} - -extern void update_vm_cache(struct inode *, unsigned long, const char *, int); - -#endif /* ! MACH */ - -#endif diff --git a/i386/i386at/gpl/linux/include/linux/param.h b/i386/i386at/gpl/linux/include/linux/param.h deleted file mode 100644 index 092e92f6..00000000 --- a/i386/i386at/gpl/linux/include/linux/param.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _LINUX_PARAM_H -#define _LINUX_PARAM_H - -#include <asm/param.h> - -#endif diff --git a/i386/i386at/gpl/linux/include/linux/pci.h b/i386/i386at/gpl/linux/include/linux/pci.h deleted file mode 100644 index 9e059501..00000000 --- a/i386/i386at/gpl/linux/include/linux/pci.h +++ /dev/null @@ -1,618 +0,0 @@ -/* - * PCI defines and function prototypes - * Copyright 1994, Drew Eckhardt - * - * For more information, please consult - * - * PCI BIOS Specification Revision - * PCI Local Bus Specification - * PCI System Design Guide - * - * PCI Special Interest Group - * M/S HF3-15A - * 5200 N.E. Elam Young Parkway - * Hillsboro, Oregon 97124-6497 - * +1 (503) 696-2000 - * +1 (800) 433-5177 - * - * Manuals are $25 each or $50 for all three, plus $7 shipping - * within the United States, $35 abroad. - */ - - - -/* PROCEDURE TO REPORT NEW PCI DEVICES - * We are trying to collect informations on new PCI devices, using - * the standart PCI identification procedure. If some warning is - * displayed at boot time, please report - * - /proc/pci - * - your exact hardware description. Try to find out - * which device is unknown. It may be you mainboard chipset. - * PCI-CPU bridge or PCI-ISA bridge. - * - If you can't find the actual information in your hardware - * booklet, try to read the references of the chip on the board. - * - Send all that, with the word PCIPROBE in the subject, - * to frederic@cao-vlsi.ibp.fr, and I'll add your device to - * the list as soon as possible - * fred. - */ - - - -#ifndef PCI_H -#define PCI_H - -/* - * Under PCI, each device has 256 bytes of configuration address space, - * of which the first 64 bytes are standardized as follows: - */ -#define PCI_VENDOR_ID 0x00 /* 16 bits */ -#define PCI_DEVICE_ID 0x02 /* 16 bits */ -#define PCI_COMMAND 0x04 /* 16 bits */ -#define PCI_COMMAND_IO 0x1 /* Enable response in I/O space */ -#define PCI_COMMAND_MEMORY 0x2 /* Enable response in Memory space */ -#define PCI_COMMAND_MASTER 0x4 /* Enable bus mastering */ -#define PCI_COMMAND_SPECIAL 0x8 /* Enable response to special cycles */ -#define PCI_COMMAND_INVALIDATE 0x10 /* Use memory write and invalidate */ -#define PCI_COMMAND_VGA_PALETTE 0x20 /* Enable palette snooping */ -#define PCI_COMMAND_PARITY 0x40 /* Enable parity checking */ -#define PCI_COMMAND_WAIT 0x80 /* Enable address/data stepping */ -#define PCI_COMMAND_SERR 0x100 /* Enable SERR */ -#define PCI_COMMAND_FAST_BACK 0x200 /* Enable back-to-back writes */ - -#define PCI_STATUS 0x06 /* 16 bits */ -#define PCI_STATUS_66MHZ 0x20 /* Support 66 Mhz PCI 2.1 bus */ -#define PCI_STATUS_UDF 0x40 /* Support User Definable Features */ - -#define PCI_STATUS_FAST_BACK 0x80 /* Accept fast-back to back */ -#define PCI_STATUS_PARITY 0x100 /* Detected parity error */ -#define PCI_STATUS_DEVSEL_MASK 0x600 /* DEVSEL timing */ -#define PCI_STATUS_DEVSEL_FAST 0x000 -#define PCI_STATUS_DEVSEL_MEDIUM 0x200 -#define PCI_STATUS_DEVSEL_SLOW 0x400 -#define PCI_STATUS_SIG_TARGET_ABORT 0x800 /* Set on target abort */ -#define PCI_STATUS_REC_TARGET_ABORT 0x1000 /* Master ack of " */ -#define PCI_STATUS_REC_MASTER_ABORT 0x2000 /* Set on master abort */ -#define PCI_STATUS_SIG_SYSTEM_ERROR 0x4000 /* Set when we drive SERR */ -#define PCI_STATUS_DETECTED_PARITY 0x8000 /* Set on parity error */ - -#define PCI_CLASS_REVISION 0x08 /* High 24 bits are class, low 8 - revision */ -#define PCI_REVISION_ID 0x08 /* Revision ID */ -#define PCI_CLASS_PROG 0x09 /* Reg. Level Programming Interface */ -#define PCI_CLASS_DEVICE 0x0a /* Device class */ - -#define PCI_CACHE_LINE_SIZE 0x0c /* 8 bits */ -#define PCI_LATENCY_TIMER 0x0d /* 8 bits */ -#define PCI_HEADER_TYPE 0x0e /* 8 bits */ -#define PCI_BIST 0x0f /* 8 bits */ -#define PCI_BIST_CODE_MASK 0x0f /* Return result */ -#define PCI_BIST_START 0x40 /* 1 to start BIST, 2 secs or less */ -#define PCI_BIST_CAPABLE 0x80 /* 1 if BIST capable */ - -/* - * Base addresses specify locations in memory or I/O space. - * Decoded size can be determined by writing a value of - * 0xffffffff to the register, and reading it back. Only - * 1 bits are decoded. - */ -#define PCI_BASE_ADDRESS_0 0x10 /* 32 bits */ -#define PCI_BASE_ADDRESS_1 0x14 /* 32 bits */ -#define PCI_BASE_ADDRESS_2 0x18 /* 32 bits */ -#define PCI_BASE_ADDRESS_3 0x1c /* 32 bits */ -#define PCI_BASE_ADDRESS_4 0x20 /* 32 bits */ -#define PCI_BASE_ADDRESS_5 0x24 /* 32 bits */ -#define PCI_BASE_ADDRESS_SPACE 0x01 /* 0 = memory, 1 = I/O */ -#define PCI_BASE_ADDRESS_SPACE_IO 0x01 -#define PCI_BASE_ADDRESS_SPACE_MEMORY 0x00 -#define PCI_BASE_ADDRESS_MEM_TYPE_MASK 0x06 -#define PCI_BASE_ADDRESS_MEM_TYPE_32 0x00 /* 32 bit address */ -#define PCI_BASE_ADDRESS_MEM_TYPE_1M 0x02 /* Below 1M */ -#define PCI_BASE_ADDRESS_MEM_TYPE_64 0x04 /* 64 bit address */ -#define PCI_BASE_ADDRESS_MEM_PREFETCH 0x08 /* prefetchable? */ -#define PCI_BASE_ADDRESS_MEM_MASK (~0x0f) -#define PCI_BASE_ADDRESS_IO_MASK (~0x03) -/* bit 1 is reserved if address_space = 1 */ - -#define PCI_CARDBUS_CIS 0x28 -#define PCI_SUBSYSTEM_ID 0x2c -#define PCI_SUBSYSTEM_VENDOR_ID 0x2e -#define PCI_ROM_ADDRESS 0x30 /* 32 bits */ -#define PCI_ROM_ADDRESS_ENABLE 0x01 /* Write 1 to enable ROM, - bits 31..11 are address, - 10..2 are reserved */ -/* 0x34-0x3b are reserved */ -#define PCI_INTERRUPT_LINE 0x3c /* 8 bits */ -#define PCI_INTERRUPT_PIN 0x3d /* 8 bits */ -#define PCI_MIN_GNT 0x3e /* 8 bits */ -#define PCI_MAX_LAT 0x3f /* 8 bits */ - -#define PCI_CLASS_NOT_DEFINED 0x0000 -#define PCI_CLASS_NOT_DEFINED_VGA 0x0001 - -#define PCI_BASE_CLASS_STORAGE 0x01 -#define PCI_CLASS_STORAGE_SCSI 0x0100 -#define PCI_CLASS_STORAGE_IDE 0x0101 -#define PCI_CLASS_STORAGE_FLOPPY 0x0102 -#define PCI_CLASS_STORAGE_IPI 0x0103 -#define PCI_CLASS_STORAGE_RAID 0x0104 -#define PCI_CLASS_STORAGE_OTHER 0x0180 - -#define PCI_BASE_CLASS_NETWORK 0x02 -#define PCI_CLASS_NETWORK_ETHERNET 0x0200 -#define PCI_CLASS_NETWORK_TOKEN_RING 0x0201 -#define PCI_CLASS_NETWORK_FDDI 0x0202 -#define PCI_CLASS_NETWORK_ATM 0x0203 -#define PCI_CLASS_NETWORK_OTHER 0x0280 - -#define PCI_BASE_CLASS_DISPLAY 0x03 -#define PCI_CLASS_DISPLAY_VGA 0x0300 -#define PCI_CLASS_DISPLAY_XGA 0x0301 -#define PCI_CLASS_DISPLAY_OTHER 0x0380 - -#define PCI_BASE_CLASS_MULTIMEDIA 0x04 -#define PCI_CLASS_MULTIMEDIA_VIDEO 0x0400 -#define PCI_CLASS_MULTIMEDIA_AUDIO 0x0401 -#define PCI_CLASS_MULTIMEDIA_OTHER 0x0480 - -#define PCI_BASE_CLASS_MEMORY 0x05 -#define PCI_CLASS_MEMORY_RAM 0x0500 -#define PCI_CLASS_MEMORY_FLASH 0x0501 -#define PCI_CLASS_MEMORY_OTHER 0x0580 - -#define PCI_BASE_CLASS_BRIDGE 0x06 -#define PCI_CLASS_BRIDGE_HOST 0x0600 -#define PCI_CLASS_BRIDGE_ISA 0x0601 -#define PCI_CLASS_BRIDGE_EISA 0x0602 -#define PCI_CLASS_BRIDGE_MC 0x0603 -#define PCI_CLASS_BRIDGE_PCI 0x0604 -#define PCI_CLASS_BRIDGE_PCMCIA 0x0605 -#define PCI_CLASS_BRIDGE_NUBUS 0x0606 -#define PCI_CLASS_BRIDGE_CARDBUS 0x0607 -#define PCI_CLASS_BRIDGE_OTHER 0x0680 - - -#define PCI_BASE_CLASS_COMMUNICATION 0x07 -#define PCI_CLASS_COMMUNICATION_SERIAL 0x0700 -#define PCI_CLASS_COMMUNICATION_PARALLEL 0x0701 -#define PCI_CLASS_COMMUNICATION_OTHER 0x0780 - -#define PCI_BASE_CLASS_SYSTEM 0x08 -#define PCI_CLASS_SYSTEM_PIC 0x0800 -#define PCI_CLASS_SYSTEM_DMA 0x0801 -#define PCI_CLASS_SYSTEM_TIMER 0x0802 -#define PCI_CLASS_SYSTEM_RTC 0x0803 -#define PCI_CLASS_SYSTEM_OTHER 0x0880 - -#define PCI_BASE_CLASS_INPUT 0x09 -#define PCI_CLASS_INPUT_KEYBOARD 0x0900 -#define PCI_CLASS_INPUT_PEN 0x0901 -#define PCI_CLASS_INPUT_MOUSE 0x0902 -#define PCI_CLASS_INPUT_OTHER 0x0980 - -#define PCI_BASE_CLASS_DOCKING 0x0a -#define PCI_CLASS_DOCKING_GENERIC 0x0a00 -#define PCI_CLASS_DOCKING_OTHER 0x0a01 - -#define PCI_BASE_CLASS_PROCESSOR 0x0b -#define PCI_CLASS_PROCESSOR_386 0x0b00 -#define PCI_CLASS_PROCESSOR_486 0x0b01 -#define PCI_CLASS_PROCESSOR_PENTIUM 0x0b02 -#define PCI_CLASS_PROCESSOR_ALPHA 0x0b10 -#define PCI_CLASS_PROCESSOR_POWERPC 0x0b20 -#define PCI_CLASS_PROCESSOR_CO 0x0b40 - -#define PCI_BASE_CLASS_SERIAL 0x0c -#define PCI_CLASS_SERIAL_FIREWIRE 0x0c00 -#define PCI_CLASS_SERIAL_ACCESS 0x0c01 -#define PCI_CLASS_SERIAL_SSA 0x0c02 -#define PCI_CLASS_SERIAL_USB 0x0c03 -#define PCI_CLASS_SERIAL_FIBER 0x0c04 - -#define PCI_CLASS_OTHERS 0xff - -/* - * Vendor and card ID's: sort these numerically according to vendor - * (and according to card ID within vendor) - */ -#define PCI_VENDOR_ID_COMPAQ 0x0e11 -#define PCI_DEVICE_ID_COMPAQ_1280 0x3033 -#define PCI_DEVICE_ID_COMPAQ_THUNDER 0xf130 - -#define PCI_VENDOR_ID_NCR 0x1000 -#define PCI_DEVICE_ID_NCR_53C810 0x0001 -#define PCI_DEVICE_ID_NCR_53C820 0x0002 -#define PCI_DEVICE_ID_NCR_53C825 0x0003 -#define PCI_DEVICE_ID_NCR_53C815 0x0004 - -#define PCI_VENDOR_ID_ATI 0x1002 -#define PCI_DEVICE_ID_ATI_68800 0x4158 -#define PCI_DEVICE_ID_ATI_215CT222 0x4354 -#define PCI_DEVICE_ID_ATI_210888CX 0x4358 -#define PCI_DEVICE_ID_ATI_210888GX 0x4758 - -#define PCI_VENDOR_ID_VLSI 0x1004 -#define PCI_DEVICE_ID_VLSI_82C592 0x0005 -#define PCI_DEVICE_ID_VLSI_82C593 0x0006 -#define PCI_DEVICE_ID_VLSI_82C594 0x0007 -#define PCI_DEVICE_ID_VLSI_82C597 0x0009 - -#define PCI_VENDOR_ID_ADL 0x1005 -#define PCI_DEVICE_ID_ADL_2301 0x2301 - -#define PCI_VENDOR_ID_NS 0x100b -#define PCI_DEVICE_ID_NS_87410 0xd001 - -#define PCI_VENDOR_ID_TSENG 0x100c -#define PCI_DEVICE_ID_TSENG_W32P_2 0x3202 -#define PCI_DEVICE_ID_TSENG_W32P_b 0x3205 -#define PCI_DEVICE_ID_TSENG_W32P_c 0x3206 -#define PCI_DEVICE_ID_TSENG_W32P_d 0x3207 - -#define PCI_VENDOR_ID_WEITEK 0x100e -#define PCI_DEVICE_ID_WEITEK_P9000 0x9001 -#define PCI_DEVICE_ID_WEITEK_P9100 0x9100 - -#define PCI_VENDOR_ID_DEC 0x1011 -#define PCI_DEVICE_ID_DEC_BRD 0x0001 -#define PCI_DEVICE_ID_DEC_TULIP 0x0002 -#define PCI_DEVICE_ID_DEC_TGA 0x0004 -#define PCI_DEVICE_ID_DEC_TULIP_FAST 0x0009 -#define PCI_DEVICE_ID_DEC_FDDI 0x000F -#define PCI_DEVICE_ID_DEC_TULIP_PLUS 0x0014 - -#define PCI_VENDOR_ID_CIRRUS 0x1013 -#define PCI_DEVICE_ID_CIRRUS_5430 0x00a0 -#define PCI_DEVICE_ID_CIRRUS_5434_4 0x00a4 -#define PCI_DEVICE_ID_CIRRUS_5434_8 0x00a8 -#define PCI_DEVICE_ID_CIRRUS_5436 0x00ac -#define PCI_DEVICE_ID_CIRRUS_6205 0x0205 -#define PCI_DEVICE_ID_CIRRUS_6729 0x1100 -#define PCI_DEVICE_ID_CIRRUS_7542 0x1200 -#define PCI_DEVICE_ID_CIRRUS_7543 0x1202 - -#define PCI_VENDOR_ID_IBM 0x1014 -#define PCI_DEVICE_ID_IBM_82G2675 0x001d - -#define PCI_VENDOR_ID_WD 0x101c -#define PCI_DEVICE_ID_WD_7197 0x3296 - -#define PCI_VENDOR_ID_AMD 0x1022 -#define PCI_DEVICE_ID_AMD_LANCE 0x2000 -#define PCI_DEVICE_ID_AMD_SCSI 0x2020 - -#define PCI_VENDOR_ID_TRIDENT 0x1023 -#define PCI_DEVICE_ID_TRIDENT_9420 0x9420 -#define PCI_DEVICE_ID_TRIDENT_9440 0x9440 -#define PCI_DEVICE_ID_TRIDENT_9660 0x9660 - -#define PCI_VENDOR_ID_AI 0x1025 -#define PCI_DEVICE_ID_AI_M1435 0x1435 - -#define PCI_VENDOR_ID_MATROX 0x102B -#define PCI_DEVICE_ID_MATROX_MGA_2 0x0518 -#define PCI_DEVICE_ID_MATROX_MIL 0x0519 -#define PCI_DEVICE_ID_MATROX_MGA_IMP 0x0d10 - -#define PCI_VENDOR_ID_CT 0x102c -#define PCI_DEVICE_ID_CT_65545 0x00d8 - -#define PCI_VENDOR_ID_FD 0x1036 -#define PCI_DEVICE_ID_FD_36C70 0x0000 - -#define PCI_VENDOR_ID_SI 0x1039 -#define PCI_DEVICE_ID_SI_6201 0x0001 -#define PCI_DEVICE_ID_SI_6202 0x0002 -#define PCI_DEVICE_ID_SI_503 0x0008 -#define PCI_DEVICE_ID_SI_501 0x0406 -#define PCI_DEVICE_ID_SI_496 0x0496 -#define PCI_DEVICE_ID_SI_601 0x0601 -#define PCI_DEVICE_ID_SI_5511 0x5511 -#define PCI_DEVICE_ID_SI_5513 0x5513 - -#define PCI_VENDOR_ID_HP 0x103c -#define PCI_DEVICE_ID_HP_J2585A 0x1030 - -#define PCI_VENDOR_ID_PCTECH 0x1042 -#define PCI_DEVICE_ID_PCTECH_RZ1000 0x1000 - -#define PCI_VENDOR_ID_DPT 0x1044 -#define PCI_DEVICE_ID_DPT 0xa400 - -#define PCI_VENDOR_ID_OPTI 0x1045 -#define PCI_DEVICE_ID_OPTI_92C178 0xc178 -#define PCI_DEVICE_ID_OPTI_82C557 0xc557 -#define PCI_DEVICE_ID_OPTI_82C558 0xc558 -#define PCI_DEVICE_ID_OPTI_82C621 0xc621 -#define PCI_DEVICE_ID_OPTI_82C822 0xc822 - -#define PCI_VENDOR_ID_SGS 0x104a -#define PCI_DEVICE_ID_SGS_2000 0x0008 -#define PCI_DEVICE_ID_SGS_1764 0x0009 - -#define PCI_VENDOR_ID_BUSLOGIC 0x104B -#define PCI_DEVICE_ID_BUSLOGIC_946C_2 0x0140 -#define PCI_DEVICE_ID_BUSLOGIC_946C 0x1040 -#define PCI_DEVICE_ID_BUSLOGIC_930 0x8130 - -#define PCI_VENDOR_ID_OAK 0x104e -#define PCI_DEVICE_ID_OAK_OTI107 0x0107 - -#define PCI_VENDOR_ID_PROMISE 0x105a -#define PCI_DEVICE_ID_PROMISE_5300 0x5300 - -#define PCI_VENDOR_ID_N9 0x105d -#define PCI_DEVICE_ID_N9_I128 0x2309 -#define PCI_DEVICE_ID_N9_I128_2 0x2339 - -#define PCI_VENDOR_ID_UMC 0x1060 -#define PCI_DEVICE_ID_UMC_UM8673F 0x0101 -#define PCI_DEVICE_ID_UMC_UM8891A 0x0891 -#define PCI_DEVICE_ID_UMC_UM8886BF 0x673a -#define PCI_DEVICE_ID_UMC_UM8886A 0x886a -#define PCI_DEVICE_ID_UMC_UM8881F 0x8881 -#define PCI_DEVICE_ID_UMC_UM8886F 0x8886 -#define PCI_DEVICE_ID_UMC_UM9017F 0x9017 -#define PCI_DEVICE_ID_UMC_UM8886N 0xe886 -#define PCI_DEVICE_ID_UMC_UM8891N 0xe891 - -#define PCI_VENDOR_ID_X 0x1061 -#define PCI_DEVICE_ID_X_AGX016 0x0001 - -#define PCI_VENDOR_ID_NEXGEN 0x1074 -#define PCI_DEVICE_ID_NEXGEN_82C501 0x4e78 - -#define PCI_VENDOR_ID_QLOGIC 0x1077 -#define PCI_DEVICE_ID_QLOGIC_ISP1020 0x1020 -#define PCI_DEVICE_ID_QLOGIC_ISP1022 0x1022 - -#define PCI_VENDOR_ID_LEADTEK 0x107d -#define PCI_DEVICE_ID_LEADTEK_805 0x0000 - -#define PCI_VENDOR_ID_CONTAQ 0x1080 -#define PCI_DEVICE_ID_CONTAQ_82C599 0x0600 - -#define PCI_VENDOR_ID_FOREX 0x1083 - -#define PCI_VENDOR_ID_OLICOM 0x108d - -#define PCI_VENDOR_ID_CMD 0x1095 -#define PCI_DEVICE_ID_CMD_640 0x0640 -#define PCI_DEVICE_ID_CMD_646 0x0646 - -#define PCI_VENDOR_ID_VISION 0x1098 -#define PCI_DEVICE_ID_VISION_QD8500 0x0001 -#define PCI_DEVICE_ID_VISION_QD8580 0x0002 - -#define PCI_VENDOR_ID_SIERRA 0x10a8 -#define PCI_DEVICE_ID_SIERRA_STB 0x0000 - -#define PCI_VENDOR_ID_ACC 0x10aa -#define PCI_DEVICE_ID_ACC_2056 0x0000 - -#define PCI_VENDOR_ID_WINBOND 0x10ad -#define PCI_DEVICE_ID_WINBOND_83769 0x0001 -#define PCI_DEVICE_ID_WINBOND_82C105 0x0105 - -#define PCI_VENDOR_ID_3COM 0x10b7 -#define PCI_DEVICE_ID_3COM_3C590 0x5900 -#define PCI_DEVICE_ID_3COM_3C595TX 0x5950 -#define PCI_DEVICE_ID_3COM_3C595T4 0x5951 -#define PCI_DEVICE_ID_3COM_3C595MII 0x5952 - -#define PCI_VENDOR_ID_AL 0x10b9 -#define PCI_DEVICE_ID_AL_M1445 0x1445 -#define PCI_DEVICE_ID_AL_M1449 0x1449 -#define PCI_DEVICE_ID_AL_M1451 0x1451 -#define PCI_DEVICE_ID_AL_M1461 0x1461 -#define PCI_DEVICE_ID_AL_M1489 0x1489 -#define PCI_DEVICE_ID_AL_M1511 0x1511 -#define PCI_DEVICE_ID_AL_M1513 0x1513 -#define PCI_DEVICE_ID_AL_M4803 0x5215 - -#define PCI_VENDOR_ID_ASP 0x10cd -#define PCI_DEVICE_ID_ASP_ABP940 0x1200 - -#define PCI_VENDOR_ID_IMS 0x10e0 -#define PCI_DEVICE_ID_IMS_8849 0x8849 - -#define PCI_VENDOR_ID_TEKRAM2 0x10e1 -#define PCI_DEVICE_ID_TEKRAM2_690c 0x690c - -#define PCI_VENDOR_ID_AMCC 0x10e8 -#define PCI_DEVICE_ID_AMCC_MYRINET 0x8043 - -#define PCI_VENDOR_ID_INTERG 0x10ea -#define PCI_DEVICE_ID_INTERG_1680 0x1680 - -#define PCI_VENDOR_ID_REALTEK 0x10ec -#define PCI_DEVICE_ID_REALTEK_8029 0x8029 - -#define PCI_VENDOR_ID_INIT 0x1101 -#define PCI_DEVICE_ID_INIT_320P 0x9100 - -#define PCI_VENDOR_ID_VIA 0x1106 -#define PCI_DEVICE_ID_VIA_82C505 0x0505 -#define PCI_DEVICE_ID_VIA_82C561 0x0561 -#define PCI_DEVICE_ID_VIA_82C576 0x0576 -#define PCI_DEVICE_ID_VIA_82C416 0x1571 - -#define PCI_VENDOR_ID_VORTEX 0x1119 -#define PCI_DEVICE_ID_VORTEX_GDT 0x0001 - -#define PCI_VENDOR_ID_EF 0x111a -#define PCI_DEVICE_ID_EF_ATM_FPGA 0x0000 -#define PCI_DEVICE_ID_EF_ATM_ASIC 0x0002 - -#define PCI_VENDOR_ID_FORE 0x1127 -#define PCI_DEVICE_ID_FORE_PCA200PC 0x0210 - -#define PCI_VENDOR_ID_IMAGINGTECH 0x112f -#define PCI_DEVICE_ID_IMAGINGTECH_ICPCI 0x0000 - -#define PCI_VENDOR_ID_PLX 0x113c -#define PCI_DEVICE_ID_PLX_9060 0x0001 - -#define PCI_VENDOR_ID_ALLIANCE 0x1142 -#define PCI_DEVICE_ID_ALLIANCE_PROMOTIO 0x3210 -#define PCI_DEVICE_ID_ALLIANCE_PROVIDEO 0x6422 - -#define PCI_VENDOR_ID_MUTECH 0x1159 -#define PCI_DEVICE_ID_MUTECH_MV1000 0x0001 - -#define PCI_VENDOR_ID_ZEITNET 0x1193 -#define PCI_DEVICE_ID_ZEITNET_1221 0x0001 -#define PCI_DEVICE_ID_ZEITNET_1225 0x0002 - -#define PCI_VENDOR_ID_SPECIALIX 0x11cb -#define PCI_DEVICE_ID_SPECIALIX_XIO 0x4000 -#define PCI_DEVICE_ID_SPECIALIX_RIO 0x8000 - -#define PCI_VENDOR_ID_RP 0x11fe -#define PCI_DEVICE_ID_RP8OCTA 0x0001 -#define PCI_DEVICE_ID_RP8INTF 0x0002 -#define PCI_DEVICE_ID_RP16INTF 0x0003 -#define PCI_DEVICE_ID_RP32INTF 0x0004 - -#define PCI_VENDOR_ID_CYCLADES 0x120e -#define PCI_DEVICE_ID_CYCLADES_Y 0x0100 - -#define PCI_VENDOR_ID_SYMPHONY 0x1c1c -#define PCI_DEVICE_ID_SYMPHONY_101 0x0001 - -#define PCI_VENDOR_ID_TEKRAM 0x1de1 -#define PCI_DEVICE_ID_TEKRAM_DC290 0xdc29 - -#define PCI_VENDOR_ID_AVANCE 0x4005 -#define PCI_DEVICE_ID_AVANCE_2302 0x2302 - -#define PCI_VENDOR_ID_S3 0x5333 -#define PCI_DEVICE_ID_S3_811 0x8811 -#define PCI_DEVICE_ID_S3_868 0x8880 -#define PCI_DEVICE_ID_S3_928 0x88b0 -#define PCI_DEVICE_ID_S3_864_1 0x88c0 -#define PCI_DEVICE_ID_S3_864_2 0x88c1 -#define PCI_DEVICE_ID_S3_964_1 0x88d0 -#define PCI_DEVICE_ID_S3_964_2 0x88d1 -#define PCI_DEVICE_ID_S3_968 0x88f0 - -#define PCI_VENDOR_ID_INTEL 0x8086 -#define PCI_DEVICE_ID_INTEL_82375 0x0482 -#define PCI_DEVICE_ID_INTEL_82424 0x0483 -#define PCI_DEVICE_ID_INTEL_82378 0x0484 -#define PCI_DEVICE_ID_INTEL_82430 0x0486 -#define PCI_DEVICE_ID_INTEL_82434 0x04a3 -#define PCI_DEVICE_ID_INTEL_7116 0x1223 -#define PCI_DEVICE_ID_INTEL_82596 0x1226 -#define PCI_DEVICE_ID_INTEL_82865 0x1227 -#define PCI_DEVICE_ID_INTEL_82557 0x1229 -#define PCI_DEVICE_ID_INTEL_82437 0x122d -#define PCI_DEVICE_ID_INTEL_82371_0 0x122e -#define PCI_DEVICE_ID_INTEL_82371_1 0x1230 -#define PCI_DEVICE_ID_INTEL_P6 0x84c4 - -#define PCI_VENDOR_ID_ADAPTEC 0x9004 -#define PCI_DEVICE_ID_ADAPTEC_7850 0x5078 -#define PCI_DEVICE_ID_ADAPTEC_7870 0x7078 -#define PCI_DEVICE_ID_ADAPTEC_7871 0x7178 -#define PCI_DEVICE_ID_ADAPTEC_7872 0x7278 -#define PCI_DEVICE_ID_ADAPTEC_7873 0x7378 -#define PCI_DEVICE_ID_ADAPTEC_7874 0x7478 -#define PCI_DEVICE_ID_ADAPTEC_7880 0x8078 -#define PCI_DEVICE_ID_ADAPTEC_7881 0x8178 -#define PCI_DEVICE_ID_ADAPTEC_7882 0x8278 -#define PCI_DEVICE_ID_ADAPTEC_7883 0x8378 -#define PCI_DEVICE_ID_ADAPTEC_7884 0x8478 - -#define PCI_VENDOR_ID_ATRONICS 0x907f -#define PCI_DEVICE_ID_ATRONICS_2015 0x2015 - -#define PCI_VENDOR_ID_HER 0xedd8 -#define PCI_DEVICE_ID_HER_STING 0xa091 -#define PCI_DEVICE_ID_HER_STINGARK 0xa099 - -/* - * The PCI interface treats multi-function devices as independent - * devices. The slot/function address of each device is encoded - * in a single byte as follows: - * - * 7:4 = slot - * 3:0 = function - */ -#define PCI_DEVFN(slot,func) ((((slot) & 0x1f) << 3) | ((func) & 0x07)) -#define PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f) -#define PCI_FUNC(devfn) ((devfn) & 0x07) - -/* - * There is one pci_dev structure for each slot-number/function-number - * combination: - */ -struct pci_dev { - struct pci_bus *bus; /* bus this device is on */ - struct pci_dev *sibling; /* next device on this bus */ - struct pci_dev *next; /* chain of all devices */ - - void *sysdata; /* hook for sys-specific extension */ - - unsigned int devfn; /* encoded device & function index */ - unsigned short vendor; - unsigned short device; - unsigned int class; /* 3 bytes: (base,sub,prog-if) */ - unsigned int master : 1; /* set if device is master capable */ - /* - * In theory, the irq level can be read from configuration - * space and all would be fine. However, old PCI chips don't - * support these registers and return 0 instead. For example, - * the Vision864-P rev 0 chip can uses INTA, but returns 0 in - * the interrupt line and pin registers. pci_init() - * initializes this field with the value at PCI_INTERRUPT_LINE - * and it is the job of pcibios_fixup() to change it if - * necessary. The field must not be 0 unless the device - * cannot generate interrupts at all. - */ - unsigned char irq; /* irq generated by this device */ -}; - -struct pci_bus { - struct pci_bus *parent; /* parent bus this bridge is on */ - struct pci_bus *children; /* chain of P2P bridges on this bus */ - struct pci_bus *next; /* chain of all PCI buses */ - - struct pci_dev *self; /* bridge device as seen by parent */ - struct pci_dev *devices; /* devices behind this bridge */ - - void *sysdata; /* hook for sys-specific extension */ - - unsigned char number; /* bus number */ - unsigned char primary; /* number of primary bridge */ - unsigned char secondary; /* number of secondary bridge */ - unsigned char subordinate; /* max number of subordinate buses */ -}; - -/* - * This is used to map a vendor-id/device-id pair into device-specific - * information. - */ -struct pci_dev_info { - unsigned short vendor; /* vendor id */ - unsigned short device; /* device id */ - - const char *name; /* device name */ - unsigned char bridge_type; /* bridge type or 0xff */ -}; - -extern struct pci_bus pci_root; /* root bus */ -extern struct pci_dev *pci_devices; /* list of all devices */ - - -extern unsigned long pci_init (unsigned long mem_start, unsigned long mem_end); - -extern struct pci_dev_info *pci_lookup_dev (unsigned int vendor, - unsigned int dev); -extern const char *pci_strclass (unsigned int class); -extern const char *pci_strvendor (unsigned int vendor); -extern const char *pci_strdev (unsigned int vendor, unsigned int device); - -extern int get_pci_list (char *buf); - -#endif /* PCI_H */ diff --git a/i386/i386at/gpl/linux/include/linux/personality.h b/i386/i386at/gpl/linux/include/linux/personality.h deleted file mode 100644 index 3e465eaa..00000000 --- a/i386/i386at/gpl/linux/include/linux/personality.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef _PERSONALITY_H -#define _PERSONALITY_H - -#include <linux/linkage.h> -#include <linux/ptrace.h> - - -/* Flags for bug emulation. These occupy the top three bytes. */ -#define STICKY_TIMEOUTS 0x4000000 -#define WHOLE_SECONDS 0x2000000 - -/* Personality types. These go in the low byte. Avoid using the top bit, - * it will conflict with error returns. - */ -#define PER_MASK (0x00ff) -#define PER_LINUX (0x0000) -#define PER_SVR4 (0x0001 | STICKY_TIMEOUTS) -#define PER_SVR3 (0x0002 | STICKY_TIMEOUTS) -#define PER_SCOSVR3 (0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS) -#define PER_WYSEV386 (0x0004 | STICKY_TIMEOUTS) -#define PER_ISCR4 (0x0005 | STICKY_TIMEOUTS) -#define PER_BSD (0x0006) -#define PER_XENIX (0x0007 | STICKY_TIMEOUTS) - -/* Prototype for an lcall7 syscall handler. */ -typedef asmlinkage void (*lcall7_func)(struct pt_regs *); - - -/* Description of an execution domain - personality range supported, - * lcall7 syscall handler, start up / shut down functions etc. - * N.B. The name and lcall7 handler must be where they are since the - * offset of the handler is hard coded in kernel/sys_call.S. - */ -struct exec_domain { - const char *name; - lcall7_func handler; - unsigned char pers_low, pers_high; - unsigned long * signal_map; - unsigned long * signal_invmap; - int *use_count; - struct exec_domain *next; -}; - -extern struct exec_domain default_exec_domain; - -extern struct exec_domain *lookup_exec_domain(unsigned long personality); -extern int register_exec_domain(struct exec_domain *it); -extern int unregister_exec_domain(struct exec_domain *it); -extern asmlinkage int sys_personality(unsigned long personality); - -#endif /* _PERSONALITY_H */ diff --git a/i386/i386at/gpl/linux/include/linux/proc_fs.h b/i386/i386at/gpl/linux/include/linux/proc_fs.h deleted file mode 100644 index cc674c9b..00000000 --- a/i386/i386at/gpl/linux/include/linux/proc_fs.h +++ /dev/null @@ -1,269 +0,0 @@ -#ifndef _LINUX_PROC_FS_H -#define _LINUX_PROC_FS_H - -#include <linux/fs.h> -#include <linux/malloc.h> - -/* - * The proc filesystem constants/structures - */ - -/* - * We always define these enumerators - */ - -enum root_directory_inos { - PROC_ROOT_INO = 1, - PROC_LOADAVG, - PROC_UPTIME, - PROC_MEMINFO, - PROC_KMSG, - PROC_VERSION, - PROC_CPUINFO, - PROC_PCI, - PROC_SELF, /* will change inode # */ - PROC_NET, - PROC_SCSI, - PROC_MALLOC, - PROC_KCORE, - PROC_MODULES, - PROC_STAT, - PROC_DEVICES, - PROC_INTERRUPTS, - PROC_FILESYSTEMS, - PROC_KSYMS, - PROC_DMA, - PROC_IOPORTS, - PROC_APM, -#ifdef __SMP_PROF__ - PROC_SMP_PROF, -#endif - PROC_PROFILE, /* whether enabled or not */ - PROC_CMDLINE, - PROC_SYS, - PROC_MTAB -}; - -enum pid_directory_inos { - PROC_PID_INO = 2, - PROC_PID_STATUS, - PROC_PID_MEM, - PROC_PID_CWD, - PROC_PID_ROOT, - PROC_PID_EXE, - PROC_PID_FD, - PROC_PID_ENVIRON, - PROC_PID_CMDLINE, - PROC_PID_STAT, - PROC_PID_STATM, - PROC_PID_MAPS -}; - -enum pid_subdirectory_inos { - PROC_PID_FD_DIR = 1 -}; - -enum net_directory_inos { - PROC_NET_UNIX = 128, - PROC_NET_ARP, - PROC_NET_ROUTE, - PROC_NET_DEV, - PROC_NET_RAW, - PROC_NET_TCP, - PROC_NET_UDP, - PROC_NET_SNMP, - PROC_NET_RARP, - PROC_NET_IGMP, - PROC_NET_IPMR_VIF, - PROC_NET_IPMR_MFC, - PROC_NET_IPFWFWD, - PROC_NET_IPFWIN, - PROC_NET_IPFWOUT, - PROC_NET_IPACCT, - PROC_NET_IPMSQHST, - PROC_NET_WAVELAN, - PROC_NET_IPX_INTERFACE, - PROC_NET_IPX_ROUTE, - PROC_NET_IPX, - PROC_NET_ATALK, - PROC_NET_AT_ROUTE, - PROC_NET_ATIF, - PROC_NET_AX25_ROUTE, - PROC_NET_AX25, - PROC_NET_AX25_CALLS, - PROC_NET_NR_NODES, - PROC_NET_NR_NEIGH, - PROC_NET_NR, - PROC_NET_SOCKSTAT, - PROC_NET_RTCACHE, - PROC_NET_AX25_BPQETHER, - PROC_NET_ALIAS_TYPES, - PROC_NET_ALIASES, - PROC_NET_LAST -}; - -enum scsi_directory_inos { - PROC_SCSI_SCSI = 256, - PROC_SCSI_ADVANSYS, - PROC_SCSI_EATA, - PROC_SCSI_EATA_PIO, - PROC_SCSI_AHA152X, - PROC_SCSI_AHA1542, - PROC_SCSI_AHA1740, - PROC_SCSI_AIC7XXX, - PROC_SCSI_BUSLOGIC, - PROC_SCSI_U14_34F, - PROC_SCSI_FDOMAIN, - PROC_SCSI_GENERIC_NCR5380, - PROC_SCSI_IN2000, - PROC_SCSI_PAS16, - PROC_SCSI_QLOGIC, - PROC_SCSI_SEAGATE, - PROC_SCSI_T128, - PROC_SCSI_NCR53C7xx, - PROC_SCSI_ULTRASTOR, - PROC_SCSI_7000FASST, - PROC_SCSI_EATA2X, - PROC_SCSI_AM53C974, - PROC_SCSI_SSC, - PROC_SCSI_NCR53C406A, - PROC_SCSI_SCSI_DEBUG, - PROC_SCSI_NOT_PRESENT, - PROC_SCSI_FILE, /* I'm asuming here that we */ - PROC_SCSI_LAST = (PROC_SCSI_FILE + 16) /* won't ever see more than */ -}; /* 16 HBAs in one machine */ - -/* Finally, the dynamically allocatable proc entries are reserved: */ - -#define PROC_DYNAMIC_FIRST 4096 -#define PROC_NDYNAMIC 4096 - -#define PROC_SUPER_MAGIC 0x9fa0 - -/* - * This is not completely implemented yet. The idea is to - * create a in-memory tree (like the actual /proc filesystem - * tree) of these proc_dir_entries, so that we can dynamically - * add new files to /proc. - * - * The "next" pointer creates a linked list of one /proc directory, - * while parent/subdir create the directory structure (every - * /proc file has a parent, but "subdir" is NULL for all - * non-directory entries). - * - * "get_info" is called at "read", while "fill_inode" is used to - * fill in file type/protection/owner information specific to the - * particular /proc file. - */ -struct proc_dir_entry { - unsigned short low_ino; - unsigned short namelen; - const char *name; - mode_t mode; - nlink_t nlink; - uid_t uid; - gid_t gid; - unsigned long size; - struct inode_operations * ops; - int (*get_info)(char *, char **, off_t, int, int); - void (*fill_inode)(struct inode *); - struct proc_dir_entry *next, *parent, *subdir; - void *data; -}; - -extern int (* dispatch_scsi_info_ptr) (int ino, char *buffer, char **start, - off_t offset, int length, int inout); - -extern struct proc_dir_entry proc_root; -extern struct proc_dir_entry proc_net; -extern struct proc_dir_entry proc_scsi; -extern struct proc_dir_entry proc_sys; -extern struct proc_dir_entry proc_pid; -extern struct proc_dir_entry proc_pid_fd; - -extern struct inode_operations proc_scsi_inode_operations; - -extern void proc_root_init(void); -extern void proc_base_init(void); -extern void proc_net_init(void); - -extern int proc_register(struct proc_dir_entry *, struct proc_dir_entry *); -extern int proc_register_dynamic(struct proc_dir_entry *, - struct proc_dir_entry *); -extern int proc_unregister(struct proc_dir_entry *, int); - -static inline int proc_net_register(struct proc_dir_entry * x) -{ - return proc_register(&proc_net, x); -} - -static inline int proc_net_unregister(int x) -{ - return proc_unregister(&proc_net, x); -} - -static inline int proc_scsi_register(struct proc_dir_entry *driver, - struct proc_dir_entry *x) -{ - x->ops = &proc_scsi_inode_operations; - if(x->low_ino < PROC_SCSI_FILE){ - return(proc_register(&proc_scsi, x)); - }else{ - return(proc_register(driver, x)); - } -} - -static inline int proc_scsi_unregister(struct proc_dir_entry *driver, int x) -{ - extern void scsi_init_free(char *ptr, unsigned int size); - - if(x <= PROC_SCSI_FILE) - return(proc_unregister(&proc_scsi, x)); - else { - struct proc_dir_entry **p = &driver->subdir, *dp; - int ret; - - while ((dp = *p) != NULL) { - if (dp->low_ino == x) - break; - p = &dp->next; - } - ret = proc_unregister(driver, x); - scsi_init_free((char *) dp, sizeof(struct proc_dir_entry) + 4); - return(ret); - } -} - -extern struct super_block *proc_read_super(struct super_block *,void *,int); -extern int init_proc_fs(void); -extern struct inode * proc_get_inode(struct super_block *, int, struct proc_dir_entry *); -extern void proc_statfs(struct super_block *, struct statfs *, int); -extern void proc_read_inode(struct inode *); -extern void proc_write_inode(struct inode *); -extern int proc_match(int, const char *, struct proc_dir_entry *); - -/* - * These are generic /proc routines that use the internal - * "struct proc_dir_entry" tree to traverse the filesystem. - * - * The /proc root directory has extended versions to take care - * of the /proc/<pid> subdirectories. - */ -extern int proc_readdir(struct inode *, struct file *, void *, filldir_t); -extern int proc_lookup(struct inode *, const char *, int, struct inode **); - -extern struct inode_operations proc_dir_inode_operations; -extern struct inode_operations proc_net_inode_operations; -extern struct inode_operations proc_netdir_inode_operations; -extern struct inode_operations proc_scsi_inode_operations; -extern struct inode_operations proc_mem_inode_operations; -extern struct inode_operations proc_sys_inode_operations; -extern struct inode_operations proc_array_inode_operations; -extern struct inode_operations proc_arraylong_inode_operations; -extern struct inode_operations proc_kcore_inode_operations; -extern struct inode_operations proc_profile_inode_operations; -extern struct inode_operations proc_kmsg_inode_operations; -extern struct inode_operations proc_link_inode_operations; -extern struct inode_operations proc_fd_inode_operations; - -#endif diff --git a/i386/i386at/gpl/linux/include/linux/ptrace.h b/i386/i386at/gpl/linux/include/linux/ptrace.h deleted file mode 100644 index 0a02879d..00000000 --- a/i386/i386at/gpl/linux/include/linux/ptrace.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef _LINUX_PTRACE_H -#define _LINUX_PTRACE_H -/* ptrace.h */ -/* structs and defines to help the user use the ptrace system call. */ - -/* has the defines to get at the registers. */ - -#define PTRACE_TRACEME 0 -#define PTRACE_PEEKTEXT 1 -#define PTRACE_PEEKDATA 2 -#define PTRACE_PEEKUSR 3 -#define PTRACE_POKETEXT 4 -#define PTRACE_POKEDATA 5 -#define PTRACE_POKEUSR 6 -#define PTRACE_CONT 7 -#define PTRACE_KILL 8 -#define PTRACE_SINGLESTEP 9 - -#define PTRACE_ATTACH 0x10 -#define PTRACE_DETACH 0x11 - -#define PTRACE_SYSCALL 24 - -#include <asm/ptrace.h> - -#endif diff --git a/i386/i386at/gpl/linux/include/linux/quota.h b/i386/i386at/gpl/linux/include/linux/quota.h deleted file mode 100644 index 59b86fe8..00000000 --- a/i386/i386at/gpl/linux/include/linux/quota.h +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright (c) 1982, 1986 Regents of the University of California. - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Robert Elz at The University of Melbourne. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * Version: $Id: quota.h,v 1.1.1.1 1997/02/25 21:27:30 thomas Exp $ - */ - -#ifndef _LINUX_QUOTA_ -#define _LINUX_QUOTA_ - -#include <linux/errno.h> - -/* - * Convert diskblocks to blocks and the other way around. - * currently only to fool the BSD source. :-) - */ -#define dbtob(num) (num << 10) -#define btodb(num) (num >> 10) - -/* - * Convert count of filesystem blocks to diskquota blocks, meant - * for filesystems where i_blksize != BLOCK_SIZE - */ -#define fs_to_dq_blocks(num, blksize) (((num) * (blksize)) / BLOCK_SIZE) - -/* - * Definitions for disk quotas imposed on the average user - * (big brother finally hits Linux). - * - * The following constants define the amount of time given a user - * before the soft limits are treated as hard limits (usually resulting - * in an allocation failure). The timer is started when the user crosses - * their soft limit, it is reset when they go below their soft limit. - */ -#define MAX_IQ_TIME 604800 /* (7*24*60*60) 1 week */ -#define MAX_DQ_TIME 604800 /* (7*24*60*60) 1 week */ - -#define MAXQUOTAS 2 -#define USRQUOTA 0 /* element used for user quotas */ -#define GRPQUOTA 1 /* element used for group quotas */ - -#include <linux/mount.h> - -/* - * Definitions for the default names of the quotas files. - */ -#define INITQFNAMES { \ - "user", /* USRQUOTA */ \ - "group", /* GRPQUOTA */ \ - "undefined", \ -}; - -#define QUOTAFILENAME "quota" -#define QUOTAGROUP "staff" - -#define NR_DQHASH 43 /* Just an arbitrary number any suggestions ? */ -#define NR_DQUOTS 256 /* Number of quotas active at one time */ - -/* - * Command definitions for the 'quotactl' system call. - * The commands are broken into a main command defined below - * and a subcommand that is used to convey the type of - * quota that is being manipulated (see above). - */ -#define SUBCMDMASK 0x00ff -#define SUBCMDSHIFT 8 -#define QCMD(cmd, type) (((cmd) << SUBCMDSHIFT) | ((type) & SUBCMDMASK)) - -#define Q_QUOTAON 0x0100 /* enable quotas */ -#define Q_QUOTAOFF 0x0200 /* disable quotas */ -#define Q_GETQUOTA 0x0300 /* get limits and usage */ -#define Q_SETQUOTA 0x0400 /* set limits and usage */ -#define Q_SETUSE 0x0500 /* set usage */ -#define Q_SYNC 0x0600 /* sync disk copy of a filesystems quotas */ -#define Q_SETQLIM 0x0700 /* set limits */ -#define Q_GETSTATS 0x0800 /* get collected stats */ - -/* - * The following structure defines the format of the disk quota file - * (as it appears on disk) - the file is an array of these structures - * indexed by user or group number. - */ -struct dqblk { - __u32 dqb_bhardlimit; /* absolute limit on disk blks alloc */ - __u32 dqb_bsoftlimit; /* preferred limit on disk blks */ - __u32 dqb_curblocks; /* current block count */ - __u32 dqb_ihardlimit; /* maximum # allocated inodes */ - __u32 dqb_isoftlimit; /* preferred inode limit */ - __u32 dqb_curinodes; /* current # allocated inodes */ - time_t dqb_btime; /* time limit for excessive disk use */ - time_t dqb_itime; /* time limit for excessive files */ -}; - -/* - * Shorthand notation. - */ -#define dq_bhardlimit dq_dqb.dqb_bhardlimit -#define dq_bsoftlimit dq_dqb.dqb_bsoftlimit -#define dq_curblocks dq_dqb.dqb_curblocks -#define dq_ihardlimit dq_dqb.dqb_ihardlimit -#define dq_isoftlimit dq_dqb.dqb_isoftlimit -#define dq_curinodes dq_dqb.dqb_curinodes -#define dq_btime dq_dqb.dqb_btime -#define dq_itime dq_dqb.dqb_itime - -#define dqoff(UID) ((off_t)((UID) * sizeof (struct dqblk))) - -struct dqstats { - __u32 lookups; - __u32 drops; - __u32 reads; - __u32 writes; - __u32 cache_hits; - __u32 pages_allocated; - __u32 allocated_dquots; - __u32 free_dquots; - __u32 syncs; -}; - -#ifdef __KERNEL__ - -/* - * Maximum lenght of a message generated in the quota system, - * that needs to be kicked onto the tty. - */ -#define MAX_QUOTA_MESSAGE 75 - -#define DQ_LOCKED 0x01 /* locked for update */ -#define DQ_WANT 0x02 /* wanted for update */ -#define DQ_MOD 0x04 /* dquot modified since read */ -#define DQ_BLKS 0x10 /* uid/gid has been warned about blk limit */ -#define DQ_INODES 0x20 /* uid/gid has been warned about inode limit */ -#define DQ_FAKE 0x40 /* no limits only usage */ - -struct dquot { - unsigned int dq_id; /* id this applies to (uid, gid) */ - short dq_type; /* type of quota */ - kdev_t dq_dev; /* Device this applies to */ - short dq_flags; /* see DQ_* */ - short dq_count; /* reference count */ - struct vfsmount *dq_mnt; /* vfsmountpoint this applies to */ - struct dqblk dq_dqb; /* diskquota usage */ - struct wait_queue *dq_wait; /* pointer to waitqueue */ - struct dquot *dq_prev; /* pointer to prev dquot */ - struct dquot *dq_next; /* pointer to next dquot */ - struct dquot *dq_hash_prev; /* pointer to prev dquot */ - struct dquot *dq_hash_next; /* pointer to next dquot */ -}; - -#define NODQUOT (struct dquot *)NULL - -/* - * Flags used for set_dqblk. - */ -#define QUOTA_SYSCALL 0x01 -#define SET_QUOTA 0x02 -#define SET_USE 0x04 -#define SET_QLIMIT 0x08 - -#define QUOTA_OK 0 -#define NO_QUOTA 1 - -/* - * declaration of quota_function calls in kernel. - */ - -extern void dquot_initialize(struct inode *inode, short type); -extern void dquot_drop(struct inode *inode); -extern int dquot_alloc_block(const struct inode *inode, unsigned long number); -extern int dquot_alloc_inode(const struct inode *inode, unsigned long number); -extern void dquot_free_block(const struct inode *inode, unsigned long number); -extern void dquot_free_inode(const struct inode *inode, unsigned long number); -extern int dquot_transfer(struct inode *inode, struct iattr *iattr, char direction); - -extern void invalidate_dquots(kdev_t dev, short type); -extern int quota_off(kdev_t dev, short type); -extern int sync_dquots(kdev_t dev, short type); - -#else - -#include <sys/cdefs.h> - -__BEGIN_DECLS -int quotactl __P ((int, const char *, int, caddr_t)); -__END_DECLS - -#endif /* __KERNEL__ */ -#endif /* _QUOTA_ */ diff --git a/i386/i386at/gpl/linux/include/linux/resource.h b/i386/i386at/gpl/linux/include/linux/resource.h deleted file mode 100644 index f3bffbd7..00000000 --- a/i386/i386at/gpl/linux/include/linux/resource.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef _LINUX_RESOURCE_H -#define _LINUX_RESOURCE_H - -#include <linux/time.h> - -/* - * Resource control/accounting header file for linux - */ - -/* - * Definition of struct rusage taken from BSD 4.3 Reno - * - * We don't support all of these yet, but we might as well have them.... - * Otherwise, each time we add new items, programs which depend on this - * structure will lose. This reduces the chances of that happening. - */ -#define RUSAGE_SELF 0 -#define RUSAGE_CHILDREN (-1) -#define RUSAGE_BOTH (-2) /* sys_wait4() uses this */ - -struct rusage { - struct timeval ru_utime; /* user time used */ - struct timeval ru_stime; /* system time used */ - long ru_maxrss; /* maximum resident set size */ - long ru_ixrss; /* integral shared memory size */ - long ru_idrss; /* integral unshared data size */ - long ru_isrss; /* integral unshared stack size */ - long ru_minflt; /* page reclaims */ - long ru_majflt; /* page faults */ - long ru_nswap; /* swaps */ - long ru_inblock; /* block input operations */ - long ru_oublock; /* block output operations */ - long ru_msgsnd; /* messages sent */ - long ru_msgrcv; /* messages received */ - long ru_nsignals; /* signals received */ - long ru_nvcsw; /* voluntary context switches */ - long ru_nivcsw; /* involuntary " */ -}; - -#define RLIM_INFINITY ((long)(~0UL>>1)) - -struct rlimit { - long rlim_cur; - long rlim_max; -}; - -#define PRIO_MIN (-20) -#define PRIO_MAX 20 - -#define PRIO_PROCESS 0 -#define PRIO_PGRP 1 -#define PRIO_USER 2 - -/* - * Due to binary compatibility, the actual resource numbers - * may be different for different linux versions.. - */ -#include <asm/resource.h> - -#endif diff --git a/i386/i386at/gpl/linux/include/linux/route.h b/i386/i386at/gpl/linux/include/linux/route.h deleted file mode 100644 index 5be4853e..00000000 --- a/i386/i386at/gpl/linux/include/linux/route.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * INET An implementation of the TCP/IP protocol suite for the LINUX - * operating system. INET is implemented using the BSD Socket - * interface as the means of communication with the user level. - * - * Global definitions for the IP router interface. - * - * Version: @(#)route.h 1.0.3 05/27/93 - * - * Authors: Original taken from Berkeley UNIX 4.3, (c) UCB 1986-1988 - * for the purposes of compatibility only. - * - * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ -#ifndef _LINUX_ROUTE_H -#define _LINUX_ROUTE_H - -#include <linux/if.h> - - -/* This structure gets passed by the SIOCADDRT and SIOCDELRT calls. */ -struct rtentry -{ - unsigned long rt_hash; /* hash key for lookups */ - struct sockaddr rt_dst; /* target address */ - struct sockaddr rt_gateway; /* gateway addr (RTF_GATEWAY) */ - struct sockaddr rt_genmask; /* target network mask (IP) */ - short rt_flags; - short rt_refcnt; - unsigned long rt_use; - struct ifnet *rt_ifp; - short rt_metric; /* +1 for binary compatibility! */ - char *rt_dev; /* forcing the device at add */ - unsigned long rt_mss; /* per route MTU/Window */ - unsigned long rt_window; /* Window clamping */ - unsigned short rt_irtt; /* Initial RTT */ -}; - - -#define RTF_UP 0x0001 /* route usable */ -#define RTF_GATEWAY 0x0002 /* destination is a gateway */ -#define RTF_HOST 0x0004 /* host entry (net otherwise) */ -#define RTF_REINSTATE 0x0008 /* reinstate route after tmout */ -#define RTF_DYNAMIC 0x0010 /* created dyn. (by redirect) */ -#define RTF_MODIFIED 0x0020 /* modified dyn. (by redirect) */ -#define RTF_MSS 0x0040 /* specific MSS for this route */ -#define RTF_WINDOW 0x0080 /* per route window clamping */ -#define RTF_IRTT 0x0100 /* Initial round trip time */ -#define RTF_REJECT 0x0200 /* Reject route */ - -/* - * This structure is passed from the kernel to user space by netlink - * routing/device announcements - */ - -struct netlink_rtinfo -{ - unsigned long rtmsg_type; - struct sockaddr rtmsg_dst; - struct sockaddr rtmsg_gateway; - struct sockaddr rtmsg_genmask; - short rtmsg_flags; - short rtmsg_metric; - char rtmsg_device[16]; -}; - -#define RTMSG_NEWROUTE 0x01 -#define RTMSG_DELROUTE 0x02 -#define RTMSG_NEWDEVICE 0x11 -#define RTMSG_DELDEVICE 0x12 - -#endif /* _LINUX_ROUTE_H */ - diff --git a/i386/i386at/gpl/linux/include/linux/sched.h b/i386/i386at/gpl/linux/include/linux/sched.h deleted file mode 100644 index 28fe7ef0..00000000 --- a/i386/i386at/gpl/linux/include/linux/sched.h +++ /dev/null @@ -1,492 +0,0 @@ -#ifndef _LINUX_SCHED_H -#define _LINUX_SCHED_H - -/* - * define DEBUG if you want the wait-queues to have some extra - * debugging code. It's not normally used, but might catch some - * wait-queue coding errors. - * - * #define DEBUG - */ - -#include <asm/param.h> /* for HZ */ - -extern unsigned long intr_count; -extern unsigned long event; - -#include <linux/binfmts.h> -#include <linux/personality.h> -#include <linux/tasks.h> -#include <linux/kernel.h> -#include <asm/system.h> -#include <asm/page.h> - -#include <linux/smp.h> -#include <linux/tty.h> -#include <linux/sem.h> - -/* - * cloning flags: - */ -#define CSIGNAL 0x000000ff /* signal mask to be sent at exit */ -#define CLONE_VM 0x00000100 /* set if VM shared between processes */ -#define CLONE_FS 0x00000200 /* set if fs info shared between processes */ -#define CLONE_FILES 0x00000400 /* set if open files shared between processes */ -#define CLONE_SIGHAND 0x00000800 /* set if signal handlers shared */ -#define CLONE_PID 0x00001000 /* set if pid shared */ - -/* - * These are the constant used to fake the fixed-point load-average - * counting. Some notes: - * - 11 bit fractions expand to 22 bits by the multiplies: this gives - * a load-average precision of 10 bits integer + 11 bits fractional - * - if you want to count load-averages more often, you need more - * precision, or rounding will get you. With 2-second counting freq, - * the EXP_n values would be 1981, 2034 and 2043 if still using only - * 11 bit fractions. - */ -extern unsigned long avenrun[]; /* Load averages */ - -#define FSHIFT 11 /* nr of bits of precision */ -#define FIXED_1 (1<<FSHIFT) /* 1.0 as fixed-point */ -#define LOAD_FREQ (5*HZ) /* 5 sec intervals */ -#define EXP_1 1884 /* 1/exp(5sec/1min) as fixed-point */ -#define EXP_5 2014 /* 1/exp(5sec/5min) */ -#define EXP_15 2037 /* 1/exp(5sec/15min) */ - -#define CALC_LOAD(load,exp,n) \ - load *= exp; \ - load += n*(FIXED_1-exp); \ - load >>= FSHIFT; - -#define CT_TO_SECS(x) ((x) / HZ) -#define CT_TO_USECS(x) (((x) % HZ) * 1000000/HZ) - -extern int nr_running, nr_tasks; - -#define FIRST_TASK task[0] -#define LAST_TASK task[NR_TASKS-1] - -#include <linux/head.h> -#include <linux/fs.h> -#include <linux/signal.h> -#include <linux/time.h> -#include <linux/param.h> -#include <linux/resource.h> -#include <linux/vm86.h> -#include <linux/math_emu.h> -#include <linux/ptrace.h> -#include <linux/timer.h> - -#include <asm/processor.h> - -#define TASK_RUNNING 0 -#define TASK_INTERRUPTIBLE 1 -#define TASK_UNINTERRUPTIBLE 2 -#define TASK_ZOMBIE 3 -#define TASK_STOPPED 4 -#define TASK_SWAPPING 5 - -/* - * Scheduling policies - */ -#define SCHED_OTHER 0 -#define SCHED_FIFO 1 -#define SCHED_RR 2 - -struct sched_param { - int sched_priority; -}; - -#ifndef NULL -#define NULL ((void *) 0) -#endif - -#ifdef __KERNEL__ - -#define barrier() __asm__("": : :"memory") - -extern void sched_init(void); -extern void show_state(void); -extern void trap_init(void); - -asmlinkage void schedule(void); - -struct files_struct { - int count; - fd_set close_on_exec; - struct file * fd[NR_OPEN]; -}; - -#define INIT_FILES { \ - 1, \ - { { 0, } }, \ - { NULL, } \ -} - -struct fs_struct { - int count; - unsigned short umask; - struct inode * root, * pwd; -}; - -#define INIT_FS { \ - 1, \ - 0022, \ - NULL, NULL \ -} - -struct mm_struct { - int count; - pgd_t * pgd; - unsigned long context; - unsigned long start_code, end_code, start_data, end_data; - unsigned long start_brk, brk, start_stack, start_mmap; - unsigned long arg_start, arg_end, env_start, env_end; - unsigned long rss, total_vm, locked_vm; - unsigned long def_flags; - struct vm_area_struct * mmap; - struct vm_area_struct * mmap_avl; -}; - -#define INIT_MM { \ - 1, \ - swapper_pg_dir, \ - 0, \ - 0, 0, 0, 0, \ - 0, 0, 0, 0, \ - 0, 0, 0, 0, \ - 0, 0, 0, \ - 0, \ - &init_mmap, &init_mmap } - -struct signal_struct { - int count; - struct sigaction action[32]; -}; - -#define INIT_SIGNALS { \ - 1, \ - { {0,}, } } - -struct task_struct { -/* these are hardcoded - don't touch */ - volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */ - long counter; - long priority; - unsigned long signal; - unsigned long blocked; /* bitmap of masked signals */ - unsigned long flags; /* per process flags, defined below */ - int errno; - long debugreg[8]; /* Hardware debugging registers */ - struct exec_domain *exec_domain; -/* various fields */ - struct linux_binfmt *binfmt; - struct task_struct *next_task, *prev_task; - struct task_struct *next_run, *prev_run; - unsigned long saved_kernel_stack; - unsigned long kernel_stack_page; - int exit_code, exit_signal; - unsigned long personality; - int dumpable:1; - int did_exec:1; - int pid,pgrp,tty_old_pgrp,session,leader; - int groups[NGROUPS]; - /* - * pointers to (original) parent process, youngest child, younger sibling, - * older sibling, respectively. (p->father can be replaced with - * p->p_pptr->pid) - */ - struct task_struct *p_opptr, *p_pptr, *p_cptr, *p_ysptr, *p_osptr; - struct wait_queue *wait_chldexit; /* for wait4() */ - unsigned short uid,euid,suid,fsuid; - unsigned short gid,egid,sgid,fsgid; - unsigned long timeout, policy, rt_priority; - unsigned long it_real_value, it_prof_value, it_virt_value; - unsigned long it_real_incr, it_prof_incr, it_virt_incr; - struct timer_list real_timer; - long utime, stime, cutime, cstime, start_time; -/* mm fault and swap info: this can arguably be seen as either mm-specific or thread-specific */ - unsigned long min_flt, maj_flt, nswap, cmin_flt, cmaj_flt, cnswap; - int swappable:1; - unsigned long swap_address; - unsigned long old_maj_flt; /* old value of maj_flt */ - unsigned long dec_flt; /* page fault count of the last time */ - unsigned long swap_cnt; /* number of pages to swap on next pass */ -/* limits */ - struct rlimit rlim[RLIM_NLIMITS]; - unsigned short used_math; - char comm[16]; -/* file system info */ - int link_count; - struct tty_struct *tty; /* NULL if no tty */ -/* ipc stuff */ - struct sem_undo *semundo; - struct sem_queue *semsleeping; -/* ldt for this task - used by Wine. If NULL, default_ldt is used */ - struct desc_struct *ldt; -/* tss for this task */ - struct thread_struct tss; -/* filesystem information */ - struct fs_struct *fs; -/* open file information */ - struct files_struct *files; -/* memory management info */ - struct mm_struct *mm; -/* signal handlers */ - struct signal_struct *sig; -#ifdef __SMP__ - int processor; - int last_processor; - int lock_depth; /* Lock depth. We can context switch in and out of holding a syscall kernel lock... */ -#endif -}; - -/* - * Per process flags - */ -#define PF_ALIGNWARN 0x00000001 /* Print alignment warning msgs */ - /* Not implemented yet, only for 486*/ -#define PF_PTRACED 0x00000010 /* set if ptrace (0) has been called. */ -#define PF_TRACESYS 0x00000020 /* tracing system calls */ - -#define PF_STARTING 0x00000100 /* being created */ -#define PF_EXITING 0x00000200 /* getting shut down */ - -#define PF_USEDFPU 0x00100000 /* Process used the FPU this quantum (SMP only) */ - -/* - * Limit the stack by to some sane default: root can always - * increase this limit if needed.. 8MB seems reasonable. - */ -#define _STK_LIM (8*1024*1024) - -#define DEF_PRIORITY (20*HZ/100) /* 200 ms time slices */ - -/* - * INIT_TASK is used to set up the first task table, touch at - * your own risk!. Base=0, limit=0x1fffff (=2MB) - */ -#define INIT_TASK \ -/* state etc */ { 0,DEF_PRIORITY,DEF_PRIORITY,0,0,0,0, \ -/* debugregs */ { 0, }, \ -/* exec domain */&default_exec_domain, \ -/* binfmt */ NULL, \ -/* schedlink */ &init_task,&init_task, &init_task, &init_task, \ -/* stack */ 0,(unsigned long) &init_kernel_stack, \ -/* ec,brk... */ 0,0,0,0,0, \ -/* pid etc.. */ 0,0,0,0,0, \ -/* suppl grps*/ {NOGROUP,}, \ -/* proc links*/ &init_task,&init_task,NULL,NULL,NULL,NULL, \ -/* uid etc */ 0,0,0,0,0,0,0,0, \ -/* timeout */ 0,SCHED_OTHER,0,0,0,0,0,0,0, \ -/* timer */ { NULL, NULL, 0, 0, it_real_fn }, \ -/* utime */ 0,0,0,0,0, \ -/* flt */ 0,0,0,0,0,0, \ -/* swp */ 0,0,0,0,0, \ -/* rlimits */ INIT_RLIMITS, \ -/* math */ 0, \ -/* comm */ "swapper", \ -/* fs info */ 0,NULL, \ -/* ipc */ NULL, NULL, \ -/* ldt */ NULL, \ -/* tss */ INIT_TSS, \ -/* fs */ &init_fs, \ -/* files */ &init_files, \ -/* mm */ &init_mm, \ -/* signals */ &init_signals, \ -} - -extern struct mm_struct init_mm; -extern struct task_struct init_task; -extern struct task_struct *task[NR_TASKS]; -extern struct task_struct *last_task_used_math; -extern struct task_struct *current_set[NR_CPUS]; -/* - * On a single processor system this comes out as current_set[0] when cpp - * has finished with it, which gcc will optimise away. - */ -#define current (0+current_set[smp_processor_id()]) /* Current on this processor */ -extern unsigned long volatile jiffies; -extern unsigned long itimer_ticks; -extern unsigned long itimer_next; -extern struct timeval xtime; -extern int need_resched; -extern void do_timer(struct pt_regs *); - -extern unsigned int * prof_buffer; -extern unsigned long prof_len; -extern unsigned long prof_shift; - -extern int securelevel; /* system security level */ - -#define CURRENT_TIME (xtime.tv_sec) - -extern void sleep_on(struct wait_queue ** p); -extern void interruptible_sleep_on(struct wait_queue ** p); -extern void wake_up(struct wait_queue ** p); -extern void wake_up_interruptible(struct wait_queue ** p); -extern void wake_up_process(struct task_struct * tsk); - -extern void notify_parent(struct task_struct * tsk); -extern int send_sig(unsigned long sig,struct task_struct * p,int priv); -extern int in_group_p(gid_t grp); - -extern int request_irq(unsigned int irq,void (*handler)(int, struct pt_regs *), - unsigned long flags, const char *device); -extern void free_irq(unsigned int irq); - -extern void copy_thread(int, unsigned long, unsigned long, struct task_struct *, struct pt_regs *); -extern void flush_thread(void); -extern void exit_thread(void); - -extern void exit_fs(struct task_struct *); -extern void exit_files(struct task_struct *); -extern void exit_sighand(struct task_struct *); -extern void release_thread(struct task_struct *); - -extern int do_execve(char *, char **, char **, struct pt_regs *); -extern int do_fork(unsigned long, unsigned long, struct pt_regs *); - -#ifdef MACH -extern void add_wait_queue(struct wait_queue **, struct wait_queue *); -extern void remove_wait_queue(struct wait_queue **, struct wait_queue *); -#else /* ! MACH */ -/* - * The wait-queues are circular lists, and you have to be *very* sure - * to keep them correct. Use only these two functions to add/remove - * entries in the queues. - */ -extern inline void add_wait_queue(struct wait_queue ** p, struct wait_queue * wait) -{ - unsigned long flags; - -#ifdef DEBUG - if (wait->next) { - __label__ here; - unsigned long pc; - pc = (unsigned long) &&here; - here: - printk("add_wait_queue (%08lx): wait->next = %08lx\n",pc,(unsigned long) wait->next); - } -#endif - save_flags(flags); - cli(); - if (!*p) { - wait->next = wait; - *p = wait; - } else { - wait->next = (*p)->next; - (*p)->next = wait; - } - restore_flags(flags); -} - -extern inline void remove_wait_queue(struct wait_queue ** p, struct wait_queue * wait) -{ - unsigned long flags; - struct wait_queue * tmp; -#ifdef DEBUG - unsigned long ok = 0; -#endif - - save_flags(flags); - cli(); - if ((*p == wait) && -#ifdef DEBUG - (ok = 1) && -#endif - ((*p = wait->next) == wait)) { - *p = NULL; - } else { - tmp = wait; - while (tmp->next != wait) { - tmp = tmp->next; -#ifdef DEBUG - if (tmp == *p) - ok = 1; -#endif - } - tmp->next = wait->next; - } - wait->next = NULL; - restore_flags(flags); -#ifdef DEBUG - if (!ok) { - __label__ here; - ok = (unsigned long) &&here; - printk("removed wait_queue not on list.\n"); - printk("list = %08lx, queue = %08lx\n",(unsigned long) p, (unsigned long) wait); - here: - printk("eip = %08lx\n",ok); - } -#endif -} - -extern inline void select_wait(struct wait_queue ** wait_address, select_table * p) -{ - struct select_table_entry * entry; - - if (!p || !wait_address) - return; - if (p->nr >= __MAX_SELECT_TABLE_ENTRIES) - return; - entry = p->entry + p->nr; - entry->wait_address = wait_address; - entry->wait.task = current; - entry->wait.next = NULL; - add_wait_queue(wait_address,&entry->wait); - p->nr++; -} -#endif /* ! MACH */ - -extern void __down(struct semaphore * sem); - -/* - * These are not yet interrupt-safe - */ -extern inline void down(struct semaphore * sem) -{ - if (sem->count <= 0) - __down(sem); - sem->count--; -} - -extern inline void up(struct semaphore * sem) -{ - sem->count++; - wake_up(&sem->wait); -} - -#define REMOVE_LINKS(p) do { unsigned long flags; \ - save_flags(flags) ; cli(); \ - (p)->next_task->prev_task = (p)->prev_task; \ - (p)->prev_task->next_task = (p)->next_task; \ - restore_flags(flags); \ - if ((p)->p_osptr) \ - (p)->p_osptr->p_ysptr = (p)->p_ysptr; \ - if ((p)->p_ysptr) \ - (p)->p_ysptr->p_osptr = (p)->p_osptr; \ - else \ - (p)->p_pptr->p_cptr = (p)->p_osptr; \ - } while (0) - -#define SET_LINKS(p) do { unsigned long flags; \ - save_flags(flags); cli(); \ - (p)->next_task = &init_task; \ - (p)->prev_task = init_task.prev_task; \ - init_task.prev_task->next_task = (p); \ - init_task.prev_task = (p); \ - restore_flags(flags); \ - (p)->p_ysptr = NULL; \ - if (((p)->p_osptr = (p)->p_pptr->p_cptr) != NULL) \ - (p)->p_osptr->p_ysptr = p; \ - (p)->p_pptr->p_cptr = p; \ - } while (0) - -#define for_each_task(p) \ - for (p = &init_task ; (p = p->next_task) != &init_task ; ) - -#endif /* __KERNEL__ */ - -#endif diff --git a/i386/i386at/gpl/linux/include/linux/scsi.h b/i386/i386at/gpl/linux/include/linux/scsi.h deleted file mode 100644 index a05072cf..00000000 --- a/i386/i386at/gpl/linux/include/linux/scsi.h +++ /dev/null @@ -1,198 +0,0 @@ -#ifndef _LINUX_SCSI_H -#define _LINUX_SCSI_H - -/* - * This header file contains public constants and structures used by - * the scsi code for linux. - */ - -/* - $Header: cvs/gnumach/i386/i386at/gpl/linux/include/linux/Attic/scsi.h,v 1.1.1.1 1997/02/25 21:27:31 thomas Exp $ - - For documentation on the OPCODES, MESSAGES, and SENSE values, - please consult the SCSI standard. - -*/ - -/* - * SCSI opcodes - */ - -#define TEST_UNIT_READY 0x00 -#define REZERO_UNIT 0x01 -#define REQUEST_SENSE 0x03 -#define FORMAT_UNIT 0x04 -#define READ_BLOCK_LIMITS 0x05 -#define REASSIGN_BLOCKS 0x07 -#define READ_6 0x08 -#define WRITE_6 0x0a -#define SEEK_6 0x0b -#define READ_REVERSE 0x0f -#define WRITE_FILEMARKS 0x10 -#define SPACE 0x11 -#define INQUIRY 0x12 -#define RECOVER_BUFFERED_DATA 0x14 -#define MODE_SELECT 0x15 -#define RESERVE 0x16 -#define RELEASE 0x17 -#define COPY 0x18 -#define ERASE 0x19 -#define MODE_SENSE 0x1a -#define START_STOP 0x1b -#define RECEIVE_DIAGNOSTIC 0x1c -#define SEND_DIAGNOSTIC 0x1d -#define ALLOW_MEDIUM_REMOVAL 0x1e - -#define SET_WINDOW 0x24 -#define READ_CAPACITY 0x25 -#define READ_10 0x28 -#define WRITE_10 0x2a -#define SEEK_10 0x2b -#define WRITE_VERIFY 0x2e -#define VERIFY 0x2f -#define SEARCH_HIGH 0x30 -#define SEARCH_EQUAL 0x31 -#define SEARCH_LOW 0x32 -#define SET_LIMITS 0x33 -#define PRE_FETCH 0x34 -#define READ_POSITION 0x34 -#define SYNCHRONIZE_CACHE 0x35 -#define LOCK_UNLOCK_CACHE 0x36 -#define READ_DEFECT_DATA 0x37 -#define MEDIUM_SCAN 0x38 -#define COMPARE 0x39 -#define COPY_VERIFY 0x3a -#define WRITE_BUFFER 0x3b -#define READ_BUFFER 0x3c -#define UPDATE_BLOCK 0x3d -#define READ_LONG 0x3e -#define WRITE_LONG 0x3f -#define CHANGE_DEFINITION 0x40 -#define WRITE_SAME 0x41 -#define LOG_SELECT 0x4c -#define LOG_SENSE 0x4d -#define MODE_SELECT_10 0x55 -#define MODE_SENSE_10 0x5a -#define READ_12 0xa8 -#define WRITE_12 0xaa -#define WRITE_VERIFY_12 0xae -#define SEARCH_HIGH_12 0xb0 -#define SEARCH_EQUAL_12 0xb1 -#define SEARCH_LOW_12 0xb2 -#define SEND_VOLUME_TAG 0xb6 -#define WRITE_LONG_2 0xea - -/* - * Status codes - */ - -#define GOOD 0x00 -#define CHECK_CONDITION 0x01 -#define CONDITION_GOOD 0x02 -#define BUSY 0x04 -#define INTERMEDIATE_GOOD 0x08 -#define INTERMEDIATE_C_GOOD 0x0a -#define RESERVATION_CONFLICT 0x0c -#define QUEUE_FULL 0x1a - -#define STATUS_MASK 0x1e - -/* - * SENSE KEYS - */ - -#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 BLANK_CHECK 0x08 -#define COPY_ABORTED 0x0a -#define ABORTED_COMMAND 0x0b -#define VOLUME_OVERFLOW 0x0d -#define MISCOMPARE 0x0e - - -/* - * DEVICE TYPES - */ - -#define TYPE_DISK 0x00 -#define TYPE_TAPE 0x01 -#define TYPE_PROCESSOR 0x03 /* HP scanners use this */ -#define TYPE_WORM 0x04 /* Treated as ROM by our system */ -#define TYPE_ROM 0x05 -#define TYPE_SCANNER 0x06 -#define TYPE_MOD 0x07 /* Magneto-optical disk - - * - treated as TYPE_DISK */ -#define TYPE_NO_LUN 0x7f - - -/* - * MESSAGE CODES - */ - -#define COMMAND_COMPLETE 0x00 -#define EXTENDED_MESSAGE 0x01 -#define EXTENDED_MODIFY_DATA_POINTER 0x00 -#define EXTENDED_SDTR 0x01 -#define EXTENDED_EXTENDED_IDENTIFY 0x02 /* SCSI-I only */ -#define EXTENDED_WDTR 0x03 -#define SAVE_POINTERS 0x02 -#define RESTORE_POINTERS 0x03 -#define DISCONNECT 0x04 -#define INITIATOR_ERROR 0x05 -#define ABORT 0x06 -#define MESSAGE_REJECT 0x07 -#define NOP 0x08 -#define MSG_PARITY_ERROR 0x09 -#define LINKED_CMD_COMPLETE 0x0a -#define LINKED_FLG_CMD_COMPLETE 0x0b -#define BUS_DEVICE_RESET 0x0c - -#define INITIATE_RECOVERY 0x0f /* SCSI-II only */ -#define RELEASE_RECOVERY 0x10 /* SCSI-II only */ - -#define SIMPLE_QUEUE_TAG 0x20 -#define HEAD_OF_QUEUE_TAG 0x21 -#define ORDERED_QUEUE_TAG 0x22 - -/* - * Here are some scsi specific ioctl commands which are sometimes useful. - */ -/* These are a few other constants only used by scsi devices */ - -#define SCSI_IOCTL_GET_IDLUN 0x5382 - -/* Used to turn on and off tagged queuing for scsi devices */ - -#define SCSI_IOCTL_TAGGED_ENABLE 0x5383 -#define SCSI_IOCTL_TAGGED_DISABLE 0x5384 - -/* Used to obtain the host number of a device. */ -#define SCSI_IOCTL_PROBE_HOST 0x5385 - - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 4 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -4 - * c-argdecl-indent: 4 - * c-label-offset: -4 - * c-continued-statement-offset: 4 - * c-continued-brace-offset: 0 - * indent-tabs-mode: nil - * tab-width: 8 - * End: - */ - -#endif diff --git a/i386/i386at/gpl/linux/include/linux/scsicam.h b/i386/i386at/gpl/linux/include/linux/scsicam.h deleted file mode 100644 index 954e1407..00000000 --- a/i386/i386at/gpl/linux/include/linux/scsicam.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * scsicam.h - SCSI CAM support functions, use for HDIO_GETGEO, etc. - * - * Copyright 1993, 1994 Drew Eckhardt - * Visionary Computing - * (Unix and Linux consulting and custom programming) - * drew@Colorado.EDU - * +1 (303) 786-7975 - * - * For more information, please consult the SCSI-CAM draft. - */ - -#ifndef SCSICAM_H -#define SCSICAM_H -#include <linux/kdev_t.h> -extern int scsicam_bios_param (Disk *disk, kdev_t dev, int *ip); -#endif /* def SCSICAM_H */ diff --git a/i386/i386at/gpl/linux/include/linux/sem.h b/i386/i386at/gpl/linux/include/linux/sem.h deleted file mode 100644 index 0eb1d024..00000000 --- a/i386/i386at/gpl/linux/include/linux/sem.h +++ /dev/null @@ -1,112 +0,0 @@ -#ifndef _LINUX_SEM_H -#define _LINUX_SEM_H -#include <linux/ipc.h> - -/* semop flags */ -#define SEM_UNDO 0x1000 /* undo the operation on exit */ - -/* semctl Command Definitions. */ -#define GETPID 11 /* get sempid */ -#define GETVAL 12 /* get semval */ -#define GETALL 13 /* get all semval's */ -#define GETNCNT 14 /* get semncnt */ -#define GETZCNT 15 /* get semzcnt */ -#define SETVAL 16 /* set semval */ -#define SETALL 17 /* set all semval's */ - -/* One semid data structure for each set of semaphores in the system. */ -struct semid_ds { - struct ipc_perm sem_perm; /* permissions .. see ipc.h */ - time_t sem_otime; /* last semop time */ - time_t sem_ctime; /* last change time */ - struct sem *sem_base; /* ptr to first semaphore in array */ - struct sem_queue *sem_pending; /* pending operations to be processed */ - struct sem_queue **sem_pending_last; /* last pending operation */ - struct sem_undo *undo; /* undo requests on this array */ - ushort sem_nsems; /* no. of semaphores in array */ -}; - -/* semop system calls takes an array of these. */ -struct sembuf { - ushort sem_num; /* semaphore index in array */ - short sem_op; /* semaphore operation */ - short sem_flg; /* operation flags */ -}; - -/* arg for semctl system calls. */ -union semun { - int val; /* value for SETVAL */ - struct semid_ds *buf; /* buffer for IPC_STAT & IPC_SET */ - ushort *array; /* array for GETALL & SETALL */ - struct seminfo *__buf; /* buffer for IPC_INFO */ - void *__pad; -}; - -struct seminfo { - int semmap; - int semmni; - int semmns; - int semmnu; - int semmsl; - int semopm; - int semume; - int semusz; - int semvmx; - int semaem; -}; - -#define SEMMNI 128 /* ? max # of semaphore identifiers */ -#define SEMMSL 32 /* <= 512 max num of semaphores per id */ -#define SEMMNS (SEMMNI*SEMMSL) /* ? max # of semaphores in system */ -#define SEMOPM 32 /* ~ 100 max num of ops per semop call */ -#define SEMVMX 32767 /* semaphore maximum value */ - -/* unused */ -#define SEMUME SEMOPM /* max num of undo entries per process */ -#define SEMMNU SEMMNS /* num of undo structures system wide */ -#define SEMAEM (SEMVMX >> 1) /* adjust on exit max value */ -#define SEMMAP SEMMNS /* # of entries in semaphore map */ -#define SEMUSZ 20 /* sizeof struct sem_undo */ - -#ifdef __KERNEL__ - -/* One semaphore structure for each semaphore in the system. */ -struct sem { - short semval; /* current value */ - short sempid; /* pid of last operation */ -}; - -/* ipcs ctl cmds */ -#define SEM_STAT 18 -#define SEM_INFO 19 - -/* One queue for each semaphore set in the system. */ -struct sem_queue { - struct sem_queue * next; /* next entry in the queue */ - struct sem_queue ** prev; /* previous entry in the queue, *(q->prev) == q */ - struct wait_queue * sleeper; /* sleeping process */ - struct sem_undo * undo; /* undo structure */ - int pid; /* process id of requesting process */ - int status; /* completion status of operation */ - struct semid_ds * sma; /* semaphore array for operations */ - struct sembuf * sops; /* array of pending operations */ - int nsops; /* number of operations */ -}; - -/* Each task has a list of undo requests. They are executed automatically - * when the process exits. - */ -struct sem_undo { - struct sem_undo * proc_next; /* next entry on this process */ - struct sem_undo * id_next; /* next entry on this semaphore set */ - int semid; /* semaphore set identifier */ - short * semadj; /* array of adjustments, one per semaphore */ -}; - -asmlinkage int sys_semget (key_t key, int nsems, int semflg); -asmlinkage int sys_semop (int semid, struct sembuf *sops, unsigned nsops); -asmlinkage int sys_semctl (int semid, int semnum, int cmd, union semun arg); - -#endif /* __KERNEL__ */ - -#endif /* _LINUX_SEM_H */ diff --git a/i386/i386at/gpl/linux/include/linux/signal.h b/i386/i386at/gpl/linux/include/linux/signal.h deleted file mode 100644 index 9d1afa91..00000000 --- a/i386/i386at/gpl/linux/include/linux/signal.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _LINUX_SIGNAL_H -#define _LINUX_SIGNAL_H - -#include <asm/signal.h> - -#endif diff --git a/i386/i386at/gpl/linux/include/linux/skbuff.h b/i386/i386at/gpl/linux/include/linux/skbuff.h deleted file mode 100644 index 65418168..00000000 --- a/i386/i386at/gpl/linux/include/linux/skbuff.h +++ /dev/null @@ -1,474 +0,0 @@ -/* - * Definitions for the 'struct sk_buff' memory handlers. - * - * Authors: - * Alan Cox, <gw4pts@gw4pts.ampr.org> - * Florian La Roche, <rzsfl@rz.uni-sb.de> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#ifndef _LINUX_SKBUFF_H -#define _LINUX_SKBUFF_H -#include <linux/malloc.h> -#include <linux/wait.h> -#include <linux/time.h> -#include <linux/config.h> - -#define CONFIG_SKB_CHECK 0 - -#define HAVE_ALLOC_SKB /* For the drivers to know */ -#define HAVE_ALIGNABLE_SKB /* Ditto 8) */ - - -#define FREE_READ 1 -#define FREE_WRITE 0 - -#define CHECKSUM_NONE 0 -#define CHECKSUM_HW 1 -#define CHECKSUM_UNNECESSARY 2 - -struct sk_buff_head -{ - struct sk_buff * volatile next; - struct sk_buff * volatile prev; - __u32 qlen; /* Must be same length as a pointer - for using debugging */ -#if CONFIG_SKB_CHECK - int magic_debug_cookie; -#endif -}; - - -struct sk_buff -{ - struct sk_buff * volatile next; /* Next buffer in list */ - struct sk_buff * volatile prev; /* Previous buffer in list */ - struct sk_buff_head * list; /* List we are on */ -#if CONFIG_SKB_CHECK - int magic_debug_cookie; -#endif - struct sk_buff * volatile link3; /* Link for IP protocol level buffer chains */ - struct sock *sk; /* Socket we are owned by */ - unsigned long when; /* used to compute rtt's */ - struct timeval stamp; /* Time we arrived */ - struct linux_device *dev; /* Device we arrived on/are leaving by */ - union - { - struct tcphdr *th; - struct ethhdr *eth; - struct iphdr *iph; - struct udphdr *uh; - unsigned char *raw; - /* for passing an fd in a unix domain socket */ - struct file *filp; - } h; - - union - { - /* As yet incomplete physical layer views */ - unsigned char *raw; - struct ethhdr *ethernet; - } mac; - - struct iphdr *ip_hdr; /* For IPPROTO_RAW */ - unsigned long len; /* Length of actual data */ - unsigned long csum; /* Checksum */ - __u32 saddr; /* IP source address */ - __u32 daddr; /* IP target address */ - __u32 raddr; /* IP next hop address */ - __u32 seq; /* TCP sequence number */ - __u32 end_seq; /* seq [+ fin] [+ syn] + datalen */ - __u32 ack_seq; /* TCP ack sequence number */ - unsigned char proto_priv[16]; /* Protocol private data */ - volatile char acked, /* Are we acked ? */ - used, /* Are we in use ? */ - free, /* How to free this buffer */ - arp; /* Has IP/ARP resolution finished */ - unsigned char tries, /* Times tried */ - lock, /* Are we locked ? */ - localroute, /* Local routing asserted for this frame */ - pkt_type, /* Packet class */ - ip_summed; /* Driver fed us an IP checksum */ -#define PACKET_HOST 0 /* To us */ -#define PACKET_BROADCAST 1 /* To all */ -#define PACKET_MULTICAST 2 /* To group */ -#define PACKET_OTHERHOST 3 /* To someone else */ - unsigned short users; /* User count - see datagram.c,tcp.c */ - unsigned short protocol; /* Packet protocol from driver. */ - unsigned short truesize; /* Buffer size */ - - int count; /* reference count */ - struct sk_buff *data_skb; /* Link to the actual data skb */ - unsigned char *head; /* Head of buffer */ - unsigned char *data; /* Data head pointer */ - unsigned char *tail; /* Tail pointer */ - unsigned char *end; /* End pointer */ - void (*destructor)(struct sk_buff *this); /* Destruct function */ -#ifdef MACH -#ifdef MACH_INCLUDE - ipc_port_t reply; - mach_msg_type_name_t reply_type; - vm_map_copy_t copy; -#else - void *reply; - unsigned reply_type; - void *copy; -#endif -#endif -}; - -#ifdef CONFIG_SKB_LARGE -#define SK_WMEM_MAX 65535 -#define SK_RMEM_MAX 65535 -#else -#define SK_WMEM_MAX 32767 -#define SK_RMEM_MAX 32767 -#endif - -#if CONFIG_SKB_CHECK -#define SK_FREED_SKB 0x0DE2C0DE -#define SK_GOOD_SKB 0xDEC0DED1 -#define SK_HEAD_SKB 0x12231298 -#endif - -#ifdef __KERNEL__ -/* - * Handling routines are only of interest to the kernel - */ - -#include <asm/system.h> - -#if 0 -extern void print_skb(struct sk_buff *); -#endif -extern void kfree_skb(struct sk_buff *skb, int rw); -extern void skb_queue_head_init(struct sk_buff_head *list); -extern void skb_queue_head(struct sk_buff_head *list,struct sk_buff *buf); -extern void skb_queue_tail(struct sk_buff_head *list,struct sk_buff *buf); -extern struct sk_buff * skb_dequeue(struct sk_buff_head *list); -extern void skb_insert(struct sk_buff *old,struct sk_buff *newsk); -extern void skb_append(struct sk_buff *old,struct sk_buff *newsk); -extern void skb_unlink(struct sk_buff *buf); -extern __u32 skb_queue_len(struct sk_buff_head *list); -extern struct sk_buff * skb_peek_copy(struct sk_buff_head *list); -extern struct sk_buff * alloc_skb(unsigned int size, int priority); -extern struct sk_buff * dev_alloc_skb(unsigned int size); -extern void kfree_skbmem(struct sk_buff *skb); -extern struct sk_buff * skb_clone(struct sk_buff *skb, int priority); -extern struct sk_buff * skb_copy(struct sk_buff *skb, int priority); -extern void skb_device_lock(struct sk_buff *skb); -extern void skb_device_unlock(struct sk_buff *skb); -extern void dev_kfree_skb(struct sk_buff *skb, int mode); -extern int skb_device_locked(struct sk_buff *skb); -#ifdef MACH -#define skb_put(skb, len) ((skb)->data) -#else -extern unsigned char * skb_put(struct sk_buff *skb, int len); -#endif -extern unsigned char * skb_push(struct sk_buff *skb, int len); -extern unsigned char * skb_pull(struct sk_buff *skb, int len); -extern int skb_headroom(struct sk_buff *skb); -extern int skb_tailroom(struct sk_buff *skb); -#ifdef MACH -#define skb_reserve(skb, len) -#else -extern void skb_reserve(struct sk_buff *skb, int len); -#endif -extern void skb_trim(struct sk_buff *skb, int len); - -/* - * Peek an sk_buff. Unlike most other operations you _MUST_ - * be careful with this one. A peek leaves the buffer on the - * list and someone else may run off with it. For an interrupt - * type system cli() peek the buffer copy the data and sti(); - */ -extern __inline__ struct sk_buff *skb_peek(struct sk_buff_head *list_) -{ - struct sk_buff *list = ((struct sk_buff *)list_)->next; - if (list == (struct sk_buff *)list_) - list = NULL; - return list; -} - -/* - * Return the length of an sk_buff queue - */ - -extern __inline__ __u32 skb_queue_len(struct sk_buff_head *list_) -{ - return(list_->qlen); -} - -#if CONFIG_SKB_CHECK -extern int skb_check(struct sk_buff *skb,int,int, char *); -#define IS_SKB(skb) skb_check((skb), 0, __LINE__,__FILE__) -#define IS_SKB_HEAD(skb) skb_check((skb), 1, __LINE__,__FILE__) -#else -#define IS_SKB(skb) -#define IS_SKB_HEAD(skb) - -extern __inline__ void skb_queue_head_init(struct sk_buff_head *list) -{ - list->prev = (struct sk_buff *)list; - list->next = (struct sk_buff *)list; - list->qlen = 0; -} - -/* - * Insert an sk_buff at the start of a list. - * - * The "__skb_xxxx()" functions are the non-atomic ones that - * can only be called with interrupts disabled. - */ - -extern __inline__ void __skb_queue_head(struct sk_buff_head *list, struct sk_buff *newsk) -{ - struct sk_buff *prev, *next; - - newsk->list = list; - list->qlen++; - prev = (struct sk_buff *)list; - next = prev->next; - newsk->next = next; - newsk->prev = prev; - next->prev = newsk; - prev->next = newsk; -} - -extern __inline__ void skb_queue_head(struct sk_buff_head *list, struct sk_buff *newsk) -{ - unsigned long flags; - - save_flags(flags); - cli(); - __skb_queue_head(list, newsk); - restore_flags(flags); -} - -/* - * Insert an sk_buff at the end of a list. - */ - -extern __inline__ void __skb_queue_tail(struct sk_buff_head *list, struct sk_buff *newsk) -{ - struct sk_buff *prev, *next; - - newsk->list = list; - list->qlen++; - next = (struct sk_buff *)list; - prev = next->prev; - newsk->next = next; - newsk->prev = prev; - next->prev = newsk; - prev->next = newsk; -} - -extern __inline__ void skb_queue_tail(struct sk_buff_head *list, struct sk_buff *newsk) -{ - unsigned long flags; - - save_flags(flags); - cli(); - __skb_queue_tail(list, newsk); - restore_flags(flags); -} - -/* - * Remove an sk_buff from a list. - */ - -extern __inline__ struct sk_buff *__skb_dequeue(struct sk_buff_head *list) -{ - struct sk_buff *next, *prev, *result; - - prev = (struct sk_buff *) list; - next = prev->next; - result = NULL; - if (next != prev) { - result = next; - next = next->next; - list->qlen--; - next->prev = prev; - prev->next = next; - result->next = NULL; - result->prev = NULL; - result->list = NULL; - } - return result; -} - -extern __inline__ struct sk_buff *skb_dequeue(struct sk_buff_head *list) -{ - long flags; - struct sk_buff *result; - - save_flags(flags); - cli(); - result = __skb_dequeue(list); - restore_flags(flags); - return result; -} - -/* - * Insert a packet before another one in a list. - */ - -extern __inline__ void __skb_insert(struct sk_buff *next, struct sk_buff *newsk) -{ - struct sk_buff * prev = next->prev; - - newsk->next = next; - newsk->prev = prev; - next->prev = newsk; - prev->next = newsk; - newsk->list = next->list; - newsk->list->qlen++; -} - -extern __inline__ void skb_insert(struct sk_buff *old, struct sk_buff *newsk) -{ - unsigned long flags; - - save_flags(flags); - cli(); - __skb_insert(old, newsk); - restore_flags(flags); -} - -/* - * Place a packet after a given packet in a list. - */ - -extern __inline__ void __skb_append(struct sk_buff *prev, struct sk_buff *newsk) -{ - struct sk_buff * next = prev->next; - - newsk->next = next; - newsk->prev = prev; - next->prev = newsk; - prev->next = newsk; - newsk->list = prev->list; - newsk->list->qlen++; -} - -extern __inline__ void skb_append(struct sk_buff *old, struct sk_buff *newsk) -{ - unsigned long flags; - - save_flags(flags); - cli(); - __skb_append(old, newsk); - restore_flags(flags); -} - -/* - * remove sk_buff from list. _Must_ be called atomically, and with - * the list known.. - */ -extern __inline__ void __skb_unlink(struct sk_buff *skb, struct sk_buff_head *list) -{ - struct sk_buff * next, * prev; - - list->qlen--; - next = skb->next; - prev = skb->prev; - skb->next = NULL; - skb->prev = NULL; - skb->list = NULL; - next->prev = prev; - prev->next = next; -} - -/* - * Remove an sk_buff from its list. Works even without knowing the list it - * is sitting on, which can be handy at times. It also means that THE LIST - * MUST EXIST when you unlink. Thus a list must have its contents unlinked - * _FIRST_. - */ - -extern __inline__ void skb_unlink(struct sk_buff *skb) -{ - unsigned long flags; - - save_flags(flags); - cli(); - if(skb->list) - __skb_unlink(skb, skb->list); - restore_flags(flags); -} - -#ifndef MACH -/* - * Add data to an sk_buff - */ - -extern __inline__ unsigned char *skb_put(struct sk_buff *skb, int len) -{ - unsigned char *tmp=skb->tail; - skb->tail+=len; - skb->len+=len; - if(skb->tail>skb->end) - panic("skput:over: %p:%d", __builtin_return_address(0),len); - return tmp; -} -#endif - -extern __inline__ unsigned char *skb_push(struct sk_buff *skb, int len) -{ - skb->data-=len; - skb->len+=len; - if(skb->data<skb->head) - panic("skpush:under: %p:%d", __builtin_return_address(0),len); - return skb->data; -} - -extern __inline__ unsigned char * skb_pull(struct sk_buff *skb, int len) -{ - if(len > skb->len) - return NULL; - skb->data+=len; - skb->len-=len; - return skb->data; -} - -extern __inline__ int skb_headroom(struct sk_buff *skb) -{ - return skb->data-skb->head; -} - -extern __inline__ int skb_tailroom(struct sk_buff *skb) -{ - return skb->end-skb->tail; -} - -#ifndef MACH -extern __inline__ void skb_reserve(struct sk_buff *skb, int len) -{ - skb->data+=len; - skb->tail+=len; -} -#endif - -extern __inline__ void skb_trim(struct sk_buff *skb, int len) -{ - if(skb->len>len) - { - skb->len=len; - skb->tail=skb->data+len; - } -} - -#endif - -extern struct sk_buff * skb_recv_datagram(struct sock *sk,unsigned flags,int noblock, int *err); -extern int datagram_select(struct sock *sk, int sel_type, select_table *wait); -extern void skb_copy_datagram(struct sk_buff *from, int offset, char *to,int size); -extern void skb_copy_datagram_iovec(struct sk_buff *from, int offset, struct iovec *to,int size); -extern void skb_free_datagram(struct sock * sk, struct sk_buff *skb); - -#endif /* __KERNEL__ */ -#endif /* _LINUX_SKBUFF_H */ diff --git a/i386/i386at/gpl/linux/include/linux/smp.h b/i386/i386at/gpl/linux/include/linux/smp.h deleted file mode 100644 index 72984f15..00000000 --- a/i386/i386at/gpl/linux/include/linux/smp.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef __LINUX_SMP_H -#define __LINUX_SMP_H - -/* - * Generic SMP support - * Alan Cox. <alan@cymru.net> - */ - -#ifdef __SMP__ -#include <asm/smp.h> - -extern void smp_message_pass(int target, int msg, unsigned long data, int wait); -extern void smp_boot_cpus(void); /* Boot processor call to load the other CPU's */ -extern void smp_callin(void); /* Processor call in. Must hold processors until .. */ -extern void smp_commence(void); /* Multiprocessors may now schedule */ -extern int smp_num_cpus; -extern int smp_threads_ready; /* True once the per process idle is forked */ -#ifdef __SMP_PROF__ -extern volatile unsigned long smp_spins[NR_CPUS]; /* count of interrupt spins */ -extern volatile unsigned long smp_spins_sys_idle[]; /* count of idle spins */ -extern volatile unsigned long smp_spins_syscall[]; /* count of syscall spins */ -extern volatile unsigned long smp_spins_syscall_cur[]; /* count of syscall spins for the current - call */ -extern volatile unsigned long smp_idle_count[1+NR_CPUS];/* count idle ticks */ -extern volatile unsigned long smp_idle_map; /* map with idle cpus */ -#else -extern volatile unsigned long smp_spins; -#endif - - -extern volatile unsigned long smp_msg_data; -extern volatile int smp_src_cpu; -extern volatile int smp_msg_id; - -#define MSG_ALL_BUT_SELF 0x8000 /* Assume <32768 CPU's */ -#define MSG_ALL 0x8001 - -#define MSG_INVALIDATE_TLB 0x0001 /* Remote processor TLB invalidate */ -#define MSG_STOP_CPU 0x0002 /* Sent to shut down slave CPU's when rebooting */ -#define MSG_RESCHEDULE 0x0003 /* Reschedule request from master CPU */ - -#else - -/* - * These macros fold the SMP functionality into a single CPU system - */ - -#define smp_num_cpus 1 -#define smp_processor_id() 0 -#define smp_message_pass(t,m,d,w) -#define smp_threads_ready 1 -#define kernel_lock() -#endif -#endif diff --git a/i386/i386at/gpl/linux/include/linux/socket.h b/i386/i386at/gpl/linux/include/linux/socket.h deleted file mode 100644 index bf2991ad..00000000 --- a/i386/i386at/gpl/linux/include/linux/socket.h +++ /dev/null @@ -1,126 +0,0 @@ -#ifndef _LINUX_SOCKET_H -#define _LINUX_SOCKET_H - -#include <asm/socket.h> /* arch-dependent defines */ -#include <linux/sockios.h> /* the SIOCxxx I/O controls */ -#include <linux/uio.h> /* iovec support */ - -struct sockaddr { - unsigned short sa_family; /* address family, AF_xxx */ - char sa_data[14]; /* 14 bytes of protocol address */ -}; - -struct linger { - int l_onoff; /* Linger active */ - int l_linger; /* How long to linger for */ -}; - -struct msghdr -{ - void * msg_name; /* Socket name */ - int msg_namelen; /* Length of name */ - struct iovec * msg_iov; /* Data blocks */ - int msg_iovlen; /* Number of blocks */ - void * msg_accrights; /* Per protocol magic (eg BSD file descriptor passing) */ - int msg_accrightslen; /* Length of rights list */ -}; - -/* Socket types. */ -#define SOCK_STREAM 1 /* stream (connection) socket */ -#define SOCK_DGRAM 2 /* datagram (conn.less) socket */ -#define SOCK_RAW 3 /* raw socket */ -#define SOCK_RDM 4 /* reliably-delivered message */ -#define SOCK_SEQPACKET 5 /* sequential packet socket */ -#define SOCK_PACKET 10 /* linux specific way of */ - /* getting packets at the dev */ - /* level. For writing rarp and */ - /* other similar things on the */ - /* user level. */ - -/* Supported address families. */ -#define AF_UNSPEC 0 -#define AF_UNIX 1 /* Unix domain sockets */ -#define AF_INET 2 /* Internet IP Protocol */ -#define AF_AX25 3 /* Amateur Radio AX.25 */ -#define AF_IPX 4 /* Novell IPX */ -#define AF_APPLETALK 5 /* Appletalk DDP */ -#define AF_NETROM 6 /* Amateur radio NetROM */ -#define AF_BRIDGE 7 /* Multiprotocol bridge */ -#define AF_AAL5 8 /* Reserved for Werner's ATM */ -#define AF_X25 9 /* Reserved for X.25 project */ -#define AF_INET6 10 /* IP version 6 */ -#define AF_MAX 12 /* For now.. */ - -/* Protocol families, same as address families. */ -#define PF_UNSPEC AF_UNSPEC -#define PF_UNIX AF_UNIX -#define PF_INET AF_INET -#define PF_AX25 AF_AX25 -#define PF_IPX AF_IPX -#define PF_APPLETALK AF_APPLETALK -#define PF_NETROM AF_NETROM -#define PF_BRIDGE AF_BRIDGE -#define PF_AAL5 AF_AAL5 -#define PF_X25 AF_X25 -#define PF_INET6 AF_INET6 - -#define PF_MAX AF_MAX - -/* Maximum queue length specificable by listen. */ -#define SOMAXCONN 128 - -/* Flags we can use with send/ and recv. */ -#define MSG_OOB 1 -#define MSG_PEEK 2 -#define MSG_DONTROUTE 4 - -/* Setsockoptions(2) level. Thanks to BSD these must match IPPROTO_xxx */ -#define SOL_IP 0 -#define SOL_IPX 256 -#define SOL_AX25 257 -#define SOL_ATALK 258 -#define SOL_NETROM 259 -#define SOL_TCP 6 -#define SOL_UDP 17 - -/* IP options */ -#define IP_TOS 1 -#define IPTOS_LOWDELAY 0x10 -#define IPTOS_THROUGHPUT 0x08 -#define IPTOS_RELIABILITY 0x04 -#define IP_TTL 2 -#define IP_HDRINCL 3 -#define IP_OPTIONS 4 - -#define IP_MULTICAST_IF 32 -#define IP_MULTICAST_TTL 33 -#define IP_MULTICAST_LOOP 34 -#define IP_ADD_MEMBERSHIP 35 -#define IP_DROP_MEMBERSHIP 36 - - -/* These need to appear somewhere around here */ -#define IP_DEFAULT_MULTICAST_TTL 1 -#define IP_DEFAULT_MULTICAST_LOOP 1 -#define IP_MAX_MEMBERSHIPS 20 - -/* IPX options */ -#define IPX_TYPE 1 - -/* TCP options - this way around because someone left a set in the c library includes */ -#define TCP_NODELAY 1 -#define TCP_MAXSEG 2 - -/* The various priorities. */ -#define SOPRI_INTERACTIVE 0 -#define SOPRI_NORMAL 1 -#define SOPRI_BACKGROUND 2 - -#ifdef __KERNEL__ -extern void memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len); -extern int verify_iovec(struct msghdr *m, struct iovec *iov, char *address, int mode); -extern void memcpy_toiovec(struct iovec *v, unsigned char *kdata, int len); -extern int move_addr_to_user(void *kaddr, int klen, void *uaddr, int *ulen); -extern int move_addr_to_kernel(void *uaddr, int ulen, void *kaddr); -#endif -#endif /* _LINUX_SOCKET_H */ diff --git a/i386/i386at/gpl/linux/include/linux/sockios.h b/i386/i386at/gpl/linux/include/linux/sockios.h deleted file mode 100644 index ee20a0b1..00000000 --- a/i386/i386at/gpl/linux/include/linux/sockios.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * INET An implementation of the TCP/IP protocol suite for the LINUX - * operating system. INET is implemented using the BSD Socket - * interface as the means of communication with the user level. - * - * Definitions of the socket-level I/O control calls. - * - * Version: @(#)sockios.h 1.0.2 03/09/93 - * - * Authors: Ross Biro, <bir7@leland.Stanford.Edu> - * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ -#ifndef _LINUX_SOCKIOS_H -#define _LINUX_SOCKIOS_H - -/* Routing table calls. */ -#define SIOCADDRT 0x890B /* add routing table entry */ -#define SIOCDELRT 0x890C /* delete routing table entry */ - -/* Socket configuration controls. */ -#define SIOCGIFNAME 0x8910 /* get iface name */ -#define SIOCSIFLINK 0x8911 /* set iface channel */ -#define SIOCGIFCONF 0x8912 /* get iface list */ -#define SIOCGIFFLAGS 0x8913 /* get flags */ -#define SIOCSIFFLAGS 0x8914 /* set flags */ -#define SIOCGIFADDR 0x8915 /* get PA address */ -#define SIOCSIFADDR 0x8916 /* set PA address */ -#define SIOCGIFDSTADDR 0x8917 /* get remote PA address */ -#define SIOCSIFDSTADDR 0x8918 /* set remote PA address */ -#define SIOCGIFBRDADDR 0x8919 /* get broadcast PA address */ -#define SIOCSIFBRDADDR 0x891a /* set broadcast PA address */ -#define SIOCGIFNETMASK 0x891b /* get network PA mask */ -#define SIOCSIFNETMASK 0x891c /* set network PA mask */ -#define SIOCGIFMETRIC 0x891d /* get metric */ -#define SIOCSIFMETRIC 0x891e /* set metric */ -#define SIOCGIFMEM 0x891f /* get memory address (BSD) */ -#define SIOCSIFMEM 0x8920 /* set memory address (BSD) */ -#define SIOCGIFMTU 0x8921 /* get MTU size */ -#define SIOCSIFMTU 0x8922 /* set MTU size */ -#define SIOCSIFHWADDR 0x8924 /* set hardware address (NI) */ -#define SIOCGIFENCAP 0x8925 /* get/set slip encapsulation */ -#define SIOCSIFENCAP 0x8926 -#define SIOCGIFHWADDR 0x8927 /* Get hardware address */ -#define SIOCGIFSLAVE 0x8929 /* Driver slaving support */ -#define SIOCSIFSLAVE 0x8930 -/* begin multicast support change */ -#define SIOCADDMULTI 0x8931 -#define SIOCDELMULTI 0x8932 -/* end multicast support change */ - -/* ARP cache control calls. */ -#define OLD_SIOCDARP 0x8950 /* old delete ARP table entry */ -#define OLD_SIOCGARP 0x8951 /* old get ARP table entry */ -#define OLD_SIOCSARP 0x8952 /* old set ARP table entry */ -#define SIOCDARP 0x8953 /* delete ARP table entry */ -#define SIOCGARP 0x8954 /* get ARP table entry */ -#define SIOCSARP 0x8955 /* set ARP table entry */ - -/* RARP cache control calls. */ -#define SIOCDRARP 0x8960 /* delete RARP table entry */ -#define SIOCGRARP 0x8961 /* get RARP table entry */ -#define SIOCSRARP 0x8962 /* set RARP table entry */ - -/* Driver configuration calls */ - -#define SIOCGIFMAP 0x8970 /* Get device parameters */ -#define SIOCSIFMAP 0x8971 /* Set device parameters */ - - -/* Device private ioctl calls */ - -/* - * These 16 ioctls are available to devices via the do_ioctl() device - * vector. Each device should include this file and redefine these names - * as their own. Because these are device dependent it is a good idea - * _NOT_ to issue them to random objects and hope. - */ - -#define SIOCDEVPRIVATE 0x89F0 /* to 89FF */ - -/* - * These 16 ioctl calls are protocol private - */ - -#define SIOCPROTOPRIVATE 0x89E0 /* to 89EF */ -#endif /* _LINUX_SOCKIOS_H */ diff --git a/i386/i386at/gpl/linux/include/linux/stat.h b/i386/i386at/gpl/linux/include/linux/stat.h deleted file mode 100644 index d86b1646..00000000 --- a/i386/i386at/gpl/linux/include/linux/stat.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef _LINUX_STAT_H -#define _LINUX_STAT_H - -#ifdef __KERNEL__ - -#include <asm/stat.h> - -#endif - -#define S_IFMT 00170000 -#define S_IFSOCK 0140000 -#define S_IFLNK 0120000 -#define S_IFREG 0100000 -#define S_IFBLK 0060000 -#define S_IFDIR 0040000 -#define S_IFCHR 0020000 -#define S_IFIFO 0010000 -#define S_ISUID 0004000 -#define S_ISGID 0002000 -#define S_ISVTX 0001000 - -#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) -#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) -#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) -#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) -#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) -#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) -#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) - -#define S_IRWXU 00700 -#define S_IRUSR 00400 -#define S_IWUSR 00200 -#define S_IXUSR 00100 - -#define S_IRWXG 00070 -#define S_IRGRP 00040 -#define S_IWGRP 00020 -#define S_IXGRP 00010 - -#define S_IRWXO 00007 -#define S_IROTH 00004 -#define S_IWOTH 00002 -#define S_IXOTH 00001 - -#ifdef __KERNEL__ -#define S_IRWXUGO (S_IRWXU|S_IRWXG|S_IRWXO) -#define S_IALLUGO (S_ISUID|S_ISGID|S_ISVTX|S_IRWXUGO) -#define S_IRUGO (S_IRUSR|S_IRGRP|S_IROTH) -#define S_IWUGO (S_IWUSR|S_IWGRP|S_IWOTH) -#define S_IXUGO (S_IXUSR|S_IXGRP|S_IXOTH) -#endif - -#endif diff --git a/i386/i386at/gpl/linux/include/linux/stddef.h b/i386/i386at/gpl/linux/include/linux/stddef.h deleted file mode 100644 index c6221e71..00000000 --- a/i386/i386at/gpl/linux/include/linux/stddef.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef _LINUX_STDDEF_H -#define _LINUX_STDDEF_H - -#ifndef _SIZE_T -#define _SIZE_T -typedef unsigned int size_t; -#endif - -#undef NULL -#define NULL ((void *)0) - -#undef offsetof -#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) - -#endif diff --git a/i386/i386at/gpl/linux/include/linux/string.h b/i386/i386at/gpl/linux/include/linux/string.h deleted file mode 100644 index e9162b38..00000000 --- a/i386/i386at/gpl/linux/include/linux/string.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef _LINUX_STRING_H_ -#define _LINUX_STRING_H_ - -#include <linux/types.h> /* for size_t */ - -#ifndef NULL -#define NULL ((void *) 0) -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -extern char * ___strtok; -extern char * strcpy(char *,const char *); -extern char * strncpy(char *,const char *,size_t); -extern char * strcat(char *, const char *); -extern char * strncat(char *, const char *, size_t); -extern char * strchr(const char *,int); -extern char * strpbrk(const char *,const char *); -extern char * strtok(char *,const char *); -extern char * strstr(const char *,const char *); -extern size_t strlen(const char *); -extern size_t strnlen(const char *,size_t); -extern size_t strspn(const char *,const char *); -extern int strcmp(const char *,const char *); -extern int strncmp(const char *,const char *,size_t); - -extern void * memset(void *,int,size_t); -extern void * memcpy(void *,const void *,size_t); -extern void * memmove(void *,const void *,size_t); -extern void * memscan(void *,int,size_t); -extern int memcmp(const void *,const void *,size_t); - -/* - * Include machine specific inline routines - */ -#include <asm/string.h> - -#ifdef __cplusplus -} -#endif - -#endif /* _LINUX_STRING_H_ */ diff --git a/i386/i386at/gpl/linux/include/linux/tasks.h b/i386/i386at/gpl/linux/include/linux/tasks.h deleted file mode 100644 index 4540e34f..00000000 --- a/i386/i386at/gpl/linux/include/linux/tasks.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef _LINUX_TASKS_H -#define _LINUX_TASKS_H - -/* - * This is the maximum nr of tasks - change it if you need to - */ - -#ifdef __SMP__ -#define NR_CPUS 32 /* Max processors that can be running in SMP */ -#else -#define NR_CPUS 1 -#endif - -#define NR_TASKS 512 - -#define MAX_TASKS_PER_USER (NR_TASKS/2) -#define MIN_TASKS_LEFT_FOR_ROOT 4 - -#endif diff --git a/i386/i386at/gpl/linux/include/linux/tcp.h b/i386/i386at/gpl/linux/include/linux/tcp.h deleted file mode 100644 index ae6a063e..00000000 --- a/i386/i386at/gpl/linux/include/linux/tcp.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * INET An implementation of the TCP/IP protocol suite for the LINUX - * operating system. INET is implemented using the BSD Socket - * interface as the means of communication with the user level. - * - * Definitions for the TCP protocol. - * - * Version: @(#)tcp.h 1.0.2 04/28/93 - * - * Author: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ -#ifndef _LINUX_TCP_H -#define _LINUX_TCP_H - -#include <linux/types.h> -#include <asm/byteorder.h> - -struct tcphdr { - __u16 source; - __u16 dest; - __u32 seq; - __u32 ack_seq; -#if defined(__LITTLE_ENDIAN_BITFIELD) - __u16 res1:4, - doff:4, - fin:1, - syn:1, - rst:1, - psh:1, - ack:1, - urg:1, - res2:2; -#elif defined(__BIG_ENDIAN_BITFIELD) - __u16 doff:4, - res1:4, - res2:2, - urg:1, - ack:1, - psh:1, - rst:1, - syn:1, - fin:1; -#else -#error "Adjust your <asm/byteorder.h> defines" -#endif - __u16 window; - __u16 check; - __u16 urg_ptr; -}; - - -enum { - TCP_ESTABLISHED = 1, - TCP_SYN_SENT, - TCP_SYN_RECV, - TCP_FIN_WAIT1, - TCP_FIN_WAIT2, - TCP_TIME_WAIT, - TCP_CLOSE, - TCP_CLOSE_WAIT, - TCP_LAST_ACK, - TCP_LISTEN, - TCP_CLOSING /* now a valid state */ -}; - -#endif /* _LINUX_TCP_H */ diff --git a/i386/i386at/gpl/linux/include/linux/termios.h b/i386/i386at/gpl/linux/include/linux/termios.h deleted file mode 100644 index 47866288..00000000 --- a/i386/i386at/gpl/linux/include/linux/termios.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef _LINUX_TERMIOS_H -#define _LINUX_TERMIOS_H - -#include <linux/types.h> -#include <asm/termios.h> - -#endif diff --git a/i386/i386at/gpl/linux/include/linux/time.h b/i386/i386at/gpl/linux/include/linux/time.h deleted file mode 100644 index 269e9dc6..00000000 --- a/i386/i386at/gpl/linux/include/linux/time.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef _LINUX_TIME_H -#define _LINUX_TIME_H - -struct timespec { - long tv_sec; /* seconds */ - long tv_nsec; /* nanoseconds */ -}; - -struct timeval { - int tv_sec; /* seconds */ - int tv_usec; /* microseconds */ -}; - -struct timezone { - int tz_minuteswest; /* minutes west of Greenwich */ - int tz_dsttime; /* type of dst correction */ -}; - -#define NFDBITS __NFDBITS - -#ifdef __KERNEL__ -void do_gettimeofday(struct timeval *tv); -void do_settimeofday(struct timeval *tv); -#endif - -#define FD_SETSIZE __FD_SETSIZE -#define FD_SET(fd,fdsetp) __FD_SET(fd,fdsetp) -#define FD_CLR(fd,fdsetp) __FD_CLR(fd,fdsetp) -#define FD_ISSET(fd,fdsetp) __FD_ISSET(fd,fdsetp) -#define FD_ZERO(fdsetp) __FD_ZERO(fdsetp) - -/* - * Names of the interval timers, and structure - * defining a timer setting. - */ -#define ITIMER_REAL 0 -#define ITIMER_VIRTUAL 1 -#define ITIMER_PROF 2 - -struct itimerspec { - struct timespec it_interval; /* timer period */ - struct timespec it_value; /* timer expiration */ -}; - -struct itimerval { - struct timeval it_interval; /* timer interval */ - struct timeval it_value; /* current value */ -}; - -#endif diff --git a/i386/i386at/gpl/linux/include/linux/timer.h b/i386/i386at/gpl/linux/include/linux/timer.h deleted file mode 100644 index c54e8c5e..00000000 --- a/i386/i386at/gpl/linux/include/linux/timer.h +++ /dev/null @@ -1,101 +0,0 @@ -#ifndef _LINUX_TIMER_H -#define _LINUX_TIMER_H - -/* - * DON'T CHANGE THESE!! Most of them are hardcoded into some assembly language - * as well as being defined here. - */ - -/* - * The timers are: - * - * BLANK_TIMER console screen-saver timer - * - * BEEP_TIMER console beep timer - * - * RS_TIMER timer for the RS-232 ports - * - * SWAP_TIMER timer for the background pageout daemon - * - * HD_TIMER harddisk timer - * - * HD_TIMER2 (atdisk2 patches) - * - * FLOPPY_TIMER floppy disk timer (not used right now) - * - * SCSI_TIMER scsi.c timeout timer - * - * NET_TIMER tcp/ip timeout timer - * - * COPRO_TIMER 387 timeout for buggy hardware.. - * - * QIC02_TAPE_TIMER timer for QIC-02 tape driver (it's not hardcoded) - * - * MCD_TIMER Mitsumi CD-ROM Timer - * - * GSCD_TIMER Goldstar CD-ROM Timer - * - * OPTCD_TIMER Optics Storage CD-ROM Timer - * - */ - -#define BLANK_TIMER 0 -#define BEEP_TIMER 1 -#define RS_TIMER 2 -#define SWAP_TIMER 3 - -#define HD_TIMER 16 -#define FLOPPY_TIMER 17 -#define SCSI_TIMER 18 -#define NET_TIMER 19 -#define SOUND_TIMER 20 -#define COPRO_TIMER 21 - -#define QIC02_TAPE_TIMER 22 /* hhb */ -#define MCD_TIMER 23 - -#define HD_TIMER2 24 -#define GSCD_TIMER 25 -#define OPTCD_TIMER 26 - -struct timer_struct { - unsigned long expires; - void (*fn)(void); -}; - -extern unsigned long timer_active; -extern struct timer_struct timer_table[32]; - -/* - * This is completely separate from the above, and is the - * "new and improved" way of handling timers more dynamically. - * Hopefully efficient and general enough for most things. - * - * The "hardcoded" timers above are still useful for well- - * defined problems, but the timer-list is probably better - * when you need multiple outstanding timers or similar. - * - * The "data" field is in case you want to use the same - * timeout function for several timeouts. You can use this - * to distinguish between the different invocations. - */ -struct timer_list { - struct timer_list *next; - struct timer_list *prev; - unsigned long expires; - unsigned long data; - void (*function)(unsigned long); -}; - -extern void add_timer(struct timer_list * timer); -extern int del_timer(struct timer_list * timer); - -extern void it_real_fn(unsigned long); - -extern inline void init_timer(struct timer_list * timer) -{ - timer->next = NULL; - timer->prev = NULL; -} - -#endif diff --git a/i386/i386at/gpl/linux/include/linux/tqueue.h b/i386/i386at/gpl/linux/include/linux/tqueue.h deleted file mode 100644 index d483a155..00000000 --- a/i386/i386at/gpl/linux/include/linux/tqueue.h +++ /dev/null @@ -1,163 +0,0 @@ -/* - * tqueue.h --- task queue handling for Linux. - * - * Mostly based on a proposed bottom-half replacement code written by - * Kai Petzke, wpp@marie.physik.tu-berlin.de. - * - * Modified for use in the Linux kernel by Theodore Ts'o, - * tytso@mit.edu. Any bugs are my fault, not Kai's. - * - * The original comment follows below. - */ - -#ifndef _LINUX_TQUEUE_H -#define _LINUX_TQUEUE_H - -#include <asm/bitops.h> -#include <asm/system.h> - -#ifdef INCLUDE_INLINE_FUNCS -#define _INLINE_ extern -#else -#define _INLINE_ extern __inline__ -#endif - -/* - * New proposed "bottom half" handlers: - * (C) 1994 Kai Petzke, wpp@marie.physik.tu-berlin.de - * - * Advantages: - * - Bottom halfs are implemented as a linked list. You can have as many - * of them, as you want. - * - No more scanning of a bit field is required upon call of a bottom half. - * - Support for chained bottom half lists. The run_task_queue() function can be - * used as a bottom half handler. This is for example useful for bottom - * halfs, which want to be delayed until the next clock tick. - * - * Problems: - * - The queue_task_irq() inline function is only atomic with respect to itself. - * Problems can occur, when queue_task_irq() is called from a normal system - * call, and an interrupt comes in. No problems occur, when queue_task_irq() - * is called from an interrupt or bottom half, and interrupted, as run_task_queue() - * will not be executed/continued before the last interrupt returns. If in - * doubt, use queue_task(), not queue_task_irq(). - * - Bottom halfs are called in the reverse order that they were linked into - * the list. - */ - -struct tq_struct { - struct tq_struct *next; /* linked list of active bh's */ - int sync; /* must be initialized to zero */ - void (*routine)(void *); /* function to call */ - void *data; /* argument to function */ -}; - -typedef struct tq_struct * task_queue; - -#define DECLARE_TASK_QUEUE(q) task_queue q = &tq_last - -extern struct tq_struct tq_last; -extern task_queue tq_timer, tq_immediate, tq_scheduler; - -#ifdef INCLUDE_INLINE_FUNCS -struct tq_struct tq_last = { - &tq_last, 0, 0, 0 -}; -#endif - -/* - * To implement your own list of active bottom halfs, use the following - * two definitions: - * - * struct tq_struct *my_bh = &tq_last; - * struct tq_struct run_my_bh = { - * 0, 0, (void *)(void *) run_task_queue, &my_bh - * }; - * - * To activate a bottom half on your list, use: - * - * queue_task(tq_pointer, &my_bh); - * - * To run the bottom halfs on your list put them on the immediate list by: - * - * queue_task(&run_my_bh, &tq_immediate); - * - * This allows you to do deferred procession. For example, you could - * have a bottom half list tq_timer, which is marked active by the timer - * interrupt. - */ - -/* - * queue_task_irq: put the bottom half handler "bh_pointer" on the list - * "bh_list". You may call this function only from an interrupt - * handler or a bottom half handler. - */ -_INLINE_ void queue_task_irq(struct tq_struct *bh_pointer, - task_queue *bh_list) -{ - if (!set_bit(0,&bh_pointer->sync)) { - bh_pointer->next = *bh_list; - *bh_list = bh_pointer; - } -} - -/* - * queue_task_irq_off: put the bottom half handler "bh_pointer" on the list - * "bh_list". You may call this function only when interrupts are off. - */ -_INLINE_ void queue_task_irq_off(struct tq_struct *bh_pointer, - task_queue *bh_list) -{ - if (!(bh_pointer->sync & 1)) { - bh_pointer->sync = 1; - bh_pointer->next = *bh_list; - *bh_list = bh_pointer; - } -} - - -/* - * queue_task: as queue_task_irq, but can be called from anywhere. - */ -_INLINE_ void queue_task(struct tq_struct *bh_pointer, - task_queue *bh_list) -{ - if (!set_bit(0,&bh_pointer->sync)) { - unsigned long flags; - save_flags(flags); - cli(); - bh_pointer->next = *bh_list; - *bh_list = bh_pointer; - restore_flags(flags); - } -} - -/* - * Call all "bottom halfs" on a given list. - */ -_INLINE_ void run_task_queue(task_queue *list) -{ - register struct tq_struct *save_p; - register struct tq_struct *p; - void *arg; - void (*f) (void *); - - while(1) { - p = xchg(list,&tq_last); - if(p == &tq_last) - break; - - do { - arg = p -> data; - f = p -> routine; - save_p = p -> next; - p -> sync = 0; - (*f)(arg); - p = save_p; - } while(p != &tq_last); - } -} - -#undef _INLINE_ - -#endif /* _LINUX_TQUEUE_H */ diff --git a/i386/i386at/gpl/linux/include/linux/trdevice.h b/i386/i386at/gpl/linux/include/linux/trdevice.h deleted file mode 100644 index 96801763..00000000 --- a/i386/i386at/gpl/linux/include/linux/trdevice.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * INET An implementation of the TCP/IP protocol suite for the LINUX - * operating system. NET is implemented using the BSD Socket - * interface as the means of communication with the user level. - * - * Definitions for the Ethernet handlers. - * - * Version: @(#)eth.h 1.0.4 05/13/93 - * - * Authors: Ross Biro, <bir7@leland.Stanford.Edu> - * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> - * - * Relocated to include/linux where it belongs by Alan Cox - * <gw4pts@gw4pts.ampr.org> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * WARNING: This move may well be temporary. This file will get merged with others RSN. - * - */ -#ifndef _LINUX_TRDEVICE_H -#define _LINUX_TRDEVICE_H - - -#include <linux/if_tr.h> - -#ifdef __KERNEL__ -extern int tr_header(struct sk_buff *skb, struct device *dev, - unsigned short type, void *daddr, - void *saddr, unsigned len); -extern int tr_rebuild_header(void *buff, struct device *dev, - unsigned long raddr, struct sk_buff *skb); -extern unsigned short tr_type_trans(struct sk_buff *skb, struct device *dev); - -#endif - -#endif /* _LINUX_TRDEVICE_H */ diff --git a/i386/i386at/gpl/linux/include/linux/tty.h b/i386/i386at/gpl/linux/include/linux/tty.h deleted file mode 100644 index fe139511..00000000 --- a/i386/i386at/gpl/linux/include/linux/tty.h +++ /dev/null @@ -1,340 +0,0 @@ -#ifndef _LINUX_TTY_H -#define _LINUX_TTY_H - -/* - * 'tty.h' defines some structures used by tty_io.c and some defines. - */ - -#ifdef __KERNEL__ -#include <linux/fs.h> -#include <linux/termios.h> -#include <linux/tqueue.h> -#include <linux/tty_driver.h> -#include <linux/tty_ldisc.h> - -#include <asm/system.h> - - -/* - * Note: don't mess with NR_PTYS until you understand the tty minor - * number allocation game... - * (Note: the *_driver.minor_start values 1, 64, 128, 192 are - * hardcoded at present.) - */ -#define MIN_NR_CONSOLES 1 /* must be at least 1 */ -#define MAX_NR_CONSOLES 63 /* serial lines start at 64 */ -#define MAX_NR_USER_CONSOLES 63 /* must be root to allocate above this */ - /* Note: the ioctl VT_GETSTATE does not work for - consoles 16 and higher (since it returns a short) */ -#define NR_PTYS 256 -#define NR_LDISCS 16 - -/* - * These are set up by the setup-routine at boot-time: - */ - -struct screen_info { - unsigned char orig_x; - unsigned char orig_y; - unsigned char unused1[2]; - unsigned short orig_video_page; - unsigned char orig_video_mode; - unsigned char orig_video_cols; - unsigned short unused2; - unsigned short orig_video_ega_bx; - unsigned short unused3; - unsigned char orig_video_lines; - unsigned char orig_video_isVGA; - unsigned short orig_video_points; -}; - -extern struct screen_info screen_info; - -#define ORIG_X (screen_info.orig_x) -#define ORIG_Y (screen_info.orig_y) -#define ORIG_VIDEO_PAGE (screen_info.orig_video_page) -#define ORIG_VIDEO_MODE (screen_info.orig_video_mode) -#define ORIG_VIDEO_COLS (screen_info.orig_video_cols) -#define ORIG_VIDEO_EGA_BX (screen_info.orig_video_ega_bx) -#define ORIG_VIDEO_LINES (screen_info.orig_video_lines) -#define ORIG_VIDEO_ISVGA (screen_info.orig_video_isVGA) -#define ORIG_VIDEO_POINTS (screen_info.orig_video_points) - -#define VIDEO_TYPE_MDA 0x10 /* Monochrome Text Display */ -#define VIDEO_TYPE_CGA 0x11 /* CGA Display */ -#define VIDEO_TYPE_EGAM 0x20 /* EGA/VGA in Monochrome Mode */ -#define VIDEO_TYPE_EGAC 0x21 /* EGA in Color Mode */ -#define VIDEO_TYPE_VGAC 0x22 /* VGA+ in Color Mode */ - -#define VIDEO_TYPE_TGAC 0x40 /* DEC TGA */ - -/* - * This character is the same as _POSIX_VDISABLE: it cannot be used as - * a c_cc[] character, but indicates that a particular special character - * isn't in use (eg VINTR has no character etc) - */ -#define __DISABLED_CHAR '\0' - -/* - * This is the flip buffer used for the tty driver. The buffer is - * located in the tty structure, and is used as a high speed interface - * between the tty driver and the tty line discipline. - */ -#define TTY_FLIPBUF_SIZE 512 - -struct tty_flip_buffer { - struct tq_struct tqueue; - unsigned char char_buf[2*TTY_FLIPBUF_SIZE]; - char flag_buf[2*TTY_FLIPBUF_SIZE]; - char *char_buf_ptr; - unsigned char *flag_buf_ptr; - int count; - int buf_num; -}; - -/* - * When a break, frame error, or parity error happens, these codes are - * stuffed into the flags buffer. - */ -#define TTY_NORMAL 0 -#define TTY_BREAK 1 -#define TTY_FRAME 2 -#define TTY_PARITY 3 -#define TTY_OVERRUN 4 - -#define INTR_CHAR(tty) ((tty)->termios->c_cc[VINTR]) -#define QUIT_CHAR(tty) ((tty)->termios->c_cc[VQUIT]) -#define ERASE_CHAR(tty) ((tty)->termios->c_cc[VERASE]) -#define KILL_CHAR(tty) ((tty)->termios->c_cc[VKILL]) -#define EOF_CHAR(tty) ((tty)->termios->c_cc[VEOF]) -#define TIME_CHAR(tty) ((tty)->termios->c_cc[VTIME]) -#define MIN_CHAR(tty) ((tty)->termios->c_cc[VMIN]) -#define SWTC_CHAR(tty) ((tty)->termios->c_cc[VSWTC]) -#define START_CHAR(tty) ((tty)->termios->c_cc[VSTART]) -#define STOP_CHAR(tty) ((tty)->termios->c_cc[VSTOP]) -#define SUSP_CHAR(tty) ((tty)->termios->c_cc[VSUSP]) -#define EOL_CHAR(tty) ((tty)->termios->c_cc[VEOL]) -#define REPRINT_CHAR(tty) ((tty)->termios->c_cc[VREPRINT]) -#define DISCARD_CHAR(tty) ((tty)->termios->c_cc[VDISCARD]) -#define WERASE_CHAR(tty) ((tty)->termios->c_cc[VWERASE]) -#define LNEXT_CHAR(tty) ((tty)->termios->c_cc[VLNEXT]) -#define EOL2_CHAR(tty) ((tty)->termios->c_cc[VEOL2]) - -#define _I_FLAG(tty,f) ((tty)->termios->c_iflag & (f)) -#define _O_FLAG(tty,f) ((tty)->termios->c_oflag & (f)) -#define _C_FLAG(tty,f) ((tty)->termios->c_cflag & (f)) -#define _L_FLAG(tty,f) ((tty)->termios->c_lflag & (f)) - -#define I_IGNBRK(tty) _I_FLAG((tty),IGNBRK) -#define I_BRKINT(tty) _I_FLAG((tty),BRKINT) -#define I_IGNPAR(tty) _I_FLAG((tty),IGNPAR) -#define I_PARMRK(tty) _I_FLAG((tty),PARMRK) -#define I_INPCK(tty) _I_FLAG((tty),INPCK) -#define I_ISTRIP(tty) _I_FLAG((tty),ISTRIP) -#define I_INLCR(tty) _I_FLAG((tty),INLCR) -#define I_IGNCR(tty) _I_FLAG((tty),IGNCR) -#define I_ICRNL(tty) _I_FLAG((tty),ICRNL) -#define I_IUCLC(tty) _I_FLAG((tty),IUCLC) -#define I_IXON(tty) _I_FLAG((tty),IXON) -#define I_IXANY(tty) _I_FLAG((tty),IXANY) -#define I_IXOFF(tty) _I_FLAG((tty),IXOFF) -#define I_IMAXBEL(tty) _I_FLAG((tty),IMAXBEL) - -#define O_OPOST(tty) _O_FLAG((tty),OPOST) -#define O_OLCUC(tty) _O_FLAG((tty),OLCUC) -#define O_ONLCR(tty) _O_FLAG((tty),ONLCR) -#define O_OCRNL(tty) _O_FLAG((tty),OCRNL) -#define O_ONOCR(tty) _O_FLAG((tty),ONOCR) -#define O_ONLRET(tty) _O_FLAG((tty),ONLRET) -#define O_OFILL(tty) _O_FLAG((tty),OFILL) -#define O_OFDEL(tty) _O_FLAG((tty),OFDEL) -#define O_NLDLY(tty) _O_FLAG((tty),NLDLY) -#define O_CRDLY(tty) _O_FLAG((tty),CRDLY) -#define O_TABDLY(tty) _O_FLAG((tty),TABDLY) -#define O_BSDLY(tty) _O_FLAG((tty),BSDLY) -#define O_VTDLY(tty) _O_FLAG((tty),VTDLY) -#define O_FFDLY(tty) _O_FLAG((tty),FFDLY) - -#define C_BAUD(tty) _C_FLAG((tty),CBAUD) -#define C_CSIZE(tty) _C_FLAG((tty),CSIZE) -#define C_CSTOPB(tty) _C_FLAG((tty),CSTOPB) -#define C_CREAD(tty) _C_FLAG((tty),CREAD) -#define C_PARENB(tty) _C_FLAG((tty),PARENB) -#define C_PARODD(tty) _C_FLAG((tty),PARODD) -#define C_HUPCL(tty) _C_FLAG((tty),HUPCL) -#define C_CLOCAL(tty) _C_FLAG((tty),CLOCAL) -#define C_CIBAUD(tty) _C_FLAG((tty),CIBAUD) -#define C_CRTSCTS(tty) _C_FLAG((tty),CRTSCTS) - -#define L_ISIG(tty) _L_FLAG((tty),ISIG) -#define L_ICANON(tty) _L_FLAG((tty),ICANON) -#define L_XCASE(tty) _L_FLAG((tty),XCASE) -#define L_ECHO(tty) _L_FLAG((tty),ECHO) -#define L_ECHOE(tty) _L_FLAG((tty),ECHOE) -#define L_ECHOK(tty) _L_FLAG((tty),ECHOK) -#define L_ECHONL(tty) _L_FLAG((tty),ECHONL) -#define L_NOFLSH(tty) _L_FLAG((tty),NOFLSH) -#define L_TOSTOP(tty) _L_FLAG((tty),TOSTOP) -#define L_ECHOCTL(tty) _L_FLAG((tty),ECHOCTL) -#define L_ECHOPRT(tty) _L_FLAG((tty),ECHOPRT) -#define L_ECHOKE(tty) _L_FLAG((tty),ECHOKE) -#define L_FLUSHO(tty) _L_FLAG((tty),FLUSHO) -#define L_PENDIN(tty) _L_FLAG((tty),PENDIN) -#define L_IEXTEN(tty) _L_FLAG((tty),IEXTEN) - -/* - * Where all of the state associated with a tty is kept while the tty - * is open. Since the termios state should be kept even if the tty - * has been closed --- for things like the baud rate, etc --- it is - * not stored here, but rather a pointer to the real state is stored - * here. Possible the winsize structure should have the same - * treatment, but (1) the default 80x24 is usually right and (2) it's - * most often used by a windowing system, which will set the correct - * size each time the window is created or resized anyway. - * IMPORTANT: since this structure is dynamically allocated, it must - * be no larger than 4096 bytes. Changing TTY_BUF_SIZE will change - * the size of this structure, and it needs to be done with care. - * - TYT, 9/14/92 - */ -struct tty_struct { - int magic; - struct tty_driver driver; - struct tty_ldisc ldisc; - struct termios *termios, *termios_locked; - int pgrp; - int session; - kdev_t device; - unsigned long flags; - int count; - struct winsize winsize; - unsigned char stopped:1, hw_stopped:1, packet:1; - unsigned char ctrl_status; - - struct tty_struct *link; - struct fasync_struct *fasync; - struct tty_flip_buffer flip; - int max_flip_cnt; - struct wait_queue *write_wait; - struct wait_queue *read_wait; - void *disc_data; - void *driver_data; - -#define N_TTY_BUF_SIZE 4096 - - /* - * The following is data for the N_TTY line discipline. For - * historical reasons, this is included in the tty structure. - */ - unsigned int column; - unsigned char lnext:1, erasing:1, raw:1, real_raw:1, icanon:1; - unsigned char closing:1; - unsigned short minimum_to_wake; - unsigned overrun_time; - int num_overrun; - unsigned long process_char_map[256/(8*sizeof(unsigned long))]; - char *read_buf; - int read_head; - int read_tail; - int read_cnt; - unsigned long read_flags[N_TTY_BUF_SIZE/(8*sizeof(unsigned long))]; - int canon_data; - unsigned long canon_head; - unsigned int canon_column; -}; - -/* tty magic number */ -#define TTY_MAGIC 0x5401 - -/* - * These bits are used in the flags field of the tty structure. - * - * So that interrupts won't be able to mess up the queues, - * copy_to_cooked must be atomic with respect to itself, as must - * tty->write. Thus, you must use the inline functions set_bit() and - * clear_bit() to make things atomic. - */ -#define TTY_THROTTLED 0 -#define TTY_IO_ERROR 1 -#define TTY_SLAVE_CLOSED 2 -#define TTY_EXCLUSIVE 3 -#define TTY_DEBUG 4 -#define TTY_DO_WRITE_WAKEUP 5 -#define TTY_PUSH 6 -#define TTY_CLOSING 7 - -#define TTY_WRITE_FLUSH(tty) tty_write_flush((tty)) - -extern void tty_write_flush(struct tty_struct *); - -extern struct termios tty_std_termios; -extern struct tty_struct * redirect; -extern struct tty_ldisc ldiscs[]; -extern int fg_console, last_console, want_console; - -extern int kmsg_redirect; -extern struct wait_queue * keypress_wait; - -extern unsigned long con_init(unsigned long); - -extern int rs_init(void); -extern int lp_init(void); -extern int pty_init(void); -extern int tty_init(void); -extern int vcs_init(void); -extern int cy_init(void); -extern int stl_init(void); -extern int stli_init(void); - -extern int tty_paranoia_check(struct tty_struct *tty, kdev_t device, - const char *routine); -extern char *_tty_name(struct tty_struct *tty, char *buf); -extern char *tty_name(struct tty_struct *tty); -extern void tty_wait_until_sent(struct tty_struct * tty, int timeout); -extern int tty_check_change(struct tty_struct * tty); -extern void stop_tty(struct tty_struct * tty); -extern void start_tty(struct tty_struct * tty); -extern int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc); -extern int tty_register_driver(struct tty_driver *driver); -extern int tty_unregister_driver(struct tty_driver *driver); -extern int tty_read_raw_data(struct tty_struct *tty, unsigned char *bufp, - int buflen); -extern void tty_write_message(struct tty_struct *tty, char *msg); - -extern int is_orphaned_pgrp(int pgrp); -extern int is_ignored(int sig); -extern int tty_signal(int sig, struct tty_struct *tty); -extern void tty_hangup(struct tty_struct * tty); -extern void tty_vhangup(struct tty_struct * tty); -extern void tty_unhangup(struct file *filp); -extern int tty_hung_up_p(struct file * filp); -extern void do_SAK(struct tty_struct *tty); -extern void disassociate_ctty(int priv); - -/* n_tty.c */ -extern struct tty_ldisc tty_ldisc_N_TTY; - -/* tty_ioctl.c */ -extern int n_tty_ioctl(struct tty_struct * tty, struct file * file, - unsigned int cmd, unsigned long arg); - -/* serial.c */ - -extern int rs_open(struct tty_struct * tty, struct file * filp); - -/* pty.c */ - -extern int pty_open(struct tty_struct * tty, struct file * filp); - -/* console.c */ - -extern int con_open(struct tty_struct * tty, struct file * filp); -extern void update_screen(int new_console); -extern void console_print(const char *); - -/* vt.c */ - -extern int vt_ioctl(struct tty_struct *tty, struct file * file, - unsigned int cmd, unsigned long arg); - -#endif /* __KERNEL__ */ -#endif diff --git a/i386/i386at/gpl/linux/include/linux/tty_driver.h b/i386/i386at/gpl/linux/include/linux/tty_driver.h deleted file mode 100644 index 3468fa2d..00000000 --- a/i386/i386at/gpl/linux/include/linux/tty_driver.h +++ /dev/null @@ -1,189 +0,0 @@ -#ifndef _LINUX_TTY_DRIVER_H -#define _LINUX_TTY_DRIVER_H - -/* - * This structure defines the interface between the low-level tty - * driver and the tty routines. The following routines can be - * defined; unless noted otherwise, they are optional, and can be - * filled in with a null pointer. - * - * int (*open)(struct tty_struct * tty, struct file * filp); - * - * This routine is called when a particular tty device is opened. - * This routine is mandatory; if this routine is not filled in, - * the attempted open will fail with ENODEV. - * - * void (*close)(struct tty_struct * tty, struct file * filp); - * - * This routine is called when a particular tty device is closed. - * - * int (*write)(struct tty_struct * tty, int from_user, - * const unsigned char *buf, int count); - * - * This routine is called by the kernel to write a series of - * characters to the tty device. The characters may come from - * user space or kernel space. This routine will return the - * number of characters actually accepted for writing. This - * routine is mandatory. - * - * void (*put_char)(struct tty_struct *tty, unsigned char ch); - * - * This routine is called by the kernel to write a single - * character to the tty device. If the kernel uses this routine, - * it must call the flush_chars() routine (if defined) when it is - * done stuffing characters into the driver. If there is no room - * in the queue, the character is ignored. - * - * void (*flush_chars)(struct tty_struct *tty); - * - * This routine is called by the kernel after it has written a - * series of characters to the tty device using put_char(). - * - * int (*write_room)(struct tty_struct *tty); - * - * This routine returns the numbers of characters the tty driver - * will accept for queuing to be written. This number is subject - * to change as output buffers get emptied, or if the output flow - * control is acted. - * - * int (*ioctl)(struct tty_struct *tty, struct file * file, - * unsigned int cmd, unsigned long arg); - * - * This routine allows the tty driver to implement - * device-specific ioctl's. If the ioctl number passed in cmd - * is not recognized by the driver, it should return ENOIOCTLCMD. - * - * void (*set_termios)(struct tty_struct *tty, struct termios * old); - * - * This routine allows the tty driver to be notified when - * device's termios settings have changed. Note that a - * well-designed tty driver should be prepared to accept the case - * where old == NULL, and try to do something rational. - * - * void (*set_ldisc)(struct tty_struct *tty); - * - * This routine allows the tty driver to be notified when the - * device's termios settings have changed. - * - * void (*throttle)(struct tty_struct * tty); - * - * This routine notifies the tty driver that input buffers for - * the line discipline are close to full, and it should somehow - * signal that no more characters should be sent to the tty. - * - * void (*unthrottle)(struct tty_struct * tty); - * - * This routine notifies the tty drivers that it should signals - * that characters can now be sent to the tty without fear of - * overrunning the input buffers of the line disciplines. - * - * void (*stop)(struct tty_struct *tty); - * - * This routine notifies the tty driver that it should stop - * outputting characters to the tty device. - * - * void (*start)(struct tty_struct *tty); - * - * This routine notifies the tty driver that it resume sending - * characters to the tty device. - * - * void (*hangup)(struct tty_struct *tty); - * - * This routine notifies the tty driver that it should hangup the - * tty device. - * - */ - -#include <linux/fs.h> - -struct tty_driver { - int magic; /* magic number for this structure */ - const char *name; - int name_base; /* offset of printed name */ - short major; /* major device number */ - short minor_start; /* start of minor device number*/ - short num; /* number of devices */ - short type; /* type of tty driver */ - short subtype; /* subtype of tty driver */ - struct termios init_termios; /* Initial termios */ - int flags; /* tty driver flags */ - int *refcount; /* for loadable tty drivers */ - struct tty_driver *other; /* only used for the PTY driver */ - - /* - * Pointer to the tty data structures - */ - struct tty_struct **table; - struct termios **termios; - struct termios **termios_locked; - - /* - * Interface routines from the upper tty layer to the tty - * driver. - */ - int (*open)(struct tty_struct * tty, struct file * filp); - void (*close)(struct tty_struct * tty, struct file * filp); - int (*write)(struct tty_struct * tty, int from_user, - const unsigned char *buf, int count); - void (*put_char)(struct tty_struct *tty, unsigned char ch); - void (*flush_chars)(struct tty_struct *tty); - int (*write_room)(struct tty_struct *tty); - int (*chars_in_buffer)(struct tty_struct *tty); - int (*ioctl)(struct tty_struct *tty, struct file * file, - unsigned int cmd, unsigned long arg); - void (*set_termios)(struct tty_struct *tty, struct termios * old); - void (*throttle)(struct tty_struct * tty); - void (*unthrottle)(struct tty_struct * tty); - void (*stop)(struct tty_struct *tty); - void (*start)(struct tty_struct *tty); - void (*hangup)(struct tty_struct *tty); - void (*flush_buffer)(struct tty_struct *tty); - void (*set_ldisc)(struct tty_struct *tty); - - /* - * linked list pointers - */ - struct tty_driver *next; - struct tty_driver *prev; -}; - -/* tty driver magic number */ -#define TTY_DRIVER_MAGIC 0x5402 - -/* - * tty driver flags - * - * TTY_DRIVER_RESET_TERMIOS --- requests the tty layer to reset the - * termios setting when the last process has closed the device. - * Used for PTY's, in particular. - * - * TTY_DRIVER_REAL_RAW --- if set, indicates that the driver will - * guarantee never not to set any special character handling - * flags if ((IGNBRK || (!BRKINT && !PARMRK)) && (IGNPAR || - * !INPCK)). That is, if there is no reason for the driver to - * send notifications of parity and break characters up to the - * line driver, it won't do so. This allows the line driver to - * optimize for this case if this flag is set. (Note that there - * is also a promise, if the above case is true, not to signal - * overruns, either.) - */ -#define TTY_DRIVER_INSTALLED 0x0001 -#define TTY_DRIVER_RESET_TERMIOS 0x0002 -#define TTY_DRIVER_REAL_RAW 0x0004 - -/* tty driver types */ -#define TTY_DRIVER_TYPE_SYSTEM 0x0001 -#define TTY_DRIVER_TYPE_CONSOLE 0x0002 -#define TTY_DRIVER_TYPE_SERIAL 0x0003 -#define TTY_DRIVER_TYPE_PTY 0x0004 -#define TTY_DRIVER_TYPE_SCC 0x0005 /* scc driver */ - -/* system subtypes (magic, used by tty_io.c) */ -#define SYSTEM_TYPE_TTY 0x0001 -#define SYSTEM_TYPE_CONSOLE 0x0002 - -/* pty subtypes (magic, used by tty_io.c) */ -#define PTY_TYPE_MASTER 0x0001 -#define PTY_TYPE_SLAVE 0x0002 - -#endif /* #ifdef _LINUX_TTY_DRIVER_H */ diff --git a/i386/i386at/gpl/linux/include/linux/tty_ldisc.h b/i386/i386at/gpl/linux/include/linux/tty_ldisc.h deleted file mode 100644 index 87b54ca3..00000000 --- a/i386/i386at/gpl/linux/include/linux/tty_ldisc.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef _LINUX_TTY_LDISC_H -#define _LINUX_TTY_LDISC_H - -/* - * Definitions for the tty line discipline - */ - -#include <linux/fs.h> -#include <linux/wait.h> - -struct tty_ldisc { - int magic; - int num; - int flags; - /* - * The following routines are called from above. - */ - int (*open)(struct tty_struct *); - void (*close)(struct tty_struct *); - void (*flush_buffer)(struct tty_struct *tty); - int (*chars_in_buffer)(struct tty_struct *tty); - int (*read)(struct tty_struct * tty, struct file * file, - unsigned char * buf, unsigned int nr); - int (*write)(struct tty_struct * tty, struct file * file, - const unsigned char * buf, unsigned int nr); - int (*ioctl)(struct tty_struct * tty, struct file * file, - unsigned int cmd, unsigned long arg); - void (*set_termios)(struct tty_struct *tty, struct termios * old); - int (*select)(struct tty_struct * tty, struct inode * inode, - struct file * file, int sel_type, - struct select_table_struct *wait); - - /* - * The following routines are called from below. - */ - void (*receive_buf)(struct tty_struct *, const unsigned char *cp, - char *fp, int count); - int (*receive_room)(struct tty_struct *); - void (*write_wakeup)(struct tty_struct *); -}; - -#define TTY_LDISC_MAGIC 0x5403 - -#define LDISC_FLAG_DEFINED 0x00000001 - -#endif /* _LINUX_TTY_LDISC_H */ diff --git a/i386/i386at/gpl/linux/include/linux/types.h b/i386/i386at/gpl/linux/include/linux/types.h deleted file mode 100644 index 376d3ac3..00000000 --- a/i386/i386at/gpl/linux/include/linux/types.h +++ /dev/null @@ -1,72 +0,0 @@ -#ifndef _LINUX_TYPES_H -#define _LINUX_TYPES_H - -/* - * This allows for 256 file descriptors: if NR_OPEN is ever grown beyond that - * you'll have to change this too. But 256 fd's seem to be enough even for such - * "real" unices like SunOS, so hopefully this is one limit that doesn't have - * to be changed. - * - * Note that POSIX wants the FD_CLEAR(fd,fdsetp) defines to be in <sys/time.h> - * (and thus <linux/time.h>) - but this is a more logical place for them. Solved - * by having dummy defines in <sys/time.h>. - */ - -/* - * Those macros may have been defined in <gnu/types.h>. But we always - * use the ones here. - */ -#undef __NFDBITS -#define __NFDBITS (8 * sizeof(unsigned int)) - -#undef __FD_SETSIZE -#define __FD_SETSIZE 256 - -#undef __FDSET_INTS -#define __FDSET_INTS (__FD_SETSIZE/__NFDBITS) - -typedef struct fd_set { - unsigned int fds_bits [__FDSET_INTS]; -} fd_set; - -#include <asm/types.h> - -#ifndef NULL -#define NULL ((void *) 0) -#endif - -#if defined(__GNUC__) && !defined(__STRICT_ANSI__) -#define _LOFF_T -typedef long long loff_t; -#endif - -#ifndef MACH_INCLUDE -/* bsd */ -typedef unsigned char u_char; -typedef unsigned short u_short; -typedef unsigned int u_int; -typedef unsigned long u_long; -#endif - -/* sysv */ -typedef unsigned char unchar; -typedef unsigned short ushort; -typedef unsigned int uint; -typedef unsigned long ulong; - -#ifndef MACH_INCLUDE -typedef char *caddr_t; -#endif - -typedef unsigned char cc_t; -typedef unsigned int speed_t; -typedef unsigned int tcflag_t; - -struct ustat { - daddr_t f_tfree; - ino_t f_tinode; - char f_fname[6]; - char f_fpack[6]; -}; - -#endif diff --git a/i386/i386at/gpl/linux/include/linux/uio.h b/i386/i386at/gpl/linux/include/linux/uio.h deleted file mode 100644 index 8051b3d0..00000000 --- a/i386/i386at/gpl/linux/include/linux/uio.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef __LINUX_UIO_H -#define __LINUX_UIO_H - -/* - * Berkeley style UIO structures - Alan Cox 1994. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - - -/* A word of warning: Our uio structure will clash with the C library one (which is now obsolete). Remove the C - library one from sys/uio.h */ - -struct iovec -{ - void *iov_base; /* BSD uses caddr_t (same thing in effect) */ - int iov_len; -}; - -#define MAX_IOVEC 8 /* Maximum iovec's in one operation */ - -#endif diff --git a/i386/i386at/gpl/linux/include/linux/unistd.h b/i386/i386at/gpl/linux/include/linux/unistd.h deleted file mode 100644 index 10ed9834..00000000 --- a/i386/i386at/gpl/linux/include/linux/unistd.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef _LINUX_UNISTD_H_ -#define _LINUX_UNISTD_H_ - -extern int errno; - -/* - * Include machine specific syscallX macros - */ -#include <asm/unistd.h> - -#endif /* _LINUX_UNISTD_H_ */ diff --git a/i386/i386at/gpl/linux/include/linux/utsname.h b/i386/i386at/gpl/linux/include/linux/utsname.h deleted file mode 100644 index 7aef28fc..00000000 --- a/i386/i386at/gpl/linux/include/linux/utsname.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef _LINUX_UTSNAME_H -#define _LINUX_UTSNAME_H - -#define __OLD_UTS_LEN 8 - -struct oldold_utsname { - char sysname[9]; - char nodename[9]; - char release[9]; - char version[9]; - char machine[9]; -}; - -#define __NEW_UTS_LEN 64 - -struct old_utsname { - char sysname[65]; - char nodename[65]; - char release[65]; - char version[65]; - char machine[65]; -}; - -struct new_utsname { - char sysname[65]; - char nodename[65]; - char release[65]; - char version[65]; - char machine[65]; - char domainname[65]; -}; - -extern struct new_utsname system_utsname; - -#endif diff --git a/i386/i386at/gpl/linux/include/linux/version.h b/i386/i386at/gpl/linux/include/linux/version.h deleted file mode 100644 index 39c1b599..00000000 --- a/i386/i386at/gpl/linux/include/linux/version.h +++ /dev/null @@ -1,8 +0,0 @@ -#define UTS_RELEASE "1.3.68" -#define UTS_VERSION "#1 Thu Feb 29 16:37:10 MST 1996" -#define LINUX_COMPILE_TIME "09:03:52" -#define LINUX_COMPILE_BY "goel" -#define LINUX_COMPILE_HOST "stamp.cs.utah.edu" -#define LINUX_COMPILE_DOMAIN "cs.utah.edu" -#define LINUX_COMPILER "gcc version 2.7.2" -#define LINUX_VERSION_CODE (65536 + 4 * 256) diff --git a/i386/i386at/gpl/linux/include/linux/vfs.h b/i386/i386at/gpl/linux/include/linux/vfs.h deleted file mode 100644 index b3a58657..00000000 --- a/i386/i386at/gpl/linux/include/linux/vfs.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _LINUX_VFS_H -#define _LINUX_VFS_H - -#include <asm/statfs.h> - -#endif diff --git a/i386/i386at/gpl/linux/include/linux/vm86.h b/i386/i386at/gpl/linux/include/linux/vm86.h deleted file mode 100644 index ceb10358..00000000 --- a/i386/i386at/gpl/linux/include/linux/vm86.h +++ /dev/null @@ -1,109 +0,0 @@ -#ifndef _LINUX_VM86_H -#define _LINUX_VM86_H - -/* - * I'm guessing at the VIF/VIP flag usage, but hope that this is how - * the Pentium uses them. Linux will return from vm86 mode when both - * VIF and VIP is set. - * - * On a Pentium, we could probably optimize the virtual flags directly - * in the eflags register instead of doing it "by hand" in vflags... - * - * Linus - */ - -#define TF_MASK 0x00000100 -#define IF_MASK 0x00000200 -#define IOPL_MASK 0x00003000 -#define NT_MASK 0x00004000 -#define VM_MASK 0x00020000 -#define AC_MASK 0x00040000 -#define VIF_MASK 0x00080000 /* virtual interrupt flag */ -#define VIP_MASK 0x00100000 /* virtual interrupt pending */ -#define ID_MASK 0x00200000 - -#define BIOSSEG 0x0f000 - -#define CPU_086 0 -#define CPU_186 1 -#define CPU_286 2 -#define CPU_386 3 -#define CPU_486 4 -#define CPU_586 5 - -/* - * Return values for the 'vm86()' system call - */ -#define VM86_TYPE(retval) ((retval) & 0xff) -#define VM86_ARG(retval) ((retval) >> 8) - -#define VM86_SIGNAL 0 /* return due to signal */ -#define VM86_UNKNOWN 1 /* unhandled GP fault - IO-instruction or similar */ -#define VM86_INTx 2 /* int3/int x instruction (ARG = x) */ -#define VM86_STI 3 /* sti/popf/iret instruction enabled virtual interrupts */ - -/* - * This is the stack-layout when we have done a "SAVE_ALL" from vm86 - * mode - the main change is that the old segment descriptors aren't - * useful any more and are forced to be zero by the kernel (and the - * hardware when a trap occurs), and the real segment descriptors are - * at the end of the structure. Look at ptrace.h to see the "normal" - * setup. - */ - -struct vm86_regs { -/* - * normal regs, with special meaning for the segment descriptors.. - */ - long ebx; - long ecx; - long edx; - long esi; - long edi; - long ebp; - long eax; - long __null_ds; - long __null_es; - long __null_fs; - long __null_gs; - long orig_eax; - long eip; - unsigned short cs, __csh; - long eflags; - long esp; - unsigned short ss, __ssh; -/* - * these are specific to v86 mode: - */ - unsigned short es, __esh; - unsigned short ds, __dsh; - unsigned short fs, __fsh; - unsigned short gs, __gsh; -}; - -struct revectored_struct { - unsigned long __map[8]; /* 256 bits */ -}; - -struct vm86_struct { - struct vm86_regs regs; - unsigned long flags; - unsigned long screen_bitmap; - unsigned long cpu_type; - struct revectored_struct int_revectored; - struct revectored_struct int21_revectored; -}; - -/* - * flags masks - */ -#define VM86_SCREEN_BITMAP 0x0001 - -#ifdef __KERNEL__ - -void handle_vm86_fault(struct vm86_regs *, long); -void handle_vm86_debug(struct vm86_regs *, long); - -#endif - -#endif diff --git a/i386/i386at/gpl/linux/include/linux/wait.h b/i386/i386at/gpl/linux/include/linux/wait.h deleted file mode 100644 index 90ffe7b3..00000000 --- a/i386/i386at/gpl/linux/include/linux/wait.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef _LINUX_WAIT_H -#define _LINUX_WAIT_H - -#define WNOHANG 0x00000001 -#define WUNTRACED 0x00000002 - -#define __WCLONE 0x80000000 - -#ifdef __KERNEL__ - -struct wait_queue { - struct task_struct * task; - struct wait_queue * next; -}; - -struct semaphore { - int count; - struct wait_queue * wait; -}; - -#define MUTEX ((struct semaphore) { 1, NULL }) -#define MUTEX_LOCKED ((struct semaphore) { 0, NULL }) - -struct select_table_entry { - struct wait_queue wait; - struct wait_queue ** wait_address; -}; - -typedef struct select_table_struct { - int nr; - struct select_table_entry * entry; -} select_table; - -#define __MAX_SELECT_TABLE_ENTRIES (4096 / sizeof (struct select_table_entry)) - -#endif /* __KERNEL__ */ - -#endif diff --git a/i386/i386at/gpl/linux/include/net/af_unix.h b/i386/i386at/gpl/linux/include/net/af_unix.h deleted file mode 100644 index dc4a48d6..00000000 --- a/i386/i386at/gpl/linux/include/net/af_unix.h +++ /dev/null @@ -1,4 +0,0 @@ -extern void unix_proto_init(struct net_proto *pro); - -typedef struct sock unix_socket; - diff --git a/i386/i386at/gpl/linux/include/net/arp.h b/i386/i386at/gpl/linux/include/net/arp.h deleted file mode 100644 index db7a29c3..00000000 --- a/i386/i386at/gpl/linux/include/net/arp.h +++ /dev/null @@ -1,17 +0,0 @@ -/* linux/net/inet/arp.h */ -#ifndef _ARP_H -#define _ARP_H - -extern void arp_init(void); -extern int arp_rcv(struct sk_buff *skb, struct device *dev, - struct packet_type *pt); -extern int arp_query(unsigned char *haddr, u32 paddr, struct device *dev); -extern int arp_find(unsigned char *haddr, u32 paddr, - struct device *dev, u32 saddr, struct sk_buff *skb); -extern int arp_ioctl(unsigned int cmd, void *arg); -extern void arp_send(int type, int ptype, u32 dest_ip, - struct device *dev, u32 src_ip, - unsigned char *dest_hw, unsigned char *src_hw, unsigned char *th); -extern int arp_bind_cache(struct hh_cache ** hhp, struct device *dev, unsigned short type, __u32 daddr); -extern int arp_update_cache(struct hh_cache * hh); -#endif /* _ARP_H */ diff --git a/i386/i386at/gpl/linux/include/net/atalkcall.h b/i386/i386at/gpl/linux/include/net/atalkcall.h deleted file mode 100644 index 726e33cd..00000000 --- a/i386/i386at/gpl/linux/include/net/atalkcall.h +++ /dev/null @@ -1,2 +0,0 @@ -/* Separate to keep compilation of protocols.c simpler */ -extern void atalk_proto_init(struct net_proto *pro); diff --git a/i386/i386at/gpl/linux/include/net/ax25.h b/i386/i386at/gpl/linux/include/net/ax25.h deleted file mode 100644 index 45967cb1..00000000 --- a/i386/i386at/gpl/linux/include/net/ax25.h +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Declarations of AX.25 type objects. - * - * Alan Cox (GW4PTS) 10/11/93 - */ - -#ifndef _AX25_H -#define _AX25_H -#include <linux/ax25.h> - -#define PR_SLOWHZ 10 /* Run timing at 1/10 second - gives us better resolution for 56kbit links */ - -#define AX25_T1CLAMPLO (1 * PR_SLOWHZ) /* If defined, clamp at 1 second **/ -#define AX25_T1CLAMPHI (30 * PR_SLOWHZ) /* If defined, clamp at 30 seconds **/ - -#define AX25_BROKEN_NETMAC - -#define AX25_BPQ_HEADER_LEN 16 -#define AX25_KISS_HEADER_LEN 1 - -#define AX25_HEADER_LEN 17 -#define AX25_ADDR_LEN 7 -#define AX25_DIGI_HEADER_LEN (AX25_MAX_DIGIS * AX25_ADDR_LEN) -#define AX25_MAX_HEADER_LEN (AX25_HEADER_LEN + AX25_DIGI_HEADER_LEN) - -#define AX25_P_IP 0xCC -#define AX25_P_ARP 0xCD -#define AX25_P_TEXT 0xF0 -#define AX25_P_NETROM 0xCF -#define AX25_P_SEGMENT 0x08 - -#define SEG_REM 0x7F -#define SEG_FIRST 0x80 - -#define LAPB_UI 0x03 -#define LAPB_C 0x80 -#define LAPB_E 0x01 - -#define SSSID_SPARE 0x60 /* Unused bits in SSID for standard AX.25 */ -#define ESSID_SPARE 0x20 /* Unused bits in SSID for extended AX.25 */ -#define DAMA_FLAG 0x40 /* Well, it is *NOT* unused! (dl1bke 951121 */ - -#define AX25_REPEATED 0x80 - -#define ACK_PENDING_CONDITION 0x01 -#define REJECT_CONDITION 0x02 -#define PEER_RX_BUSY_CONDITION 0x04 -#define OWN_RX_BUSY_CONDITION 0x08 - -#ifndef _LINUX_NETDEVICE_H -#include <linux/netdevice.h> -#endif - -/* - * These headers are taken from the KA9Q package by Phil Karn. These specific - * files have been placed under the GPL (not the whole package) by Phil. - * - * - * Copyright 1991 Phil Karn, KA9Q - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 dated June, 1991. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave., Cambridge, MA 02139, USA. - */ - -/* Upper sub-layer (LAPB) definitions */ - -/* Control field templates */ -#define I 0x00 /* Information frames */ -#define S 0x01 /* Supervisory frames */ -#define RR 0x01 /* Receiver ready */ -#define RNR 0x05 /* Receiver not ready */ -#define REJ 0x09 /* Reject */ -#define U 0x03 /* Unnumbered frames */ -#define SABM 0x2f /* Set Asynchronous Balanced Mode */ -#define SABME 0x6f /* Set Asynchronous Balanced Mode Extended */ -#define DISC 0x43 /* Disconnect */ -#define DM 0x0f /* Disconnected mode */ -#define UA 0x63 /* Unnumbered acknowledge */ -#define FRMR 0x87 /* Frame reject */ -#define UI 0x03 /* Unnumbered information */ -#define PF 0x10 /* Poll/final bit for standard AX.25 */ -#define EPF 0x01 /* Poll/final bit for extended AX.25 */ - -#define ILLEGAL 0x100 /* Impossible to be a real frame type */ - -#define POLLOFF 0 -#define POLLON 1 - -/* AX25 L2 C-bit */ - -#define C_COMMAND 1 /* C_ otherwise it clashes with the de600 defines (sigh)) */ -#define C_RESPONSE 2 - -/* Define Link State constants. */ - -#define AX25_STATE_0 0 -#define AX25_STATE_1 1 -#define AX25_STATE_2 2 -#define AX25_STATE_3 3 -#define AX25_STATE_4 4 - -#define MODULUS 8 /* Standard AX.25 modulus */ -#define EMODULUS 128 /* Extended AX.25 modulus */ - -#define AX25_DEF_IPDEFMODE 'D' -#define AX25_DEF_AXDEFMODE 8 -#define AX25_DEF_NETROM 1 -#define AX25_DEF_TEXT 1 -#define AX25_DEF_BACKOFF 'E' -#define AX25_DEF_CONMODE 1 -#define AX25_DEF_WINDOW 2 -#define AX25_DEF_EWINDOW 32 -#define AX25_DEF_T1 10 -#define AX25_DEF_T2 3 -#define AX25_DEF_T3 300 -#define AX25_DEF_N2 10 -#define AX25_DEF_DIGI (AX25_DIGI_INBAND|AX25_DIGI_XBAND) - -typedef struct ax25_uid_assoc { - struct ax25_uid_assoc *next; - uid_t uid; - ax25_address call; -} ax25_uid_assoc; - -typedef struct { - ax25_address calls[AX25_MAX_DIGIS]; - unsigned char repeated[AX25_MAX_DIGIS]; - unsigned char ndigi; - char lastrepeat; -} ax25_digi; - -typedef struct ax25_cb { - struct ax25_cb *next; - ax25_address source_addr, dest_addr; - struct device *device; - unsigned char dama_slave; /* dl1bke 951121 */ - unsigned char state, modulus, hdrincl; - unsigned short vs, vr, va; - unsigned char condition, backoff; - unsigned char n2, n2count; - unsigned short t1, t2, t3, rtt; - unsigned short t1timer, t2timer, t3timer; - unsigned short fragno, fraglen; - ax25_digi *digipeat; - struct sk_buff_head write_queue; - struct sk_buff_head reseq_queue; - struct sk_buff_head ack_queue; - struct sk_buff_head frag_queue; - unsigned char window; - struct timer_list timer; - struct sock *sk; /* Backlink to socket */ -} ax25_cb; - -/* af_ax25.c */ -extern ax25_address null_ax25_address; -extern char *ax2asc(ax25_address *); -extern int ax25cmp(ax25_address *, ax25_address *); -extern int ax25_send_frame(struct sk_buff *, ax25_address *, ax25_address *, ax25_digi *, struct device *); -extern void ax25_destroy_socket(ax25_cb *); -extern struct device *ax25rtr_get_dev(ax25_address *); -extern int ax25_encapsulate(struct sk_buff *, struct device *, unsigned short, - void *, void *, unsigned int); -extern int ax25_rebuild_header(unsigned char *, struct device *, unsigned long, struct sk_buff *); -extern ax25_uid_assoc *ax25_uid_list; -extern int ax25_uid_policy; -extern ax25_address *ax25_findbyuid(uid_t); -extern void ax25_queue_xmit(struct sk_buff *, struct device *, int); -extern int ax25_dev_is_dama_slave(struct device *); /* dl1bke 951121 */ - -#include <net/ax25call.h> - -/* ax25_in.c */ -extern int ax25_process_rx_frame(ax25_cb *, struct sk_buff *, int, int); - -/* ax25_out.c */ -extern void ax25_output(ax25_cb *, struct sk_buff *); -extern void ax25_kick(ax25_cb *); -extern void ax25_transmit_buffer(ax25_cb *, struct sk_buff *, int); -extern void ax25_nr_error_recovery(ax25_cb *); -extern void ax25_establish_data_link(ax25_cb *); -extern void ax25_transmit_enquiry(ax25_cb *); -extern void ax25_enquiry_response(ax25_cb *); -extern void ax25_timeout_response(ax25_cb *); -extern void ax25_check_iframes_acked(ax25_cb *, unsigned short); -extern void ax25_check_need_response(ax25_cb *, int, int); -extern void dama_enquiry_response(ax25_cb *); /* dl1bke 960114 */ -extern void dama_check_need_response(ax25_cb *, int, int); /* dl1bke 960114 */ -extern void dama_establish_data_link(ax25_cb *); - -/* ax25_route.c */ -extern void ax25_rt_rx_frame(ax25_address *, struct device *, ax25_digi *); -extern int ax25_rt_get_info(char *, char **, off_t, int, int); -extern int ax25_cs_get_info(char *, char **, off_t, int, int); -extern int ax25_rt_autobind(ax25_cb *, ax25_address *); -extern void ax25_rt_build_path(ax25_cb *, ax25_address *); -extern void ax25_dg_build_path(struct sk_buff *, ax25_address *, struct device *); -extern void ax25_rt_device_down(struct device *); -extern int ax25_rt_ioctl(unsigned int, void *); -extern void ax25_ip_mode_set(ax25_address *, struct device *, char); -extern char ax25_ip_mode_get(ax25_address *, struct device *); -extern unsigned short ax25_dev_get_value(struct device *, int); -extern void ax25_dev_device_up(struct device *); -extern void ax25_dev_device_down(struct device *); -extern int ax25_dev_ioctl(unsigned int, void *); -extern int ax25_bpq_get_info(char *, char **, off_t, int, int); -extern ax25_address *ax25_bpq_get_addr(struct device *); -extern int ax25_bpq_ioctl(unsigned int, void *); - -/* ax25_subr.c */ -extern void ax25_clear_queues(ax25_cb *); -extern void ax25_frames_acked(ax25_cb *, unsigned short); -extern void ax25_requeue_frames(ax25_cb *); -extern int ax25_validate_nr(ax25_cb *, unsigned short); -extern int ax25_decode(ax25_cb *, struct sk_buff *, int *, int *, int *); -extern void ax25_send_control(ax25_cb *, int, int, int); -extern unsigned short ax25_calculate_t1(ax25_cb *); -extern void ax25_calculate_rtt(ax25_cb *); -extern unsigned char *ax25_parse_addr(unsigned char *, int, ax25_address *, - ax25_address *, ax25_digi *, int *, int *); /* dl1bke 951121 */ -extern int build_ax25_addr(unsigned char *, ax25_address *, ax25_address *, - ax25_digi *, int, int); -extern int size_ax25_addr(ax25_digi *); -extern void ax25_digi_invert(ax25_digi *, ax25_digi *); -extern void ax25_return_dm(struct device *, ax25_address *, ax25_address *, ax25_digi *); -extern void ax25_dama_on(ax25_cb *); /* dl1bke 951121 */ -extern void ax25_dama_off(ax25_cb *); /* dl1bke 951121 */ - -/* ax25_timer */ -extern void ax25_set_timer(ax25_cb *); -extern void ax25_t1_timeout(ax25_cb *); - -/* ... */ - -extern ax25_cb * volatile ax25_list; - -#endif diff --git a/i386/i386at/gpl/linux/include/net/ax25call.h b/i386/i386at/gpl/linux/include/net/ax25call.h deleted file mode 100644 index 89569656..00000000 --- a/i386/i386at/gpl/linux/include/net/ax25call.h +++ /dev/null @@ -1,2 +0,0 @@ -/* Seperate to keep compilation of protocols.c simpler */ -extern void ax25_proto_init(struct net_proto *pro); diff --git a/i386/i386at/gpl/linux/include/net/checksum.h b/i386/i386at/gpl/linux/include/net/checksum.h deleted file mode 100644 index aee4fd47..00000000 --- a/i386/i386at/gpl/linux/include/net/checksum.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * INET An implementation of the TCP/IP protocol suite for the LINUX - * operating system. INET is implemented using the BSD Socket - * interface as the means of communication with the user level. - * - * Checksumming functions for IP, TCP, UDP and so on - * - * Authors: Jorge Cwik, <jorge@laser.satlink.net> - * Arnt Gulbrandsen, <agulbra@nvg.unit.no> - * Borrows very liberally from tcp.c and ip.c, see those - * files for more names. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ -#ifndef _CHECKSUM_H -#define _CHECKSUM_H - -#include <asm/byteorder.h> -#include <net/ip.h> -#include <asm/checksum.h> - -#endif diff --git a/i386/i386at/gpl/linux/include/net/datalink.h b/i386/i386at/gpl/linux/include/net/datalink.h deleted file mode 100644 index 44e56990..00000000 --- a/i386/i386at/gpl/linux/include/net/datalink.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef _NET_INET_DATALINK_H_ -#define _NET_INET_DATALINK_H_ - -struct datalink_proto { - unsigned short type_len; - unsigned char type[8]; - const char *string_name; - unsigned short header_length; - int (*rcvfunc)(struct sk_buff *, struct device *, - struct packet_type *); - void (*datalink_header)(struct datalink_proto *, struct sk_buff *, - unsigned char *); - struct datalink_proto *next; -}; - -#endif diff --git a/i386/i386at/gpl/linux/include/net/icmp.h b/i386/i386at/gpl/linux/include/net/icmp.h deleted file mode 100644 index e4ae8213..00000000 --- a/i386/i386at/gpl/linux/include/net/icmp.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * INET An implementation of the TCP/IP protocol suite for the LINUX - * operating system. INET is implemented using the BSD Socket - * interface as the means of communication with the user level. - * - * Definitions for the ICMP module. - * - * Version: @(#)icmp.h 1.0.4 05/13/93 - * - * Authors: Ross Biro, <bir7@leland.Stanford.Edu> - * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ -#ifndef _ICMP_H -#define _ICMP_H - -#include <linux/icmp.h> -#include <linux/skbuff.h> - -#include <net/sock.h> -#include <net/protocol.h> - -extern struct icmp_err icmp_err_convert[]; -extern struct icmp_mib icmp_statistics; - -extern void icmp_send(struct sk_buff *skb_in, int type, int code, - unsigned long info, struct device *dev); -extern int icmp_rcv(struct sk_buff *skb1, struct device *dev, - struct options *opt, __u32 daddr, - unsigned short len, __u32 saddr, - int redo, struct inet_protocol *protocol); -extern int icmp_ioctl(struct sock *sk, int cmd, - unsigned long arg); -extern void icmp_init(struct proto_ops *ops); - -#endif /* _ICMP_H */ diff --git a/i386/i386at/gpl/linux/include/net/ip.h b/i386/i386at/gpl/linux/include/net/ip.h deleted file mode 100644 index c7bd9987..00000000 --- a/i386/i386at/gpl/linux/include/net/ip.h +++ /dev/null @@ -1,154 +0,0 @@ -/* - * INET An implementation of the TCP/IP protocol suite for the LINUX - * operating system. INET is implemented using the BSD Socket - * interface as the means of communication with the user level. - * - * Definitions for the IP module. - * - * Version: @(#)ip.h 1.0.2 05/07/93 - * - * Authors: Ross Biro, <bir7@leland.Stanford.Edu> - * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> - * Alan Cox, <gw4pts@gw4pts.ampr.org> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ -#ifndef _IP_H -#define _IP_H - - -#include <linux/config.h> -#include <linux/types.h> -#include <linux/socket.h> -#include <linux/ip.h> -#include <linux/netdevice.h> -#include <net/route.h> - -#ifndef _SNMP_H -#include <net/snmp.h> -#endif - -#include <net/sock.h> /* struct sock */ - -/* IP flags. */ -#define IP_CE 0x8000 /* Flag: "Congestion" */ -#define IP_DF 0x4000 /* Flag: "Don't Fragment" */ -#define IP_MF 0x2000 /* Flag: "More Fragments" */ -#define IP_OFFSET 0x1FFF /* "Fragment Offset" part */ - -#define IP_FRAG_TIME (30 * HZ) /* fragment lifetime */ - -#ifdef CONFIG_IP_MULTICAST -extern void ip_mc_dropsocket(struct sock *); -extern void ip_mc_dropdevice(struct device *dev); -extern int ip_mc_procinfo(char *, char **, off_t, int, int); -#endif - -#include <net/ip_forward.h> - -/* Describe an IP fragment. */ -struct ipfrag -{ - int offset; /* offset of fragment in IP datagram */ - int end; /* last byte of data in datagram */ - int len; /* length of this fragment */ - struct sk_buff *skb; /* complete received fragment */ - unsigned char *ptr; /* pointer into real fragment data */ - struct ipfrag *next; /* linked list pointers */ - struct ipfrag *prev; -}; - -/* - * Describe an entry in the "incomplete datagrams" queue. - */ - -struct ipq -{ - unsigned char *mac; /* pointer to MAC header */ - struct iphdr *iph; /* pointer to IP header */ - int len; /* total length of original datagram */ - short ihlen; /* length of the IP header */ - short maclen; /* length of the MAC header */ - struct timer_list timer; /* when will this queue expire? */ - struct ipfrag *fragments; /* linked list of received fragments */ - struct ipq *next; /* linked list pointers */ - struct ipq *prev; - struct device *dev; /* Device - for icmp replies */ -}; - -/* - * Functions provided by ip.c - */ - -extern void ip_print(const struct iphdr *ip); -extern int ip_ioctl(struct sock *sk, int cmd, unsigned long arg); -extern void ip_route_check(__u32 daddr); -extern int ip_send(struct rtable *rt, struct sk_buff *skb, __u32 daddr, int len, struct device *dev, __u32 saddr); -extern int ip_build_header(struct sk_buff *skb, - __u32 saddr, - __u32 daddr, - struct device **dev, int type, - struct options *opt, int len, - int tos,int ttl,struct rtable **rp); -extern int ip_rcv(struct sk_buff *skb, struct device *dev, - struct packet_type *pt); -extern int ip_options_echo(struct options * dopt, struct options * sopt, - __u32 daddr, __u32 saddr, - struct sk_buff * skb); -extern int ip_options_compile(struct options * opt, struct sk_buff * skb); -extern void ip_send_check(struct iphdr *ip); -extern int ip_id_count; -extern void ip_queue_xmit(struct sock *sk, - struct device *dev, struct sk_buff *skb, - int free); -extern void ip_init(void); -extern int ip_build_xmit(struct sock *sk, - void getfrag (const void *, - __u32, - char *, - unsigned int, - unsigned int), - const void *frag, - unsigned short int length, - __u32 daddr, - __u32 saddr, - struct options * opt, - int flags, - int type, - int noblock); - -extern struct ip_mib ip_statistics; - -/* - * Functions provided by ip_fragment.o - */ - -struct sk_buff *ip_defrag(struct iphdr *iph, struct sk_buff *skb, struct device *dev); -void ip_fragment(struct sock *sk, struct sk_buff *skb, struct device *dev, int is_frag); - -/* - * Functions provided by ip_forward.c - */ - -extern int ip_forward(struct sk_buff *skb, struct device *dev, int is_frag, __u32 target_addr); - -/* - * Functions provided by ip_options.c - */ - -extern void ip_options_build(struct sk_buff *skb, struct options *opt, __u32 daddr, __u32 saddr, int is_frag); -extern int ip_options_echo(struct options *dopt, struct options *sopt, __u32 daddr, __u32 saddr, struct sk_buff *skb); -extern void ip_options_fragment(struct sk_buff *skb); -extern int ip_options_compile(struct options *opt, struct sk_buff *skb); - -/* - * Functions provided by ip_sockglue.c - */ - -extern int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int optlen); -extern int ip_getsockopt(struct sock *sk, int level, int optname, char *optval, int *optlen); - -#endif /* _IP_H */ diff --git a/i386/i386at/gpl/linux/include/net/ip_alias.h b/i386/i386at/gpl/linux/include/net/ip_alias.h deleted file mode 100644 index 683a0427..00000000 --- a/i386/i386at/gpl/linux/include/net/ip_alias.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * IP_ALIAS (AF_INET) aliasing definitions. - * - * - * Version: @(#)ip_alias.h 0.43 12/20/95 - * - * Author: Juan Jose Ciarlante, <jjciarla@raiz.uncu.edu.ar> - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - */ - -#ifndef _IP_ALIAS_H -#define _IP_ALIAS_H - -extern int ip_alias_init(void); -extern int ip_alias_done(void); - -#endif /* _IP_ALIAS_H */ diff --git a/i386/i386at/gpl/linux/include/net/ip_forward.h b/i386/i386at/gpl/linux/include/net/ip_forward.h deleted file mode 100644 index b8596500..00000000 --- a/i386/i386at/gpl/linux/include/net/ip_forward.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef __NET_IP_FORWARD_H -#define __NET_IP_FORWARD_H - -#define IPFWD_FRAGMENT 1 -#define IPFWD_LASTFRAG 2 -#define IPFWD_MASQUERADED 4 -#define IPFWD_MULTICASTING 8 -#define IPFWD_MULTITUNNEL 16 - -#endif diff --git a/i386/i386at/gpl/linux/include/net/ipip.h b/i386/i386at/gpl/linux/include/net/ipip.h deleted file mode 100644 index bba1492e..00000000 --- a/i386/i386at/gpl/linux/include/net/ipip.h +++ /dev/null @@ -1,4 +0,0 @@ -extern int ipip_rcv(struct sk_buff *skb, struct device *dev, struct options *opt, - __u32 daddr, unsigned short len, __u32 saddr, - int redo, struct inet_protocol *protocol); - diff --git a/i386/i386at/gpl/linux/include/net/ipx.h b/i386/i386at/gpl/linux/include/net/ipx.h deleted file mode 100644 index 96c62405..00000000 --- a/i386/i386at/gpl/linux/include/net/ipx.h +++ /dev/null @@ -1,85 +0,0 @@ - -/* - * The following information is in its entirety obtained from: - * - * Novell 'IPX Router Specification' Version 1.10 - * Part No. 107-000029-001 - * - * Which is available from ftp.novell.com - */ - -#ifndef _NET_INET_IPX_H_ -#define _NET_INET_IPX_H_ - -#include <linux/skbuff.h> -#include <net/datalink.h> -#include <linux/ipx.h> - -typedef struct -{ - unsigned long net; - unsigned char node[IPX_NODE_LEN]; - unsigned short sock; -} ipx_address; - -#define ipx_broadcast_node "\377\377\377\377\377\377" -#define ipx_this_node "\0\0\0\0\0\0" - -typedef struct ipx_packet -{ - unsigned short ipx_checksum; -#define IPX_NO_CHECKSUM 0xFFFF - unsigned short ipx_pktsize; - unsigned char ipx_tctrl; - unsigned char ipx_type; -#define IPX_TYPE_UNKNOWN 0x00 -#define IPX_TYPE_RIP 0x01 /* may also be 0 */ -#define IPX_TYPE_SAP 0x04 /* may also be 0 */ -#define IPX_TYPE_SPX 0x05 /* Not yet implemented */ -#define IPX_TYPE_NCP 0x11 /* $lots for docs on this (SPIT) */ -#define IPX_TYPE_PPROP 0x14 /* complicated flood fill brdcast [Not supported] */ - ipx_address ipx_dest __attribute__ ((packed)); - ipx_address ipx_source __attribute__ ((packed)); -} ipx_packet; - - -typedef struct sock ipx_socket; - -#include <net/ipxcall.h> -extern int ipx_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt); -extern void ipxrtr_device_down(struct device *dev); - -typedef struct ipx_interface { - /* IPX address */ - unsigned long if_netnum; - unsigned char if_node[IPX_NODE_LEN]; - - /* physical device info */ - struct device *if_dev; - struct datalink_proto *if_dlink; - unsigned short if_dlink_type; - - /* socket support */ - unsigned short if_sknum; - ipx_socket *if_sklist; - - /* administrative overhead */ - int if_ipx_offset; - unsigned char if_internal; - unsigned char if_primary; - - struct ipx_interface *if_next; -} ipx_interface; - -typedef struct ipx_route { - unsigned long ir_net; - ipx_interface *ir_intrfc; - unsigned char ir_routed; - unsigned char ir_router_node[IPX_NODE_LEN]; - struct ipx_route *ir_next; -} ipx_route; - -#define IPX_MIN_EPHEMERAL_SOCKET 0x4000 -#define IPX_MAX_EPHEMERAL_SOCKET 0x7fff - -#endif diff --git a/i386/i386at/gpl/linux/include/net/ipxcall.h b/i386/i386at/gpl/linux/include/net/ipxcall.h deleted file mode 100644 index eb5bd2bd..00000000 --- a/i386/i386at/gpl/linux/include/net/ipxcall.h +++ /dev/null @@ -1,2 +0,0 @@ -/* Separate to keep compilation of protocols.c simpler */ -extern void ipx_proto_init(struct net_proto *pro); diff --git a/i386/i386at/gpl/linux/include/net/netlink.h b/i386/i386at/gpl/linux/include/net/netlink.h deleted file mode 100644 index e32af15b..00000000 --- a/i386/i386at/gpl/linux/include/net/netlink.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef __NET_NETLINK_H -#define __NET_NETLINK_H - -#define NET_MAJOR 36 /* Major 18 is reserved for networking */ -#define MAX_LINKS 4 /* 18,0 for route updates, 18,1 for SKIP, 18,2 debug tap 18,3 PPP reserved */ -#define MAX_QBYTES 32768 /* Maximum bytes in the queue */ - -#include <linux/config.h> - -extern int netlink_attach(int unit, int (*function)(struct sk_buff *skb)); -extern int netlink_donothing(struct sk_buff *skb); -extern void netlink_detach(int unit); -extern int netlink_post(int unit, struct sk_buff *skb); -extern int init_netlink(void); - -#define NETLINK_ROUTE 0 /* Routing/device hook */ -#define NETLINK_SKIP 1 /* Reserved for ENskip */ -#define NETLINK_USERSOCK 2 /* Reserved for user mode socket protocols */ -#define NETLINK_FIREWALL 3 /* Firewalling hook */ - -#ifdef CONFIG_RTNETLINK -extern void ip_netlink_msg(unsigned long, __u32, __u32, __u32, short, short, char *); -#else -#define ip_netlink_msg(a,b,c,d,e,f,g) -#endif -#endif diff --git a/i386/i386at/gpl/linux/include/net/netrom.h b/i386/i386at/gpl/linux/include/net/netrom.h deleted file mode 100644 index 5e343bbc..00000000 --- a/i386/i386at/gpl/linux/include/net/netrom.h +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Declarations of NET/ROM type objects. - * - * Jonathan Naylor G4KLX 9/4/95 - */ - -#ifndef _NETROM_H -#define _NETROM_H -#include <linux/netrom.h> - -#define NR_T1CLAMPLO (1 * PR_SLOWHZ) /* If defined, clamp at 1 second **/ -#define NR_T1CLAMPHI (300 * PR_SLOWHZ) /* If defined, clamp at 30 seconds **/ - -#define NR_NETWORK_LEN 15 -#define NR_TRANSPORT_LEN 5 - -#define NR_PROTO_IP 0x0C - -#define NR_PROTOEXT 0x00 -#define NR_CONNREQ 0x01 -#define NR_CONNACK 0x02 -#define NR_DISCREQ 0x03 -#define NR_DISCACK 0x04 -#define NR_INFO 0x05 -#define NR_INFOACK 0x06 - -#define NR_CHOKE_FLAG 0x80 -#define NR_NAK_FLAG 0x40 -#define NR_MORE_FLAG 0x20 - -/* Define Link State constants. */ - -#define NR_STATE_0 0 -#define NR_STATE_1 1 -#define NR_STATE_2 2 -#define NR_STATE_3 3 - -#define NR_DEFAULT_T1 (120 * PR_SLOWHZ) /* Outstanding frames - 120 seconds */ -#define NR_DEFAULT_T2 (5 * PR_SLOWHZ) /* Response delay - 5 seconds */ -#define NR_DEFAULT_N2 3 /* Number of Retries */ -#define NR_DEFAULT_T4 (180 * PR_SLOWHZ) /* Transport Busy Delay */ -#define NR_DEFAULT_WINDOW 4 /* Default Window Size */ -#define NR_DEFAULT_OBS 6 /* Default Obscolesence Count */ -#define NR_DEFAULT_QUAL 10 /* Default Neighbour Quality */ -#define NR_DEFAULT_TTL 16 /* Default Time To Live */ -#define NR_MODULUS 256 -#define NR_MAX_WINDOW_SIZE 127 /* Maximum Window Allowable */ - -typedef struct { - ax25_address user_addr, source_addr, dest_addr; - struct device *device; - unsigned char my_index, my_id; - unsigned char your_index, your_id; - unsigned char state, condition, bpqext, hdrincl; - unsigned short vs, vr, va, vl; - unsigned char n2, n2count; - unsigned short t1, t2, rtt; - unsigned short t1timer, t2timer, t4timer; - unsigned short fraglen; - struct sk_buff_head ack_queue; - struct sk_buff_head reseq_queue; - struct sk_buff_head frag_queue; - struct sock *sk; /* Backlink to socket */ -} nr_cb; - -struct nr_route { - unsigned char quality; - unsigned char obs_count; - unsigned short neighbour; -}; - -struct nr_node { - struct nr_node *next; - ax25_address callsign; - char mnemonic[7]; - unsigned char which; - unsigned char count; - struct nr_route routes[3]; -}; - -struct nr_neigh { - struct nr_neigh *next; - ax25_address callsign; - ax25_digi *digipeat; - struct device *dev; - unsigned char quality; - unsigned char locked; - unsigned short count; - unsigned short number; -}; - -/* af_netrom.c */ -extern struct nr_parms_struct nr_default; -extern int nr_rx_frame(struct sk_buff *, struct device *); -extern void nr_destroy_socket(struct sock *); - -/* nr_dev.c */ -extern int nr_rx_ip(struct sk_buff *, struct device *); -extern int nr_init(struct device *); - -#include <net/nrcall.h> - -/* nr_in.c */ -extern int nr_process_rx_frame(struct sock *, struct sk_buff *); - -/* nr_out.c */ -extern void nr_output(struct sock *, struct sk_buff *); -extern void nr_send_nak_frame(struct sock *); -extern void nr_kick(struct sock *); -extern void nr_transmit_buffer(struct sock *, struct sk_buff *); -extern void nr_establish_data_link(struct sock *); -extern void nr_enquiry_response(struct sock *); -extern void nr_check_iframes_acked(struct sock *, unsigned short); - -/* nr_route.c */ -extern void nr_rt_device_down(struct device *); -extern struct device *nr_dev_first(void); -extern struct device *nr_dev_get(ax25_address *); -extern int nr_rt_ioctl(unsigned int, void *); -extern void nr_link_failed(ax25_address *, struct device *); -extern int nr_route_frame(struct sk_buff *, ax25_cb *); -extern int nr_nodes_get_info(char *, char **, off_t, int, int); -extern int nr_neigh_get_info(char *, char **, off_t, int, int); - -/* nr_subr.c */ -extern void nr_clear_queues(struct sock *); -extern void nr_frames_acked(struct sock *, unsigned short); -extern void nr_requeue_frames(struct sock *); -extern int nr_validate_nr(struct sock *, unsigned short); -extern int nr_in_rx_window(struct sock *, unsigned short); -extern void nr_write_internal(struct sock *, int); -extern void nr_transmit_dm(struct sk_buff *); -extern unsigned short nr_calculate_t1(struct sock *); -extern void nr_calculate_rtt(struct sock *); - -/* ax25_timer */ -extern void nr_set_timer(struct sock *); - -#endif diff --git a/i386/i386at/gpl/linux/include/net/nrcall.h b/i386/i386at/gpl/linux/include/net/nrcall.h deleted file mode 100644 index f58c2d4f..00000000 --- a/i386/i386at/gpl/linux/include/net/nrcall.h +++ /dev/null @@ -1,2 +0,0 @@ -/* Seperate to keep compilation of protocols.c simpler */ -extern void nr_proto_init(struct net_proto *pro); diff --git a/i386/i386at/gpl/linux/include/net/p8022.h b/i386/i386at/gpl/linux/include/net/p8022.h deleted file mode 100644 index 52c676be..00000000 --- a/i386/i386at/gpl/linux/include/net/p8022.h +++ /dev/null @@ -1,2 +0,0 @@ -struct datalink_proto *register_8022_client(unsigned char type, int (*rcvfunc)(struct sk_buff *, struct device *, struct packet_type *)); - diff --git a/i386/i386at/gpl/linux/include/net/p8022call.h b/i386/i386at/gpl/linux/include/net/p8022call.h deleted file mode 100644 index 14f0c2ce..00000000 --- a/i386/i386at/gpl/linux/include/net/p8022call.h +++ /dev/null @@ -1,2 +0,0 @@ -/* Separate to keep compilation of Space.c simpler */ -extern void p8022_proto_init(struct net_proto *); diff --git a/i386/i386at/gpl/linux/include/net/protocol.h b/i386/i386at/gpl/linux/include/net/protocol.h deleted file mode 100644 index ae328b69..00000000 --- a/i386/i386at/gpl/linux/include/net/protocol.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * INET An implementation of the TCP/IP protocol suite for the LINUX - * operating system. INET is implemented using the BSD Socket - * interface as the means of communication with the user level. - * - * Definitions for the protocol dispatcher. - * - * Version: @(#)protocol.h 1.0.2 05/07/93 - * - * Author: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * Changes: - * Alan Cox : Added a name field and a frag handler - * field for later. - * Alan Cox : Cleaned up, and sorted types. - */ - -#ifndef _PROTOCOL_H -#define _PROTOCOL_H - -#define MAX_INET_PROTOS 32 /* Must be a power of 2 */ - - -/* This is used to register protocols. */ -struct inet_protocol { - int (*handler)(struct sk_buff *skb, struct device *dev, - struct options *opt, __u32 daddr, - unsigned short len, __u32 saddr, - int redo, struct inet_protocol *protocol); - void (*err_handler)(int type, int code, unsigned char *buff, - __u32 daddr, - __u32 saddr, - struct inet_protocol *protocol); - struct inet_protocol *next; - unsigned char protocol; - unsigned char copy:1; - void *data; - const char *name; -}; - - -extern struct inet_protocol *inet_protocol_base; -extern struct inet_protocol *inet_protos[MAX_INET_PROTOS]; - - -extern void inet_add_protocol(struct inet_protocol *prot); -extern int inet_del_protocol(struct inet_protocol *prot); - - -#endif /* _PROTOCOL_H */ diff --git a/i386/i386at/gpl/linux/include/net/psnap.h b/i386/i386at/gpl/linux/include/net/psnap.h deleted file mode 100644 index b69859db..00000000 --- a/i386/i386at/gpl/linux/include/net/psnap.h +++ /dev/null @@ -1,2 +0,0 @@ -struct datalink_proto *register_snap_client(unsigned char *desc, int (*rcvfunc)(struct sk_buff *, struct device *, struct packet_type *)); - diff --git a/i386/i386at/gpl/linux/include/net/psnapcall.h b/i386/i386at/gpl/linux/include/net/psnapcall.h deleted file mode 100644 index 9da5763c..00000000 --- a/i386/i386at/gpl/linux/include/net/psnapcall.h +++ /dev/null @@ -1,2 +0,0 @@ -/* Separate to keep compilation of Space.c simpler */ -extern void snap_proto_init(struct net_proto *); diff --git a/i386/i386at/gpl/linux/include/net/rarp.h b/i386/i386at/gpl/linux/include/net/rarp.h deleted file mode 100644 index 7bfb08ef..00000000 --- a/i386/i386at/gpl/linux/include/net/rarp.h +++ /dev/null @@ -1,12 +0,0 @@ -/* linux/net/inet/rarp.h */ -#ifndef _RARP_H -#define _RARP_H - -extern int rarp_ioctl(unsigned int cmd, void *arg); -extern int rarp_get_info(char *buffer, - char **start, - off_t offset, - int length, - int dummy); -#endif /* _RARP_H */ - diff --git a/i386/i386at/gpl/linux/include/net/raw.h b/i386/i386at/gpl/linux/include/net/raw.h deleted file mode 100644 index 4b424879..00000000 --- a/i386/i386at/gpl/linux/include/net/raw.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * INET An implementation of the TCP/IP protocol suite for the LINUX - * operating system. INET is implemented using the BSD Socket - * interface as the means of communication with the user level. - * - * Definitions for the RAW-IP module. - * - * Version: @(#)raw.h 1.0.2 05/07/93 - * - * Author: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ -#ifndef _RAW_H -#define _RAW_H - - -extern struct proto raw_prot; - - -extern void raw_err(int type, int code, unsigned char *header, __u32 daddr, - __u32 saddr, struct inet_protocol *protocol); -extern int raw_recvfrom(struct sock *sk, unsigned char *to, - int len, int noblock, unsigned flags, - struct sockaddr_in *sin, int *addr_len); -extern int raw_read(struct sock *sk, unsigned char *buff, - int len, int noblock, unsigned flags); -extern int raw_rcv(struct sock *, struct sk_buff *, struct device *, - __u32, __u32); - -#endif /* _RAW_H */ diff --git a/i386/i386at/gpl/linux/include/net/route.h b/i386/i386at/gpl/linux/include/net/route.h deleted file mode 100644 index 8ce67383..00000000 --- a/i386/i386at/gpl/linux/include/net/route.h +++ /dev/null @@ -1,280 +0,0 @@ -/* - * INET An implementation of the TCP/IP protocol suite for the LINUX - * operating system. INET is implemented using the BSD Socket - * interface as the means of communication with the user level. - * - * Definitions for the IP router. - * - * Version: @(#)route.h 1.0.4 05/27/93 - * - * Authors: Ross Biro, <bir7@leland.Stanford.Edu> - * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> - * Fixes: - * Alan Cox : Reformatted. Added ip_rt_local() - * Alan Cox : Support for TCP parameters. - * Alexey Kuznetsov: Major changes for new routing code. - * - * FIXME: - * Modules stuff is broken at the moment. - * Make atomic ops more generic and hide them in asm/... - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ -#ifndef _ROUTE_H -#define _ROUTE_H - -#include <linux/config.h> - -/* - * 0 - no debugging messages - * 1 - rare events and bugs situations (default) - * 2 - trace mode. - */ -#define RT_CACHE_DEBUG 1 - -#define RT_HASH_DIVISOR 256 -#define RT_CACHE_SIZE_MAX 256 - -#define RTZ_HASH_DIVISOR 256 - -#if RT_CACHE_DEBUG >= 2 -#define RTZ_HASHING_LIMIT 0 -#else -#define RTZ_HASHING_LIMIT 16 -#endif - -/* - * Maximal time to live for unused entry. - */ -#define RT_CACHE_TIMEOUT (HZ*300) - -/* - * Prevents LRU trashing, entries considered equivalent, - * if the difference between last use times is less then this number. - */ -#define RT_CACHE_BUBBLE_THRESHOULD (HZ*5) - -#include <linux/route.h> - -#ifdef __KERNEL__ -#define RTF_LOCAL 0x8000 -#endif - -/* - * Semaphores. - */ -#if defined(__alpha__) - -static __inline__ void ATOMIC_INCR(unsigned int * addr) -{ - unsigned tmp; - - __asm__ __volatile__( - "1:\n\ - ldl_l %1,%2\n\ - addl %1,1,%1\n\ - stl_c %1,%0\n\ - beq %1,1b\n" - : "m=" (*addr), "r=&" (tmp) - : "m"(*addr)); -} - -static __inline__ void ATOMIC_DECR(unsigned int * addr) -{ - unsigned tmp; - - __asm__ __volatile__( - "1:\n\ - ldl_l %1,%2\n\ - subl %1,1,%1\n\ - stl_c %1,%0\n\ - beq %1,1b\n" - : "m=" (*addr), "r=&" (tmp) - : "m"(*addr)); -} - -static __inline__ int ATOMIC_DECR_AND_CHECK (unsigned int * addr) -{ - unsigned tmp; - int result; - - __asm__ __volatile__( - "1:\n\ - ldl_l %1,%3\n\ - subl %1,1,%1\n\ - mov %1,%2\n\ - stl_c %1,%0\n\ - beq %1,1b\n" - : "m=" (*addr), "r=&" (tmp), "r=&"(result) - : "m"(*addr)); - return result; -} - -#elif defined(__i386__) -#include <asm/bitops.h> - -extern __inline__ void ATOMIC_INCR(void * addr) -{ - __asm__ __volatile__( - "incl %0" - :"=m" (ADDR)); -} - -extern __inline__ void ATOMIC_DECR(void * addr) -{ - __asm__ __volatile__( - "decl %0" - :"=m" (ADDR)); -} - -/* - * It is DECR that is ATOMIC, not CHECK! - * If you want to do atomic checks, use cli()/sti(). --ANK - */ - -extern __inline__ unsigned long ATOMIC_DECR_AND_CHECK(void * addr) -{ - unsigned long retval; - __asm__ __volatile__( - "decl %0\nmovl %0,%1" - : "=m" (ADDR), "=r"(retval)); - return retval; -} - - -#else - -static __inline__ void ATOMIC_INCR(unsigned int * addr) -{ - (*(__volatile__ unsigned int*)addr)++; -} - -static __inline__ void ATOMIC_DECR(unsigned int * addr) -{ - (*(__volatile__ unsigned int*)addr)--; -} - -static __inline__ int ATOMIC_DECR_AND_CHECK (unsigned int * addr) -{ - ATOMIC_DECR(addr); - return *(volatile unsigned int*)addr; -} - -#endif - - - -struct rtable -{ - struct rtable *rt_next; - __u32 rt_dst; - __u32 rt_src; - __u32 rt_gateway; - unsigned rt_refcnt; - unsigned rt_use; - unsigned long rt_window; - unsigned long rt_lastuse; - struct hh_cache *rt_hh; - struct device *rt_dev; - unsigned short rt_flags; - unsigned short rt_mtu; - unsigned short rt_irtt; - unsigned char rt_tos; -}; - -extern void ip_rt_flush(struct device *dev); -extern void ip_rt_redirect(__u32 src, __u32 dst, __u32 gw, struct device *dev); -extern struct rtable *ip_rt_slow_route(__u32 daddr, int local); -extern int rt_get_info(char * buffer, char **start, off_t offset, int length, int dummy); -extern int rt_cache_get_info(char *buffer, char **start, off_t offset, int length, int dummy); -extern int ip_rt_ioctl(unsigned int cmd, void *arg); -extern int ip_rt_new(struct rtentry *rt); -extern void ip_rt_check_expire(void); -extern void ip_rt_advice(struct rtable **rp, int advice); - -extern void ip_rt_run_bh(void); -extern int ip_rt_lock; -extern unsigned ip_rt_bh_mask; -extern struct rtable *ip_rt_hash_table[RT_HASH_DIVISOR]; - -extern __inline__ void ip_rt_fast_lock(void) -{ - ATOMIC_INCR(&ip_rt_lock); -} - -extern __inline__ void ip_rt_fast_unlock(void) -{ - ATOMIC_DECR(&ip_rt_lock); -} - -extern __inline__ void ip_rt_unlock(void) -{ - if (!ATOMIC_DECR_AND_CHECK(&ip_rt_lock) && ip_rt_bh_mask) - ip_rt_run_bh(); -} - -extern __inline__ unsigned ip_rt_hash_code(__u32 addr) -{ - unsigned tmp = addr + (addr>>16); - return (tmp + (tmp>>8)) & 0xFF; -} - - -extern __inline__ void ip_rt_put(struct rtable * rt) -#ifndef MODULE -{ - if (rt) - ATOMIC_DECR(&rt->rt_refcnt); -} -#else -; -#endif - -#ifdef CONFIG_KERNELD -extern struct rtable * ip_rt_route(__u32 daddr, int local); -#else -extern __inline__ struct rtable * ip_rt_route(__u32 daddr, int local) -#ifndef MODULE -{ - struct rtable * rth; - - ip_rt_fast_lock(); - - for (rth=ip_rt_hash_table[ip_rt_hash_code(daddr)^local]; rth; rth=rth->rt_next) - { - if (rth->rt_dst == daddr) - { - rth->rt_lastuse = jiffies; - ATOMIC_INCR(&rth->rt_use); - ATOMIC_INCR(&rth->rt_refcnt); - ip_rt_unlock(); - return rth; - } - } - return ip_rt_slow_route (daddr, local); -} -#else -; -#endif -#endif - -extern __inline__ struct rtable * ip_check_route(struct rtable ** rp, - __u32 daddr, int local) -{ - struct rtable * rt = *rp; - - if (!rt || rt->rt_dst != daddr || !(rt->rt_flags&RTF_UP) - || ((local==1)^((rt->rt_flags&RTF_LOCAL) != 0))) - { - ip_rt_put(rt); - rt = ip_rt_route(daddr, local); - *rp = rt; - } - return rt; -} - - -#endif /* _ROUTE_H */ diff --git a/i386/i386at/gpl/linux/include/net/slhc.h b/i386/i386at/gpl/linux/include/net/slhc.h deleted file mode 100644 index c7b39db5..00000000 --- a/i386/i386at/gpl/linux/include/net/slhc.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __NET_SLHC_H -#define __NET_SLHC_H - -extern void slhc_install(void); - -#endif diff --git a/i386/i386at/gpl/linux/include/net/snmp.h b/i386/i386at/gpl/linux/include/net/snmp.h deleted file mode 100644 index 552292be..00000000 --- a/i386/i386at/gpl/linux/include/net/snmp.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * - * SNMP MIB entries for the IP subsystem. - * - * Alan Cox <gw4pts@gw4pts.ampr.org> - * - * We don't chose to implement SNMP in the kernel (this would - * be silly as SNMP is a pain in the backside in places). We do - * however need to collect the MIB statistics and export them - * out of /proc (eventually) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - */ - -#ifndef _SNMP_H -#define _SNMP_H - -/* - * We use all unsigned longs. Linux will soon be so reliable that even these - * will rapidly get too small 8-). Seriously consider the IpInReceives count - * on the 20Gb/s + networks people expect in a few years time! - */ - -struct ip_mib -{ - unsigned long IpForwarding; - unsigned long IpDefaultTTL; - unsigned long IpInReceives; - unsigned long IpInHdrErrors; - unsigned long IpInAddrErrors; - unsigned long IpForwDatagrams; - unsigned long IpInUnknownProtos; - unsigned long IpInDiscards; - unsigned long IpInDelivers; - unsigned long IpOutRequests; - unsigned long IpOutDiscards; - unsigned long IpOutNoRoutes; - unsigned long IpReasmTimeout; - unsigned long IpReasmReqds; - unsigned long IpReasmOKs; - unsigned long IpReasmFails; - unsigned long IpFragOKs; - unsigned long IpFragFails; - unsigned long IpFragCreates; -}; - - -struct icmp_mib -{ - unsigned long IcmpInMsgs; - unsigned long IcmpInErrors; - unsigned long IcmpInDestUnreachs; - unsigned long IcmpInTimeExcds; - unsigned long IcmpInParmProbs; - unsigned long IcmpInSrcQuenchs; - unsigned long IcmpInRedirects; - unsigned long IcmpInEchos; - unsigned long IcmpInEchoReps; - unsigned long IcmpInTimestamps; - unsigned long IcmpInTimestampReps; - unsigned long IcmpInAddrMasks; - unsigned long IcmpInAddrMaskReps; - unsigned long IcmpOutMsgs; - unsigned long IcmpOutErrors; - unsigned long IcmpOutDestUnreachs; - unsigned long IcmpOutTimeExcds; - unsigned long IcmpOutParmProbs; - unsigned long IcmpOutSrcQuenchs; - unsigned long IcmpOutRedirects; - unsigned long IcmpOutEchos; - unsigned long IcmpOutEchoReps; - unsigned long IcmpOutTimestamps; - unsigned long IcmpOutTimestampReps; - unsigned long IcmpOutAddrMasks; - unsigned long IcmpOutAddrMaskReps; -}; - -struct tcp_mib -{ - unsigned long TcpRtoAlgorithm; - unsigned long TcpRtoMin; - unsigned long TcpRtoMax; - unsigned long TcpMaxConn; - unsigned long TcpActiveOpens; - unsigned long TcpPassiveOpens; - unsigned long TcpAttemptFails; - unsigned long TcpEstabResets; - unsigned long TcpCurrEstab; - unsigned long TcpInSegs; - unsigned long TcpOutSegs; - unsigned long TcpRetransSegs; -}; - -struct udp_mib -{ - unsigned long UdpInDatagrams; - unsigned long UdpNoPorts; - unsigned long UdpInErrors; - unsigned long UdpOutDatagrams; -}; - - -#endif diff --git a/i386/i386at/gpl/linux/include/net/sock.h b/i386/i386at/gpl/linux/include/net/sock.h deleted file mode 100644 index dc7a4a90..00000000 --- a/i386/i386at/gpl/linux/include/net/sock.h +++ /dev/null @@ -1,486 +0,0 @@ -/* - * INET An implementation of the TCP/IP protocol suite for the LINUX - * operating system. INET is implemented using the BSD Socket - * interface as the means of communication with the user level. - * - * Definitions for the AF_INET socket handler. - * - * Version: @(#)sock.h 1.0.4 05/13/93 - * - * Authors: Ross Biro, <bir7@leland.Stanford.Edu> - * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> - * Corey Minyard <wf-rch!minyard@relay.EU.net> - * Florian La Roche <flla@stud.uni-sb.de> - * - * Fixes: - * Alan Cox : Volatiles in skbuff pointers. See - * skbuff comments. May be overdone, - * better to prove they can be removed - * than the reverse. - * Alan Cox : Added a zapped field for tcp to note - * a socket is reset and must stay shut up - * Alan Cox : New fields for options - * Pauline Middelink : identd support - * Alan Cox : Eliminate low level recv/recvfrom - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ -#ifndef _SOCK_H -#define _SOCK_H - -#include <linux/timer.h> -#include <linux/ip.h> /* struct options */ -#include <linux/in.h> /* struct sockaddr_in */ -#include <linux/tcp.h> /* struct tcphdr */ -#include <linux/config.h> - -#include <linux/netdevice.h> -#include <linux/skbuff.h> /* struct sk_buff */ -#include <net/protocol.h> /* struct inet_protocol */ -#ifdef CONFIG_AX25 -#include <net/ax25.h> -#ifdef CONFIG_NETROM -#include <net/netrom.h> -#endif -#endif -#ifdef CONFIG_IPX -#include <net/ipx.h> -#endif -#ifdef CONFIG_ATALK -#include <linux/atalk.h> -#endif - -#include <linux/igmp.h> - -/* Think big (also on some systems a byte is faster) */ -#define SOCK_ARRAY_SIZE 256 - - -/* - * The AF_UNIX specific socket options - */ - -struct unix_opt -{ - int family; - char * name; - int locks; - struct inode * inode; - struct semaphore readsem; - struct sock * other; -}; - -/* - * IP packet socket options - */ - -struct inet_packet_opt -{ - struct notifier_block notifier; /* Used when bound */ - struct device *bound_dev; - unsigned long dev_stamp; - struct packet_type *prot_hook; - char device_name[15]; -}; - - -/* - * This structure really needs to be cleaned up. - * Most of it is for TCP, and not used by any of - * the other protocols. - */ -struct sock -{ - struct options *opt; - volatile unsigned long wmem_alloc; - volatile unsigned long rmem_alloc; - unsigned long allocation; /* Allocation mode */ - __u32 write_seq; - __u32 sent_seq; - __u32 acked_seq; - __u32 copied_seq; - __u32 rcv_ack_seq; - __u32 window_seq; - __u32 fin_seq; - __u32 urg_seq; - __u32 urg_data; - int users; /* user count */ - /* - * Not all are volatile, but some are, so we - * might as well say they all are. - */ - volatile char dead, - urginline, - intr, - blog, - done, - reuse, - keepopen, - linger, - delay_acks, - destroy, - ack_timed, - no_check, - zapped, /* In ax25 & ipx means not linked */ - broadcast, - nonagle, - bsdism; - unsigned long lingertime; - int proc; - struct sock *next; - struct sock *prev; /* Doubly linked chain.. */ - struct sock *pair; - struct sk_buff * volatile send_head; - struct sk_buff * volatile send_tail; - struct sk_buff_head back_log; - struct sk_buff *partial; - struct timer_list partial_timer; - long retransmits; - struct sk_buff_head write_queue, - receive_queue; - struct proto *prot; - struct wait_queue **sleep; - __u32 daddr; - __u32 saddr; /* Sending source */ - __u32 rcv_saddr; /* Bound address */ - unsigned short max_unacked; - unsigned short window; - __u32 lastwin_seq; /* sequence number when we last updated the window we offer */ - volatile unsigned long ato; /* ack timeout */ - volatile unsigned long lrcvtime; /* jiffies at last rcv */ - unsigned short bytes_rcv; -/* - * mss is min(mtu, max_window) - */ - unsigned short mtu; /* mss negotiated in the syn's */ - volatile unsigned short mss; /* current eff. mss - can change */ - volatile unsigned short user_mss; /* mss requested by user in ioctl */ - volatile unsigned short max_window; - unsigned long window_clamp; - unsigned short num; - volatile unsigned short cong_window; - volatile unsigned short cong_count; - volatile unsigned short ssthresh; - volatile unsigned short packets_out; - volatile unsigned short shutdown; - volatile unsigned long rtt; - volatile unsigned long mdev; - volatile unsigned long rto; - -/* - * currently backoff isn't used, but I'm maintaining it in case - * we want to go back to a backoff formula that needs it - */ - - volatile unsigned short backoff; - volatile int err, err_soft; /* Soft holds errors that don't - cause failure but are the cause - of a persistent failure not just - 'timed out' */ - unsigned char protocol; - volatile unsigned char state; - volatile unsigned char ack_backlog; - unsigned char max_ack_backlog; - unsigned char priority; - unsigned char debug; - unsigned short rcvbuf; - unsigned short sndbuf; - unsigned short type; - unsigned char localroute; /* Route locally only */ -#ifdef CONFIG_IPX -/* - * Once the IPX ncpd patches are in these are going into protinfo - */ - ipx_address ipx_dest_addr; - ipx_interface *ipx_intrfc; - unsigned short ipx_port; - -/* To handle asynchronous messages from the NetWare server, we have to - * know the connection this socket belongs to. Sorry to blow up this - * structure even more. */ - struct ncp_server *ipx_ncp_server; - -#ifdef CONFIG_IPX_INTERN - unsigned char ipx_node[IPX_NODE_LEN]; -#endif - unsigned short ipx_type; -#endif -#ifdef CONFIG_AX25 - ax25_cb *ax25; -#ifdef CONFIG_NETROM - nr_cb *nr; -#endif -#endif - -/* - * This is where all the private (optional) areas that don't - * overlap will eventually live. - */ - - union - { - struct unix_opt af_unix; -#ifdef CONFIG_ATALK - struct atalk_sock af_at; -#endif -#ifdef CONFIG_INET - struct inet_packet_opt af_packet; -#endif - } protinfo; - -/* - * IP 'private area' or will be eventually - */ - int ip_ttl; /* TTL setting */ - int ip_tos; /* TOS */ - struct tcphdr dummy_th; - struct timer_list keepalive_timer; /* TCP keepalive hack */ - struct timer_list retransmit_timer; /* TCP retransmit timer */ - struct timer_list ack_timer; /* TCP delayed ack timer */ - int ip_xmit_timeout; /* Why the timeout is running */ - struct rtable *ip_route_cache; /* Cached output route */ - unsigned char ip_hdrincl; /* Include headers ? */ -#ifdef CONFIG_IP_MULTICAST - int ip_mc_ttl; /* Multicasting TTL */ - int ip_mc_loop; /* Loopback */ - char ip_mc_name[MAX_ADDR_LEN];/* Multicast device name */ - struct ip_mc_socklist *ip_mc_list; /* Group array */ -#endif - -/* - * This part is used for the timeout functions (timer.c). - */ - - int timeout; /* What are we waiting for? */ - struct timer_list timer; /* This is the TIME_WAIT/receive timer - * when we are doing IP - */ - struct timeval stamp; - - /* - * Identd - */ - - struct socket *socket; - - /* - * Callbacks - */ - - void (*state_change)(struct sock *sk); - void (*data_ready)(struct sock *sk,int bytes); - void (*write_space)(struct sock *sk); - void (*error_report)(struct sock *sk); - -}; - -/* - * IP protocol blocks we attach to sockets. - */ - -struct proto -{ - void (*close)(struct sock *sk, unsigned long timeout); - int (*build_header)(struct sk_buff *skb, - __u32 saddr, - __u32 daddr, - struct device **dev, int type, - struct options *opt, int len, - int tos, int ttl, struct rtable ** rp); - int (*connect)(struct sock *sk, - struct sockaddr_in *usin, int addr_len); - struct sock * (*accept) (struct sock *sk, int flags); - void (*queue_xmit)(struct sock *sk, - struct device *dev, struct sk_buff *skb, - int free); - void (*retransmit)(struct sock *sk, int all); - void (*write_wakeup)(struct sock *sk); - void (*read_wakeup)(struct sock *sk); - int (*rcv)(struct sk_buff *buff, struct device *dev, - struct options *opt, __u32 daddr, - unsigned short len, __u32 saddr, - int redo, struct inet_protocol *protocol); - int (*select)(struct sock *sk, int which, - select_table *wait); - int (*ioctl)(struct sock *sk, int cmd, - unsigned long arg); - int (*init)(struct sock *sk); - void (*shutdown)(struct sock *sk, int how); - int (*setsockopt)(struct sock *sk, int level, int optname, - char *optval, int optlen); - int (*getsockopt)(struct sock *sk, int level, int optname, - char *optval, int *option); - int (*sendmsg)(struct sock *sk, struct msghdr *msg, int len, - int noblock, int flags); - int (*recvmsg)(struct sock *sk, struct msghdr *msg, int len, - int noblock, int flags, int *addr_len); - int (*bind)(struct sock *sk, struct sockaddr *uaddr, int addr_len); - unsigned short max_header; - unsigned long retransmits; - char name[32]; - int inuse, highestinuse; - struct sock * sock_array[SOCK_ARRAY_SIZE]; -}; - -#define TIME_WRITE 1 -#define TIME_CLOSE 2 -#define TIME_KEEPOPEN 3 -#define TIME_DESTROY 4 -#define TIME_DONE 5 /* Used to absorb those last few packets */ -#define TIME_PROBE0 6 -/* - * About 10 seconds - */ -#define SOCK_DESTROY_TIME (10*HZ) - - -/* - * Sockets 0-1023 can't be bound too unless you are superuser - */ - -#define PROT_SOCK 1024 - - -#define SHUTDOWN_MASK 3 -#define RCV_SHUTDOWN 1 -#define SEND_SHUTDOWN 2 - -/* - * Used by processes to "lock" a socket state, so that - * interrupts and bottom half handlers won't change it - * from under us. It essentially blocks any incoming - * packets, so that we won't get any new data or any - * packets that change the state of the socket. - * - * Note the 'barrier()' calls: gcc may not move a lock - * "downwards" or a unlock "upwards" when optimizing. - */ -extern void __release_sock(struct sock *sk); - -static inline void lock_sock(struct sock *sk) -{ -#if 1 -/* debugging code: the test isn't even 100% correct, but it can catch bugs */ -/* Note that a double lock is ok in theory - it's just _usually_ a bug */ - if (sk->users) { - __label__ here; - printk("double lock on socket at %p\n", &&here); -here: - } -#endif - sk->users++; - barrier(); -} - -static inline void release_sock(struct sock *sk) -{ - barrier(); -#if 1 -/* debugging code: remove me when ok */ - if (sk->users == 0) { - __label__ here; - sk->users = 1; - printk("trying to unlock unlocked socket at %p\n", &&here); -here: - } -#endif - if (!--sk->users) - __release_sock(sk); -} - - -extern void destroy_sock(struct sock *sk); -extern unsigned short get_new_socknum(struct proto *, - unsigned short); -extern void put_sock(unsigned short, struct sock *); -extern struct sock *get_sock(struct proto *, unsigned short, - unsigned long, unsigned short, - unsigned long); -extern struct sock *get_sock_mcast(struct sock *, unsigned short, - unsigned long, unsigned short, - unsigned long); -extern struct sock *get_sock_raw(struct sock *, unsigned short, - unsigned long, unsigned long); - -extern struct sk_buff *sock_wmalloc(struct sock *sk, - unsigned long size, int force, - int priority); -extern struct sk_buff *sock_rmalloc(struct sock *sk, - unsigned long size, int force, - int priority); -extern void sock_wfree(struct sock *sk, - struct sk_buff *skb); -extern void sock_rfree(struct sock *sk, - struct sk_buff *skb); -extern unsigned long sock_rspace(struct sock *sk); -extern unsigned long sock_wspace(struct sock *sk); - -extern int sock_setsockopt(struct sock *sk, int level, - int op, char *optval, - int optlen); - -extern int sock_getsockopt(struct sock *sk, int level, - int op, char *optval, - int *optlen); -extern struct sk_buff *sock_alloc_send_skb(struct sock *skb, - unsigned long size, - unsigned long fallback, - int noblock, - int *errcode); - -/* - * Queue a received datagram if it will fit. Stream and sequenced - * protocols can't normally use this as they need to fit buffers in - * and play with them. - * - * Inlined as its very short and called for pretty much every - * packet ever received. - */ - -extern __inline__ int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) -{ - unsigned long flags; - if(sk->rmem_alloc + skb->truesize >= sk->rcvbuf) - return -ENOMEM; - save_flags(flags); - cli(); - sk->rmem_alloc+=skb->truesize; - skb->sk=sk; - restore_flags(flags); - skb_queue_tail(&sk->receive_queue,skb); - if(!sk->dead) - sk->data_ready(sk,skb->len); - return 0; -} - -/* - * Recover an error report and clear atomically - */ - -extern __inline__ int sock_error(struct sock *sk) -{ - int err=xchg(&sk->err,0); - return -err; -} - -/* - * Declarations from timer.c - */ - -extern struct sock *timer_base; - -extern void delete_timer (struct sock *); -extern void reset_timer (struct sock *, int, unsigned long); -extern void net_timer (unsigned long); - - -/* - * Enable debug/info messages - */ - -#define NETDEBUG(x) x - -#endif /* _SOCK_H */ diff --git a/i386/i386at/gpl/linux/include/net/tcp.h b/i386/i386at/gpl/linux/include/net/tcp.h deleted file mode 100644 index 3c7eb7de..00000000 --- a/i386/i386at/gpl/linux/include/net/tcp.h +++ /dev/null @@ -1,329 +0,0 @@ -/* - * INET An implementation of the TCP/IP protocol suite for the LINUX - * operating system. INET is implemented using the BSD Socket - * interface as the means of communication with the user level. - * - * Definitions for the TCP module. - * - * Version: @(#)tcp.h 1.0.5 05/23/93 - * - * Authors: Ross Biro, <bir7@leland.Stanford.Edu> - * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ -#ifndef _TCP_H -#define _TCP_H - -#include <linux/tcp.h> -#include <net/checksum.h> - -#define MAX_SYN_SIZE 44 + MAX_HEADER + 15 -#define MAX_FIN_SIZE 40 + MAX_HEADER + 15 -#define MAX_ACK_SIZE 40 + MAX_HEADER + 15 -#define MAX_RESET_SIZE 40 + MAX_HEADER + 15 -#define MAX_WINDOW 32767 /* Never offer a window over 32767 without using - window scaling (not yet supported). Some poor - stacks do signed 16bit maths! */ -#define MIN_WINDOW 2048 -#define MAX_ACK_BACKLOG 2 -#define MIN_WRITE_SPACE 2048 -#define TCP_WINDOW_DIFF 2048 - -/* urg_data states */ -#define URG_VALID 0x0100 -#define URG_NOTYET 0x0200 -#define URG_READ 0x0400 - -#define TCP_RETR1 7 /* - * This is how many retries it does before it - * tries to figure out if the gateway is - * down. - */ - -#define TCP_RETR2 15 /* - * This should take at least - * 90 minutes to time out. - */ - -#define TCP_TIMEOUT_LEN (15*60*HZ) /* should be about 15 mins */ -#define TCP_TIMEWAIT_LEN (60*HZ) /* how long to wait to successfully - * close the socket, about 60 seconds */ -#define TCP_FIN_TIMEOUT (3*60*HZ) /* BSD style FIN_WAIT2 deadlock breaker */ -#define TCP_ACK_TIME (3*HZ) /* time to delay before sending an ACK */ -#define TCP_DONE_TIME (5*HZ/2)/* maximum time to wait before actually - * destroying a socket */ -#define TCP_WRITE_TIME (30*HZ) /* initial time to wait for an ACK, - * after last transmit */ -#define TCP_TIMEOUT_INIT (3*HZ) /* RFC 1122 initial timeout value */ -#define TCP_SYN_RETRIES 10 /* number of times to retry opening a - * connection (TCP_RETR2-....) */ -#define TCP_PROBEWAIT_LEN (1*HZ)/* time to wait between probes when - * I've got something to write and - * there is no window */ - -#define TCP_NO_CHECK 0 /* turn to one if you want the default - * to be no checksum */ - - -/* - * TCP option - */ - -#define TCPOPT_NOP 1 /* Padding */ -#define TCPOPT_EOL 0 /* End of options */ -#define TCPOPT_MSS 2 /* Segment size negotiating */ -/* - * We don't use these yet, but they are for PAWS and big windows - */ -#define TCPOPT_WINDOW 3 /* Window scaling */ -#define TCPOPT_TIMESTAMP 8 /* Better RTT estimations/PAWS */ - - -/* - * The next routines deal with comparing 32 bit unsigned ints - * and worry about wraparound (automatic with unsigned arithmetic). - */ - -extern __inline int before(__u32 seq1, __u32 seq2) -{ - return (__s32)(seq1-seq2) < 0; -} - -extern __inline int after(__u32 seq1, __u32 seq2) -{ - return (__s32)(seq2-seq1) < 0; -} - - -/* is s2<=s1<=s3 ? */ -extern __inline int between(__u32 seq1, __u32 seq2, __u32 seq3) -{ - return (after(seq1+1, seq2) && before(seq1, seq3+1)); -} - -static __inline__ int min(unsigned int a, unsigned int b) -{ - if (a < b) - return(a); - return(b); -} - -extern struct proto tcp_prot; -extern struct tcp_mib tcp_statistics; -extern struct wait_queue *master_select_wakeup; - -extern void tcp_err(int type, int code, unsigned char *header, __u32 daddr, - __u32, struct inet_protocol *protocol); -extern void tcp_shutdown (struct sock *sk, int how); -extern int tcp_rcv(struct sk_buff *skb, struct device *dev, - struct options *opt, __u32 daddr, - unsigned short len, __u32 saddr, int redo, - struct inet_protocol *protocol); - -extern int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg); - -extern void tcp_read_wakeup(struct sock *); -extern void tcp_write_xmit(struct sock *); -extern void tcp_time_wait(struct sock *); -extern void tcp_retransmit(struct sock *, int); -extern void tcp_do_retransmit(struct sock *, int); -extern void tcp_send_check(struct tcphdr *th, unsigned long saddr, - unsigned long daddr, int len, struct sk_buff *skb); - -/* tcp_output.c */ - -extern void tcp_send_probe0(struct sock *); -extern void tcp_send_partial(struct sock *); -extern void tcp_write_wakeup(struct sock *); -extern void tcp_send_fin(struct sock *sk); -extern void tcp_send_synack(struct sock *, struct sock *, struct sk_buff *); -extern void tcp_send_skb(struct sock *, struct sk_buff *); -extern void tcp_send_ack(u32, u32, struct sock *sk, struct tcphdr *th, u32); -extern void tcp_send_reset(unsigned long saddr, unsigned long daddr, struct tcphdr *th, - struct proto *prot, struct options *opt, struct device *dev, int tos, int ttl); - -extern void tcp_enqueue_partial(struct sk_buff *, struct sock *); -extern struct sk_buff * tcp_dequeue_partial(struct sock *); - -/* tcp_input.c */ -extern void tcp_cache_zap(void); - -/* tcp_timer.c */ -#define tcp_reset_msl_timer(x,y,z) reset_timer(x,y,z) -extern void tcp_reset_xmit_timer(struct sock *, int, unsigned long); -extern void tcp_retransmit_timer(unsigned long); - -/* - * Default sequence number picking algorithm. - * As close as possible to RFC 793, which - * suggests using a 250kHz clock. - * Further reading shows this assumes 2MB/s networks. - * For 10MB/s ethernet, a 1MHz clock is appropriate. - * That's funny, Linux has one built in! Use it! - */ - -static inline u32 tcp_init_seq(void) -{ - struct timeval tv; - do_gettimeofday(&tv); - return tv.tv_usec+tv.tv_sec*1000000; -} - -/* - * This function returns the amount that we can raise the - * usable window based on the following constraints - * - * 1. The window can never be shrunk once it is offered (RFC 793) - * 2. We limit memory per socket - */ - -static __inline__ unsigned short tcp_raise_window(struct sock *sk) -{ - long free_space = sock_rspace(sk); - long window; - - if (free_space > 1024) - free_space &= ~0x3FF; /* make free space a multiple of 1024 */ - - if(sk->window_clamp) - free_space = min(sk->window_clamp, free_space); - - /* - * compute the actual window i.e. - * old_window - received_bytes_on_that_win - */ - - window = sk->window - (sk->acked_seq - sk->lastwin_seq); - - if (sk->mss == 0) - sk->mss = sk->mtu; - - if ( window < 0 ) { - window = 0; - printk(KERN_DEBUG "TRW: win < 0 w=%d 1=%u 2=%u\n", - sk->window, sk->acked_seq, sk->lastwin_seq); - } - - if ( (free_space - window) >= min(sk->mss, MAX_WINDOW/2) ) - return ((free_space - window) / sk->mss) * sk->mss; - - return 0; -} - -static __inline__ unsigned short tcp_select_window(struct sock *sk) -{ - long free_space = sock_rspace(sk); - long window; - - if (free_space > 1024) - free_space &= ~0x3FF; /* make free space a multiple of 1024 */ - - if (sk->window_clamp) - free_space = min(sk->window_clamp, free_space); - - /* - * compute the actual window i.e. - * old_window - received_bytes_on_that_win - */ - - if (sk->mss == 0) - sk->mss = sk->mtu; - - window = sk->window - (sk->acked_seq - sk->lastwin_seq); - - if ( window < 0 ) { - window = 0; - printk(KERN_DEBUG "TSW: win < 0 w=%d 1=%u 2=%u\n", - sk->window, sk->acked_seq, sk->lastwin_seq); - } - - /* - * RFC 1122: - * "the suggested [SWS] avoidance algoritm for the receiver is to keep - * RECV.NEXT + RCV.WIN fixed until: - * RCV.BUFF - RCV.USER - RCV.WINDOW >= min(1/2 RCV.BUFF, MSS)" - * - * i.e. don't raise the right edge of the window until you can't raise - * it MSS bytes - */ - - if ( (free_space - window) >= min(sk->mss, MAX_WINDOW/2) ) - window += ((free_space - window) / sk->mss) * sk->mss; - - sk->window = window; - sk->lastwin_seq = sk->acked_seq; - - return sk->window; -} - -/* - * List all states of a TCP socket that can be viewed as a "connected" - * state. This now includes TCP_SYN_RECV, although I am not yet fully - * convinced that this is the solution for the 'getpeername(2)' - * problem. Thanks to Stephen A. Wood <saw@cebaf.gov> -FvK - */ - -extern __inline const int tcp_connected(const int state) -{ - return(state == TCP_ESTABLISHED || state == TCP_CLOSE_WAIT || - state == TCP_FIN_WAIT1 || state == TCP_FIN_WAIT2 || - state == TCP_SYN_RECV); -} - -/* - * Calculate(/check) TCP checksum - */ -static __inline__ u16 tcp_check(struct tcphdr *th, int len, - unsigned long saddr, unsigned long daddr, unsigned long base) -{ - return csum_tcpudp_magic(saddr,daddr,len,IPPROTO_TCP,base); -} - -#undef STATE_TRACE - -#ifdef STATE_TRACE -static char *statename[]={ - "Unused","Established","Syn Sent","Syn Recv", - "Fin Wait 1","Fin Wait 2","Time Wait", "Close", - "Close Wait","Last ACK","Listen","Closing" -}; -#endif - -static __inline__ void tcp_set_state(struct sock *sk, int state) -{ - int oldstate = sk->state; - - sk->state = state; - -#ifdef STATE_TRACE - if(sk->debug) - printk("TCP sk=%p, State %s -> %s\n",sk, statename[oldstate],statename[state]); -#endif - - switch (state) { - case TCP_ESTABLISHED: - if (oldstate != TCP_ESTABLISHED) { - tcp_statistics.TcpCurrEstab++; - /* This is a hack but it doesn't occur often and it's going to - be a real to fix nicely */ - if (oldstate == TCP_SYN_RECV) - wake_up_interruptible(&master_select_wakeup); - } - break; - - case TCP_CLOSE: - tcp_cache_zap(); - /* Should be about 2 rtt's */ - reset_timer(sk, TIME_DONE, min(sk->rtt * 2, TCP_DONE_TIME)); - /* fall through */ - default: - if (oldstate==TCP_ESTABLISHED) - tcp_statistics.TcpCurrEstab--; - } -} - -#endif /* _TCP_H */ diff --git a/i386/i386at/gpl/linux/include/net/udp.h b/i386/i386at/gpl/linux/include/net/udp.h deleted file mode 100644 index 13735d17..00000000 --- a/i386/i386at/gpl/linux/include/net/udp.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * INET An implementation of the TCP/IP protocol suite for the LINUX - * operating system. INET is implemented using the BSD Socket - * interface as the means of communication with the user level. - * - * Definitions for the UDP module. - * - * Version: @(#)udp.h 1.0.2 05/07/93 - * - * Authors: Ross Biro, <bir7@leland.Stanford.Edu> - * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> - * - * Fixes: - * Alan Cox : Turned on udp checksums. I don't want to - * chase 'memory corruption' bugs that aren't! - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ -#ifndef _UDP_H -#define _UDP_H - -#include <linux/udp.h> - - -#define UDP_NO_CHECK 0 - - -extern struct proto udp_prot; - - -extern void udp_err(int type, int code, unsigned char *header, __u32 daddr, - __u32 saddr, struct inet_protocol *protocol); -extern void udp_send_check(struct udphdr *uh, __u32 saddr, - __u32 daddr, int len, struct sock *sk); -extern int udp_recvfrom(struct sock *sk, unsigned char *to, - int len, int noblock, unsigned flags, - struct sockaddr_in *sin, int *addr_len); -extern int udp_read(struct sock *sk, unsigned char *buff, - int len, int noblock, unsigned flags); -extern int udp_connect(struct sock *sk, - struct sockaddr_in *usin, int addr_len); -extern int udp_rcv(struct sk_buff *skb, struct device *dev, - struct options *opt, __u32 daddr, - unsigned short len, __u32 saddr, int redo, - struct inet_protocol *protocol); -extern int udp_ioctl(struct sock *sk, int cmd, unsigned long arg); -extern void udp_cache_zap(void); /* Remove udp last socket cache */ - -#endif /* _UDP_H */ diff --git a/i386/i386at/gpl/linux/linux_autoirq.c b/i386/i386at/gpl/linux/linux_autoirq.c deleted file mode 100644 index 2e3d4e61..00000000 --- a/i386/i386at/gpl/linux/linux_autoirq.c +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Linux auto-irq support. - * Copyright (C) 1995 Shantanu Goel. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* - * Written 1994 by Donald Becker. - * - * The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O - * Center of Excellence in Space Data and Information Sciences - * Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771 - * - * This code is a general-purpose IRQ line detector for devices with - * jumpered IRQ lines. If you can make the device raise an IRQ (and - * that IRQ line isn't already being used), these routines will tell - * you what IRQ line it's using -- perfect for those oh-so-cool boot-time - * device probes! - * - * To use this, first call autoirq_setup(timeout). TIMEOUT is how many - * 'jiffies' (1/100 sec.) to detect other devices that have active IRQ lines, - * and can usually be zero at boot. 'autoirq_setup()' returns the bit - * vector of nominally-available IRQ lines (lines may be physically in-use, - * but not yet registered to a device). - * Next, set up your device to trigger an interrupt. - * Finally call autoirq_report(TIMEOUT) to find out which IRQ line was - * most recently active. The TIMEOUT should usually be zero, but may - * be set to the number of jiffies to wait for a slow device to raise an IRQ. - * - * The idea of using the setup timeout to filter out bogus IRQs came from - * the serial driver. - */ - -#include <i386/pic.h> -#include <i386/ipl.h> - -#include <linux/sched.h> -#include <linux/ptrace.h> - -#include <asm/bitops.h> -#include <asm/system.h> - -/* - * IRQ to network device map. - */ -void *irq2dev_map[16]; - -/* - * Set of fixed IRQs - * (fpu, rtc, com1, PIC slave cascade, keyboard, timer). - */ -int irqs_busy = 0x2147; - -static volatile int irq_number; /* latest irq found */ -static volatile int irq_bitmap; /* bitmap of IRQs found */ -static int irq_handled; /* irq lines we have a handler on */ - -extern unsigned long loops_per_sec; - -/* - * Interrupt handler when probing an IRQ. - */ -static void -autoirq_probe(irq) - int irq; -{ - /* - * Mark this IRQ as the last one - * that interrupted and disable it. - */ - irq_number = irq; - set_bit(irq, (void *)&irq_bitmap); - disable_irq(irq); -} - -/* - * Set up for auto-irq. - */ -int -autoirq_setup(waittime) - int waittime; -{ - int i, mask; - int timeout = jiffies + waittime; - int boguscount = (waittime * loops_per_sec) / 100; - - /* - * Allocate all possible IRQs. - */ - irq_handled = 0; - for (i = 0; i < 16; i++) { - if (test_bit(i, (void *)&irqs_busy) == 0 - && request_irq(i, autoirq_probe, 0, 0) == 0) - set_bit(i, (void *)&irq_handled); - } - - irq_number = 0; - irq_bitmap = 0; - - /* - * Hang out at least <waittime> - * jiffies waiting for bogus IRQ hits. - */ - while (timeout > jiffies && --boguscount > 0) - ; - - /* - * Free IRQs that caused bogus hits. - */ - for (i = 0, mask = 0x01; i < 16; i++, mask <<= 1) { - if (irq_bitmap & irq_handled & mask) { - irq_handled &= ~mask; - free_irq(i); - } - } - - return (irq_handled); -} - -/* - * Return the last IRQ that caused an interrupt. - */ -int -autoirq_report(waittime) - int waittime; -{ - int i; - int timeout = jiffies + waittime; - int boguscount = (waittime * loops_per_sec) / 100; - - /* - * Hang out at least <waittime> - * jiffies waiting for the IRQ. - */ - while (timeout > jiffies && --boguscount > 0) - if (irq_number) - break; - - /* - * Retract the IRQ handlers that we handled. - */ - for (i = 0; i < 16; i++) { - if (test_bit(i, (void *)&irq_handled)) - free_irq(i); - } - - return (irq_number); -} diff --git a/i386/i386at/gpl/linux/linux_block.c b/i386/i386at/gpl/linux/linux_block.c deleted file mode 100644 index 93f1a5cd..00000000 --- a/i386/i386at/gpl/linux/linux_block.c +++ /dev/null @@ -1,1625 +0,0 @@ -/* - * Linux block driver support. - * - * Copyright (C) 1996 The University of Utah and the Computer Systems - * Laboratory at the University of Utah (CSL) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Author: Shantanu Goel, University of Utah CSL - */ - -/* - * linux/drivers/block/ll_rw_blk.c - * - * Copyright (C) 1991, 1992 Linus Torvalds - * Copyright (C) 1994, Karl Keyte: Added support for disk statistics - */ - -/* - * linux/fs/block_dev.c - * - * Copyright (C) 1991, 1992 Linus Torvalds - */ - -/* - * linux/fs/buffer.c - * - * Copyright (C) 1991, 1992 Linus Torvalds - */ - -#include <sys/types.h> -#include <mach/mach_types.h> -#include <mach/kern_return.h> -#include <mach/mig_errors.h> -#include <mach/port.h> -#include <mach/vm_param.h> -#include <mach/notify.h> - -#include <ipc/ipc_port.h> -#include <ipc/ipc_space.h> - -#include <vm/vm_map.h> -#include <vm/vm_kern.h> -#include <vm/vm_page.h> - -#include <device/device_types.h> -#include <device/device_port.h> -#include <device/disk_status.h> -#include "device_reply.h" - -#include <i386at/dev_hdr.h> -#include <i386at/device_emul.h> -#include <i386at/disk.h> - -#include <i386at/gpl/linux/linux_emul.h> - -#define MACH_INCLUDE -#include <linux/fs.h> -#include <linux/blk.h> -#include <linux/string.h> -#include <linux/errno.h> -#include <linux/fcntl.h> -#include <linux/major.h> -#include <linux/kdev_t.h> -#include <linux/delay.h> -#include <linux/malloc.h> - -/* Location of VTOC in units for sectors (512 bytes). */ -#define PDLOCATION 29 - -/* Linux kernel variables. */ - -/* Temporary data allocated on the stack. */ -struct temp_data -{ - struct inode inode; - struct file file; - struct request req; - queue_head_t pages; -}; - -/* One of these exists for each - driver associated with a major number. */ -struct device_struct -{ - const char *name; /* device name */ - struct file_operations *fops; /* operations vector */ - int busy:1; /* driver is being opened/closed */ - int want:1; /* someone wants to open/close driver */ - struct gendisk *gd; /* DOS partition information */ - int default_slice; /* what slice to use when none is given */ - struct disklabel **labels; /* disklabels for each DOS partition */ -}; - -/* An entry in the Mach name to Linux major number conversion table. */ -struct name_map -{ - const char *name; /* Mach name for device */ - unsigned major; /* Linux major number */ - unsigned unit; /* Linux unit number */ - int read_only; /* 1 if device is read only */ -}; - -/* Driver operation table. */ -static struct device_struct blkdevs[MAX_BLKDEV]; - -/* Driver request function table. */ -struct blk_dev_struct blk_dev[MAX_BLKDEV] = -{ - { NULL, NULL }, /* 0 no_dev */ - { NULL, NULL }, /* 1 dev mem */ - { NULL, NULL }, /* 2 dev fd */ - { NULL, NULL }, /* 3 dev ide0 or hd */ - { NULL, NULL }, /* 4 dev ttyx */ - { NULL, NULL }, /* 5 dev tty */ - { NULL, NULL }, /* 6 dev lp */ - { NULL, NULL }, /* 7 dev pipes */ - { NULL, NULL }, /* 8 dev sd */ - { NULL, NULL }, /* 9 dev st */ - { NULL, NULL }, /* 10 */ - { NULL, NULL }, /* 11 */ - { NULL, NULL }, /* 12 */ - { NULL, NULL }, /* 13 */ - { NULL, NULL }, /* 14 */ - { NULL, NULL }, /* 15 */ - { NULL, NULL }, /* 16 */ - { NULL, NULL }, /* 17 */ - { NULL, NULL }, /* 18 */ - { NULL, NULL }, /* 19 */ - { NULL, NULL }, /* 20 */ - { NULL, NULL }, /* 21 */ - { NULL, NULL } /* 22 dev ide1 */ -}; - -/* - * blk_size contains the size of all block-devices in units of 1024 byte - * sectors: - * - * blk_size[MAJOR][MINOR] - * - * if (!blk_size[MAJOR]) then no minor size checking is done. - */ -int *blk_size[MAX_BLKDEV] = { NULL, NULL, }; - -/* - * blksize_size contains the size of all block-devices: - * - * blksize_size[MAJOR][MINOR] - * - * if (!blksize_size[MAJOR]) then 1024 bytes is assumed. - */ -int *blksize_size[MAX_BLKDEV] = { NULL, NULL, }; - -/* - * hardsect_size contains the size of the hardware sector of a device. - * - * hardsect_size[MAJOR][MINOR] - * - * if (!hardsect_size[MAJOR]) - * then 512 bytes is assumed. - * else - * sector_size is hardsect_size[MAJOR][MINOR] - * This is currently set by some scsi device and read by the msdos fs driver - * This might be a some uses later. - */ -int *hardsect_size[MAX_BLKDEV] = { NULL, NULL, }; - -/* This specifies how many sectors to read ahead on the disk. - This is unused in Mach. It is here to make drivers compile. */ -int read_ahead[MAX_BLKDEV] = {0, }; - -/* Use to wait on when there are no free requests. - This is unused in Mach. It is here to make drivers compile. */ -struct wait_queue *wait_for_request = NULL; - -/* Map for allocating device memory. */ -extern vm_map_t device_io_map; - -/* Initialize block drivers. */ -void -blk_dev_init () -{ -#ifdef CONFIG_BLK_DEV_IDE - ide_init (); -#endif -#ifdef CONFIG_BLK_DEV_FD - floppy_init (); -#endif -} - -/* Return 1 if major number MAJOR corresponds to a disk device. */ -static inline int -disk_major (int major) -{ - return (major == IDE0_MAJOR - || major == IDE1_MAJOR - || major == IDE2_MAJOR - || major == IDE3_MAJOR - || major == SCSI_DISK_MAJOR); -} - -/* Linux kernel block support routines. */ - -/* Register a driver for major number MAJOR, - with name NAME, and operations vector FOPS. */ -int -register_blkdev (unsigned major, const char *name, - struct file_operations *fops) -{ - int err = 0; - - if (major == 0) - { - for (major = MAX_BLKDEV - 1; major > 0; major--) - if (blkdevs[major].fops == NULL) - goto out; - return -LINUX_EBUSY; - } - if (major >= MAX_BLKDEV) - return -LINUX_EINVAL; - if (blkdevs[major].fops && blkdevs[major].fops != fops) - return -LINUX_EBUSY; - -out: - blkdevs[major].name = name; - blkdevs[major].fops = fops; - blkdevs[major].busy = 0; - blkdevs[major].want = 0; - blkdevs[major].gd = NULL; - blkdevs[major].default_slice = 0; - blkdevs[major].labels = NULL; - return 0; -} - -/* Unregister the driver associated with - major number MAJOR and having the name NAME. */ -int -unregister_blkdev (unsigned major, const char *name) -{ - int err; - - if (major >= MAX_BLKDEV) - return -LINUX_EINVAL; - if (! blkdevs[major].fops || strcmp (blkdevs[major].name, name)) - return -LINUX_EINVAL; - blkdevs[major].fops = NULL; - if (blkdevs[major].labels) - { - assert (blkdevs[major].gd); - kfree ((vm_offset_t) blkdevs[major].labels, - (sizeof (struct disklabel *) - * blkdevs[major].gd->max_p * blkdevs[major].gd->max_nr)); - } - return 0; -} - -/* Allocate a buffer SIZE bytes long. */ -static void * -alloc_buffer (int size) -{ - vm_page_t m; - struct temp_data *d; - - assert (size <= PAGE_SIZE); - - if (! linux_auto_config) - { - while ((m = vm_page_grab ()) == 0) - VM_PAGE_WAIT (0); - d = current_thread ()->pcb->data; - assert (d); - queue_enter (&d->pages, m, vm_page_t, pageq); - return (void *) m->phys_addr; - } - return (void *) __get_free_pages (GFP_KERNEL, 0, ~0UL); -} - -/* Free buffer P which is SIZE bytes long. */ -static void -free_buffer (void *p, int size) -{ - int i; - struct temp_data *d; - vm_page_t m; - - assert (size <= PAGE_SIZE); - - if (! linux_auto_config) - { - d = current_thread ()->pcb->data; - assert (d); - queue_iterate (&d->pages, m, vm_page_t, pageq) - { - if (m->phys_addr == (vm_offset_t) p) - { - queue_remove (&d->pages, m, vm_page_t, pageq); - vm_page_lock_queues (); - vm_page_free (m); - vm_page_lock_queues (); - return; - } - } - panic ("free_buffer"); - } - free_pages ((unsigned long) p, 0); -} - -/* Allocate a buffer of SIZE bytes and - associate it with block number BLOCK of device DEV. */ -struct buffer_head * -getblk (kdev_t dev, int block, int size) -{ - struct buffer_head *bh; - static struct buffer_head bhead; - - assert (size <= PAGE_SIZE); - - if (! linux_auto_config) - bh = (struct buffer_head *) kalloc (sizeof (struct buffer_head)); - else - bh = &bhead; - if (bh) - { - memset (bh, 0, sizeof (struct buffer_head)); - bh->b_data = alloc_buffer (size); - if (! bh->b_data) - { - if (! linux_auto_config) - kfree ((vm_offset_t) bh, sizeof (struct buffer_head)); - return NULL; - } - bh->b_dev = dev; - bh->b_size = size; - bh->b_state = 1 << BH_Lock; - bh->b_blocknr = block; - } - return bh; -} - -/* Release buffer BH previously allocated by getblk. */ -void -__brelse (struct buffer_head *bh) -{ - free_buffer (bh->b_data, bh->b_size); - if (! linux_auto_config) - kfree ((vm_offset_t) bh, sizeof (*bh)); -} - -/* Allocate a buffer of SIZE bytes and fill it with data - from device DEV starting at block number BLOCK. */ -struct buffer_head * -bread (kdev_t dev, int block, int size) -{ - int err; - struct buffer_head *bh; - - bh = getblk (dev, block, size); - if (bh) - { - ll_rw_block (READ, 1, &bh); - wait_on_buffer (bh); - if (! buffer_uptodate (bh)) - { - __brelse (bh); - return NULL; - } - } - return bh; -} - -/* Return the block size for device DEV in *BSIZE and - log2(block size) in *BSHIFT. */ -static void -get_block_size (kdev_t dev, int *bsize, int *bshift) -{ - int i; - - *bsize = BLOCK_SIZE; - if (blksize_size[MAJOR (dev)] - && blksize_size[MAJOR (dev)][MINOR (dev)]) - *bsize = blksize_size[MAJOR (dev)][MINOR (dev)]; - for (i = *bsize, *bshift = 0; i != 1; i >>= 1, (*bshift)++) - ; -} - -/* Enqueue request REQ on a driver's queue. */ -static inline void -enqueue_request (struct request *req) -{ - struct request *tmp; - struct blk_dev_struct *dev; - - dev = blk_dev + MAJOR (req->rq_dev); - cli (); - tmp = dev->current_request; - if (! tmp) - { - dev->current_request = req; - (*dev->request_fn) (); - sti (); - return; - } - while (tmp->next) - { - if ((IN_ORDER (tmp, req) || ! IN_ORDER (tmp, tmp->next)) - && IN_ORDER (req, tmp->next)) - break; - tmp = tmp->next; - } - req->next = tmp->next; - tmp->next = req; - if (scsi_major (MAJOR (req->rq_dev))) - (*dev->request_fn) (); - sti (); -} - -/* Perform the I/O operation RW on the buffer list BH - containing NR buffers. */ -void -ll_rw_block (int rw, int nr, struct buffer_head **bh) -{ - int i, bshift, bsize; - unsigned major; - struct request *r; - static struct request req; - - major = MAJOR (bh[0]->b_dev); - assert (major < MAX_BLKDEV); - - get_block_size (bh[0]->b_dev, &bsize, &bshift); - - if (! linux_auto_config) - { - assert (current_thread ()->pcb->data); - r = &((struct temp_data *) current_thread ()->pcb->data)->req; - } - else - r = &req; - - for (i = 0, r->nr_sectors = 0; i < nr - 1; i++) - { - r->nr_sectors += bh[i]->b_size >> 9; - bh[i]->b_reqnext = bh[i + 1]; - } - r->nr_sectors += bh[i]->b_size >> 9; - bh[i]->b_reqnext = NULL; - - r->rq_status = RQ_ACTIVE; - r->rq_dev = bh[0]->b_dev; - r->cmd = rw; - r->errors = 0; - r->sector = bh[0]->b_blocknr << (bshift - 9); - r->current_nr_sectors = bh[0]->b_size >> 9; - r->buffer = bh[0]->b_data; - r->bh = bh[0]; - r->bhtail = bh[nr - 1]; - r->sem = NULL; - r->next = NULL; - - enqueue_request (r); -} - -#define BSIZE (1 << bshift) -#define BMASK (BSIZE - 1) - -/* Perform read/write operation RW on device DEV - starting at *off to/from buffer *BUF of size *RESID. - The device block size is given by BSHIFT. *OFF and - *RESID may be non-multiples of the block size. - *OFF, *BUF and *RESID are updated if the operation - completed successfully. */ -static int -rdwr_partial (int rw, kdev_t dev, loff_t *off, - char **buf, int *resid, int bshift) -{ - int c, err = 0, o; - long sect, nsect; - struct buffer_head bhead, *bh = &bhead; - struct gendisk *gd; - - memset (bh, 0, sizeof (struct buffer_head)); - bh->b_state = 1 << BH_Lock; - bh->b_dev = dev; - bh->b_blocknr = *off >> bshift; - bh->b_size = BSIZE; - - /* Check if this device has non even number of blocks. */ - for (gd = gendisk_head, nsect = -1; gd; gd = gd->next) - if (gd->major == MAJOR (dev)) - { - nsect = gd->part[MINOR (dev)].nr_sects; - break; - } - if (nsect > 0) - { - sect = bh->b_blocknr << (bshift - 9); - assert ((nsect - sect) > 0); - if (nsect - sect < (BSIZE >> 9)) - bh->b_size = (nsect - sect) << 9; - } - bh->b_data = alloc_buffer (bh->b_size); - if (! bh->b_data) - return -LINUX_ENOMEM; - ll_rw_block (READ, 1, &bh); - wait_on_buffer (bh); - if (buffer_uptodate (bh)) - { - o = *off & BMASK; - c = bh->b_size - o; - assert (*resid <= c); - if (c > *resid) - c = *resid; - if (rw == READ) - memcpy (*buf, bh->b_data + o, c); - else - { - memcpy (bh->b_data + o, *buf, c); - bh->b_state = (1 << BH_Dirty) | (1 << BH_Lock); - ll_rw_block (WRITE, 1, &bh); - wait_on_buffer (bh); - if (! buffer_uptodate (bh)) - { - err = -LINUX_EIO; - goto out; - } - } - *buf += c; - *resid -= c; - *off += c; - } - else - err = -LINUX_EIO; -out: - free_buffer (bh->b_data, bh->b_size); - return err; -} - -#define BH_Bounce 16 -#define MAX_BUF VM_MAP_COPY_PAGE_LIST_MAX - -/* Perform read/write operation RW on device DEV - starting at *off to/from buffer *BUF of size *RESID. - The device block size is given by BSHIFT. *OFF and - *RESID must be multiples of the block size. - *OFF, *BUF and *RESID are updated if the operation - completed successfully. */ -static int -rdwr_full (int rw, kdev_t dev, loff_t *off, char **buf, int *resid, int bshift) -{ - int cc, err = 0, i, j, nb, nbuf; - long blk; - struct buffer_head bhead[MAX_BUF], *bh, *bhp[MAX_BUF]; - - assert ((*off & BMASK) == 0); - assert (*resid >= bsize); - - nbuf = *resid >> bshift; - blk = *off >> bshift; - for (i = nb = 0, bh = bhead; nb < nbuf; bh++) - { - memset (bh, 0, sizeof (*bh)); - bh->b_dev = dev; - bh->b_blocknr = blk; - set_bit (BH_Lock, &bh->b_state); - if (rw == WRITE) - set_bit (BH_Dirty, &bh->b_state); - cc = PAGE_SIZE - (((int) *buf) & PAGE_MASK); - if (cc >= BSIZE && ((int) *buf & 511) == 0) - cc &= ~BMASK; - else - { - cc = PAGE_SIZE; - set_bit (BH_Bounce, &bh->b_state); - } - if (cc > ((nbuf - nb) << bshift)) - cc = (nbuf - nb) << bshift; - if (! test_bit (BH_Bounce, &bh->b_state)) - bh->b_data = (char *) pmap_extract (vm_map_pmap (device_io_map), - (((vm_offset_t) *buf) - + (nb << bshift))); - else - { - bh->b_data = alloc_buffer (cc); - if (! bh->b_data) - { - err = -LINUX_ENOMEM; - break; - } - if (rw == WRITE) - memcpy (bh->b_data, *buf + (nb << bshift), cc); - } - bh->b_size = cc; - bhp[i] = bh; - nb += cc >> bshift; - blk += nb; - if (++i == MAX_BUF) - break; - } - if (! err) - { - ll_rw_block (rw, i, bhp); - wait_on_buffer (bhp[i - 1]); - } - for (bh = bhead, cc = 0, j = 0; j < i; cc += bh->b_size, bh++, j++) - { - if (! err && buffer_uptodate (bh) - && rw == READ && test_bit (BH_Bounce, &bh->b_state)) - memcpy (*buf + cc, bh->b_data, bh->b_size); - else if (! err && ! buffer_uptodate (bh)) - err = -LINUX_EIO; - if (test_bit (BH_Bounce, &bh->b_state)) - free_buffer (bh->b_data, bh->b_size); - } - if (! err) - { - *buf += cc; - *resid -= cc; - *off += cc; - } - return err; -} - -/* Perform read/write operation RW on device DEV - starting at *off to/from buffer BUF of size COUNT. - *OFF is updated if the operation completed successfully. */ -static int -do_rdwr (int rw, kdev_t dev, loff_t *off, char *buf, int count) -{ - int bsize, bshift, err = 0, resid = count; - - get_block_size (dev, &bsize, &bshift); - if (*off & BMASK) - err = rdwr_partial (rw, dev, off, &buf, &resid, bshift); - while (resid >= bsize && ! err) - err = rdwr_full (rw, dev, off, &buf, &resid, bshift); - if (! err && resid) - err = rdwr_partial (rw, dev, off, &buf, &resid, bshift); - return err ? err : count - resid; -} - -int -block_write (struct inode *inode, struct file *filp, - const char *buf, int count) -{ - return do_rdwr (WRITE, inode->i_rdev, &filp->f_pos, (char *) buf, count); -} - -int -block_read (struct inode *inode, struct file *filp, char *buf, int count) -{ - return do_rdwr (READ, inode->i_rdev, &filp->f_pos, buf, count); -} - -/* - * This routine checks whether a removable media has been changed, - * and invalidates all buffer-cache-entries in that case. This - * is a relatively slow routine, so we have to try to minimize using - * it. Thus it is called only upon a 'mount' or 'open'. This - * is the best way of combining speed and utility, I think. - * People changing diskettes in the middle of an operation deserve - * to loose :-) - */ -int -check_disk_change (kdev_t dev) -{ - unsigned i; - struct file_operations * fops; - - i = MAJOR(dev); - if (i >= MAX_BLKDEV || (fops = blkdevs[i].fops) == NULL) - return 0; - if (fops->check_media_change == NULL) - return 0; - if (! (*fops->check_media_change) (dev)) - return 0; - - /* printf ("Disk change detected on device %s\n", kdevname(dev));*/ - - if (fops->revalidate) - (*fops->revalidate) (dev); - - return 1; -} - -/* Mach device interface routines. */ - -/* Mach name to Linux major/minor number mapping table. */ -static struct name_map name_to_major[] = -{ - /* IDE disks */ - { "hd0", IDE0_MAJOR, 0, 0 }, - { "hd1", IDE0_MAJOR, 1, 0 }, - { "hd2", IDE1_MAJOR, 0, 0 }, - { "hd3", IDE1_MAJOR, 1, 0 }, - { "hd4", IDE2_MAJOR, 0, 0 }, - { "hd5", IDE2_MAJOR, 1, 0 }, - { "hd6", IDE3_MAJOR, 0, 0 }, - { "hd7", IDE3_MAJOR, 1, 0 }, - - /* IDE CDROMs */ - { "wcd0", IDE0_MAJOR, 0, 1 }, - { "wcd1", IDE0_MAJOR, 1, 1 }, - { "wcd2", IDE1_MAJOR, 0, 1 }, - { "wcd3", IDE1_MAJOR, 1, 1 }, - { "wcd4", IDE2_MAJOR, 0, 1 }, - { "wcd5", IDE2_MAJOR, 1, 1 }, - { "wcd6", IDE3_MAJOR, 0, 1 }, - { "wcd7", IDE3_MAJOR, 1, 1 }, - - /* SCSI disks */ - { "sd0", SCSI_DISK_MAJOR, 0, 0 }, - { "sd1", SCSI_DISK_MAJOR, 1, 0 }, - { "sd2", SCSI_DISK_MAJOR, 2, 0 }, - { "sd3", SCSI_DISK_MAJOR, 3, 0 }, - { "sd4", SCSI_DISK_MAJOR, 4, 0 }, - { "sd5", SCSI_DISK_MAJOR, 5, 0 }, - { "sd6", SCSI_DISK_MAJOR, 6, 0 }, - { "sd7", SCSI_DISK_MAJOR, 7, 0 }, - - /* SCSI CDROMs */ - { "cd0", SCSI_CDROM_MAJOR, 0, 1 }, - { "cd1", SCSI_CDROM_MAJOR, 1, 1 }, - - /* Floppy disks */ - { "fd0", FLOPPY_MAJOR, 0, 0 }, - { "fd1", FLOPPY_MAJOR, 1, 0 }, -}; - -#define NUM_NAMES (sizeof (name_to_major) / sizeof (name_to_major[0])) - -/* One of these is associated with each open instance of a device. */ -struct block_data -{ - const char *name; /* Mach name for device */ - int want:1; /* someone is waiting for I/O to complete */ - int open_count; /* number of opens */ - int iocount; /* number of pending I/O operations */ - int part; /* BSD partition number (-1 if none) */ - int flags; /* Linux file flags */ - int mode; /* Linux file mode */ - kdev_t dev; /* Linux device number */ - ipc_port_t port; /* port representing device */ - struct device_struct *ds; /* driver operation table entry */ - struct device device; /* generic device header */ - struct name_map *np; /* name to inode map */ - struct block_data *next; /* forward link */ -}; - -/* List of open devices. */ -static struct block_data *open_list; - -/* Forward declarations. */ - -extern struct device_emulation_ops linux_block_emulation_ops; - -static io_return_t device_close (void *); - -/* Return a send right for block device BD. */ -static ipc_port_t -dev_to_port (void *bd) -{ - return (bd - ? ipc_port_make_send (((struct block_data *) bd)->port) - : IP_NULL); -} - -/* Return 1 if C is a letter of the alphabet. */ -static inline int -isalpha (int c) -{ - return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); -} - -/* Return 1 if C is a digit. */ -static inline int -isdigit (int c) -{ - return c >= '0' && c <= '9'; -} - -/* Find the name map entry for device NAME. - Set *SLICE to be the DOS partition and - *PART the BSD/Mach partition, if any. */ -static struct name_map * -find_name (char *name, int *slice, int *part) -{ - char *p, *q; - int i, len; - struct name_map *np; - - /* Parse name into name, unit, DOS partition (slice) and partition. */ - for (*slice = 0, *part = -1, p = name; isalpha (*p); p++) - ; - if (p == name || ! isdigit (*p)) - return NULL; - do - p++; - while (isdigit (*p)); - if (*p) - { - q = p; - if (*q == 's' && isdigit (*(q + 1))) - { - q++; - do - *slice = *slice * 10 + *q++ - '0'; - while (isdigit (*q)); - if (! *q) - goto find_major; - } - if (! isalpha (*q) || *(q + 1)) - return NULL; - *part = *q - 'a'; - } - -find_major: - /* Convert name to major number. */ - for (i = 0, np = name_to_major; i < NUM_NAMES; i++, np++) - { - len = strlen (np->name); - if (len == (p - name) && ! strncmp (np->name, name, len)) - return np; - } - return NULL; -} - -/* Attempt to read a BSD disklabel from device DEV. */ -static struct disklabel * -read_bsd_label (kdev_t dev) -{ - int bsize, bshift; - struct buffer_head *bh; - struct disklabel *dlp, *lp = NULL; - - get_block_size (dev, &bsize, &bshift); - bh = bread (dev, LBLLOC >> (bshift - 9), bsize); - if (bh) - { - dlp = (struct disklabel *) (bh->b_data + ((LBLLOC << 9) & (bsize - 1))); - if (dlp->d_magic == DISKMAGIC && dlp->d_magic2 == DISKMAGIC) - { - lp = (struct disklabel *) kalloc (sizeof (*lp)); - assert (lp); - memcpy (lp, dlp, sizeof (*lp)); - } - __brelse (bh); - } - return lp; -} - -/* Attempt to read a VTOC from device DEV. */ -static struct disklabel * -read_vtoc (kdev_t dev) -{ - int bshift, bsize, i; - struct buffer_head *bh; - struct evtoc *evp; - struct disklabel *lp = NULL; - - get_block_size (dev, &bsize, &bshift); - bh = bread (dev, PDLOCATION >> (bshift - 9), bsize); - if (bh) - { - evp = (struct evtoc *) (bh->b_data + ((PDLOCATION << 9) & (bsize - 1))); - if (evp->sanity == VTOC_SANE) - { - lp = (struct disklabel *) kalloc (sizeof (*lp)); - assert (lp); - lp->d_npartitions = evp->nparts; - if (lp->d_npartitions > MAXPARTITIONS) - lp->d_npartitions = MAXPARTITIONS; - for (i = 0; i < lp->d_npartitions; i++) - { - lp->d_partitions[i].p_size = evp->part[i].p_size; - lp->d_partitions[i].p_offset = evp->part[i].p_start; - lp->d_partitions[i].p_fstype = FS_BSDFFS; - } - } - __brelse (bh); - } - return lp; -} - -/* Initialize BSD/Mach partition table for device - specified by NP, DS and *DEV. Check SLICE and *PART for validity. */ -static kern_return_t -init_partition (struct name_map *np, kdev_t *dev, - struct device_struct *ds, int slice, int *part) -{ - int err, i, j; - struct disklabel *lp; - struct gendisk *gd = ds->gd; - struct partition *p; - struct temp_data *d = current_thread ()->pcb->data; - - if (! gd) - { - *part = -1; - return 0; - } - if (ds->labels) - goto check; - ds->labels = (struct disklabel **) kalloc (sizeof (struct disklabel *) - * gd->max_nr * gd->max_p); - if (! ds->labels) - return D_NO_MEMORY; - memset ((void *) ds->labels, 0, - sizeof (struct disklabel *) * gd->max_nr * gd->max_p); - for (i = 1; i < gd->max_p; i++) - { - d->inode.i_rdev = *dev | i; - if (gd->part[MINOR (d->inode.i_rdev)].nr_sects <= 0 - || gd->part[MINOR (d->inode.i_rdev)].start_sect < 0) - continue; - linux_intr_pri = SPL5; - d->file.f_flags = 0; - d->file.f_mode = O_RDONLY; - if (ds->fops->open && (*ds->fops->open) (&d->inode, &d->file)) - continue; - lp = read_bsd_label (d->inode.i_rdev); - if (! lp) - lp = read_vtoc (d->inode.i_rdev); - if (ds->fops->release) - (*ds->fops->release) (&d->inode, &d->file); - if (lp) - { - if (ds->default_slice == 0) - ds->default_slice = i; - for (j = 0, p = lp->d_partitions; j < lp->d_npartitions; j++, p++) - { - if (p->p_offset < 0 || p->p_size <= 0) - continue; - - /* Sanity check. */ - if (p->p_size > gd->part[MINOR (d->inode.i_rdev)].nr_sects) - p->p_size = gd->part[MINOR (d->inode.i_rdev)].nr_sects; - } - } - ds->labels[MINOR (d->inode.i_rdev)] = lp; - } - -check: - if (*part >= 0 && slice == 0) - slice = ds->default_slice; - if (*part >= 0 && slice == 0) - return D_NO_SUCH_DEVICE; - *dev = MKDEV (MAJOR (*dev), MINOR (*dev) | slice); - if (slice >= gd->max_p - || gd->part[MINOR (*dev)].start_sect < 0 - || gd->part[MINOR (*dev)].nr_sects <= 0) - return D_NO_SUCH_DEVICE; - if (*part >= 0) - { - lp = ds->labels[MINOR (*dev)]; - if (! lp - || *part >= lp->d_npartitions - || lp->d_partitions[*part].p_offset < 0 - || lp->d_partitions[*part].p_size <= 0) - return D_NO_SUCH_DEVICE; - } - return 0; -} - -#define DECL_DATA struct temp_data td -#define INIT_DATA() \ -{ \ - queue_init (&td.pages); \ - td.inode.i_rdev = bd->dev; \ - td.file.f_mode = bd->mode; \ - td.file.f_flags = bd->flags; \ - current_thread ()->pcb->data = &td; \ -} - -static io_return_t -device_open (ipc_port_t reply_port, mach_msg_type_name_t reply_port_type, - dev_mode_t mode, char *name, device_t *devp) -{ - int part, slice, err; - unsigned major, minor; - kdev_t dev; - ipc_port_t notify; - struct block_data *bd = NULL, *bdp; - struct device_struct *ds; - struct gendisk *gd; - struct name_map *np; - DECL_DATA; - - np = find_name (name, &slice, &part); - if (! np) - return D_NO_SUCH_DEVICE; - major = np->major; - ds = &blkdevs[major]; - - /* Check that driver exists. */ - if (! ds->fops) - return D_NO_SUCH_DEVICE; - - /* Wait for any other open/close calls to finish. */ - ds = &blkdevs[major]; - while (ds->busy) - { - ds->want = 1; - assert_wait ((event_t) ds, FALSE); - thread_block (0); - } - ds->busy = 1; - - /* Compute minor number. */ - if (! ds->gd) - { - for (gd = gendisk_head; gd && gd->major != major; gd = gd->next) - ; - ds->gd = gd; - } - minor = np->unit; - gd = ds->gd; - if (gd) - minor <<= gd->minor_shift; - dev = MKDEV (major, minor); - - queue_init (&td.pages); - current_thread ()->pcb->data = &td; - - /* Check partition. */ - err = init_partition (np, &dev, ds, slice, &part); - if (err) - goto out; - - /* Initialize file structure. */ - switch (mode & (D_READ|D_WRITE)) - { - case D_WRITE: - td.file.f_mode = O_WRONLY; - break; - - case D_READ|D_WRITE: - td.file.f_mode = O_RDWR; - break; - - default: - td.file.f_mode = O_RDONLY; - break; - } - td.file.f_flags = (mode & D_NODELAY) ? O_NDELAY : 0; - - /* Check if the device is currently open. */ - for (bdp = open_list; bdp; bdp = bdp->next) - if (bdp->dev == dev - && bdp->part == part - && bdp->mode == td.file.f_mode - && bdp->flags == td.file.f_flags) - { - bd = bdp; - goto out; - } - - /* Open the device. */ - if (ds->fops->open) - { - td.inode.i_rdev = dev; - linux_intr_pri = SPL5; - err = (*ds->fops->open) (&td.inode, &td.file); - if (err) - { - err = linux_to_mach_error (err); - goto out; - } - } - - /* Allocate and initialize device data. */ - bd = (struct block_data *) kalloc (sizeof (struct block_data)); - if (! bd) - { - err = D_NO_MEMORY; - goto bad; - } - bd->want = 0; - bd->open_count = 0; - bd->iocount = 0; - bd->part = part; - bd->ds = ds; - bd->device.emul_data = bd; - bd->device.emul_ops = &linux_block_emulation_ops; - bd->dev = dev; - bd->mode = td.file.f_mode; - bd->flags = td.file.f_flags; - bd->port = ipc_port_alloc_kernel (); - if (bd->port == IP_NULL) - { - err = KERN_RESOURCE_SHORTAGE; - goto bad; - } - ipc_kobject_set (bd->port, (ipc_kobject_t) &bd->device, IKOT_DEVICE); - notify = ipc_port_make_sonce (bd->port); - ip_lock (bd->port); - ipc_port_nsrequest (bd->port, 1, notify, ¬ify); - assert (notify == IP_NULL); - goto out; - -bad: - if (ds->fops->release) - (*ds->fops->release) (&td.inode, &td.file); - -out: - ds->busy = 0; - if (ds->want) - { - ds->want = 0; - thread_wakeup ((event_t) ds); - } - - if (bd && bd->open_count > 0) - { - if (err) - *devp = NULL; - else - { - *devp = &bd->device; - bd->open_count++; - } - return err; - } - - if (err) - { - if (bd) - { - if (bd->port != IP_NULL) - { - ipc_kobject_set (bd->port, IKO_NULL, IKOT_NONE); - ipc_port_dealloc_kernel (bd->port); - } - kfree ((vm_offset_t) bd, sizeof (struct block_data)); - bd = NULL; - } - } - else - { - bd->open_count = 1; - bd->next = open_list; - open_list = bd; - } - - if (IP_VALID (reply_port)) - ds_device_open_reply (reply_port, reply_port_type, err, dev_to_port (bd)); - else if (! err) - device_close (bd); - - return MIG_NO_REPLY; -} - -static io_return_t -device_close (void *d) -{ - struct block_data *bd = d, *bdp, **prev; - struct device_struct *ds = bd->ds; - DECL_DATA; - - INIT_DATA (); - - /* Wait for any other open/close to complete. */ - while (ds->busy) - { - ds->want = 1; - assert_wait ((event_t) ds, FALSE); - thread_block (0); - } - ds->busy = 1; - - if (--bd->open_count == 0) - { - /* Wait for pending I/O to complete. */ - while (bd->iocount > 0) - { - bd->want = 1; - assert_wait ((event_t) bd, FALSE); - thread_block (0); - } - - /* Remove device from open list. */ - prev = &open_list; - bdp = open_list; - while (bdp) - { - if (bdp == bd) - { - *prev = bdp->next; - break; - } - prev = &bdp->next; - bdp = bdp->next; - } - - assert (bdp == bd); - - if (ds->fops->release) - (*ds->fops->release) (&td.inode, &td.file); - - ipc_kobject_set (bd->port, IKO_NULL, IKOT_NONE); - ipc_port_dealloc_kernel (bd->port); - kfree ((vm_offset_t) bd, sizeof (struct block_data)); - } - - ds->busy = 0; - if (ds->want) - { - ds->want = 0; - thread_wakeup ((event_t) ds); - } - return D_SUCCESS; -} - -#define MAX_COPY (VM_MAP_COPY_PAGE_LIST_MAX << PAGE_SHIFT) - -/* Check block BN and size COUNT for I/O validity - to from device BD. Set *OFF to the byte offset - where I/O is to begin and return the size of transfer. */ -static int -check_limit (struct block_data *bd, loff_t *off, long bn, int count) -{ - int major, minor; - long maxsz, sz; - struct disklabel *lp = NULL; - - if (count <= 0) - return count; - - major = MAJOR (bd->dev); - minor = MINOR (bd->dev); - - if (bd->ds->gd) - { - if (bd->part >= 0) - { - assert (bd->ds->labels); - assert (bd->ds->labels[minor]); - lp = bd->ds->labels[minor]; - maxsz = lp->d_partitions[bd->part].p_size; - } - else - maxsz = bd->ds->gd->part[minor].nr_sects; - } - else - { - assert (blk_size[major]); - maxsz = blk_size[major][minor] << (BLOCK_SIZE_BITS - 9); - } - assert (maxsz > 0); - sz = maxsz - bn; - if (sz <= 0) - return sz; - if (sz < ((count + 511) >> 9)) - count = sz << 9; - if (lp) - bn += (lp->d_partitions[bd->part].p_offset - - bd->ds->gd->part[minor].start_sect); - *off = (loff_t) bn << 9; - bd->iocount++; - return count; -} - -static io_return_t -device_write (void *d, ipc_port_t reply_port, - mach_msg_type_name_t reply_port_type, dev_mode_t mode, - recnum_t bn, io_buf_ptr_t data, unsigned int orig_count, - int *bytes_written) -{ - int resid, amt, i; - int count = (int) orig_count; - io_return_t err = 0; - vm_map_copy_t copy; - vm_offset_t addr, uaddr; - vm_size_t len, size; - struct block_data *bd = d; - DECL_DATA; - - INIT_DATA (); - - *bytes_written = 0; - - if (bd->mode == O_RDONLY) - return D_INVALID_OPERATION; - if (! bd->ds->fops->write) - return D_READ_ONLY; - count = check_limit (bd, &td.file.f_pos, bn, count); - if (count < 0) - return D_INVALID_SIZE; - if (count == 0) - { - vm_map_copy_discard (copy); - return 0; - } - - resid = count; - copy = (vm_map_copy_t) data; - uaddr = copy->offset; - - /* Allocate a kernel buffer. */ - size = round_page (uaddr + count) - trunc_page (uaddr); - if (size > MAX_COPY) - size = MAX_COPY; - addr = vm_map_min (device_io_map); - err = vm_map_enter (device_io_map, &addr, size, 0, TRUE, - NULL, 0, FALSE, VM_PROT_READ|VM_PROT_WRITE, - VM_PROT_READ|VM_PROT_WRITE, VM_INHERIT_NONE); - if (err) - { - vm_map_copy_discard (copy); - goto out; - } - - /* Determine size of I/O this time around. */ - len = size - (uaddr & PAGE_MASK); - if (len > resid) - len = resid; - - while (1) - { - /* Map user pages. */ - for (i = 0; i < copy->cpy_npages; i++) - pmap_enter (vm_map_pmap (device_io_map), - addr + (i << PAGE_SHIFT), - copy->cpy_page_list[i]->phys_addr, - VM_PROT_READ|VM_PROT_WRITE, TRUE); - - /* Do the write. */ - amt = (*bd->ds->fops->write) (&td.inode, &td.file, - (char *) addr + (uaddr & PAGE_MASK), len); - - /* Unmap pages and deallocate copy. */ - pmap_remove (vm_map_pmap (device_io_map), - addr, addr + (copy->cpy_npages << PAGE_SHIFT)); - vm_map_copy_discard (copy); - - /* Check result of write. */ - if (amt > 0) - { - resid -= amt; - if (resid == 0) - break; - uaddr += amt; - } - else - { - if (amt < 0) - err = linux_to_mach_error (amt); - break; - } - - /* Determine size of I/O this time around and copy in pages. */ - len = round_page (uaddr + resid) - trunc_page (uaddr); - if (len > MAX_COPY) - len = MAX_COPY; - len -= uaddr & PAGE_MASK; - if (len > resid) - len = resid; - err = vm_map_copyin_page_list (current_map (), uaddr, len, - FALSE, FALSE, ©, FALSE); - if (err) - break; - } - - /* Delete kernel buffer. */ - vm_map_remove (device_io_map, addr, addr + size); - -out: - if (--bd->iocount == 0 && bd->want) - { - bd->want = 0; - thread_wakeup ((event_t) bd); - } - if (IP_VALID (reply_port)) - ds_device_write_reply (reply_port, reply_port_type, err, count - resid); - return MIG_NO_REPLY; -} - -static io_return_t -device_read (void *d, ipc_port_t reply_port, - mach_msg_type_name_t reply_port_type, dev_mode_t mode, - recnum_t bn, int count, io_buf_ptr_t *data, - unsigned *bytes_read) -{ - boolean_t dirty; - int resid, amt; - io_return_t err = 0; - queue_head_t pages; - vm_map_copy_t copy; - vm_offset_t addr, offset, alloc_offset, o; - vm_object_t object; - vm_page_t m; - vm_size_t len, size; - struct block_data *bd = d; - DECL_DATA; - - INIT_DATA (); - - *data = 0; - *bytes_read = 0; - - if (! bd->ds->fops->read) - return D_INVALID_OPERATION; - count = check_limit (bd, &td.file.f_pos, bn, count); - if (count < 0) - return D_INVALID_SIZE; - if (count == 0) - return 0; - - /* Allocate an object to hold the data. */ - size = round_page (count); - object = vm_object_allocate (size); - if (! object) - { - err = D_NO_MEMORY; - goto out; - } - alloc_offset = offset = 0; - resid = count; - - /* Allocate a kernel buffer. */ - addr = vm_map_min (device_io_map); - if (size > MAX_COPY) - size = MAX_COPY; - err = vm_map_enter (device_io_map, &addr, size, 0, TRUE, NULL, - 0, FALSE, VM_PROT_READ|VM_PROT_WRITE, - VM_PROT_READ|VM_PROT_WRITE, VM_INHERIT_NONE); - if (err) - goto out; - - queue_init (&pages); - - while (resid) - { - /* Determine size of I/O this time around. */ - len = round_page (offset + resid) - trunc_page (offset); - if (len > MAX_COPY) - len = MAX_COPY; - - /* Map any pages left from previous operation. */ - o = trunc_page (offset); - queue_iterate (&pages, m, vm_page_t, pageq) - { - pmap_enter (vm_map_pmap (device_io_map), - addr + o - trunc_page (offset), - m->phys_addr, VM_PROT_READ|VM_PROT_WRITE, TRUE); - o += PAGE_SIZE; - } - assert (o == alloc_offset); - - /* Allocate and map pages. */ - while (alloc_offset < trunc_page (offset) + len) - { - while ((m = vm_page_grab ()) == 0) - VM_PAGE_WAIT (0); - assert (! m->active && ! m->inactive); - m->busy = TRUE; - queue_enter (&pages, m, vm_page_t, pageq); - pmap_enter (vm_map_pmap (device_io_map), - addr + alloc_offset - trunc_page (offset), - m->phys_addr, VM_PROT_READ|VM_PROT_WRITE, TRUE); - alloc_offset += PAGE_SIZE; - } - - /* Do the read. */ - amt = len - (offset & PAGE_MASK); - if (amt > resid) - amt = resid; - amt = (*bd->ds->fops->read) (&td.inode, &td.file, - (char *) addr + (offset & PAGE_MASK), amt); - - /* Compute number of pages to insert in object. */ - o = trunc_page (offset); - if (amt > 0) - { - dirty = TRUE; - resid -= amt; - if (resid == 0) - { - /* Zero any unused space. */ - if (offset + amt < o + len) - memset ((void *) (addr + offset - o + amt), - 0, o + len - offset - amt); - offset = o + len; - } - else - offset += amt; - } - else - { - dirty = FALSE; - offset = o + len; - } - - /* Unmap pages and add them to the object. */ - pmap_remove (vm_map_pmap (device_io_map), addr, addr + len); - vm_object_lock (object); - while (o < trunc_page (offset)) - { - m = (vm_page_t) queue_first (&pages); - assert (! queue_end (&pages, (queue_entry_t) m)); - queue_remove (&pages, m, vm_page_t, pageq); - assert (m->busy); - vm_page_lock_queues (); - if (dirty) - { - PAGE_WAKEUP_DONE (m); - m->dirty = TRUE; - vm_page_insert (m, object, o); - } - else - vm_page_free (m); - vm_page_unlock_queues (); - o += PAGE_SIZE; - } - vm_object_unlock (object); - if (amt <= 0) - { - if (amt < 0) - err = linux_to_mach_error (amt); - break; - } - } - - /* Delete kernel buffer. */ - vm_map_remove (device_io_map, addr, addr + size); - - assert (queue_empty (&pages)); - -out: - if (! err) - err = vm_map_copyin_object (object, 0, round_page (count), ©); - if (! err) - { - *data = (io_buf_ptr_t) copy; - *bytes_read = count - resid; - } - else - vm_object_deallocate (object); - if (--bd->iocount == 0 && bd->want) - { - bd->want = 0; - thread_wakeup ((event_t) bd); - } - return err; -} - -static io_return_t -device_get_status (void *d, dev_flavor_t flavor, dev_status_t status, - mach_msg_type_number_t *status_count) -{ - struct block_data *bd = d; - - switch (flavor) - { - case DEV_GET_SIZE: - if (*status_count != DEV_GET_SIZE_COUNT) - return D_INVALID_SIZE; - if (disk_major (MAJOR (bd->dev))) - { - assert (bd->ds->gd); - - if (bd->part >= 0) - { - struct disklabel *lp; - - assert (bd->ds->labels); - lp = bd->ds->labels[MINOR (bd->dev)]; - assert (lp); - (status[DEV_GET_SIZE_DEVICE_SIZE] - = lp->d_partitions[bd->part].p_size << 9); - } - else - (status[DEV_GET_SIZE_DEVICE_SIZE] - = bd->ds->gd->part[MINOR (bd->dev)].nr_sects << 9); - } - else - { - assert (blk_size[MAJOR (bd->dev)]); - (status[DEV_GET_SIZE_DEVICE_SIZE] - = (blk_size[MAJOR (bd->dev)][MINOR (bd->dev)] - << BLOCK_SIZE_BITS)); - } - /* It would be nice to return the block size as reported by - the driver, but a lot of user level code assumes the sector - size to be 512. */ - status[DEV_GET_SIZE_RECORD_SIZE] = 512; - break; - - default: - return D_INVALID_OPERATION; - } - - return D_SUCCESS; -} - -struct device_emulation_ops linux_block_emulation_ops = -{ - NULL, - NULL, - dev_to_port, - device_open, - device_close, - device_write, - NULL, - device_read, - NULL, - NULL, - device_get_status, - NULL, - NULL, - NULL, - NULL, - NULL -}; diff --git a/i386/i386at/gpl/linux/linux_dma.c b/i386/i386at/gpl/linux/linux_dma.c deleted file mode 100644 index aab0fa8e..00000000 --- a/i386/i386at/gpl/linux/linux_dma.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Linux DMA channel management. - * Copyright (C) 1995 Shantanu Goel. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#define MACH_INCLUDE -#include <linux/errno.h> -#include <asm/dma.h> - -/* - * Bitmap of allocated/free DMA channels. - */ -static int dma_busy = 0x10; - -/* - * Allocate a DMA channel. - */ -int -request_dma(unsigned int drq, const char *name) -{ - if (drq > 7) - panic("request_dma: bad DRQ number"); - if (dma_busy & (1 << drq)) - return (-LINUX_EBUSY); - dma_busy |= 1 << drq; - return (0); -} - -/* - * Free a DMA channel. - */ -void -free_dma(unsigned int drq) -{ - if (drq > 7) - panic("free_dma: bad DRQ number"); - dma_busy &= ~(1 << drq); -} diff --git a/i386/i386at/gpl/linux/linux_emul.h b/i386/i386at/gpl/linux/linux_emul.h deleted file mode 100644 index dc338020..00000000 --- a/i386/i386at/gpl/linux/linux_emul.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Defintions for Linux driver emulation. - * - * Copyright (C) 1996 The University of Utah and the Computer Systems - * Laboratory at the University of Utah (CSL) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Author: Shantanu Goel, University of Utah CSL - */ - -#include <i386/ipl.h> - -extern int linux_auto_config; -extern int linux_intr_pri; - -int linux_to_mach_error (int); -void *alloc_contig_mem (unsigned, unsigned, unsigned, vm_page_t *); -void free_contig_mem (vm_page_t); -void collect_buffer_pages (void); diff --git a/i386/i386at/gpl/linux/linux_init.c b/i386/i386at/gpl/linux/linux_init.c deleted file mode 100644 index 4e7b006a..00000000 --- a/i386/i386at/gpl/linux/linux_init.c +++ /dev/null @@ -1,416 +0,0 @@ -/* - * Linux initialization. - * - * Copyright (C) 1996 The University of Utah and the Computer Systems - * Laboratory at the University of Utah (CSL) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Author: Shantanu Goel, University of Utah CSL - */ - -/* - * linux/init/main.c - * - * Copyright (C) 1991, 1992 Linus Torvalds - */ - -#include <sys/types.h> - -#include <mach/vm_param.h> -#include <mach/vm_prot.h> -#include <mach/machine.h> - -#include <vm/vm_page.h> - -#include <i386/ipl.h> -#include <i386/pic.h> -#include <i386/pit.h> -#include <i386/machspl.h> -#include <i386/pmap.h> -#include <i386/vm_param.h> - -#include <i386at/gpl/linux/linux_emul.h> - -#define MACH_INCLUDE -#include <linux/sched.h> -#include <linux/mm.h> -#include <linux/interrupt.h> -#include <linux/delay.h> -#include <linux/ioport.h> -#include <linux/string.h> - -#include <asm/system.h> - -#include <i386/device-drivers.h> - -/* - * Set if the machine has an EISA bus. - */ -int EISA_bus = 0; - -/* - * Timing loop count. - */ -unsigned long loops_per_sec = 1; - -/* - * End of physical memory. - */ -unsigned long high_memory; - -/* - * Flag to indicate auto-configuration is in progress. - */ -int linux_auto_config = 1; - -/* - * Hard drive parameters obtained from the BIOS. - */ -struct drive_info_struct { - char dummy[32]; -} drive_info; - -/* - * Forward declarations. - */ -static void calibrate_delay(void); - -extern int hz; -extern vm_offset_t phys_last_addr; - -extern void timer_bh(void *); -extern void tqueue_bh(void *); -extern void startrtclock(void); -extern void linux_version_init(void); -extern void linux_kmem_init(void); -extern unsigned long pci_init(unsigned long, unsigned long); -extern void linux_net_emulation_init (void); -extern void device_setup(void); -extern void linux_printk(char *, ...); -extern int linux_timer_intr(); - -/* - * Amount of contiguous memory to allocate for initialization. - */ -#define CONTIG_ALLOC (512 * 1024) - -/* - * Initialize Linux drivers. - */ -void -linux_init() -{ - char *p; - int i, addr; - int (*old_clock_handler)(), old_clock_pri; - unsigned memory_start, memory_end; - vm_page_t pages; - - /* - * Initialize memory size. - */ - high_memory = phys_last_addr; - - /* - * Ensure interrupts are disabled. - */ - (void) splhigh(); - - /* - * Program counter 0 of 8253 to interrupt hz times per second. - */ - outb(PITCTL_PORT, PIT_C0|PIT_SQUAREMODE|PIT_READMODE); - outb(PITCTR0_PORT, CLKNUM / hz); - outb(PITCTR0_PORT, (CLKNUM / hz) >> 8); - - /* - * Install our clock interrupt handler. - */ - old_clock_handler = ivect[0]; - old_clock_pri = intpri[0]; - ivect[0] = linux_timer_intr; - intpri[0] = SPLHI; - form_pic_mask(); - - /* - * Enable interrupts. - */ - (void) spl0(); - - /* - * Set Linux version. - */ - linux_version_init(); - - /* - * Check if the machine has an EISA bus. - */ - p = (char *)0x0FFFD9; - if (*p++ == 'E' && *p++ == 'I' && *p++ == 'S' && *p == 'A') - EISA_bus = 1; - - /* - * Permanently allocate standard device ports. - */ - request_region(0x00, 0x20, "dma1"); - request_region(0x40, 0x20, "timer"); - request_region(0x70, 0x10, "rtc"); - request_region(0x80, 0x20, "dma page reg"); - request_region(0xc0, 0x20, "dma2"); - request_region(0xf0, 0x02, "fpu"); - request_region(0xf8, 0x08, "fpu"); - - /* - * Install software interrupt handlers. - */ - bh_base[TIMER_BH].routine = timer_bh; - bh_base[TIMER_BH].data = 0; - enable_bh(TIMER_BH); - bh_base[TQUEUE_BH].routine = tqueue_bh; - bh_base[TQUEUE_BH].data = 0; - enable_bh(TQUEUE_BH); - - /* - * Set loop count. - */ - calibrate_delay(); - - /* - * Initialize drive info. - */ - addr = *((unsigned *)phystokv(0x104)); - memcpy (&drive_info, - (void *)((addr & 0xffff) + ((addr >> 12) & 0xffff0)), 16); - addr = *((unsigned *)phystokv(0x118)); - memcpy ((char *)&drive_info + 16, - (void *)((addr & 0xffff) + ((addr >> 12) & 0xffff0)), 16); - - /* - * Initialize Linux memory allocator. - */ - linux_kmem_init(); - - /* - * Allocate contiguous memory below 16 MB. - */ - memory_start = (unsigned long)alloc_contig_mem(CONTIG_ALLOC, - 16 * 1024 * 1024, - 0, &pages); - if (memory_start == 0) - panic("linux_init: alloc_contig_mem failed"); - memory_end = memory_start + CONTIG_ALLOC; - - /* - * Initialize PCI bus. - */ - memory_start = pci_init(memory_start, memory_end); - - if (memory_start > memory_end) - panic("linux_init: ran out memory"); - - /* - * Free unused memory. - */ - while (pages && pages->phys_addr < round_page(memory_start)) - pages = (vm_page_t)pages->pageq.next; - if (pages) - free_contig_mem(pages); - - /* - * Initialize devices. - */ -#ifdef CONFIG_INET - linux_net_emulation_init(); -#endif - cli(); - device_setup(); - - /* - * Disable interrupts. - */ - (void) splhigh(); - - /* - * Restore clock interrupt handler. - */ - ivect[0] = old_clock_handler; - intpri[0] = old_clock_pri; - form_pic_mask(); - - linux_auto_config = 0; -} - -#ifndef NBPW -#define NBPW 32 -#endif - -/* - * Allocate contiguous memory with the given constraints. - * This routine is horribly inefficient but it is presently - * only used during initialization so it's not that bad. - */ -void * -alloc_contig_mem(unsigned size, unsigned limit, - unsigned mask, vm_page_t *pages) -{ - int i, j, bits_len; - unsigned *bits, len; - void *m; - vm_page_t p, page_list, tail, prev; - vm_offset_t addr, max_addr; - - if (size == 0) - return (NULL); - size = round_page(size); - if ((size >> PAGE_SHIFT) > vm_page_free_count) - return (NULL); - - /* Allocate bit array. */ - max_addr = phys_last_addr; - if (max_addr > limit) - max_addr = limit; - bits_len = ((((max_addr >> PAGE_SHIFT) + NBPW - 1) / NBPW) - * sizeof(unsigned)); - bits = (unsigned *)kalloc(bits_len); - if (!bits) - return (NULL); - memset (bits, 0, bits_len); - - /* - * Walk the page free list and set a bit for every usable page. - */ - simple_lock(&vm_page_queue_free_lock); - p = vm_page_queue_free; - while (p) { - if (p->phys_addr < limit) - (bits[(p->phys_addr >> PAGE_SHIFT) / NBPW] - |= 1 << ((p->phys_addr >> PAGE_SHIFT) % NBPW)); - p = (vm_page_t)p->pageq.next; - } - - /* - * Scan bit array for contiguous pages. - */ - len = 0; - m = NULL; - for (i = 0; len < size && i < bits_len / sizeof (unsigned); i++) - for (j = 0; len < size && j < NBPW; j++) - if (!(bits[i] & (1 << j))) { - len = 0; - m = NULL; - } else { - if (len == 0) { - addr = ((vm_offset_t)(i * NBPW + j) - << PAGE_SHIFT); - if ((addr & mask) == 0) { - len += PAGE_SIZE; - m = (void *) addr; - } - } else - len += PAGE_SIZE; - } - - if (len != size) { - simple_unlock(&vm_page_queue_free_lock); - kfree ((vm_offset_t)bits, bits_len); - return (NULL); - } - - /* - * Remove pages from free list - * and construct list to return to caller. - */ - page_list = NULL; - for (len = 0; len < size; len += PAGE_SIZE, addr += PAGE_SIZE) { - prev = NULL; - for (p = vm_page_queue_free; p; p = (vm_page_t)p->pageq.next) { - if (p->phys_addr == addr) - break; - prev = p; - } - if (!p) - panic("alloc_contig_mem: page not on free list"); - if (prev) - prev->pageq.next = p->pageq.next; - else - vm_page_queue_free = (vm_page_t)p->pageq.next; - p->free = FALSE; - p->pageq.next = NULL; - if (!page_list) - page_list = tail = p; - else { - tail->pageq.next = (queue_entry_t)p; - tail = p; - } - vm_page_free_count--; - } - - simple_unlock(&vm_page_queue_free_lock); - kfree((vm_offset_t)bits, bits_len); - if (pages) - *pages = page_list; - return (m); -} - -/* - * Free memory allocated by alloc_contig_mem. - */ -void -free_contig_mem(vm_page_t pages) -{ - int i; - vm_page_t p; - - for (p = pages, i = 0; p->pageq.next; p = (vm_page_t)p->pageq.next, i++) - p->free = TRUE; - p->free = TRUE; - simple_lock(&vm_page_queue_free_lock); - vm_page_free_count += i + 1; - p->pageq.next = (queue_entry_t)vm_page_queue_free; - vm_page_queue_free = pages; - simple_unlock(&vm_page_queue_free_lock); -} - -/* - * Calibrate delay loop. - * Lifted straight from Linux. - */ -static void -calibrate_delay() -{ - int ticks; - - /* printk("Calibrating delay loop.. "); */ - while (loops_per_sec <<= 1) { - /* Wait for "start of" clock tick. */ - ticks = jiffies; - while (ticks == jiffies) - /* nothing */; - /* Go .. */ - ticks = jiffies; - __delay(loops_per_sec); - ticks = jiffies - ticks; - if (ticks >= hz) { - loops_per_sec = muldiv(loops_per_sec, - hz, ticks); - /*printk("ok - %lu.%02lu BogoMips\n", - loops_per_sec / 500000, - (loops_per_sec / 5000) % 100);*/ - return; - } - } -/* printk("failed\n");*/ -} diff --git a/i386/i386at/gpl/linux/linux_irq.c b/i386/i386at/gpl/linux/linux_irq.c deleted file mode 100644 index d04e0531..00000000 --- a/i386/i386at/gpl/linux/linux_irq.c +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Linux IRQ management. - * Copyright (C) 1995 Shantanu Goel. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* - * linux/arch/i386/kernel/irq.c - * - * Copyright (C) 1992 Linus Torvalds - */ - -#include <sys/types.h> - -#include <kern/assert.h> - -#include <i386/machspl.h> -#include <i386/ipl.h> -#include <i386/pic.h> - -#define MACH_INCLUDE -#include <linux/sched.h> -#include <linux/interrupt.h> -#include <linux/ptrace.h> -#include <linux/errno.h> -#include <linux/delay.h> -#include <linux/kernel_stat.h> - -#include <asm/system.h> -#include <asm/bitops.h> -#include <asm/irq.h> - -/* - * Priority at which a Linux handler should be called. - * This is used at the time of an IRQ allocation. It is - * set by emulation routines for each class of device. - */ -spl_t linux_intr_pri; - -/* - * Flag indicating an interrupt is being handled. - */ -unsigned long intr_count = 0; - -/* - * List of Linux interrupt handlers. - */ -static void (*linux_handlers[16])(int, struct pt_regs *); - -extern spl_t curr_ipl; -extern int curr_pic_mask; -extern int pic_mask[]; - -extern int intnull(), prtnull(); - -/* - * Generic interrupt handler for Linux devices. - * Set up a fake `struct pt_regs' then call the real handler. - */ -static int -linux_intr(irq) - int irq; -{ - struct pt_regs regs; - - kstat.interrupts[irq]++; - intr_count++; - (*linux_handlers[irq])(irq, ®s); - intr_count--; -} - -/* - * Mask an IRQ. - */ -void -disable_irq(irq) - unsigned int irq; -{ - int i, flags; - - assert (irq < NR_IRQS); - - save_flags(flags); - cli(); - for (i = 0; i < intpri[irq]; i++) - pic_mask[i] |= 1 << irq; - if (curr_pic_mask != pic_mask[curr_ipl]) { - curr_pic_mask = pic_mask[curr_ipl]; - outb(PIC_MASTER_OCW, curr_pic_mask); - outb(PIC_SLAVE_OCW, curr_pic_mask >> 8); - } - restore_flags(flags); -} - -/* - * Unmask an IRQ. - */ -void -enable_irq(irq) - unsigned int irq; -{ - int mask, i, flags; - - assert (irq < NR_IRQS); - - mask = 1 << irq; - if (irq >= 8) - mask |= 1 << 2; - save_flags(flags); - cli(); - for (i = 0; i < intpri[irq]; i++) - pic_mask[i] &= ~mask; - if (curr_pic_mask != pic_mask[curr_ipl]) { - curr_pic_mask = pic_mask[curr_ipl]; - outb(PIC_MASTER_OCW, curr_pic_mask); - outb(PIC_SLAVE_OCW, curr_pic_mask >> 8); - } - restore_flags(flags); -} - -/* - * Attach a handler to an IRQ. - */ -int -request_irq(unsigned int irq, void (*handler)(int, struct pt_regs *), - unsigned long flags, const char *device) -{ - assert(irq < 16); - - if (ivect[irq] == intnull || ivect[irq] == prtnull) { - if (!handler) - return (-LINUX_EINVAL); - linux_handlers[irq] = handler; - ivect[irq] = linux_intr; - iunit[irq] = irq; - intpri[irq] = linux_intr_pri; - enable_irq(irq); - return (0); - } - return (-LINUX_EBUSY); -} - -/* - * Deallocate an irq. - */ -void -free_irq(unsigned int irq) -{ - if (irq > 15) - panic("free_irq: bad irq number"); - - disable_irq(irq); - ivect[irq] = (irq == 7) ? prtnull : intnull; - iunit[irq] = irq; - intpri[irq] = SPL0; -} - -/* - * IRQ probe interrupt handler. - */ -void -probe_intr(irq) - int irq; -{ - disable_irq(irq); -} - -/* - * Set for an irq probe. - */ -unsigned long -probe_irq_on() -{ - unsigned i, irqs = 0; - unsigned long delay; - - assert (curr_ipl == 0); - - /* - * Allocate all available IRQs. - */ - for (i = 15; i > 0; i--) - if (request_irq(i, probe_intr, 0, "probe") == 0) - irqs |= 1 << i; - - /* - * Wait for spurious interrupts to mask themselves out. - */ - for (delay = jiffies + 2; delay > jiffies; ) - ; - - /* - * Free IRQs that caused spurious interrupts. - */ - for (i = 15; i > 0; i--) { - if (irqs & (1 << i) & pic_mask[0]) { - irqs ^= 1 << i; - free_irq(i); - } - } - - return (irqs); -} - -/* - * Return the result of an irq probe. - */ -int -probe_irq_off(unsigned long irqs) -{ - unsigned i, irqs_save = irqs; - - assert (curr_ipl == 0); - - irqs &= pic_mask[0]; - - /* - * Deallocate IRQs. - */ - for (i = 15; i > 0; i--) - if (irqs_save & (1 << i)) - free_irq(i); - - /* - * Return IRQ number. - */ - if (!irqs) - return (0); - i = ffz(~irqs); - if (irqs != (irqs & (1 << i))) - i = -i; - return (i); -} diff --git a/i386/i386at/gpl/linux/linux_kmem.c b/i386/i386at/gpl/linux/linux_kmem.c deleted file mode 100644 index e5e44399..00000000 --- a/i386/i386at/gpl/linux/linux_kmem.c +++ /dev/null @@ -1,480 +0,0 @@ -/* - * Linux memory allocation. - * - * Copyright (C) 1996 The University of Utah and the Computer Systems - * Laboratory at the University of Utah (CSL) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Author: Shantanu Goel, University of Utah CSL - * - */ - -#include <sys/types.h> - -#include <mach/mach_types.h> -#include <mach/vm_param.h> - -#include <kern/assert.h> -#include <kern/kalloc.h> - -#include <vm/vm_page.h> - -#include <i386at/gpl/linux/linux_emul.h> - -#define MACH_INCLUDE -#include <linux/sched.h> -#include <linux/malloc.h> -#include <linux/delay.h> - -#include <asm/system.h> - -/* Amount of memory to reserve for Linux memory allocator. - We reserve 64K chunks to stay within DMA limits. - Increase MEM_CHUNKS if the kernel is running out of memory. */ -#define MEM_CHUNK_SIZE (64 * 1024) -#define MEM_CHUNKS 7 - -/* Mininum amount that linux_kmalloc will allocate. */ -#define MIN_ALLOC 12 - -#ifndef NBPW -#define NBPW 32 -#endif - -/* Memory block header. */ -struct blkhdr -{ - unsigned short free; /* 1 if block is free */ - unsigned short size; /* size of block */ -}; - -/* This structure heads a page allocated by linux_kmalloc. */ -struct pagehdr -{ - unsigned size; /* size (multiple of PAGE_SIZE) */ - struct pagehdr *next; /* next header in list */ -}; - -/* This structure describes a memory chunk. */ -struct chunkhdr -{ - unsigned long start; /* start address */ - unsigned long end; /* end address */ - unsigned long bitmap; /* busy/free bitmap of pages */ -}; - -/* Chunks from which pages are allocated. */ -static struct chunkhdr pages_free[MEM_CHUNKS]; - -/* Memory list maintained by linux_kmalloc. */ -static struct pagehdr *memlist; - -/* Some statistics. */ -int num_block_coalesce = 0; -int num_page_collect = 0; -int linux_mem_avail; - -/* Initialize the Linux memory allocator. */ -void -linux_kmem_init () -{ - int i, j; - vm_page_t p, pages; - - for (i = 0; i < MEM_CHUNKS; i++) - { - /* Allocate memory. */ - pages_free[i].start = (unsigned long) alloc_contig_mem (MEM_CHUNK_SIZE, - 16 * 1024 * 1024, - 0xffff, &pages); - - assert (pages_free[i].start); - assert ((pages_free[i].start & 0xffff) == 0); - - /* Sanity check: ensure pages are contiguous and within DMA limits. */ - for (p = pages, j = 0; j < MEM_CHUNK_SIZE - PAGE_SIZE; j += PAGE_SIZE) - { - assert (p->phys_addr < 16 * 1024 * 1024); - assert (p->phys_addr + PAGE_SIZE - == ((vm_page_t) p->pageq.next)->phys_addr); - - p = (vm_page_t) p->pageq.next; - } - - pages_free[i].end = pages_free[i].start + MEM_CHUNK_SIZE; - - /* Initialize free page bitmap. */ - pages_free[i].bitmap = 0; - j = MEM_CHUNK_SIZE >> PAGE_SHIFT; - while (--j >= 0) - pages_free[i].bitmap |= 1 << j; - } - - linux_mem_avail = (MEM_CHUNKS * MEM_CHUNK_SIZE) >> PAGE_SHIFT; -} - -/* Return the number by which the page size should be - shifted such that the resulting value is >= SIZE. */ -static unsigned long -get_page_order (int size) -{ - unsigned long order; - - for (order = 0; (PAGE_SIZE << order) < size; order++) - ; - return order; -} - -#ifdef LINUX_DEV_DEBUG -static void -check_page_list (int line) -{ - unsigned size; - struct pagehdr *ph; - struct blkhdr *bh; - - for (ph = memlist; ph; ph = ph->next) - { - if ((int) ph & PAGE_MASK) - panic ("%s:%d: page header not aligned", __FILE__, line); - - size = 0; - bh = (struct blkhdr *) (ph + 1); - while (bh < (struct blkhdr *) ((void *) ph + ph->size)) - { - size += bh->size + sizeof (struct blkhdr); - bh = (void *) (bh + 1) + bh->size; - } - - if (size + sizeof (struct pagehdr) != ph->size) - panic ("%s:%d: memory list destroyed", __FILE__, line); - } -} -#else -#define check_page_list(line) -#endif - -/* Merge adjacent free blocks in the memory list. */ -static void -coalesce_blocks () -{ - struct pagehdr *ph; - struct blkhdr *bh, *bhp, *ebh; - - num_block_coalesce++; - - for (ph = memlist; ph; ph = ph->next) - { - bh = (struct blkhdr *) (ph + 1); - ebh = (struct blkhdr *) ((void *) ph + ph->size); - while (1) - { - /* Skip busy blocks. */ - while (bh < ebh && ! bh->free) - bh = (struct blkhdr *) ((void *) (bh + 1) + bh->size); - if (bh == ebh) - break; - - /* Merge adjacent free blocks. */ - while (1) - { - bhp = (struct blkhdr *) ((void *) (bh + 1) + bh->size); - if (bhp == ebh) - { - bh = bhp; - break; - } - if (! bhp->free) - { - bh = (struct blkhdr *) ((void *) (bhp + 1) + bhp->size); - break; - } - bh->size += bhp->size + sizeof (struct blkhdr); - } - } - } -} - -/* Allocate SIZE bytes of memory. - The PRIORITY parameter specifies various flags - such as DMA, atomicity, etc. It is not used by Mach. */ -void * -linux_kmalloc (unsigned int size, int priority) -{ - int order, coalesced = 0; - unsigned flags; - struct pagehdr *ph; - struct blkhdr *bh, *new_bh; - - if (size < MIN_ALLOC) - size = MIN_ALLOC; - else - size = (size + sizeof (int) - 1) & ~(sizeof (int) - 1); - - assert (size <= (MEM_CHUNK_SIZE - - sizeof (struct pagehdr) - - sizeof (struct blkhdr))); - - save_flags (flags); - cli (); - -again: - check_page_list (__LINE__); - - /* Walk the page list and find the first free block with size - greater than or equal to the one required. */ - for (ph = memlist; ph; ph = ph->next) - { - bh = (struct blkhdr *) (ph + 1); - while (bh < (struct blkhdr *) ((void *) ph + ph->size)) - { - if (bh->free && bh->size >= size) - { - bh->free = 0; - if (bh->size - size >= MIN_ALLOC + sizeof (struct blkhdr)) - { - /* Split the current block and create a new free block. */ - new_bh = (void *) (bh + 1) + size; - new_bh->free = 1; - new_bh->size = bh->size - size - sizeof (struct blkhdr); - bh->size = size; - } - - check_page_list (__LINE__); - - restore_flags (flags); - return bh + 1; - } - bh = (void *) (bh + 1) + bh->size; - } - } - - check_page_list (__LINE__); - - /* Allocation failed; coalesce free blocks and try again. */ - if (! coalesced) - { - coalesce_blocks (); - coalesced = 1; - goto again; - } - - /* Allocate more pages. */ - order = get_page_order (size - + sizeof (struct pagehdr) - + sizeof (struct blkhdr)); - ph = (struct pagehdr *) __get_free_pages (GFP_KERNEL, order, ~0UL); - if (! ph) - { - restore_flags (flags); - return NULL; - } - - ph->size = PAGE_SIZE << order; - ph->next = memlist; - memlist = ph; - bh = (struct blkhdr *) (ph + 1); - bh->free = 0; - bh->size = ph->size - sizeof (struct pagehdr) - sizeof (struct blkhdr); - if (bh->size - size >= MIN_ALLOC + sizeof (struct blkhdr)) - { - new_bh = (void *) (bh + 1) + size; - new_bh->free = 1; - new_bh->size = bh->size - size - sizeof (struct blkhdr); - bh->size = size; - } - - check_page_list (__LINE__); - - restore_flags (flags); - return bh + 1; -} - -/* Free memory P previously allocated by linux_kmalloc. */ -void -linux_kfree (void *p) -{ - unsigned flags; - struct blkhdr *bh, *bhp; - struct pagehdr *ph; - - assert (((int) p & (sizeof (int) - 1)) == 0); - - save_flags (flags); - cli (); - - check_page_list (__LINE__); - - for (ph = memlist; ph; ph = ph->next) - if (p >= (void *) ph && p < (void *) ph + ph->size) - break; - - assert (ph); - - bh = (struct blkhdr *) p - 1; - - assert (! bh->free); - assert (bh->size >= MIN_ALLOC); - assert ((bh->size & (sizeof (int) - 1)) == 0); - - bh->free = 1; - - check_page_list (__LINE__); - - restore_flags (flags); -} - -/* Free any pages that are not in use. - Called by __get_free_pages when pages are running low. */ -static void -collect_kmalloc_pages () -{ - struct blkhdr *bh; - struct pagehdr *ph, **prev_ph; - - check_page_list (__LINE__); - - coalesce_blocks (); - - check_page_list (__LINE__); - - ph = memlist; - prev_ph = &memlist; - while (ph) - { - bh = (struct blkhdr *) (ph + 1); - if (bh->free && (void *) (bh + 1) + bh->size == (void *) ph + ph->size) - { - *prev_ph = ph->next; - free_pages ((unsigned long) ph, get_page_order (ph->size)); - ph = *prev_ph; - } - else - { - prev_ph = &ph->next; - ph = ph->next; - } - } - - check_page_list (__LINE__); -} - -/* Allocate ORDER + 1 number of physically contiguous pages. - PRIORITY and MAX_ADDR are not used in Mach. - - XXX: This needs to be dynamic. To do that we need to make - the Mach page manipulation routines interrupt safe and they - must provide machine dependant hooks. */ -unsigned long -__get_free_pages (int priority, unsigned long order, unsigned long max_addr) -{ - int i, pages_collected = 0; - unsigned flags, bits, off, j, len; - - assert ((PAGE_SIZE << order) <= MEM_CHUNK_SIZE); - - /* Construct bitmap of contiguous pages. */ - bits = 0; - j = 0; - len = 0; - while (len < (PAGE_SIZE << order)) - { - bits |= 1 << j++; - len += PAGE_SIZE; - } - -again: - save_flags (flags); - cli (); - - /* Search each chunk for the required number of contiguous pages. */ - for (i = 0; i < MEM_CHUNKS; i++) - { - off = 0; - j = bits; - while (MEM_CHUNK_SIZE - off >= (PAGE_SIZE << order)) - { - if ((pages_free[i].bitmap & j) == j) - { - pages_free[i].bitmap &= ~j; - linux_mem_avail -= order + 1; - restore_flags (flags); - return pages_free[i].start + off; - } - j <<= 1; - off += PAGE_SIZE; - } - } - - /* Allocation failed; collect kmalloc and buffer pages - and try again. */ - if (! pages_collected) - { - num_page_collect++; - collect_kmalloc_pages (); - pages_collected = 1; - goto again; - } - - printf ("%s:%d: __get_free_pages: ran out of pages\n", __FILE__, __LINE__); - - restore_flags (flags); - return 0; -} - -/* Free ORDER + 1 number of physically - contiguous pages starting at address ADDR. */ -void -free_pages (unsigned long addr, unsigned long order) -{ - int i; - unsigned flags, bits, len, j; - - assert ((addr & PAGE_MASK) == 0); - - for (i = 0; i < MEM_CHUNKS; i++) - if (addr >= pages_free[i].start && addr < pages_free[i].end) - break; - - assert (i < MEM_CHUNKS); - - /* Contruct bitmap of contiguous pages. */ - len = 0; - j = 0; - bits = 0; - while (len < (PAGE_SIZE << order)) - { - bits |= 1 << j++; - len += PAGE_SIZE; - } - bits <<= (addr - pages_free[i].start) >> PAGE_SHIFT; - - save_flags (flags); - cli (); - - assert ((pages_free[i].bitmap & bits) == 0); - - pages_free[i].bitmap |= bits; - linux_mem_avail += order + 1; - restore_flags (flags); -} - -/* Allocate SIZE bytes of memory. The pages need not be contiguous. */ -void * -vmalloc (unsigned long size) -{ - return (void *) __get_free_pages (GFP_KERNEL, get_page_order (size), ~0UL); -} diff --git a/i386/i386at/gpl/linux/linux_misc.c b/i386/i386at/gpl/linux/linux_misc.c deleted file mode 100644 index 6e7b33b9..00000000 --- a/i386/i386at/gpl/linux/linux_misc.c +++ /dev/null @@ -1,303 +0,0 @@ -/* - * Miscellaneous routines and data for Linux emulation. - * - * Copyright (C) 1996 The University of Utah and the Computer Systems - * Laboratory at the University of Utah (CSL) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Author: Shantanu Goel, University of Utah CSL - */ - -/* - * linux/fs/proc/scsi.c - * (c) 1995 Michael Neuffer neuffer@goofy.zdv.uni-mainz.de - * - * The original version was derived from linux/fs/proc/net.c, - * which is Copyright (C) 1991, 1992 Linus Torvalds. - * Much has been rewritten, but some of the code still remains. - * - * /proc/scsi directory handling functions - * - * last change: 95/07/04 - * - * Initial version: March '95 - * 95/05/15 Added subdirectories for each driver and show every - * registered HBA as a single file. - * 95/05/30 Added rudimentary write support for parameter passing - * 95/07/04 Fixed bugs in directory handling - * 95/09/13 Update to support the new proc-dir tree - * - * TODO: Improve support to write to the driver files - * Add some more comments - */ - -/* - * linux/fs/buffer.c - * - * Copyright (C) 1991, 1992 Linus Torvalds - */ - -#include <sys/types.h> -#include <mach/vm_param.h> -#include <kern/thread.h> -#include <vm/vm_map.h> -#include <vm/vm_page.h> -#include <device/device_types.h> -#include <i386at/gpl/linux/linux_emul.h> - -#define MACH_INCLUDE -#include <linux/errno.h> -#include <linux/mm.h> -#include <linux/fs.h> -#include <linux/blk.h> -#include <linux/proc_fs.h> -#include <linux/kernel_stat.h> - -int (*dispatch_scsi_info_ptr) (int ino, char *buffer, char **start, - off_t offset, int length, int inout) = 0; - -struct kernel_stat kstat; - -int -linux_to_mach_error (int err) -{ - switch (err) - { - case 0: - return D_SUCCESS; - - case -LINUX_EPERM: - return D_INVALID_OPERATION; - - case -LINUX_EIO: - return D_IO_ERROR; - - case -LINUX_ENXIO: - return D_NO_SUCH_DEVICE; - - case -LINUX_EACCES: - return D_INVALID_OPERATION; - - case -LINUX_EFAULT: - return D_INVALID_SIZE; - - case -LINUX_EBUSY: - return D_ALREADY_OPEN; - - case -LINUX_EINVAL: - return D_INVALID_SIZE; - - case -LINUX_EROFS: - return D_READ_ONLY; - - case -LINUX_EWOULDBLOCK: - return D_WOULD_BLOCK; - - default: - printf ("linux_to_mach_error: unknown code %d\n", err); - return D_IO_ERROR; - } -} - -int -issig () -{ - return current_thread ()->wait_result != THREAD_AWAKENED; -} - -int -block_fsync (struct inode *inode, struct file *filp) -{ - return 0; -} - -int -verify_area (int rw, const void *p, unsigned long size) -{ - vm_prot_t prot = (rw == VERIFY_WRITE) ? VM_PROT_WRITE : VM_PROT_READ; - vm_offset_t addr = trunc_page ((vm_offset_t) p); - vm_size_t len = round_page ((vm_size_t) size); - vm_map_entry_t entry; - - vm_map_lock_read (current_map ()); - - while (1) - { - if (! vm_map_lookup_entry (current_map (), addr, &entry) - || (entry->protection & prot) != prot) - { - vm_map_unlock_read (current_map ()); - return -LINUX_EFAULT; - } - if (entry->vme_end - entry->vme_start >= len) - break; - len -= entry->vme_end - entry->vme_start; - addr += entry->vme_end - entry->vme_start; - } - - vm_map_unlock_read (current_map ()); - return 0; -} - -/* - * Print device name (in decimal, hexadecimal or symbolic) - - * at present hexadecimal only. - * Note: returns pointer to static data! - */ -char * -kdevname(kdev_t dev) -{ - static char buffer[32]; - sprintf(buffer, "%02x:%02x", MAJOR(dev), MINOR(dev)); - return buffer; -} - -/* RO fail safe mechanism */ - -static long ro_bits[MAX_BLKDEV][8]; - -int -is_read_only(kdev_t dev) -{ - int minor,major; - - major = MAJOR(dev); - minor = MINOR(dev); - if (major < 0 || major >= MAX_BLKDEV) return 0; - return ro_bits[major][minor >> 5] & (1 << (minor & 31)); -} - -void -set_device_ro(kdev_t dev,int flag) -{ - int minor,major; - - major = MAJOR(dev); - minor = MINOR(dev); - if (major < 0 || major >= MAX_BLKDEV) return; - if (flag) ro_bits[major][minor >> 5] |= 1 << (minor & 31); - else ro_bits[major][minor >> 5] &= ~(1 << (minor & 31)); -} - -/* - * linux/lib/string.c - * - * Copyright (C) 1991, 1992 Linus Torvalds - */ - -/* - * stupid library routines.. The optimized versions should generally be found - * as inline code in <asm-xx/string.h> - * - * These are buggy as well.. - */ - -#include <linux/types.h> -#include <linux/string.h> - -char * ___strtok = NULL; - -#ifndef __HAVE_ARCH_STRSPN -size_t strspn(const char *s, const char *accept) -{ - const char *p; - const char *a; - size_t count = 0; - - for (p = s; *p != '\0'; ++p) { - for (a = accept; *a != '\0'; ++a) { - if (*p == *a) - break; - } - if (*a == '\0') - return count; - ++count; - } - - return count; -} -#endif - -#ifndef __HAVE_ARCH_STRPBRK -char * strpbrk(const char * cs,const char * ct) -{ - const char *sc1,*sc2; - - for( sc1 = cs; *sc1 != '\0'; ++sc1) { - for( sc2 = ct; *sc2 != '\0'; ++sc2) { - if (*sc1 == *sc2) - return (char *) sc1; - } - } - return NULL; -} -#endif - -#ifndef __HAVE_ARCH_STRTOK -char * strtok(char * s,const char * ct) -{ - char *sbegin, *send; - - sbegin = s ? s : ___strtok; - if (!sbegin) { - return NULL; - } - sbegin += strspn(sbegin,ct); - if (*sbegin == '\0') { - ___strtok = NULL; - return( NULL ); - } - send = strpbrk( sbegin, ct); - if (send && *send != '\0') - *send++ = '\0'; - ___strtok = send; - return (sbegin); -} -#endif - -struct proc_dir_entry proc_scsi; -struct inode_operations proc_scsi_inode_operations; -struct proc_dir_entry proc_net; -struct inode_operations proc_net_inode_operations; - -int -proc_register (struct proc_dir_entry *xxx1, struct proc_dir_entry *xxx2) -{ - return 0; -} - -int -proc_unregister (struct proc_dir_entry *xxx1, int xxx2) -{ - return 0; -} - -void -add_blkdev_randomness (int major) -{ -} - -void -do_gettimeofday (struct timeval *tv) -{ - host_get_time (1, tv); -} - -int -dev_get_info (char *buffer, char **start, off_t offset, int length, int dummy) -{ - return 0; -} diff --git a/i386/i386at/gpl/linux/linux_net.c b/i386/i386at/gpl/linux/linux_net.c deleted file mode 100644 index 6a83a98f..00000000 --- a/i386/i386at/gpl/linux/linux_net.c +++ /dev/null @@ -1,520 +0,0 @@ -/* - * Linux network driver support. - * - * Copyright (C) 1996 The University of Utah and the Computer Systems - * Laboratory at the University of Utah (CSL) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Author: Shantanu Goel, University of Utah CSL - */ - -/* - * INET An implementation of the TCP/IP protocol suite for the LINUX - * operating system. INET is implemented using the BSD Socket - * interface as the means of communication with the user level. - * - * Ethernet-type device handling. - * - * Version: @(#)eth.c 1.0.7 05/25/93 - * - * Authors: Ross Biro, <bir7@leland.Stanford.Edu> - * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> - * Mark Evans, <evansmp@uhura.aston.ac.uk> - * Florian La Roche, <rzsfl@rz.uni-sb.de> - * Alan Cox, <gw4pts@gw4pts.ampr.org> - * - * Fixes: - * Mr Linux : Arp problems - * Alan Cox : Generic queue tidyup (very tiny here) - * Alan Cox : eth_header ntohs should be htons - * Alan Cox : eth_rebuild_header missing an htons and - * minor other things. - * Tegge : Arp bug fixes. - * Florian : Removed many unnecessary functions, code cleanup - * and changes for new arp and skbuff. - * Alan Cox : Redid header building to reflect new format. - * Alan Cox : ARP only when compiled with CONFIG_INET - * Greg Page : 802.2 and SNAP stuff. - * Alan Cox : MAC layer pointers/new format. - * Paul Gortmaker : eth_copy_and_sum shouldn't csum padding. - * Alan Cox : Protect against forwarding explosions with - * older network drivers and IFF_ALLMULTI - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#include <sys/types.h> - -#include <mach/mach_types.h> -#include <mach/kern_return.h> -#include <mach/mig_errors.h> -#include <mach/port.h> -#include <mach/vm_param.h> -#include <mach/notify.h> - -#include <ipc/ipc_port.h> -#include <ipc/ipc_space.h> - -#include <vm/vm_map.h> -#include <vm/vm_kern.h> -#include <vm/vm_page.h> - -#include <device/device_types.h> -#include <device/device_port.h> -#include <device/if_hdr.h> -#include <device/if_ether.h> -#include <device/if_hdr.h> -#include <device/net_io.h> -#include "device_reply.h" - -#include <i386at/dev_hdr.h> -#include <i386at/device_emul.h> - -#include <i386at/gpl/linux/linux_emul.h> - -#define MACH_INCLUDE -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/string.h> -#include <linux/errno.h> -#include <linux/delay.h> -#include <linux/interrupt.h> -#include <linux/malloc.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> - -/* One of these is associated with each instance of a device. */ -struct net_data -{ - ipc_port_t port; /* device port */ - struct ifnet ifnet; /* Mach ifnet structure (needed for filters) */ - struct device device; /* generic device structure */ - struct linux_device *dev; /* Linux network device structure */ -}; - -/* List of sk_buffs waiting to be freed. */ -static struct sk_buff_head skb_done_list; - -/* Forward declarations. */ - -extern struct device_emulation_ops linux_net_emulation_ops; - -static int print_packet_size = 0; - -/* Linux kernel network support routines. */ - -/* Requeue packet SKB for transmission after the interface DEV - has timed out. The priority of the packet is PRI. - In Mach, we simply drop the packet like the native drivers. */ -void -dev_queue_xmit (struct sk_buff *skb, struct linux_device *dev, int pri) -{ - dev_kfree_skb (skb, FREE_WRITE); -} - -/* Close the device DEV. */ -int -dev_close (struct linux_device *dev) -{ - return 0; -} - -/* Network software interrupt handler. */ -void -net_bh (void *xxx) -{ - int len; - struct sk_buff *skb; - struct linux_device *dev; - - /* Start transmission on interfaces. */ - for (dev = dev_base; dev; dev = dev->next) - { - if (dev->base_addr && dev->base_addr != 0xffe0) - while (1) - { - skb = skb_dequeue (&dev->buffs[0]); - if (skb) - { - len = skb->len; - if ((*dev->hard_start_xmit) (skb, dev)) - { - skb_queue_head (&dev->buffs[0], skb); - mark_bh (NET_BH); - break; - } - else if (print_packet_size) - printf ("net_bh: length %d\n", len); - } - else - break; - } - } -} - -/* Free all sk_buffs on the done list. - This routine is called by the iodone thread in ds_routines.c. */ -void -free_skbuffs () -{ - struct sk_buff *skb; - - while (1) - { - skb = skb_dequeue (&skb_done_list); - if (skb) - { - if (skb->copy) - { - vm_map_copy_discard (skb->copy); - skb->copy = NULL; - } - if (IP_VALID (skb->reply)) - { - ds_device_write_reply (skb->reply, skb->reply_type, 0, skb->len); - skb->reply = IP_NULL; - } - dev_kfree_skb (skb, FREE_WRITE); - } - else - break; - } -} - -/* Allocate an sk_buff with SIZE bytes of data space. */ -struct sk_buff * -alloc_skb (unsigned int size, int priority) -{ - return dev_alloc_skb (size); -} - -/* Free SKB. */ -void -kfree_skb (struct sk_buff *skb, int priority) -{ - dev_kfree_skb (skb, priority); -} - -/* Allocate an sk_buff with SIZE bytes of data space. */ -struct sk_buff * -dev_alloc_skb (unsigned int size) -{ - struct sk_buff *skb; - - skb = linux_kmalloc (sizeof (struct sk_buff) + size, GFP_KERNEL); - if (skb) - { - skb->dev = NULL; - skb->reply = IP_NULL; - skb->copy = NULL; - skb->len = size; - skb->prev = skb->next = NULL; - skb->list = NULL; - if (size) - { - skb->data = (unsigned char *) (skb + 1); - skb->tail = skb->data + size; - } - else - skb->data = skb->tail = NULL; - skb->head = skb->data; - } - return skb; -} - -/* Free the sk_buff SKB. */ -void -dev_kfree_skb (struct sk_buff *skb, int mode) -{ - unsigned flags; - extern void *io_done_list; - - /* Queue sk_buff on done list if there is a - page list attached or we need to send a reply. - Wakeup the iodone thread to process the list. */ - if (skb->copy || IP_VALID (skb->reply)) - { - skb_queue_tail (&skb_done_list, skb); - save_flags (flags); - thread_wakeup ((event_t) &io_done_list); - restore_flags (flags); - return; - } - linux_kfree (skb); -} - -/* Accept packet SKB received on an interface. */ -void -netif_rx (struct sk_buff *skb) -{ - ipc_kmsg_t kmsg; - struct ether_header *eh; - struct packet_header *ph; - struct linux_device *dev = skb->dev; - - assert (skb != NULL); - - if (print_packet_size) - printf ("netif_rx: length %d\n", skb->len); - - /* Allocate a kernel message buffer. */ - kmsg = net_kmsg_get (); - if (! kmsg) - { - dev_kfree_skb (skb, FREE_READ); - return; - } - - /* Copy packet into message buffer. */ - eh = (struct ether_header *) (net_kmsg (kmsg)->header); - ph = (struct packet_header *) (net_kmsg (kmsg)->packet); - memcpy (eh, skb->data, sizeof (struct ether_header)); - memcpy (ph + 1, skb->data + sizeof (struct ether_header), - skb->len - sizeof (struct ether_header)); - ph->type = eh->ether_type; - ph->length = (skb->len - sizeof (struct ether_header) - + sizeof (struct packet_header)); - - dev_kfree_skb (skb, FREE_READ); - - /* Pass packet up to the microkernel. */ - net_packet (&dev->net_data->ifnet, kmsg, - ph->length, ethernet_priority (kmsg)); -} - -/* Mach device interface routines. */ - -/* Return a send right associated with network device ND. */ -static ipc_port_t -dev_to_port (void *nd) -{ - return (nd - ? ipc_port_make_send (((struct net_data *) nd)->port) - : IP_NULL); -} - -static io_return_t -device_open (ipc_port_t reply_port, mach_msg_type_name_t reply_port_type, - dev_mode_t mode, char *name, device_t *devp) -{ - io_return_t err = D_SUCCESS; - ipc_port_t notify; - struct ifnet *ifp; - struct linux_device *dev; - struct net_data *nd; - - /* Search for the device. */ - for (dev = dev_base; dev; dev = dev->next) - if (dev->base_addr - && dev->base_addr != 0xffe0 - && ! strcmp (name, dev->name)) - break; - if (! dev) - return D_NO_SUCH_DEVICE; - - /* Allocate and initialize device data if this is the first open. */ - nd = dev->net_data; - if (! nd) - { - dev->net_data = nd = ((struct net_data *) - kalloc (sizeof (struct net_data))); - if (! nd) - { - err = D_NO_MEMORY; - goto out; - } - nd->dev = dev; - nd->device.emul_data = nd; - nd->device.emul_ops = &linux_net_emulation_ops; - nd->port = ipc_port_alloc_kernel (); - if (nd->port == IP_NULL) - { - err = KERN_RESOURCE_SHORTAGE; - goto out; - } - ipc_kobject_set (nd->port, (ipc_kobject_t) &nd->device, IKOT_DEVICE); - notify = ipc_port_make_sonce (nd->port); - ip_lock (nd->port); - ipc_port_nsrequest (nd->port, 1, notify, ¬ify); - assert (notify == IP_NULL); - - ifp = &nd->ifnet; - ifp->if_unit = dev->name[strlen (dev->name) - 1] - '0'; - ifp->if_flags = IFF_UP|IFF_RUNNING; - ifp->if_mtu = dev->mtu; - ifp->if_header_size = dev->hard_header_len; - ifp->if_header_format = dev->type; - ifp->if_address_size = dev->addr_len; - ifp->if_address = dev->dev_addr; - if_init_queues (ifp); - - if (dev->open) - { - linux_intr_pri = SPL6; - if ((*dev->open) (dev)) - err = D_NO_SUCH_DEVICE; - } - - out: - if (err) - { - if (nd) - { - if (nd->port != IP_NULL) - { - ipc_kobject_set (nd->port, IKO_NULL, IKOT_NONE); - ipc_port_dealloc_kernel (nd->port); - } - kfree ((vm_offset_t) nd, sizeof (struct net_data)); - nd = NULL; - dev->net_data = NULL; - } - } - else - { - dev->flags |= LINUX_IFF_UP|LINUX_IFF_RUNNING; - skb_queue_head_init (&dev->buffs[0]); - } - if (IP_VALID (reply_port)) - ds_device_open_reply (reply_port, reply_port_type, - err, dev_to_port (nd)); - return MIG_NO_REPLY; - } - - *devp = &nd->device; - return D_SUCCESS; -} - -static io_return_t -device_write (void *d, ipc_port_t reply_port, - mach_msg_type_name_t reply_port_type, dev_mode_t mode, - recnum_t bn, io_buf_ptr_t data, unsigned int count, - int *bytes_written) -{ - unsigned char *p; - int i, amt, skblen, s; - io_return_t err = 0; - vm_map_copy_t copy = (vm_map_copy_t) data; - struct net_data *nd = d; - struct linux_device *dev = nd->dev; - struct sk_buff *skb; - - if (count == 0 || count > dev->mtu + dev->hard_header_len) - return D_INVALID_SIZE; - - /* Allocate a sk_buff. */ - amt = PAGE_SIZE - (copy->offset & PAGE_MASK); - skblen = (amt >= count) ? 0 : count; - skb = dev_alloc_skb (skblen); - if (! skb) - return D_NO_MEMORY; - - /* Copy user data. This is only required if it spans multiple pages. */ - if (skblen == 0) - { - assert (copy->cpy_npages == 1); - - skb->copy = copy; - skb->data = ((void *) copy->cpy_page_list[0]->phys_addr - + (copy->offset & PAGE_MASK)); - skb->len = count; - skb->head = skb->data; - skb->tail = skb->data + skb->len; - } - else - { - memcpy (skb->data, - ((void *) copy->cpy_page_list[0]->phys_addr - + (copy->offset & PAGE_MASK)), - amt); - count -= amt; - p = skb->data + amt; - for (i = 1; count > 0 && i < copy->cpy_npages; i++) - { - amt = PAGE_SIZE; - if (amt > count) - amt = count; - memcpy (p, (void *) copy->cpy_page_list[i]->phys_addr, amt); - count -= amt; - p += amt; - } - - assert (count == 0); - - vm_map_copy_discard (copy); - } - - skb->dev = dev; - skb->reply = reply_port; - skb->reply_type = reply_port_type; - - /* Queue packet for transmission and schedule a software interrupt. */ - s = splimp (); - if (dev->buffs[0].next != (struct sk_buff *) &dev->buffs[0] - || (*dev->hard_start_xmit) (skb, dev)) - { - __skb_queue_tail (&dev->buffs[0], skb); - mark_bh (NET_BH); - } - splx (s); - - return MIG_NO_REPLY; -} - -static io_return_t -device_get_status (void *d, dev_flavor_t flavor, dev_status_t status, - mach_msg_type_number_t *count) -{ - return net_getstat (&((struct net_data *) d)->ifnet, flavor, status, count); -} - -static io_return_t -device_set_filter (void *d, ipc_port_t port, int priority, - filter_t *filter, unsigned filter_count) -{ - return net_set_filter (&((struct net_data *) d)->ifnet, - port, priority, filter, filter_count); -} - -struct device_emulation_ops linux_net_emulation_ops = -{ - NULL, - NULL, - dev_to_port, - device_open, - NULL, - device_write, - NULL, - NULL, - NULL, - NULL, - device_get_status, - device_set_filter, - NULL, - NULL, - NULL, - NULL -}; - -/* Do any initialization required for network devices. */ -void -linux_net_emulation_init () -{ - skb_queue_head_init (&skb_done_list); -} diff --git a/i386/i386at/gpl/linux/linux_port.c b/i386/i386at/gpl/linux/linux_port.c deleted file mode 100644 index 4a79c499..00000000 --- a/i386/i386at/gpl/linux/linux_port.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Linux I/O port management. - * Copyright (C) 1995 Shantanu Goel. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/ioport.h> - -#define NPORTS 65536 -#define BITS_PER_WORD 32 -#define NWORDS (NPORTS / BITS_PER_WORD) - -/* - * This bitmap keeps track of all allocated ports. - * A bit is set if the port has been allocated. - */ -static unsigned port_bitmap[NWORDS]; - -void snarf_region(unsigned, unsigned); - -/* - * Check if a region is available for use. - */ -int -check_region(unsigned port, unsigned size) -{ - unsigned i; - - for (i = port; i < port + size; i++) - if (port_bitmap[i/BITS_PER_WORD] & (1 << (i%BITS_PER_WORD))) - return (1); - return (0); -} - -/* - * Allocate a region. - */ -void -request_region(unsigned port, unsigned size, const char *name) -{ - unsigned i; - - for (i = port; i < port + size; i++) - port_bitmap[i / BITS_PER_WORD] |= 1 << (i % BITS_PER_WORD); -} - -/* - * For compatibility with older kernels. - */ -void -snarf_region(unsigned port, unsigned size) -{ - request_region(port, size, 0); -} - -/* - * Deallocate a region. - */ -void -release_region(unsigned port, unsigned size) -{ - unsigned i; - - for (i = port; i < port + size; i++) - port_bitmap[i / BITS_PER_WORD] &= ~(1 << (i % BITS_PER_WORD)); -} diff --git a/i386/i386at/gpl/linux/linux_printk.c b/i386/i386at/gpl/linux/linux_printk.c deleted file mode 100644 index c4e489d2..00000000 --- a/i386/i386at/gpl/linux/linux_printk.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Linux kernel print routine. - * Copyright (C) 1995 Shantanu Goel. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* - * linux/kernel/printk.c - * - * Copyright (C) 1991, 1992 Linus Torvalds - */ - -#include <stdarg.h> -#include <asm/system.h> - -static char buf[2048]; - -void -printk(char *fmt, ...) -{ - va_list args; - int i, n, flags; - extern void cnputc(); - extern int linux_vsprintf(char *buf, char *fmt, ...); - - save_flags(flags); - cli(); - va_start(args, fmt); - n = linux_vsprintf(buf, fmt, args); - va_end(args); - for (i = 0; i < n; i++) - cnputc(buf[i]); - restore_flags(flags); -} diff --git a/i386/i386at/gpl/linux/linux_sched.c b/i386/i386at/gpl/linux/linux_sched.c deleted file mode 100644 index fdb0f693..00000000 --- a/i386/i386at/gpl/linux/linux_sched.c +++ /dev/null @@ -1,237 +0,0 @@ -/* - * Linux scheduling support. - * - * Copyright (C) 1996 The University of Utah and the Computer Systems - * Laboratory at the University of Utah (CSL) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Author: Shantanu Goel, University of Utah CSL - */ - -/* - * linux/kernel/sched.c - * - * Copyright (C) 1991, 1992 Linus Torvalds - */ - -#include <sys/types.h> - -#include <mach/boolean.h> - -#include <kern/thread.h> -#include <kern/sched_prim.h> - -#include <i386at/gpl/linux/linux_emul.h> - -#define MACH_INCLUDE -#include <linux/sched.h> -#include <linux/fs.h> -#include <linux/blkdev.h> - -#include <asm/system.h> - -struct tq_struct tq_last = -{ - &tq_last, 0, 0, 0 -}; - -DECLARE_TASK_QUEUE(tq_timer); - -static struct wait_queue **auto_config_queue; - -void -tqueue_bh (void *unused) -{ - run_task_queue(&tq_timer); -} - -void -add_wait_queue (struct wait_queue **q, struct wait_queue *wait) -{ - unsigned long flags; - - if (! linux_auto_config) - { - save_flags (flags); - cli (); - assert_wait ((event_t) q, FALSE); - restore_flags (flags); - return; - } - - if (auto_config_queue) - printf ("add_wait_queue: queue not empty\n"); - auto_config_queue = q; -} - -void -remove_wait_queue (struct wait_queue **q, struct wait_queue *wait) -{ - unsigned long flags; - - if (! linux_auto_config) - { - save_flags (flags); - thread_wakeup ((event_t) q); - restore_flags (flags); - return; - } - - auto_config_queue = NULL; -} - -void -__down (struct semaphore *sem) -{ - int s; - unsigned long flags; - - if (! linux_auto_config) - { - save_flags (flags); - s = splhigh (); - while (sem->count <= 0) - { - assert_wait ((event_t) &sem->wait, FALSE); - splx (s); - thread_block (0); - s = splhigh (); - } - splx (s); - restore_flags (flags); - return; - } - - while (sem->count <= 0) - barrier (); -} - -void -__sleep_on (struct wait_queue **q, int interruptible) -{ - unsigned long flags; - - if (! q) - return; - save_flags (flags); - if (! linux_auto_config) - { - assert_wait ((event_t) q, interruptible); - sti (); - thread_block (0); - restore_flags (flags); - return; - } - - add_wait_queue (q, NULL); - sti (); - while (auto_config_queue) - barrier (); - restore_flags (flags); -} - -void -sleep_on (struct wait_queue **q) -{ - __sleep_on (q, FALSE); -} - -void -interruptible_sleep_on (struct wait_queue **q) -{ - __sleep_on (q, TRUE); -} - -void -wake_up (struct wait_queue **q) -{ - unsigned long flags; - - if (! linux_auto_config) - { - if (q != &wait_for_request) - { - save_flags (flags); - thread_wakeup ((event_t) q); - restore_flags (flags); - } - return; - } - - if (auto_config_queue == q) - auto_config_queue = NULL; -} - -void -__wait_on_buffer (struct buffer_head *bh) -{ - unsigned long flags; - - save_flags (flags); - if (! linux_auto_config) - { - while (1) - { - cli (); - if (! buffer_locked (bh)) - break; - bh->b_wait = (struct wait_queue *) 1; - assert_wait ((event_t) bh, FALSE); - sti (); - thread_block (0); - } - restore_flags (flags); - return; - } - - sti (); - while (buffer_locked (bh)) - barrier (); - restore_flags (flags); -} - -void -unlock_buffer (struct buffer_head *bh) -{ - unsigned long flags; - - save_flags (flags); - cli (); - clear_bit (BH_Lock, &bh->b_state); - if (bh->b_wait && ! linux_auto_config) - { - bh->b_wait = NULL; - thread_wakeup ((event_t) bh); - } - restore_flags (flags); -} - -void -schedule () -{ - if (! linux_auto_config) - thread_block (0); -} - -void -cdrom_sleep (int t) -{ - int xxx; - - assert_wait ((event_t) &xxx, TRUE); - thread_set_timeout (t); - thread_block (0); -} diff --git a/i386/i386at/gpl/linux/linux_soft.c b/i386/i386at/gpl/linux/linux_soft.c deleted file mode 100644 index efcae987..00000000 --- a/i386/i386at/gpl/linux/linux_soft.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Linux software interrupts. - * Copyright (C) 1995 Shantanu Goel. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* - * linux/kernel/softirq.c - * - * Copyright (C) 1992 Linus Torvalds - */ - -#include <linux/sched.h> -#include <linux/interrupt.h> -#include <asm/system.h> -#include <asm/bitops.h> - -/* - * Mask of pending interrupts. - */ -unsigned long bh_active = 0; - -/* - * Mask of enabled interrupts. - */ -unsigned long bh_mask = 0; - -/* - * List of software interrupt handlers. - */ -struct bh_struct bh_base[32]; - - -/* - * Software interrupt handler. - */ -void -linux_soft_intr() -{ - unsigned long active; - unsigned long mask, left; - struct bh_struct *bh; - - bh = bh_base; - active = bh_active & bh_mask; - for (mask = 1, left = ~0; - left & active; bh++, mask += mask, left += left) { - if (mask & active) { - void (*fn)(void *); - - bh_active &= ~mask; - fn = bh->routine; - if (fn == 0) - goto bad_bh; - (*fn)(bh->data); - } - } - return; - bad_bh: - printf("linux_soft_intr: bad interrupt handler entry 0x%08lx\n", mask); -} diff --git a/i386/i386at/gpl/linux/linux_timer.c b/i386/i386at/gpl/linux/linux_timer.c deleted file mode 100644 index c1575323..00000000 --- a/i386/i386at/gpl/linux/linux_timer.c +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Linux timers. - * - * Copyright (C) 1996 The University of Utah and the Computer Systems - * Laboratory at the University of Utah (CSL) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Author: Shantanu Goel, University of Utah CSL - */ - -/* - * linux/kernel/sched.c - * - * Copyright (C) 1991, 1992 Linus Torvalds - */ - -#include <linux/sched.h> -#include <linux/timer.h> -#include <linux/interrupt.h> -#include <asm/system.h> - -unsigned long volatile jiffies = 0; - -/* - * Mask of active timers. - */ -unsigned long timer_active = 0; - -/* - * List of timeout routines. - */ -struct timer_struct timer_table[32]; - -/* - * The head for the timer-list has a "expires" field of MAX_UINT, - * and the sorting routine counts on this.. - */ -static struct timer_list timer_head = -{ - &timer_head, &timer_head, ~0, 0, NULL -}; - -#define SLOW_BUT_DEBUGGING_TIMERS 0 - -void -add_timer(struct timer_list *timer) -{ - unsigned long flags; - struct timer_list *p; - -#if SLOW_BUT_DEBUGGING_TIMERS - if (timer->next || timer->prev) { - printk("add_timer() called with non-zero list from %p\n", - __builtin_return_address(0)); - return; - } -#endif - p = &timer_head; - save_flags(flags); - cli(); - do { - p = p->next; - } while (timer->expires > p->expires); - timer->next = p; - timer->prev = p->prev; - p->prev = timer; - timer->prev->next = timer; - restore_flags(flags); -} - -int -del_timer(struct timer_list *timer) -{ - unsigned long flags; -#if SLOW_BUT_DEBUGGING_TIMERS - struct timer_list * p; - - p = &timer_head; - save_flags(flags); - cli(); - while ((p = p->next) != &timer_head) { - if (p == timer) { - timer->next->prev = timer->prev; - timer->prev->next = timer->next; - timer->next = timer->prev = NULL; - restore_flags(flags); - return 1; - } - } - if (timer->next || timer->prev) - printk("del_timer() called from %p with timer not initialized\n", - __builtin_return_address(0)); - restore_flags(flags); - return 0; -#else - struct timer_list * next; - int ret = 0; - save_flags(flags); - cli(); - if ((next = timer->next) != NULL) { - (next->prev = timer->prev)->next = next; - timer->next = timer->prev = NULL; - ret = 1; - } - restore_flags(flags); - return ret; -#endif -} - -/* - * Timer software interrupt handler. - */ -void -timer_bh() -{ - unsigned long mask; - struct timer_struct *tp; - struct timer_list * timer; - - cli(); - while ((timer = timer_head.next) != &timer_head - && timer->expires <= jiffies) { - void (*fn)(unsigned long) = timer->function; - unsigned long data = timer->data; - - timer->next->prev = timer->prev; - timer->prev->next = timer->next; - timer->next = timer->prev = NULL; - sti(); - fn(data); - cli(); - } - sti(); - - for (mask = 1, tp = timer_table; mask; tp++, mask <<= 1) { - if (mask > timer_active) - break; - if ((mask & timer_active) - && tp->expires > jiffies) { - timer_active &= ~mask; - (*tp->fn)(); - sti(); - } - } -} - -int linux_timer_print = 0; - -/* - * Timer interrupt handler. - */ -void -linux_timer_intr() -{ - unsigned long mask; - struct timer_struct *tp; - extern int pic_mask[]; - - jiffies++; - - for (mask = 1, tp = timer_table; mask; tp++, mask += mask) { - if (mask > timer_active) - break; - if (!(mask & timer_active)) - continue; - if (tp->expires > jiffies) - continue; - mark_bh(TIMER_BH); - } - if (timer_head.next->expires <= jiffies) - mark_bh(TIMER_BH); - if (tq_timer != &tq_last) - mark_bh(TQUEUE_BH); - if (linux_timer_print) - printf ("linux_timer_intr: pic_mask[0] %x\n", pic_mask[0]); -} - diff --git a/i386/i386at/gpl/linux/linux_version.c b/i386/i386at/gpl/linux/linux_version.c deleted file mode 100644 index 0195c42f..00000000 --- a/i386/i386at/gpl/linux/linux_version.c +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 1996 The University of Utah and - * the Computer Systems Laboratory at the University of Utah (CSL). - * All rights reserved. - * - * Permission to use, copy, modify and distribute this software is hereby - * granted provided that (1) source code retains these copyright, permission, - * and disclaimer notices, and (2) redistributions including binaries - * reproduce the notices in supporting documentation, and (3) all advertising - * materials mentioning features or use of this software display the following - * acknowledgement: ``This product includes software developed by the - * Computer Systems Laboratory at the University of Utah.'' - * - * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS - * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF - * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * CSL requests users of this software to return to csl-dist@cs.utah.edu any - * improvements that they make and grant CSL redistribution rights. - * - * Author: Shantanu Goel, University of Utah CSL - */ - -#include <linux/utsname.h> -#include <linux/string.h> - -struct new_utsname system_utsname; - -void -linux_version_init () -{ - strcpy (system_utsname.version, "1.3.68"); -} diff --git a/i386/i386at/gpl/linux/linux_vsprintf.c b/i386/i386at/gpl/linux/linux_vsprintf.c deleted file mode 100644 index 236d38da..00000000 --- a/i386/i386at/gpl/linux/linux_vsprintf.c +++ /dev/null @@ -1,341 +0,0 @@ -/* - * linux/kernel/vsprintf.c - * - * Copyright (C) 1991, 1992 Linus Torvalds - */ - -/* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */ -/* - * Wirzenius wrote this portably, Torvalds fucked it up :-) - */ - -#include <stdarg.h> -#include <linux/types.h> -#include <linux/string.h> -#include <linux/kernel.h> - -static inline -isxdigit(c) - char c; -{ - return ((c >= '0' && c <= '9') - || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')); -} - -static inline -islower(c) - char c; -{ - return (c >= 'a' && c <= 'z'); -} - -static inline -toupper(c) - char c; -{ - return (islower(c) ? c - 'a' + 'A' : c); -} - -static inline -isdigit(c) - char c; -{ - return (c >= '0' && c <= '9'); -} - -unsigned long -simple_strtoul(const char *cp,char **endp,unsigned int base) -{ - unsigned long result = 0,value; - - if (!base) { - base = 10; - if (*cp == '0') { - base = 8; - cp++; - if ((*cp == 'x') && isxdigit(cp[1])) { - cp++; - base = 16; - } - } - } - while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp) - ? toupper(*cp) : *cp)-'A'+10) < base) { - result = result*base + value; - cp++; - } - if (endp) - *endp = (char *)cp; - return result; -} - -/* we use this so that we can do without the ctype library */ -#define is_digit(c) ((c) >= '0' && (c) <= '9') - -static int -skip_atoi(const char **s) -{ - int i=0; - - while (is_digit(**s)) - i = i*10 + *((*s)++) - '0'; - return i; -} - -#define ZEROPAD 1 /* pad with zero */ -#define SIGN 2 /* unsigned/signed long */ -#define PLUS 4 /* show plus */ -#define SPACE 8 /* space if plus */ -#define LEFT 16 /* left justified */ -#define SPECIAL 32 /* 0x */ -#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ - -#define do_div(n,base) ({ \ -int __res; \ -__res = ((unsigned long) n) % (unsigned) base; \ -n = ((unsigned long) n) / (unsigned) base; \ -__res; }) - -static char * -number(char * str, long num, int base, int size, int precision, int type) -{ - char c,sign,tmp[36]; - const char *digits="0123456789abcdefghijklmnopqrstuvwxyz"; - int i; - - if (type & LARGE) - digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - if (type & LEFT) - type &= ~ZEROPAD; - if (base < 2 || base > 36) - return 0; - c = (type & ZEROPAD) ? '0' : ' '; - sign = 0; - if (type & SIGN) { - if (num < 0) { - sign = '-'; - num = -num; - size--; - } else if (type & PLUS) { - sign = '+'; - size--; - } else if (type & SPACE) { - sign = ' '; - size--; - } - } - if (type & SPECIAL) { - if (base == 16) - size -= 2; - else if (base == 8) - size--; - } - i = 0; - if (num == 0) - tmp[i++]='0'; - else while (num != 0) - tmp[i++] = digits[do_div(num,base)]; - if (i > precision) - precision = i; - size -= precision; - if (!(type&(ZEROPAD+LEFT))) - while(size-->0) - *str++ = ' '; - if (sign) - *str++ = sign; - if (type & SPECIAL) - if (base==8) - *str++ = '0'; - else if (base==16) { - *str++ = '0'; - *str++ = digits[33]; - } - if (!(type & LEFT)) - while (size-- > 0) - *str++ = c; - while (i < precision--) - *str++ = '0'; - while (i-- > 0) - *str++ = tmp[i]; - while (size-- > 0) - *str++ = ' '; - return str; -} - -int -linux_vsprintf(char *buf, const char *fmt, va_list args) -{ - int len; - unsigned long num; - int i, base; - char * str; - char *s; - - int flags; /* flags to number() */ - - int field_width; /* width of output field */ - int precision; /* min. # of digits for integers; max - number of chars for from string */ - int qualifier; /* 'h', 'l', or 'L' for integer fields */ - - for (str=buf ; *fmt ; ++fmt) { - if (*fmt != '%') { - *str++ = *fmt; - continue; - } - - /* process flags */ - flags = 0; - repeat: - ++fmt; /* this also skips first '%' */ - switch (*fmt) { - case '-': flags |= LEFT; goto repeat; - case '+': flags |= PLUS; goto repeat; - case ' ': flags |= SPACE; goto repeat; - case '#': flags |= SPECIAL; goto repeat; - case '0': flags |= ZEROPAD; goto repeat; - } - - /* get field width */ - field_width = -1; - if (is_digit(*fmt)) - field_width = skip_atoi(&fmt); - else if (*fmt == '*') { - ++fmt; - /* it's the next argument */ - field_width = va_arg(args, int); - if (field_width < 0) { - field_width = -field_width; - flags |= LEFT; - } - } - - /* get the precision */ - precision = -1; - if (*fmt == '.') { - ++fmt; - if (is_digit(*fmt)) - precision = skip_atoi(&fmt); - else if (*fmt == '*') { - ++fmt; - /* it's the next argument */ - precision = va_arg(args, int); - } - if (precision < 0) - precision = 0; - } - - /* get the conversion qualifier */ - qualifier = -1; - if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') { - qualifier = *fmt; - ++fmt; - } - - /* default base */ - base = 10; - - switch (*fmt) { - case 'c': - if (!(flags & LEFT)) - while (--field_width > 0) - *str++ = ' '; - *str++ = (unsigned char) va_arg(args, int); - while (--field_width > 0) - *str++ = ' '; - continue; - - case 's': - s = va_arg(args, char *); - if (!s) - s = "<NULL>"; - len = strlen(s); - if (precision < 0) - precision = len; - else if (len > precision) - len = precision; - - if (!(flags & LEFT)) - while (len < field_width--) - *str++ = ' '; - for (i = 0; i < len; ++i) - *str++ = *s++; - while (len < field_width--) - *str++ = ' '; - continue; - - case 'p': - if (field_width == -1) { - field_width = 2*sizeof(void *); - flags |= ZEROPAD; - } - str = number(str, - (unsigned long) va_arg(args, void *), 16, - field_width, precision, flags); - continue; - - - case 'n': - if (qualifier == 'l') { - long * ip = va_arg(args, long *); - *ip = (str - buf); - } else { - int * ip = va_arg(args, int *); - *ip = (str - buf); - } - continue; - - /* integer number formats - set up the flags and "break" */ - case 'o': - base = 8; - break; - - case 'X': - flags |= LARGE; - case 'x': - base = 16; - break; - - case 'd': - case 'i': - flags |= SIGN; - case 'u': - break; - - default: - if (*fmt != '%') - *str++ = '%'; - if (*fmt) - *str++ = *fmt; - else - --fmt; - continue; - } - if (qualifier == 'l') - num = va_arg(args, unsigned long); - else if (qualifier == 'h') - if (flags & SIGN) - num = va_arg(args, short); - else - num = va_arg(args, unsigned short); - else if (flags & SIGN) - num = va_arg(args, int); - else - num = va_arg(args, unsigned int); - str = number(str, num, base, field_width, precision, flags); - } - *str = '\0'; - return str-buf; -} - -int -linux_sprintf(char * buf, const char *fmt, ...) -{ - va_list args; - int i; - - va_start(args, fmt); - i = linux_vsprintf(buf, fmt, args); - va_end(args); - return i; -} diff --git a/i386/i386at/gpl/linux/net/3c501.c b/i386/i386at/gpl/linux/net/3c501.c deleted file mode 100644 index 6f8dceb6..00000000 --- a/i386/i386at/gpl/linux/net/3c501.c +++ /dev/null @@ -1,860 +0,0 @@ -/* 3c501.c: A 3Com 3c501 ethernet driver for linux. */ -/* - Written 1992,1993,1994 Donald Becker - - Copyright 1993 United States Government as represented by the - Director, National Security Agency. This software may be used and - distributed according to the terms of the GNU Public License, - incorporated herein by reference. - - This is a device driver for the 3Com Etherlink 3c501. - Do not purchase this card, even as a joke. It's performance is horrible, - and it breaks in many ways. - - The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O - Center of Excellence in Space Data and Information Sciences - Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771 - - Fixed (again!) the missing interrupt locking on TX/RX shifting. - Alan Cox <Alan.Cox@linux.org> - - Removed calls to init_etherdev since they are no longer needed, and - cleaned up modularization just a bit. The driver still allows only - the default address for cards when loaded as a module, but that's - really less braindead than anyone using a 3c501 board. :) - 19950208 (invid@msen.com) - - Added traps for interrupts hitting the window as we clear and TX load - the board. Now getting 150K/second FTP with a 3c501 card. Still playing - with a TX-TX optimisation to see if we can touch 180-200K/second as seems - theoretically maximum. - 19950402 Alan Cox <Alan.Cox@linux.org> - - Some notes on this thing if you have to hack it. [Alan] - - 1] Some documentation is available from 3Com. Due to the boards age - standard responses when you ask for this will range from 'be serious' - to 'give it to a museum'. The documentation is incomplete and mostly - of historical interest anyway. - - 2] The basic system is a single buffer which can be used to receive or - transmit a packet. A third command mode exists when you are setting - things up. - - 3] If it's transmitting it's not receiving and vice versa. In fact the - time to get the board back into useful state after an operation is - quite large. - - 4] The driver works by keeping the board in receive mode waiting for a - packet to arrive. When one arrives it is copied out of the buffer - and delivered to the kernel. The card is reloaded and off we go. - - 5] When transmitting dev->tbusy is set and the card is reset (from - receive mode) [possibly losing a packet just received] to command - mode. A packet is loaded and transmit mode triggered. The interrupt - handler runs different code for transmit interrupts and can handle - returning to receive mode or retransmissions (yes you have to help - out with those too). - - Problems: - There are a wide variety of undocumented error returns from the card - and you basically have to kick the board and pray if they turn up. Most - only occur under extreme load or if you do something the board doesn't - like (eg touching a register at the wrong time). - - The driver is less efficient than it could be. It switches through - receive mode even if more transmits are queued. If this worries you buy - a real ethernet card. - - The combination of slow receive restart and no real multicast - filter makes the board unusable with a kernel compiled for IP - multicasting in a real multicast environment. Thats down to the board, - but even with no multicast programs running a multicast IP kernel is - in group 224.0.0.1 and you will therefore be listening to all multicasts. - One nv conference running over that ethernet and you can give up. - -*/ - -static const char *version = - "3c501.c: 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov).\n"; - -/* - * Braindamage remaining: - * The 3c501 board. - */ - -#include <linux/module.h> - -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/ptrace.h> -#include <linux/fcntl.h> -#include <linux/ioport.h> -#include <linux/interrupt.h> -#include <linux/malloc.h> -#include <linux/string.h> -#include <linux/ioport.h> -#include <linux/errno.h> -#include <linux/config.h> /* for CONFIG_IP_MULTICAST */ - -#include <asm/bitops.h> -#include <asm/io.h> - -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> - -#define BLOCKOUT_2 - -/* A zero-terminated list of I/O addresses to be probed. - The 3c501 can be at many locations, but here are the popular ones. */ -static unsigned int netcard_portlist[] = - { 0x280, 0x300, 0}; - - -/* - * Index to functions. - */ - -int el1_probe(struct device *dev); -static int el1_probe1(struct device *dev, int ioaddr); -static int el_open(struct device *dev); -static int el_start_xmit(struct sk_buff *skb, struct device *dev); -static void el_interrupt(int irq, struct pt_regs *regs); -static void el_receive(struct device *dev); -static void el_reset(struct device *dev); -static int el1_close(struct device *dev); -static struct enet_statistics *el1_get_stats(struct device *dev); -static void set_multicast_list(struct device *dev); - -#define EL1_IO_EXTENT 16 - -#ifndef EL_DEBUG -#define EL_DEBUG 0 /* use 0 for production, 1 for devel., >2 for debug */ -#endif /* Anything above 5 is wordy death! */ -static int el_debug = EL_DEBUG; - -/* - * Board-specific info in dev->priv. - */ - -struct net_local -{ - struct enet_statistics stats; - int tx_pkt_start; /* The length of the current Tx packet. */ - int collisions; /* Tx collisions this packet */ - int loading; /* Spot buffer load collisions */ -}; - - -#define RX_STATUS (ioaddr + 0x06) -#define RX_CMD RX_STATUS -#define TX_STATUS (ioaddr + 0x07) -#define TX_CMD TX_STATUS -#define GP_LOW (ioaddr + 0x08) -#define GP_HIGH (ioaddr + 0x09) -#define RX_BUF_CLR (ioaddr + 0x0A) -#define RX_LOW (ioaddr + 0x0A) -#define RX_HIGH (ioaddr + 0x0B) -#define SAPROM (ioaddr + 0x0C) -#define AX_STATUS (ioaddr + 0x0E) -#define AX_CMD AX_STATUS -#define DATAPORT (ioaddr + 0x0F) -#define TX_RDY 0x08 /* In TX_STATUS */ - -#define EL1_DATAPTR 0x08 -#define EL1_RXPTR 0x0A -#define EL1_SAPROM 0x0C -#define EL1_DATAPORT 0x0f - -/* - * Writes to the ax command register. - */ - -#define AX_OFF 0x00 /* Irq off, buffer access on */ -#define AX_SYS 0x40 /* Load the buffer */ -#define AX_XMIT 0x44 /* Transmit a packet */ -#define AX_RX 0x48 /* Receive a packet */ -#define AX_LOOP 0x0C /* Loopback mode */ -#define AX_RESET 0x80 - -/* - * Normal receive mode written to RX_STATUS. We must intr on short packets - * to avoid bogus rx lockups. - */ - -#define RX_NORM 0xA8 /* 0x68 == all addrs, 0xA8 only to me. */ -#define RX_PROM 0x68 /* Senior Prom, uhmm promiscuous mode. */ -#define RX_MULT 0xE8 /* Accept multicast packets. */ -#define TX_NORM 0x0A /* Interrupt on everything that might hang the chip */ - -/* - * TX_STATUS register. - */ - -#define TX_COLLISION 0x02 -#define TX_16COLLISIONS 0x04 -#define TX_READY 0x08 - -#define RX_RUNT 0x08 -#define RX_MISSED 0x01 /* Missed a packet due to 3c501 braindamage. */ -#define RX_GOOD 0x30 /* Good packet 0x20, or simple overflow 0x10. */ - - -/* - * The boilerplate probe code. - */ - -#ifdef HAVE_DEVLIST -struct netdev_entry el1_drv = {"3c501", el1_probe1, EL1_IO_EXTENT, netcard_portlist}; -#else - -int el1_probe(struct device *dev) -{ - int i; - int base_addr = dev ? dev->base_addr : 0; - - if (base_addr > 0x1ff) /* Check a single specified location. */ - return el1_probe1(dev, base_addr); - else if (base_addr != 0) /* Don't probe at all. */ - return ENXIO; - - for (i = 0; netcard_portlist[i]; i++) - { - int ioaddr = netcard_portlist[i]; - if (check_region(ioaddr, EL1_IO_EXTENT)) - continue; - if (el1_probe1(dev, ioaddr) == 0) - return 0; - } - - return ENODEV; -} -#endif - -/* - * The actual probe. - */ - -static int el1_probe1(struct device *dev, int ioaddr) -{ -#ifndef MODULE - - const char *mname; /* Vendor name */ - unsigned char station_addr[6]; - int autoirq = 0; - int i; - - /* - * Read the station address PROM data from the special port. - */ - - for (i = 0; i < 6; i++) - { - outw(i, ioaddr + EL1_DATAPTR); - station_addr[i] = inb(ioaddr + EL1_SAPROM); - } - /* - * Check the first three octets of the S.A. for 3Com's prefix, or - * for the Sager NP943 prefix. - */ - - if (station_addr[0] == 0x02 && station_addr[1] == 0x60 - && station_addr[2] == 0x8c) - { - mname = "3c501"; - } else if (station_addr[0] == 0x00 && station_addr[1] == 0x80 - && station_addr[2] == 0xC8) - { - mname = "NP943"; - } - else - return ENODEV; - - /* - * Grab the region so we can find the another board if autoIRQ fails. - */ - - request_region(ioaddr, EL1_IO_EXTENT,"3c501"); - - /* - * We auto-IRQ by shutting off the interrupt line and letting it float - * high. - */ - - if (dev->irq < 2) - { - autoirq_setup(2); - inb(RX_STATUS); /* Clear pending interrupts. */ - inb(TX_STATUS); - outb(AX_LOOP + 1, AX_CMD); - - outb(0x00, AX_CMD); - - autoirq = autoirq_report(1); - - if (autoirq == 0) - { - printk("%s probe at %#x failed to detect IRQ line.\n", - mname, ioaddr); - return EAGAIN; - } - } - - outb(AX_RESET+AX_LOOP, AX_CMD); /* Loopback mode. */ - dev->base_addr = ioaddr; - memcpy(dev->dev_addr, station_addr, ETH_ALEN); - - if (dev->mem_start & 0xf) - el_debug = dev->mem_start & 0x7; - if (autoirq) - dev->irq = autoirq; - - printk("%s: %s EtherLink at %#lx, using %sIRQ %d.\n", dev->name, mname, dev->base_addr, - autoirq ? "auto":"assigned ", dev->irq); - -#ifdef CONFIG_IP_MULTICAST - printk("WARNING: Use of the 3c501 in a multicast kernel is NOT recommended.\n"); -#endif - - if (el_debug) - printk("%s", version); - - /* - * Initialize the device structure. - */ - - dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL); - if (dev->priv == NULL) - return -ENOMEM; - memset(dev->priv, 0, sizeof(struct net_local)); - - /* - * The EL1-specific entries in the device structure. - */ - - dev->open = &el_open; - dev->hard_start_xmit = &el_start_xmit; - dev->stop = &el1_close; - dev->get_stats = &el1_get_stats; - dev->set_multicast_list = &set_multicast_list; - - /* - * Setup the generic properties - */ - - ether_setup(dev); - -#endif /* !MODULE */ - - return 0; -} - -/* - * Open/initialize the board. - */ - -static int el_open(struct device *dev) -{ - int ioaddr = dev->base_addr; - - if (el_debug > 2) - printk("%s: Doing el_open()...", dev->name); - - if (request_irq(dev->irq, &el_interrupt, 0, "3c501")) - return -EAGAIN; - - irq2dev_map[dev->irq] = dev; - el_reset(dev); - - dev->start = 1; - - outb(AX_RX, AX_CMD); /* Aux control, irq and receive enabled */ - MOD_INC_USE_COUNT; - return 0; -} - -static int el_start_xmit(struct sk_buff *skb, struct device *dev) -{ - struct net_local *lp = (struct net_local *)dev->priv; - int ioaddr = dev->base_addr; - unsigned long flags; - - if(dev->interrupt) /* May be unloading, don't stamp on */ - return 1; /* the packet buffer this time */ - - if (dev->tbusy) - { - if (jiffies - dev->trans_start < 20) - { - if (el_debug > 2) - printk(" transmitter busy, deferred.\n"); - return 1; - } - if (el_debug) - printk ("%s: transmit timed out, txsr %#2x axsr=%02x rxsr=%02x.\n", - dev->name, inb(TX_STATUS), inb(AX_STATUS), inb(RX_STATUS)); - lp->stats.tx_errors++; - outb(TX_NORM, TX_CMD); - outb(RX_NORM, RX_CMD); - outb(AX_OFF, AX_CMD); /* Just trigger a false interrupt. */ - outb(AX_RX, AX_CMD); /* Aux control, irq and receive enabled */ - dev->tbusy = 0; - dev->trans_start = jiffies; - } - - if (skb == NULL) - { - dev_tint(dev); - return 0; - } - - save_flags(flags); - - /* - * Avoid incoming interrupts between us flipping tbusy and flipping - * mode as the driver assumes tbusy is a faithful indicator of card - * state - */ - - cli(); - - /* - * Avoid timer-based retransmission conflicts. - */ - - if (set_bit(0, (void*)&dev->tbusy) != 0) - { - restore_flags(flags); - printk("%s: Transmitter access conflict.\n", dev->name); - } - else - { - int gp_start = 0x800 - (ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN); - unsigned char *buf = skb->data; - -load_it_again_sam: - lp->tx_pkt_start = gp_start; - lp->collisions = 0; - - /* - * Command mode with status cleared should [in theory] - * mean no more interrupts can be pending on the card. - */ - -#ifdef BLOCKOUT_1 - disable_irq(dev->irq); -#endif - outb_p(AX_SYS, AX_CMD); - inb_p(RX_STATUS); - inb_p(TX_STATUS); - - lp->loading=1; - - /* - * Turn interrupts back on while we spend a pleasant afternoon - * loading bytes into the board - */ - - restore_flags(flags); - outw(0x00, RX_BUF_CLR); /* Set rx packet area to 0. */ - outw(gp_start, GP_LOW); /* aim - packet will be loaded into buffer start */ - outsb(DATAPORT,buf,skb->len); /* load buffer (usual thing each byte increments the pointer) */ - outw(gp_start, GP_LOW); /* the board reuses the same register */ -#ifndef BLOCKOUT_1 - if(lp->loading==2) /* A receive upset our load, despite our best efforts */ - { - if(el_debug>2) - printk("%s: burped during tx load.\n", dev->name); - goto load_it_again_sam; /* Sigh... */ - } -#endif - outb(AX_XMIT, AX_CMD); /* fire ... Trigger xmit. */ - lp->loading=0; -#ifdef BLOCKOUT_1 - enable_irq(dev->irq); -#endif - dev->trans_start = jiffies; - } - - if (el_debug > 2) - printk(" queued xmit.\n"); - dev_kfree_skb (skb, FREE_WRITE); - return 0; -} - - -/* - * The typical workload of the driver: - * Handle the ether interface interrupts. - */ - -static void el_interrupt(int irq, struct pt_regs *regs) -{ - struct device *dev = (struct device *)(irq2dev_map[irq]); - struct net_local *lp; - int ioaddr; - int axsr; /* Aux. status reg. */ - - if (dev == NULL || dev->irq != irq) - { - printk ("3c501 driver: irq %d for unknown device.\n", irq); - return; - } - - ioaddr = dev->base_addr; - lp = (struct net_local *)dev->priv; - - /* - * What happened ? - */ - - axsr = inb(AX_STATUS); - - /* - * Log it - */ - - if (el_debug > 3) - printk("%s: el_interrupt() aux=%#02x", dev->name, axsr); - if (dev->interrupt) - printk("%s: Reentering the interrupt driver!\n", dev->name); - dev->interrupt = 1; -#ifndef BLOCKOUT_1 - if(lp->loading==1 && !dev->tbusy) - printk("%s: Inconsistent state loading while not in tx\n", - dev->name); -#endif -#ifdef BLOCKOUT_3 - lp->loading=2; /* So we can spot loading interruptions */ -#endif - - if (dev->tbusy) - { - - /* - * Board in transmit mode. May be loading. If we are - * loading we shouldn't have got this. - */ - - int txsr = inb(TX_STATUS); -#ifdef BLOCKOUT_2 - if(lp->loading==1) - { - if(el_debug > 2) - { - printk("%s: Interrupt while loading [", dev->name); - printk(" txsr=%02x gp=%04x rp=%04x]\n", txsr, inw(GP_LOW),inw(RX_LOW)); - } - lp->loading=2; /* Force a reload */ - dev->interrupt = 0; - return; - } -#endif - if (el_debug > 6) - printk(" txsr=%02x gp=%04x rp=%04x", txsr, inw(GP_LOW),inw(RX_LOW)); - - if ((axsr & 0x80) && (txsr & TX_READY) == 0) - { - /* - * FIXME: is there a logic to whether to keep on trying or - * reset immediately ? - */ - printk("%s: Unusual interrupt during Tx, txsr=%02x axsr=%02x" - " gp=%03x rp=%03x.\n", dev->name, txsr, axsr, - inw(ioaddr + EL1_DATAPTR), inw(ioaddr + EL1_RXPTR)); - dev->tbusy = 0; - mark_bh(NET_BH); - } - else if (txsr & TX_16COLLISIONS) - { - /* - * Timed out - */ - if (el_debug) - printk("%s: Transmit failed 16 times, ethernet jammed?\n",dev->name); - outb(AX_SYS, AX_CMD); - lp->stats.tx_aborted_errors++; - } - else if (txsr & TX_COLLISION) - { - /* - * Retrigger xmit. - */ - - if (el_debug > 6) - printk(" retransmitting after a collision.\n"); - /* - * Poor little chip can't reset its own start pointer - */ - - outb(AX_SYS, AX_CMD); - outw(lp->tx_pkt_start, GP_LOW); - outb(AX_XMIT, AX_CMD); - lp->stats.collisions++; - dev->interrupt = 0; - return; - } - else - { - /* - * It worked.. we will now fall through and receive - */ - lp->stats.tx_packets++; - if (el_debug > 6) - printk(" Tx succeeded %s\n", - (txsr & TX_RDY) ? "." : "but tx is busy!"); - /* - * This is safe the interrupt is atomic WRT itself. - */ - - dev->tbusy = 0; - mark_bh(NET_BH); /* In case more to transmit */ - } - } - else - { - /* - * In receive mode. - */ - - int rxsr = inb(RX_STATUS); - if (el_debug > 5) - printk(" rxsr=%02x txsr=%02x rp=%04x", rxsr, inb(TX_STATUS),inw(RX_LOW)); - /* - * Just reading rx_status fixes most errors. - */ - if (rxsr & RX_MISSED) - lp->stats.rx_missed_errors++; - else if (rxsr & RX_RUNT) - { /* Handled to avoid board lock-up. */ - lp->stats.rx_length_errors++; - if (el_debug > 5) - printk(" runt.\n"); - } - else if (rxsr & RX_GOOD) - { - /* - * Receive worked. - */ - el_receive(dev); - } - else - { - /* - * Nothing? Something is broken! - */ - if (el_debug > 2) - printk("%s: No packet seen, rxsr=%02x **resetting 3c501***\n", - dev->name, rxsr); - el_reset(dev); - } - if (el_debug > 3) - printk(".\n"); - } - - /* - * Move into receive mode - */ - - outb(AX_RX, AX_CMD); - outw(0x00, RX_BUF_CLR); - inb(RX_STATUS); /* Be certain that interrupts are cleared. */ - inb(TX_STATUS); - dev->interrupt = 0; - return; -} - - -/* - * We have a good packet. Well, not really "good", just mostly not broken. - * We must check everything to see if it is good. - */ - -static void el_receive(struct device *dev) -{ - struct net_local *lp = (struct net_local *)dev->priv; - int ioaddr = dev->base_addr; - int pkt_len; - struct sk_buff *skb; - - pkt_len = inw(RX_LOW); - - if (el_debug > 4) - printk(" el_receive %d.\n", pkt_len); - - if ((pkt_len < 60) || (pkt_len > 1536)) - { - if (el_debug) - printk("%s: bogus packet, length=%d\n", dev->name, pkt_len); - lp->stats.rx_over_errors++; - return; - } - - /* - * Command mode so we can empty the buffer - */ - - outb(AX_SYS, AX_CMD); - skb = dev_alloc_skb(pkt_len+2); - - /* - * Start of frame - */ - - outw(0x00, GP_LOW); - if (skb == NULL) - { - printk("%s: Memory squeeze, dropping packet.\n", dev->name); - lp->stats.rx_dropped++; - return; - } - else - { - skb_reserve(skb,2); /* Force 16 byte alignment */ - skb->dev = dev; - /* - * The read increments through the bytes. The interrupt - * handler will fix the pointer when it returns to - * receive mode. - */ - insb(DATAPORT, skb_put(skb,pkt_len), pkt_len); - skb->protocol=eth_type_trans(skb,dev); - netif_rx(skb); - lp->stats.rx_packets++; - } - return; -} - -static void el_reset(struct device *dev) -{ - int ioaddr = dev->base_addr; - - if (el_debug> 2) - printk("3c501 reset..."); - outb(AX_RESET, AX_CMD); /* Reset the chip */ - outb(AX_LOOP, AX_CMD); /* Aux control, irq and loopback enabled */ - { - int i; - for (i = 0; i < 6; i++) /* Set the station address. */ - outb(dev->dev_addr[i], ioaddr + i); - } - - outw(0, RX_BUF_CLR); /* Set rx packet area to 0. */ - cli(); /* Avoid glitch on writes to CMD regs */ - outb(TX_NORM, TX_CMD); /* tx irq on done, collision */ - outb(RX_NORM, RX_CMD); /* Set Rx commands. */ - inb(RX_STATUS); /* Clear status. */ - inb(TX_STATUS); - dev->interrupt = 0; - dev->tbusy = 0; - sti(); -} - -static int el1_close(struct device *dev) -{ - int ioaddr = dev->base_addr; - - if (el_debug > 2) - printk("%s: Shutting down ethercard at %#x.\n", dev->name, ioaddr); - - dev->tbusy = 1; - dev->start = 0; - - /* - * Free and disable the IRQ. - */ - - free_irq(dev->irq); - outb(AX_RESET, AX_CMD); /* Reset the chip */ - irq2dev_map[dev->irq] = 0; - - MOD_DEC_USE_COUNT; - return 0; -} - -static struct enet_statistics *el1_get_stats(struct device *dev) -{ - struct net_local *lp = (struct net_local *)dev->priv; - return &lp->stats; -} - -/* - * Set or clear the multicast filter for this adaptor. - * best-effort filtering. - */ - -static void set_multicast_list(struct device *dev) -{ - int ioaddr = dev->base_addr; - - if(dev->flags&IFF_PROMISC) - { - outb(RX_PROM, RX_CMD); - inb(RX_STATUS); - } - else if (dev->mc_list || dev->flags&IFF_ALLMULTI) - { - outb(RX_MULT, RX_CMD); /* Multicast or all multicast is the same */ - inb(RX_STATUS); /* Clear status. */ - } - else - { - outb(RX_NORM, RX_CMD); - inb(RX_STATUS); - } -} - -#ifdef MODULE - -static char devicename[9] = { 0, }; - -static struct device dev_3c501 = -{ - devicename, /* device name is inserted by linux/drivers/net/net_init.c */ - 0, 0, 0, 0, - 0x280, 5, - 0, 0, 0, NULL, el1_probe -}; - -static int io=0x280; -static int irq=5; - -int init_module(void) -{ - dev_3c501.irq=irq; - dev_3c501.base_addr=io; - if (register_netdev(&dev_3c501) != 0) - return -EIO; - return 0; -} - -void cleanup_module(void) -{ - /* - * No need to check MOD_IN_USE, as sys_delete_module() checks. - */ - - unregister_netdev(&dev_3c501); - - /* - * Free up the private structure, or leak memory :-) - */ - - kfree(dev_3c501.priv); - dev_3c501.priv = NULL; /* gets re-allocated by el1_probe1 */ - - /* - * If we don't do this, we can't re-insmod it later. - */ - release_region(dev_3c501.base_addr, EL1_IO_EXTENT); -} - -#endif /* MODULE */ - -/* - * Local variables: - * compile-command: "gcc -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -m486 -c -o 3c501.o 3c501.c" - * kept-new-versions: 5 - * End: - */ diff --git a/i386/i386at/gpl/linux/net/3c503.c b/i386/i386at/gpl/linux/net/3c503.c deleted file mode 100644 index 9a0c0b9e..00000000 --- a/i386/i386at/gpl/linux/net/3c503.c +++ /dev/null @@ -1,627 +0,0 @@ -/* 3c503.c: A shared-memory NS8390 ethernet driver for linux. */ -/* - Written 1992-94 by Donald Becker. - - Copyright 1993 United States Government as represented by the - Director, National Security Agency. This software may be used and - distributed according to the terms of the GNU Public License, - incorporated herein by reference. - - The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O - Center of Excellence in Space Data and Information Sciences - Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771 - - This driver should work with the 3c503 and 3c503/16. It should be used - in shared memory mode for best performance, although it may also work - in programmed-I/O mode. - - Sources: - EtherLink II Technical Reference Manual, - EtherLink II/16 Technical Reference Manual Supplement, - 3Com Corporation, 5400 Bayfront Plaza, Santa Clara CA 95052-8145 - - The Crynwr 3c503 packet driver. - - Changelog: - - Paul Gortmaker : add support for the 2nd 8kB of RAM on 16 bit cards. - Paul Gortmaker : multiple card support for module users. - -*/ - -static const char *version = - "3c503.c:v1.10 9/23/93 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n"; - -#include <linux/module.h> - -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/errno.h> -#include <linux/string.h> -#include <linux/delay.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> - -#include <asm/io.h> -#include <asm/system.h> - -#include "8390.h" -#include "3c503.h" - - -int el2_probe(struct device *dev); -int el2_pio_probe(struct device *dev); -int el2_probe1(struct device *dev, int ioaddr); - -/* A zero-terminated list of I/O addresses to be probed in PIO mode. */ -static unsigned int netcard_portlist[] = - { 0x300,0x310,0x330,0x350,0x250,0x280,0x2a0,0x2e0,0}; - -#define EL2_IO_EXTENT 16 - -#ifdef HAVE_DEVLIST -/* The 3c503 uses two entries, one for the safe memory-mapped probe and - the other for the typical I/O probe. */ -struct netdev_entry el2_drv = -{"3c503", el2_probe, EL1_IO_EXTENT, 0}; -struct netdev_entry el2pio_drv = -{"3c503pio", el2_pioprobe1, EL1_IO_EXTENT, netcard_portlist}; -#endif - -static int el2_open(struct device *dev); -static int el2_close(struct device *dev); -static void el2_reset_8390(struct device *dev); -static void el2_init_card(struct device *dev); -static void el2_block_output(struct device *dev, int count, - const unsigned char *buf, const start_page); -static void el2_block_input(struct device *dev, int count, struct sk_buff *skb, - int ring_offset); -static void el2_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, - int ring_page); - - -/* This routine probes for a memory-mapped 3c503 board by looking for - the "location register" at the end of the jumpered boot PROM space. - This works even if a PROM isn't there. - - If the ethercard isn't found there is an optional probe for - ethercard jumpered to programmed-I/O mode. - */ -int -el2_probe(struct device *dev) -{ - int *addr, addrs[] = { 0xddffe, 0xd9ffe, 0xcdffe, 0xc9ffe, 0}; - int base_addr = dev->base_addr; - - if (base_addr > 0x1ff) /* Check a single specified location. */ - return el2_probe1(dev, base_addr); - else if (base_addr != 0) /* Don't probe at all. */ - return ENXIO; - - for (addr = addrs; *addr; addr++) { - int i; - unsigned int base_bits = readb(*addr); - /* Find first set bit. */ - for(i = 7; i >= 0; i--, base_bits >>= 1) - if (base_bits & 0x1) - break; - if (base_bits != 1) - continue; - if (check_region(netcard_portlist[i], EL2_IO_EXTENT)) - continue; - if (el2_probe1(dev, netcard_portlist[i]) == 0) - return 0; - } -#if ! defined(no_probe_nonshared_memory) && ! defined (HAVE_DEVLIST) - return el2_pio_probe(dev); -#else - return ENODEV; -#endif -} - -#ifndef HAVE_DEVLIST -/* Try all of the locations that aren't obviously empty. This touches - a lot of locations, and is much riskier than the code above. */ -int -el2_pio_probe(struct device *dev) -{ - int i; - int base_addr = dev ? dev->base_addr : 0; - - if (base_addr > 0x1ff) /* Check a single specified location. */ - return el2_probe1(dev, base_addr); - else if (base_addr != 0) /* Don't probe at all. */ - return ENXIO; - - for (i = 0; netcard_portlist[i]; i++) { - int ioaddr = netcard_portlist[i]; - if (check_region(ioaddr, EL2_IO_EXTENT)) - continue; - if (el2_probe1(dev, ioaddr) == 0) - return 0; - } - - return ENODEV; -} -#endif - -/* Probe for the Etherlink II card at I/O port base IOADDR, - returning non-zero on success. If found, set the station - address and memory parameters in DEVICE. */ -int -el2_probe1(struct device *dev, int ioaddr) -{ - int i, iobase_reg, membase_reg, saved_406, wordlength; - static unsigned version_printed = 0; - unsigned long vendor_id; - - /* Reset and/or avoid any lurking NE2000 */ - if (inb(ioaddr + 0x408) == 0xff) { - udelay(1000); - return ENODEV; - } - - /* We verify that it's a 3C503 board by checking the first three octets - of its ethernet address. */ - iobase_reg = inb(ioaddr+0x403); - membase_reg = inb(ioaddr+0x404); - /* ASIC location registers should be 0 or have only a single bit set. */ - if ( (iobase_reg & (iobase_reg - 1)) - || (membase_reg & (membase_reg - 1))) { - return ENODEV; - } - saved_406 = inb_p(ioaddr + 0x406); - outb_p(ECNTRL_RESET|ECNTRL_THIN, ioaddr + 0x406); /* Reset it... */ - outb_p(ECNTRL_THIN, ioaddr + 0x406); - /* Map the station addr PROM into the lower I/O ports. We now check - for both the old and new 3Com prefix */ - outb(ECNTRL_SAPROM|ECNTRL_THIN, ioaddr + 0x406); - vendor_id = inb(ioaddr)*0x10000 + inb(ioaddr + 1)*0x100 + inb(ioaddr + 2); - if ((vendor_id != OLD_3COM_ID) && (vendor_id != NEW_3COM_ID)) { - /* Restore the register we frobbed. */ - outb(saved_406, ioaddr + 0x406); - return ENODEV; - } - - /* We should have a "dev" from Space.c or the static module table. */ - if (dev == NULL) { - printk("3c503.c: Passed a NULL device.\n"); - dev = init_etherdev(0, 0); - } - - if (ei_debug && version_printed++ == 0) - printk(version); - - dev->base_addr = ioaddr; - - /* Allocate dev->priv and fill in 8390 specific dev fields. */ - if (ethdev_init(dev)) { - printk ("3c503: unable to allocate memory for dev->priv.\n"); - return -ENOMEM; - } - - printk("%s: 3c503 at i/o base %#3x, node ", dev->name, ioaddr); - - /* Retrieve and print the ethernet address. */ - for (i = 0; i < 6; i++) - printk(" %2.2x", dev->dev_addr[i] = inb(ioaddr + i)); - - /* Map the 8390 back into the window. */ - outb(ECNTRL_THIN, ioaddr + 0x406); - - /* Check for EL2/16 as described in tech. man. */ - outb_p(E8390_PAGE0, ioaddr + E8390_CMD); - outb_p(0, ioaddr + EN0_DCFG); - outb_p(E8390_PAGE2, ioaddr + E8390_CMD); - wordlength = inb_p(ioaddr + EN0_DCFG) & ENDCFG_WTS; - outb_p(E8390_PAGE0, ioaddr + E8390_CMD); - - /* Probe for, turn on and clear the board's shared memory. */ - if (ei_debug > 2) printk(" memory jumpers %2.2x ", membase_reg); - outb(EGACFR_NORM, ioaddr + 0x405); /* Enable RAM */ - - /* This should be probed for (or set via an ioctl()) at run-time. - Right now we use a sleazy hack to pass in the interface number - at boot-time via the low bits of the mem_end field. That value is - unused, and the low bits would be discarded even if it was used. */ -#if defined(EI8390_THICK) || defined(EL2_AUI) - ei_status.interface_num = 1; -#else - ei_status.interface_num = dev->mem_end & 0xf; -#endif - printk(", using %sternal xcvr.\n", ei_status.interface_num == 0 ? "in" : "ex"); - - if ((membase_reg & 0xf0) == 0) { - dev->mem_start = 0; - ei_status.name = "3c503-PIO"; - } else { - dev->mem_start = ((membase_reg & 0xc0) ? 0xD8000 : 0xC8000) + - ((membase_reg & 0xA0) ? 0x4000 : 0); - -#define EL2_MEMSIZE (EL2_MB1_STOP_PG - EL2_MB1_START_PG)*256 -#ifdef EL2MEMTEST - /* This has never found an error, but someone might care. - Note that it only tests the 2nd 8kB on 16kB 3c503/16 - cards between card addr. 0x2000 and 0x3fff. */ - { /* Check the card's memory. */ - unsigned long mem_base = dev->mem_start; - unsigned int test_val = 0xbbadf00d; - writel(0xba5eba5e, mem_base); - for (i = sizeof(test_val); i < EL2_MEMSIZE; i+=sizeof(test_val)) { - writel(test_val, mem_base + i); - if (readl(mem_base) != 0xba5eba5e - || readl(mem_base + i) != test_val) { - printk("3c503.c: memory failure or memory address conflict.\n"); - dev->mem_start = 0; - ei_status.name = "3c503-PIO"; - break; - } - test_val += 0x55555555; - writel(0, mem_base + i); - } - } -#endif /* EL2MEMTEST */ - - dev->mem_end = dev->rmem_end = dev->mem_start + EL2_MEMSIZE; - - if (wordlength) { /* No Tx pages to skip over to get to Rx */ - dev->rmem_start = dev->mem_start; - ei_status.name = "3c503/16"; - } else { - dev->rmem_start = TX_PAGES*256 + dev->mem_start; - ei_status.name = "3c503"; - } - } - - /* - Divide up the memory on the card. This is the same regardless of - whether shared-mem or PIO is used. For 16 bit cards (16kB RAM), - we use the entire 8k of bank1 for an Rx ring. We only use 3k - of the bank0 for 2 full size Tx packet slots. For 8 bit cards, - (8kB RAM) we use 3kB of bank1 for two Tx slots, and the remaining - 5kB for an Rx ring. */ - - if (wordlength) { - ei_status.tx_start_page = EL2_MB0_START_PG; - ei_status.rx_start_page = EL2_MB1_START_PG; - } else { - ei_status.tx_start_page = EL2_MB1_START_PG; - ei_status.rx_start_page = EL2_MB1_START_PG + TX_PAGES; - } - - /* Finish setting the board's parameters. */ - ei_status.stop_page = EL2_MB1_STOP_PG; - ei_status.word16 = wordlength; - ei_status.reset_8390 = &el2_reset_8390; - ei_status.get_8390_hdr = &el2_get_8390_hdr; - ei_status.block_input = &el2_block_input; - ei_status.block_output = &el2_block_output; - - request_region(ioaddr, EL2_IO_EXTENT, ei_status.name); - - if (dev->irq == 2) - dev->irq = 9; - else if (dev->irq > 5 && dev->irq != 9) { - printk("3c503: configured interrupt %d invalid, will use autoIRQ.\n", - dev->irq); - dev->irq = 0; - } - - ei_status.saved_irq = dev->irq; - - dev->start = 0; - dev->open = &el2_open; - dev->stop = &el2_close; - - if (dev->mem_start) - printk("%s: %s - %dkB RAM, 8kB shared mem window at %#6lx-%#6lx.\n", - dev->name, ei_status.name, (wordlength+1)<<3, - dev->mem_start, dev->mem_end-1); - - else - printk("\n%s: %s, %dkB RAM, using programmed I/O (REJUMPER for SHARED MEMORY).\n", - dev->name, ei_status.name, (wordlength+1)<<3); - - return 0; -} - -static int -el2_open(struct device *dev) -{ - - if (dev->irq < 2) { - int irqlist[] = {5, 9, 3, 4, 0}; - int *irqp = irqlist; - - outb(EGACFR_NORM, E33G_GACFR); /* Enable RAM and interrupts. */ - do { - if (request_irq (*irqp, NULL, 0, "bogus") != -EBUSY) { - /* Twinkle the interrupt, and check if it's seen. */ - autoirq_setup(0); - outb_p(0x04 << ((*irqp == 9) ? 2 : *irqp), E33G_IDCFR); - outb_p(0x00, E33G_IDCFR); - if (*irqp == autoirq_report(0) /* It's a good IRQ line! */ - && request_irq (dev->irq = *irqp, &ei_interrupt, 0, ei_status.name) == 0) - break; - } - } while (*++irqp); - if (*irqp == 0) { - outb(EGACFR_IRQOFF, E33G_GACFR); /* disable interrupts. */ - return -EAGAIN; - } - } else { - if (request_irq(dev->irq, &ei_interrupt, 0, ei_status.name)) { - return -EAGAIN; - } - } - - el2_init_card(dev); - ei_open(dev); - MOD_INC_USE_COUNT; - return 0; -} - -static int -el2_close(struct device *dev) -{ - free_irq(dev->irq); - dev->irq = ei_status.saved_irq; - irq2dev_map[dev->irq] = NULL; - outb(EGACFR_IRQOFF, E33G_GACFR); /* disable interrupts. */ - - ei_close(dev); - MOD_DEC_USE_COUNT; - return 0; -} - -/* This is called whenever we have a unrecoverable failure: - transmit timeout - Bad ring buffer packet header - */ -static void -el2_reset_8390(struct device *dev) -{ - if (ei_debug > 1) { - printk("%s: Resetting the 3c503 board...", dev->name); - printk("%#lx=%#02x %#lx=%#02x %#lx=%#02x...", E33G_IDCFR, inb(E33G_IDCFR), - E33G_CNTRL, inb(E33G_CNTRL), E33G_GACFR, inb(E33G_GACFR)); - } - outb_p(ECNTRL_RESET|ECNTRL_THIN, E33G_CNTRL); - ei_status.txing = 0; - outb_p(ei_status.interface_num==0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL); - el2_init_card(dev); - if (ei_debug > 1) printk("done\n"); -} - -/* Initialize the 3c503 GA registers after a reset. */ -static void -el2_init_card(struct device *dev) -{ - /* Unmap the station PROM and select the DIX or BNC connector. */ - outb_p(ei_status.interface_num==0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL); - - /* Set ASIC copy of rx's first and last+1 buffer pages */ - /* These must be the same as in the 8390. */ - outb(ei_status.rx_start_page, E33G_STARTPG); - outb(ei_status.stop_page, E33G_STOPPG); - - /* Point the vector pointer registers somewhere ?harmless?. */ - outb(0xff, E33G_VP2); /* Point at the ROM restart location 0xffff0 */ - outb(0xff, E33G_VP1); - outb(0x00, E33G_VP0); - /* Turn off all interrupts until we're opened. */ - outb_p(0x00, dev->base_addr + EN0_IMR); - /* Enable IRQs iff started. */ - outb(EGACFR_NORM, E33G_GACFR); - - /* Set the interrupt line. */ - outb_p((0x04 << (dev->irq == 9 ? 2 : dev->irq)), E33G_IDCFR); - outb_p(8, E33G_DRQCNT); /* Set burst size to 8 */ - outb_p(0x20, E33G_DMAAH); /* Put a valid addr in the GA DMA */ - outb_p(0x00, E33G_DMAAL); - return; /* We always succeed */ -} - -/* Either use the shared memory (if enabled on the board) or put the packet - out through the ASIC FIFO. The latter is probably much slower. */ -static void -el2_block_output(struct device *dev, int count, - const unsigned char *buf, const start_page) -{ - int i; /* Buffer index */ - int boguscount = 0; /* timeout counter */ - - if (ei_status.word16) /* Tx packets go into bank 0 on EL2/16 card */ - outb(EGACFR_RSEL|EGACFR_TCM, E33G_GACFR); - else - outb(EGACFR_NORM, E33G_GACFR); - - if (dev->mem_start) { /* Shared memory transfer */ - unsigned long dest_addr = dev->mem_start + - ((start_page - ei_status.tx_start_page) << 8); - memcpy_toio(dest_addr, buf, count); - outb(EGACFR_NORM, E33G_GACFR); /* Back to bank1 in case on bank0 */ - return; - } - /* No shared memory, put the packet out the slow way. */ - /* Set up then start the internal memory transfer to Tx Start Page */ - outb(0x00, E33G_DMAAL); - outb_p(start_page, E33G_DMAAH); - outb_p((ei_status.interface_num ? ECNTRL_AUI : ECNTRL_THIN ) | ECNTRL_OUTPUT - | ECNTRL_START, E33G_CNTRL); - - /* This is the byte copy loop: it should probably be tuned for - speed once everything is working. I think it is possible - to output 8 bytes between each check of the status bit. */ - for(i = 0; i < count; i++) { - if (i % 8 == 0) - while ((inb(E33G_STATUS) & ESTAT_DPRDY) == 0) - if (++boguscount > (i<<3) + 32) { - printk("%s: FIFO blocked in el2_block_output (at %d of %d, bc=%d).\n", - dev->name, i, count, boguscount); - outb(EGACFR_NORM, E33G_GACFR); /* To MB1 for EL2/16 */ - return; - } - outb(buf[i], E33G_FIFOH); - } - outb_p(ei_status.interface_num==0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL); - outb(EGACFR_NORM, E33G_GACFR); /* Back to bank1 in case on bank0 */ - return; -} - -/* Read the 4 byte, page aligned 8390 specific header. */ -static void -el2_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page) -{ - unsigned int i; - unsigned long hdr_start = dev->mem_start + ((ring_page - EL2_MB1_START_PG)<<8); - unsigned long fifo_watchdog; - - if (dev->mem_start) { /* Use the shared memory. */ -#ifdef notdef - /* Officially this is what we are doing, but the readl() is faster */ - memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr)); -#else - ((unsigned int*)hdr)[0] = readl(hdr_start); -#endif - return; - } - - /* No shared memory, use programmed I/O. Ugh. */ - outb(0, E33G_DMAAL); - outb_p(ring_page & 0xff, E33G_DMAAH); - outb_p((ei_status.interface_num == 0 ? ECNTRL_THIN : ECNTRL_AUI) | ECNTRL_INPUT - | ECNTRL_START, E33G_CNTRL); - - /* Header is < 8 bytes, so only check the FIFO at the beginning. */ - fifo_watchdog = jiffies; - while ((inb(E33G_STATUS) & ESTAT_DPRDY) == 0) { - if (jiffies - fifo_watchdog > 2*HZ/100) { - printk("%s: FIFO blocked in el2_get_8390_hdr.\n", dev->name); - break; - } - } - - for(i = 0; i < sizeof(struct e8390_pkt_hdr); i++) - ((char *)(hdr))[i] = inb_p(E33G_FIFOH); - - outb_p(ei_status.interface_num == 0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL); -} - -/* Returns the new ring pointer. */ -static void -el2_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset) -{ - int boguscount = 0; - int end_of_ring = dev->rmem_end; - unsigned int i; - - /* Maybe enable shared memory just be to be safe... nahh.*/ - if (dev->mem_start) { /* Use the shared memory. */ - ring_offset -= (EL2_MB1_START_PG<<8); - if (dev->mem_start + ring_offset + count > end_of_ring) { - /* We must wrap the input move. */ - int semi_count = end_of_ring - (dev->mem_start + ring_offset); - memcpy_fromio(skb->data, dev->mem_start + ring_offset, semi_count); - count -= semi_count; - memcpy_fromio(skb->data + semi_count, dev->rmem_start, count); - } else { - /* Packet is in one chunk -- we can copy + cksum. */ - eth_io_copy_and_sum(skb, dev->mem_start + ring_offset, count, 0); - } - return; - } - /* No shared memory, use programmed I/O. */ - outb(ring_offset & 0xff, E33G_DMAAL); - outb_p((ring_offset >> 8) & 0xff, E33G_DMAAH); - outb_p((ei_status.interface_num == 0 ? ECNTRL_THIN : ECNTRL_AUI) | ECNTRL_INPUT - | ECNTRL_START, E33G_CNTRL); - - /* This is the byte copy loop: it should probably be tuned for - speed once everything is working. */ - for(i = 0; i < count; i++) { - if (i % 8 == 0) - while ((inb(E33G_STATUS) & ESTAT_DPRDY) == 0) - if (++boguscount > (i<<3) + 32) { - printk("%s: FIFO blocked in el2_block_input() (at %d of %d, bc=%d).\n", - dev->name, i, count, boguscount); - boguscount = 0; - break; - } - (skb->data)[i] = inb_p(E33G_FIFOH); - } - outb_p(ei_status.interface_num == 0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL); -} - - -#ifdef MODULE -#define MAX_EL2_CARDS 4 /* Max number of EL2 cards per module */ -#define NAMELEN 8 /* # of chars for storing dev->name */ -static char namelist[NAMELEN * MAX_EL2_CARDS] = { 0, }; -static struct device dev_el2[MAX_EL2_CARDS] = { - { - NULL, /* assign a chunk of namelist[] below */ - 0, 0, 0, 0, - 0, 0, - 0, 0, 0, NULL, NULL - }, -}; - -static int io[MAX_EL2_CARDS] = { 0, }; -static int irq[MAX_EL2_CARDS] = { 0, }; -static int xcvr[MAX_EL2_CARDS] = { 0, }; /* choose int. or ext. xcvr */ - -/* This is set up so that only a single autoprobe takes place per call. -ISA device autoprobes on a running machine are not recommended. */ -int -init_module(void) -{ - int this_dev, found = 0; - - for (this_dev = 0; this_dev < MAX_EL2_CARDS; this_dev++) { - struct device *dev = &dev_el2[this_dev]; - dev->name = namelist+(NAMELEN*this_dev); - dev->irq = irq[this_dev]; - dev->base_addr = io[this_dev]; - dev->mem_end = xcvr[this_dev]; /* low 4bits = xcvr sel. */ - dev->init = el2_probe; - if (io[this_dev] == 0) { - if (this_dev != 0) break; /* only autoprobe 1st one */ - printk(KERN_NOTICE "3c503.c: Presently autoprobing (not recommended) for a single card.\n"); - } - if (register_netdev(dev) != 0) { - printk(KERN_WARNING "3c503.c: No 3c503 card found (i/o = 0x%x).\n", io[this_dev]); - if (found != 0) return 0; /* Got at least one. */ - return -ENXIO; - } - found++; - } - - return 0; -} - -void -cleanup_module(void) -{ - int this_dev; - - for (this_dev = 0; this_dev < MAX_EL2_CARDS; this_dev++) { - struct device *dev = &dev_el2[this_dev]; - if (dev->priv != NULL) { - /* NB: el2_close() handles free_irq + irq2dev map */ - kfree(dev->priv); - dev->priv = NULL; - release_region(dev->base_addr, EL2_IO_EXTENT); - unregister_netdev(dev); - } - } -} -#endif /* MODULE */ - -/* - * Local variables: - * version-control: t - * kept-new-versions: 5 - * c-indent-level: 4 - * End: - */ diff --git a/i386/i386at/gpl/linux/net/3c503.h b/i386/i386at/gpl/linux/net/3c503.h deleted file mode 100644 index b9f8a46f..00000000 --- a/i386/i386at/gpl/linux/net/3c503.h +++ /dev/null @@ -1,91 +0,0 @@ -/* Definitions for the 3Com 3c503 Etherlink 2. */ -/* This file is distributed under the GPL. - Many of these names and comments are directly from the Crynwr packet - drivers, which are released under the GPL. */ - -#define EL2H (dev->base_addr + 0x400) -#define EL2L (dev->base_addr) - -/* Vendor unique hardware addr. prefix. 3Com has 2 because they ran - out of available addresses on the first one... */ - -#define OLD_3COM_ID 0x02608c -#define NEW_3COM_ID 0x0020af - -/* Shared memory management parameters. NB: The 8 bit cards have only - one bank (MB1) which serves both Tx and Rx packet space. The 16bit - cards have 2 banks, MB0 for Tx packets, and MB1 for Rx packets. - You choose which bank appears in the sh. mem window with EGACFR_MBSn */ - -#define EL2_MB0_START_PG (0x00) /* EL2/16 Tx packets go in bank 0 */ -#define EL2_MB1_START_PG (0x20) /* First page of bank 1 */ -#define EL2_MB1_STOP_PG (0x40) /* Last page +1 of bank 1 */ - -/* 3Com 3c503 ASIC registers */ -#define E33G_STARTPG (EL2H+0) /* Start page, matching EN0_STARTPG */ -#define E33G_STOPPG (EL2H+1) /* Stop page, must match EN0_STOPPG */ -#define E33G_DRQCNT (EL2H+2) /* DMA burst count */ -#define E33G_IOBASE (EL2H+3) /* Read of I/O base jumpers. */ - /* (non-useful, but it also appears at the end of EPROM space) */ -#define E33G_ROMBASE (EL2H+4) /* Read of memory base jumpers. */ -#define E33G_GACFR (EL2H+5) /* Config/setup bits for the ASIC GA */ -#define E33G_CNTRL (EL2H+6) /* Board's main control register */ -#define E33G_STATUS (EL2H+7) /* Status on completions. */ -#define E33G_IDCFR (EL2H+8) /* Interrupt/DMA config register */ - /* (Which IRQ to assert, DMA chan to use) */ -#define E33G_DMAAH (EL2H+9) /* High byte of DMA address reg */ -#define E33G_DMAAL (EL2H+10) /* Low byte of DMA address reg */ -/* "Vector pointer" - if this address matches a read, the EPROM (rather than - shared RAM) is mapped into memory space. */ -#define E33G_VP2 (EL2H+11) -#define E33G_VP1 (EL2H+12) -#define E33G_VP0 (EL2H+13) -#define E33G_FIFOH (EL2H+14) /* FIFO for programmed I/O moves */ -#define E33G_FIFOL (EL2H+15) /* ... low byte of above. */ - -/* Bits in E33G_CNTRL register: */ - -#define ECNTRL_RESET (0x01) /* Software reset of the ASIC and 8390 */ -#define ECNTRL_THIN (0x02) /* Onboard xcvr enable, AUI disable */ -#define ECNTRL_AUI (0x00) /* Onboard xcvr disable, AUI enable */ -#define ECNTRL_SAPROM (0x04) /* Map the station address prom */ -#define ECNTRL_DBLBFR (0x20) /* FIFO configuration bit */ -#define ECNTRL_OUTPUT (0x40) /* PC-to-3C503 direction if 1 */ -#define ECNTRL_INPUT (0x00) /* 3C503-to-PC direction if 0 */ -#define ECNTRL_START (0x80) /* Start the DMA logic */ - -/* Bits in E33G_STATUS register: */ - -#define ESTAT_DPRDY (0x80) /* Data port (of FIFO) ready */ -#define ESTAT_UFLW (0x40) /* Tried to read FIFO when it was empty */ -#define ESTAT_OFLW (0x20) /* Tried to write FIFO when it was full */ -#define ESTAT_DTC (0x10) /* Terminal Count from PC bus DMA logic */ -#define ESTAT_DIP (0x08) /* DMA In Progress */ - -/* Bits in E33G_GACFR register: */ - -#define EGACFR_NIM (0x80) /* NIC interrupt mask */ -#define EGACFR_TCM (0x40) /* DMA term. count interrupt mask */ -#define EGACFR_RSEL (0x08) /* Map a bank of card mem into system mem */ -#define EGACFR_MBS2 (0x04) /* Memory bank select, bit 2. */ -#define EGACFR_MBS1 (0x02) /* Memory bank select, bit 1. */ -#define EGACFR_MBS0 (0x01) /* Memory bank select, bit 0. */ - -#define EGACFR_NORM (0x49) /* TCM | RSEL | MBS0 */ -#define EGACFR_IRQOFF (0xc9) /* TCM | RSEL | MBS0 | NIM */ - -/* - MBS2 MBS1 MBS0 Sh. mem windows card mem at: - ---- ---- ---- ----------------------------- - 0 0 0 0x0000 -- bank 0 - 0 0 1 0x2000 -- bank 1 (only choice for 8bit card) - 0 1 0 0x4000 -- bank 2, not used - 0 1 1 0x6000 -- bank 3, not used - -There was going to be a 32k card that used bank 2 and 3, but it -never got produced. - -*/ - - -/* End of 3C503 parameter definitions */ diff --git a/i386/i386at/gpl/linux/net/3c505.c b/i386/i386at/gpl/linux/net/3c505.c deleted file mode 100644 index 63ccc9cf..00000000 --- a/i386/i386at/gpl/linux/net/3c505.c +++ /dev/null @@ -1,1518 +0,0 @@ -/* - * Linux ethernet device driver for the 3Com Etherlink Plus (3C505) - * By Craig Southeren and Juha Laiho - * - * 3c505.c This module implements an interface to the 3Com - * Etherlink Plus (3c505) ethernet card. Linux device - * driver interface reverse engineered from the Linux 3C509 - * device drivers. Some 3C505 information gleaned from - * the Crynwr packet driver. Still this driver would not - * be here without 3C505 technical reference provided by - * 3Com. - * - * Version: @(#)3c505.c 0.8.4 17-Dec-95 - * - * Authors: Linux 3c505 device driver by - * Craig Southeren, <craigs@ineluki.apana.org.au> - * Final debugging by - * Andrew Tridgell, <tridge@nimbus.anu.edu.au> - * Auto irq/address, tuning, cleanup and v1.1.4+ kernel mods by - * Juha Laiho, <jlaiho@ichaos.nullnet.fi> - * Linux 3C509 driver by - * Donald Becker, <becker@super.org> - * Crynwr packet driver by - * Krishnan Gopalan and Gregg Stefancik, - * Clemson University Engineering Computer Operations. - * Portions of the code have been adapted from the 3c505 - * driver for NCSA Telnet by Bruce Orchard and later - * modified by Warren Van Houten and krus@diku.dk. - * 3C505 technical information provided by - * Terry Murphy, of 3Com Network Adapter Division - * Linux 1.3.0 changes by - * Alan Cox <Alan.Cox@linux.org> - * - */ - -#include <linux/module.h> - -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/string.h> -#include <linux/interrupt.h> -#include <linux/ptrace.h> -#include <linux/errno.h> -#include <linux/in.h> -#include <linux/malloc.h> -#include <linux/ioport.h> -#include <asm/bitops.h> -#include <asm/io.h> - -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> - -#include "3c505.h" - -/********************************************************* - * - * define debug messages here as common strings to reduce space - * - *********************************************************/ - -static const char * filename = __FILE__; - -static const char * null_msg = "*** NULL at %s:%s (line %d) ***\n"; -#define CHECK_NULL(p) \ - if (!p) printk(null_msg, filename,__FUNCTION__,__LINE__) - -static const char * timeout_msg = "*** timeout at %s:%s (line %d) ***\n"; -#define TIMEOUT_MSG(lineno) \ - printk(timeout_msg, filename,__FUNCTION__,(lineno)) - -static const char * invalid_pcb_msg = - "*** invalid pcb length %d at %s:%s (line %d) ***\n"; -#define INVALID_PCB_MSG(len) \ - printk(invalid_pcb_msg, (len),filename,__FUNCTION__,__LINE__) - -static const char * search_msg = "%s: Looking for 3c505 adapter at address %#x..."; - -static const char * stilllooking_msg = "still looking..."; - -static const char * found_msg = "found.\n"; - -static const char * notfound_msg = "not found (reason = %d)\n"; - -static const char * couldnot_msg = "%s: 3c505 not found\n"; - -/********************************************************* - * - * various other debug stuff - * - *********************************************************/ - -#ifdef ELP_DEBUG -static int elp_debug = ELP_DEBUG; -#else -static int elp_debug = 0; -#endif - -/* - * 0 = no messages (well, some) - * 1 = messages when high level commands performed - * 2 = messages when low level commands performed - * 3 = messages when interrupts received - */ - -#define ELP_VERSION "0.8.4" - -#ifdef MACH -#define ELP_NEED_HARD_RESET 0 -#endif - -/***************************************************************** - * - * useful macros - * - *****************************************************************/ - -#ifndef TRUE -#define TRUE 1 -#endif - -#ifndef FALSE -#define FALSE 0 -#endif - - -/***************************************************************** - * - * List of I/O-addresses we try to auto-sense - * Last element MUST BE 0! - *****************************************************************/ - -const int addr_list[]={0x300,0x280,0x310,0}; - -/***************************************************************** - * - * Functions for I/O (note the inline !) - * - *****************************************************************/ - -static inline unsigned char -inb_status (unsigned int base_addr) -{ - return inb(base_addr+PORT_STATUS); -} - -static inline unsigned char -inb_control (unsigned int base_addr) -{ - return inb(base_addr+PORT_CONTROL); -} - -static inline int -inb_command (unsigned int base_addr) -{ - return inb(base_addr+PORT_COMMAND); -} - -static inline void -outb_control (unsigned char val, unsigned int base_addr) -{ - outb(val, base_addr+PORT_CONTROL); -} - -static inline void -outb_command (unsigned char val, unsigned int base_addr) -{ - outb(val, base_addr+PORT_COMMAND); -} - -static inline unsigned int -inw_data (unsigned int base_addr) -{ - return inw(base_addr+PORT_DATA); -} - -static inline void -outw_data (unsigned int val, unsigned int base_addr) -{ - outw(val, base_addr+PORT_DATA); -} - - -/***************************************************************** - * - * structure to hold context information for adapter - * - *****************************************************************/ - -typedef struct { - volatile short got[NUM_TRANSMIT_CMDS]; /* flags for command completion */ - pcb_struct tx_pcb; /* PCB for foreground sending */ - pcb_struct rx_pcb; /* PCB for foreground receiving */ - pcb_struct itx_pcb; /* PCB for background sending */ - pcb_struct irx_pcb; /* PCB for background receiving */ - struct enet_statistics stats; -} elp_device; - -static int reset_count=0; - -/***************************************************************** - * - * useful functions for accessing the adapter - * - *****************************************************************/ - -/* - * use this routine when accessing the ASF bits as they are - * changed asynchronously by the adapter - */ - -/* get adapter PCB status */ -#define GET_ASF(addr) \ - (get_status(addr)&ASF_PCB_MASK) - -static inline int -get_status (unsigned int base_addr) -{ - int timeout = jiffies + 10; - register int stat1; - do { - stat1 = inb_status(base_addr); - } while (stat1 != inb_status(base_addr) && jiffies < timeout); - if (jiffies >= timeout) - TIMEOUT_MSG(__LINE__); - return stat1; -} - -static inline void -set_hsf (unsigned int base_addr, int hsf) -{ - cli(); - outb_control((inb_control(base_addr)&~HSF_PCB_MASK)|hsf, base_addr); - sti(); -} - -#define WAIT_HCRE(addr,toval) wait_hcre((addr),(toval),__LINE__) -static inline int -wait_hcre (unsigned int base_addr, int toval, int lineno) -{ - int timeout = jiffies + toval; - while (((inb_status(base_addr)&HCRE)==0) && (jiffies <= timeout)) - ; - if (jiffies >= timeout) { - TIMEOUT_MSG(lineno); - return FALSE; - } - return TRUE; -} - -static inline int -wait_fast_hcre (unsigned int base_addr, int toval, int lineno) -{ - int timeout = 0; - while (((inb_status(base_addr)&HCRE)==0) && (timeout++ < toval)) - ; - if (timeout >= toval) { - sti(); - TIMEOUT_MSG(lineno); - return FALSE; - } - return TRUE; -} - -static int start_receive (struct device *, pcb_struct *); -static void adapter_hard_reset (struct device *); - -inline static void -adapter_reset (struct device * dev) -{ - int timeout; - unsigned char orig_hcr=inb_control(dev->base_addr); - - elp_device * adapter=dev->priv; - - outb_control(0,dev->base_addr); - - if (inb_status(dev->base_addr)&ACRF) { - do { - inb_command(dev->base_addr); - timeout=jiffies+2; - while ((jiffies<=timeout) && !(inb_status(dev->base_addr)&ACRF)) - ; - } while (inb_status(dev->base_addr)&ACRF); - set_hsf(dev->base_addr,HSF_PCB_NAK); - } - - outb_control(inb_control(dev->base_addr)|ATTN|DIR,dev->base_addr); - timeout=jiffies+1; - while (jiffies<=timeout) - ; - outb_control(inb_control(dev->base_addr)&~ATTN,dev->base_addr); - timeout=jiffies+1; - while (jiffies<=timeout) - ; - outb_control(inb_control(dev->base_addr)|FLSH,dev->base_addr); - timeout=jiffies+1; - while (jiffies<=timeout) - ; - outb_control(inb_control(dev->base_addr)&~FLSH,dev->base_addr); - timeout=jiffies+1; - while (jiffies<=timeout) - ; - - outb_control(orig_hcr, dev->base_addr); - if (!start_receive(dev, &adapter->tx_pcb)) - printk("%s: start receive command failed \n", dev->name); -} - -/***************************************************************** - * - * send_pcb - * Send a PCB to the adapter. - * - * output byte to command reg --<--+ - * wait until HCRE is non zero | - * loop until all bytes sent -->--+ - * set HSF1 and HSF2 to 1 - * output pcb length - * wait until ASF give ACK or NAK - * set HSF1 and HSF2 to 0 - * - *****************************************************************/ - -static int -send_pcb (struct device * dev, pcb_struct * pcb) -{ - int i; - int timeout; - int cont; - - /* - * load each byte into the command register and - * wait for the HCRE bit to indicate the adapter - * had read the byte - */ - set_hsf(dev->base_addr,0); - if ((cont = WAIT_HCRE(dev->base_addr,5))) { - cli(); - if (pcb->command==CMD_TRANSMIT_PACKET) - outb_control(inb_control(dev->base_addr)&~DIR,dev->base_addr); - outb_command(pcb->command, dev->base_addr); - sti(); - cont = WAIT_HCRE(dev->base_addr,5); - } - - if (cont) { - outb_command(pcb->length, dev->base_addr); - cont = WAIT_HCRE(dev->base_addr,5); - } - - cli(); - for (i = 0; cont && (i < pcb->length); i++) { - outb_command(pcb->data.raw[i], dev->base_addr); - cont = wait_fast_hcre(dev->base_addr,20000,__LINE__); - } /* if wait_fast_hcre() failed, has already done sti() */ - - /* set the host status bits to indicate end of PCB */ - /* send the total packet length as well */ - /* wait for the adapter to indicate that it has read the PCB */ - if (cont) { - set_hsf(dev->base_addr,HSF_PCB_END); - outb_command(2+pcb->length, dev->base_addr); - sti(); - timeout = jiffies + 7; - while (jiffies < timeout) { - i = GET_ASF(dev->base_addr); - if ((i == ASF_PCB_ACK) || (i == ASF_PCB_NAK)) - break; - } - - if (i == ASF_PCB_ACK) { - reset_count=0; - return TRUE; - } - else if (i == ASF_PCB_NAK) { - printk("%s: PCB send was NAKed\n", dev->name); - } else { - printk("%s: timeout after sending PCB\n", dev->name); - } - } else { - sti(); - printk("%s: timeout in middle of sending PCB\n", dev->name); - } - - adapter_reset(dev); - return FALSE; -} - -/***************************************************************** - * - * receive_pcb - * Read a PCB to the adapter - * - * wait for ACRF to be non-zero ---<---+ - * input a byte | - * if ASF1 and ASF2 were not both one | - * before byte was read, loop --->---+ - * set HSF1 and HSF2 for ack - * - *****************************************************************/ - -static int -receive_pcb (struct device * dev, pcb_struct * pcb) -{ - int i, j; - int total_length; - int stat; - int timeout; - - CHECK_NULL(pcb); - CHECK_NULL(dev); - - set_hsf(dev->base_addr,0); - - /* get the command code */ - timeout = jiffies + 2; - while (((stat = get_status(dev->base_addr))&ACRF) == 0 && jiffies < timeout) - ; - if (jiffies >= timeout) { - TIMEOUT_MSG(__LINE__); - return FALSE; - } - - pcb->command = inb_command(dev->base_addr); - - /* read the data length */ - timeout = jiffies + 3; - while (((stat = get_status(dev->base_addr)) & ACRF) == 0 && jiffies < timeout) - ; - if (jiffies >= timeout) { - TIMEOUT_MSG(__LINE__); - return FALSE; - } - pcb->length = inb_command(dev->base_addr); - - if (pcb->length > MAX_PCB_DATA) { - INVALID_PCB_MSG(pcb->length); - adapter_reset(dev); - return FALSE; - } - - /* read the data */ - cli(); - i = 0; - do { - j = 0; - while (((stat = get_status(dev->base_addr))&ACRF) == 0 && j++ < 20000) - ; - pcb->data.raw[i++] = inb_command(dev->base_addr); - if (i > MAX_PCB_DATA) - INVALID_PCB_MSG(i); - } while ((stat & ASF_PCB_MASK) != ASF_PCB_END && j < 20000); - sti(); - if (j >= 20000) { - TIMEOUT_MSG(__LINE__); - return FALSE; - } - - /* woops, the last "data" byte was really the length! */ - total_length = pcb->data.raw[--i]; - - /* safety check total length vs data length */ - if (total_length != (pcb->length + 2)) { - if (elp_debug >= 2) - printk("%s: mangled PCB received\n", dev->name); - set_hsf(dev->base_addr,HSF_PCB_NAK); - return FALSE; - } - - set_hsf(dev->base_addr,HSF_PCB_ACK); - reset_count=0; - return TRUE; -} - -static void -adapter_hard_reset (struct device * dev) -{ - int timeout; - long flags; - - CHECK_NULL(dev); - - save_flags(flags); - sti(); - - if (elp_debug > 0) - printk("%s: Resetting the adapter, please wait (approx 20 s)\n", - dev->name); - /* - * take FLSH and ATTN high - */ - outb_control(ATTN|FLSH, dev->base_addr); - - /* - * wait for a little bit - */ - for (timeout = jiffies + 20; jiffies <= timeout; ) - ; - - /* - * now take them low - */ - outb_control(0, dev->base_addr); - - /* - * wait for a little bit - */ - for (timeout = jiffies + 20; jiffies <= timeout; ) - ; - - /* - * now hang around until the board gets it's act together - */ - for (timeout = jiffies + (100 * 15); jiffies <= timeout; ) - if (GET_ASF(dev->base_addr) != ASF_PCB_END) - break; - restore_flags(flags); -} - -/****************************************************** - * - * queue a receive command on the adapter so we will get an - * interrupt when a packet is received. - * - ******************************************************/ - -static int -start_receive (struct device * dev, pcb_struct * tx_pcb) -{ - CHECK_NULL(dev); - CHECK_NULL(tx_pcb); - - if (elp_debug >= 3) - printk("%s: restarting receiver\n", dev->name); - tx_pcb->command = CMD_RECEIVE_PACKET; - tx_pcb->length = sizeof(struct Rcv_pkt); - tx_pcb->data.rcv_pkt.buf_seg - = tx_pcb->data.rcv_pkt.buf_ofs = 0; /* Unused */ - tx_pcb->data.rcv_pkt.buf_len = 1600; - tx_pcb->data.rcv_pkt.timeout = 0; /* set timeout to zero */ - return send_pcb(dev, tx_pcb); -} - -/****************************************************** - * - * extract a packet from the adapter - * this routine is only called from within the interrupt - * service routine, so no cli/sti calls are needed - * note that the length is always assumed to be even - * - ******************************************************/ - -static void -receive_packet (struct device * dev, int len) -{ - register int i; - unsigned short * ptr; - int timeout; - int rlen; - struct sk_buff *skb; - elp_device * adapter; - - CHECK_NULL(dev); - adapter=dev->priv; - - if (len <= 0 || ((len & ~1) != len)) - if (elp_debug >= 3) { - sti(); - printk("*** bad packet len %d at %s(%d)\n",len,filename,__LINE__); - cli(); - } - - rlen = (len+1) & ~1; - - skb = dev_alloc_skb(rlen+2); - - /* - * make sure the data register is going the right way - */ - - outb_control(inb_control(dev->base_addr)|DIR, dev->base_addr); - - /* - * if buffer could not be allocated, swallow it - */ - if (skb == NULL) { - for (i = 0; i < (rlen/2); i++) { - timeout = 0; - while ((inb_status(dev->base_addr)&HRDY) == 0 && timeout++ < 20000) - ; - if (timeout >= 20000) { - sti(); - TIMEOUT_MSG(__LINE__); - break; - } - - inw_data(dev->base_addr); - } - adapter->stats.rx_dropped++; - - } else { - skb_reserve(skb,2); /* 16 byte alignment */ - skb->dev = dev; - - /* - * now read the data from the adapter - */ - ptr = (unsigned short *)skb_put(skb,len); - for (i = 0; i < (rlen/2); i++) { - timeout = 0; - while ((inb_status(dev->base_addr)&HRDY) == 0 && timeout++ < 20000) - ; - if (timeout >= 20000) { - sti(); - printk("*** timeout at %s(%d) reading word %d of %d ***\n", - filename,__LINE__, i, rlen/2); - kfree_skb(skb, FREE_WRITE); - return; - } - - *ptr = inw_data(dev->base_addr); - ptr++; - } - - sti(); - skb->protocol=eth_type_trans(skb,dev); - netif_rx(skb); - } - - outb_control(inb_control(dev->base_addr)&~DIR, dev->base_addr); -} - - -/****************************************************** - * - * interrupt handler - * - ******************************************************/ - -static void -elp_interrupt (int irq, struct pt_regs *reg_ptr) -{ - int len; - int dlen; - struct device *dev; - elp_device * adapter; - int timeout; - - if (irq < 0 || irq > 15) { - printk ("elp_interrupt(): illegal IRQ number found in interrupt routine (%i)\n", irq); - return; - } - - dev = irq2dev_map[irq]; - - if (dev == NULL) { - printk ("elp_interrupt(): irq %d for unknown device.\n", irq); - return; - } - - adapter = (elp_device *) dev->priv; - - CHECK_NULL(adapter); - - if (dev->interrupt) - if (elp_debug >= 2) - printk("%s: Re-entering the interrupt handler.\n", dev->name); - dev->interrupt = 1; - - /* - * allow interrupts (we need timers!) - */ - sti(); - - /* - * receive a PCB from the adapter - */ - timeout = jiffies + 3; - while ((inb_status(dev->base_addr)&ACRF) != 0 && jiffies < timeout) { - - if (receive_pcb(dev, &adapter->irx_pcb)) { - - switch (adapter->irx_pcb.command) { - - /* - * received a packet - this must be handled fast - */ - case CMD_RECEIVE_PACKET_COMPLETE: - /* if the device isn't open, don't pass packets up the stack */ - if (dev->start == 0) - break; - cli(); - /* Set direction of adapter FIFO */ - outb_control(inb_control(dev->base_addr)|DIR, - dev->base_addr); - len = adapter->irx_pcb.data.rcv_resp.pkt_len; - dlen = adapter->irx_pcb.data.rcv_resp.buf_len; - if (adapter->irx_pcb.data.rcv_resp.timeout != 0) { - printk("%s: interrupt - packet not received correctly\n", dev->name); - sti(); - } else { - if (elp_debug >= 3) { - sti(); - printk("%s: interrupt - packet received of length %i (%i)\n", dev->name, len, dlen); - cli(); - } - receive_packet(dev, dlen); - sti(); - if (elp_debug >= 3) - printk("%s: packet received\n", dev->name); - } - if (dev->start && !start_receive(dev, &adapter->itx_pcb)) - if (elp_debug >= 2) - printk("%s: interrupt - failed to send receive start PCB\n", dev->name); - if (elp_debug >= 3) - printk("%s: receive procedure complete\n", dev->name); - - break; - - /* - * 82586 configured correctly - */ - case CMD_CONFIGURE_82586_RESPONSE: - adapter->got[CMD_CONFIGURE_82586] = 1; - if (elp_debug >= 3) - printk("%s: interrupt - configure response received\n", dev->name); - break; - - /* - * Adapter memory configuration - */ - case CMD_CONFIGURE_ADAPTER_RESPONSE: - adapter->got[CMD_CONFIGURE_ADAPTER_MEMORY] = 1; - if (elp_debug >= 3) - printk("%s: Adapter memory configuration %s.\n",dev->name, - adapter->irx_pcb.data.failed?"failed":"succeeded"); - break; - - /* - * Multicast list loading - */ - case CMD_LOAD_MULTICAST_RESPONSE: - adapter->got[CMD_LOAD_MULTICAST_LIST] = 1; - if (elp_debug >= 3) - printk("%s: Multicast address list loading %s.\n",dev->name, - adapter->irx_pcb.data.failed?"failed":"succeeded"); - break; - - /* - * Station address setting - */ - case CMD_SET_ADDRESS_RESPONSE: - adapter->got[CMD_SET_STATION_ADDRESS] = 1; - if (elp_debug >= 3) - printk("%s: Ethernet address setting %s.\n",dev->name, - adapter->irx_pcb.data.failed?"failed":"succeeded"); - break; - - - /* - * received board statistics - */ - case CMD_NETWORK_STATISTICS_RESPONSE: - adapter->stats.rx_packets += adapter->irx_pcb.data.netstat.tot_recv; - adapter->stats.tx_packets += adapter->irx_pcb.data.netstat.tot_xmit; - adapter->stats.rx_crc_errors += adapter->irx_pcb.data.netstat.err_CRC; - adapter->stats.rx_frame_errors += adapter->irx_pcb.data.netstat.err_align; - adapter->stats.rx_fifo_errors += adapter->irx_pcb.data.netstat.err_ovrrun; - adapter->got[CMD_NETWORK_STATISTICS] = 1; - if (elp_debug >= 3) - printk("%s: interrupt - statistics response received\n", dev->name); - break; - - /* - * sent a packet - */ - case CMD_TRANSMIT_PACKET_COMPLETE: - if (elp_debug >= 3) - printk("%s: interrupt - packet sent\n", dev->name); - if (dev->start == 0) - break; - if (adapter->irx_pcb.data.xmit_resp.c_stat != 0) - if (elp_debug >= 2) - printk("%s: interrupt - error sending packet %4.4x\n", - dev->name, adapter->irx_pcb.data.xmit_resp.c_stat); - dev->tbusy = 0; - mark_bh(NET_BH); - break; - - /* - * some unknown PCB - */ - default: - printk("%s: unknown PCB received - %2.2x\n", dev->name, adapter->irx_pcb.command); - break; - } - } else { - printk("%s: failed to read PCB on interrupt\n", dev->name); - adapter_reset(dev); - } - } - - /* - * indicate no longer in interrupt routine - */ - dev->interrupt = 0; -} - - -/****************************************************** - * - * open the board - * - ******************************************************/ - -static int -elp_open (struct device *dev) -{ - elp_device * adapter; - - CHECK_NULL(dev); - - adapter = dev->priv; - - if (elp_debug >= 3) - printk("%s: request to open device\n", dev->name); - - /* - * make sure we actually found the device - */ - if (adapter == NULL) { - printk("%s: Opening a non-existent physical device\n", dev->name); - return -EAGAIN; - } - - /* - * disable interrupts on the board - */ - outb_control(0x00, dev->base_addr); - - /* - * clear any pending interrupts - */ - inb_command(dev->base_addr); - adapter_reset(dev); - - /* - * interrupt routine not entered - */ - dev->interrupt = 0; - - /* - * transmitter not busy - */ - dev->tbusy = 0; - - /* - * make sure we can find the device header given the interrupt number - */ - irq2dev_map[dev->irq] = dev; - - /* - * install our interrupt service routine - */ - if (request_irq(dev->irq, &elp_interrupt, 0, "3c505")) { - irq2dev_map[dev->irq] = NULL; - return -EAGAIN; - } - - /* - * enable interrupts on the board - */ - outb_control(CMDE, dev->base_addr); - - /* - * device is now officially open! - */ - dev->start = 1; - - /* - * configure adapter memory: we need 10 multicast addresses, default==0 - */ - if (elp_debug >= 3) - printk("%s: sending 3c505 memory configuration command\n", dev->name); - adapter->tx_pcb.command = CMD_CONFIGURE_ADAPTER_MEMORY; - adapter->tx_pcb.data.memconf.cmd_q = 10; - adapter->tx_pcb.data.memconf.rcv_q = 20; - adapter->tx_pcb.data.memconf.mcast = 10; - adapter->tx_pcb.data.memconf.frame = 20; - adapter->tx_pcb.data.memconf.rcv_b = 20; - adapter->tx_pcb.data.memconf.progs = 0; - adapter->tx_pcb.length = sizeof(struct Memconf); - adapter->got[CMD_CONFIGURE_ADAPTER_MEMORY] = 0; - if (!send_pcb(dev, &adapter->tx_pcb)) - printk("%s: couldn't send memory configuration command\n", dev->name); - else { - int timeout = jiffies + TIMEOUT; - while (adapter->got[CMD_CONFIGURE_ADAPTER_MEMORY] == 0 && jiffies < timeout) - ; - if (jiffies >= timeout) - TIMEOUT_MSG(__LINE__); - } - - - /* - * configure adapter to receive broadcast messages and wait for response - */ - if (elp_debug >= 3) - printk("%s: sending 82586 configure command\n", dev->name); - adapter->tx_pcb.command = CMD_CONFIGURE_82586; - adapter->tx_pcb.data.configure = NO_LOOPBACK | RECV_BROAD; - adapter->tx_pcb.length = 2; - adapter->got[CMD_CONFIGURE_82586] = 0; - if (!send_pcb(dev, &adapter->tx_pcb)) - printk("%s: couldn't send 82586 configure command\n", dev->name); - else { - int timeout = jiffies + TIMEOUT; - while (adapter->got[CMD_CONFIGURE_82586] == 0 && jiffies < timeout) - ; - if (jiffies >= timeout) - TIMEOUT_MSG(__LINE__); - } - - /* - * queue receive commands to provide buffering - */ - if (!start_receive(dev, &adapter->tx_pcb)) - printk("%s: start receive command failed \n", dev->name); - if (elp_debug >= 3) - printk("%s: start receive command sent\n", dev->name); - - MOD_INC_USE_COUNT; - - return 0; /* Always succeed */ -} - - -/****************************************************** - * - * send a packet to the adapter - * - ******************************************************/ - -static int -send_packet (struct device * dev, unsigned char * ptr, int len) -{ - int i; - int timeout = 0; - elp_device * adapter; - - /* - * make sure the length is even and no shorter than 60 bytes - */ - unsigned int nlen = (((len < 60) ? 60 : len) + 1) & (~1); - - CHECK_NULL(dev); - CHECK_NULL(ptr); - - adapter = dev->priv; - - if (nlen < len) - printk("Warning, bad length nlen=%d len=%d %s(%d)\n",nlen,len,filename,__LINE__); - - /* - * send the adapter a transmit packet command. Ignore segment and offset - * and make sure the length is even - */ - adapter->tx_pcb.command = CMD_TRANSMIT_PACKET; - adapter->tx_pcb.length = sizeof(struct Xmit_pkt); - adapter->tx_pcb.data.xmit_pkt.buf_ofs - = adapter->tx_pcb.data.xmit_pkt.buf_seg = 0; /* Unused */ - adapter->tx_pcb.data.xmit_pkt.pkt_len = nlen; - if (!send_pcb(dev, &adapter->tx_pcb)) { - return FALSE; - } - - /* - * write data to the adapter - */ - cli(); - for (i = 0; i < (nlen/2);i++) { - while (((inb_status(dev->base_addr)&HRDY) == 0) - && (timeout++ < 20000)) - ; - if (timeout >= 20000) { - sti(); - printk("%s: timeout at %s(%d) writing word %d of %d ***\n", - dev->name,filename,__LINE__, i, nlen/2); - return FALSE; - } - - outw_data(*(short *)ptr, dev->base_addr); - ptr +=2; - } - sti(); - - return TRUE; -} - -/****************************************************** - * - * start the transmitter - * return 0 if sent OK, else return 1 - * - ******************************************************/ - -static int -elp_start_xmit (struct sk_buff *skb, struct device *dev) -{ - CHECK_NULL(dev); - - /* - * not sure what this does, but the 3c509 driver does it, so... - */ - if (skb == NULL) { - dev_tint(dev); - return 0; - } - - /* - * if we ended up with a munged length, don't send it - */ - if (skb->len <= 0) - return 0; - - if (elp_debug >= 3) - printk("%s: request to send packet of length %d\n", dev->name, (int)skb->len); - - /* - * if the transmitter is still busy, we have a transmit timeout... - */ - if (dev->tbusy) { - int tickssofar = jiffies - dev->trans_start; - int stat; - if (tickssofar < 50) /* was 500, AJT */ - return 1; - printk("%s: transmit timed out, not resetting adapter\n", dev->name); - if (((stat=inb_status(dev->base_addr))&ACRF) != 0) - printk("%s: hmmm...seemed to have missed an interrupt!\n", dev->name); - printk("%s: status %#02x\n", dev->name, stat); - dev->trans_start = jiffies; - dev->tbusy = 0; - } - - /* - * send the packet at skb->data for skb->len - */ - if (!send_packet(dev, skb->data, skb->len)) { - printk("%s: send packet PCB failed\n", dev->name); - return 1; - } - - if (elp_debug >= 3) - printk("%s: packet of length %d sent\n", dev->name, (int)skb->len); - - - /* - * start the transmit timeout - */ - dev->trans_start = jiffies; - - /* - * the transmitter is now busy - */ - dev->tbusy = 1; - - /* - * free the buffer - */ - dev_kfree_skb(skb, FREE_WRITE); - - return 0; -} - -/****************************************************** - * - * return statistics on the board - * - ******************************************************/ - -static struct enet_statistics * -elp_get_stats (struct device *dev) -{ - elp_device *adapter = (elp_device *) dev->priv; - - if (elp_debug >= 3) - printk("%s: request for stats\n", dev->name); - - /* If the device is closed, just return the latest stats we have, - - we cannot ask from the adapter without interrupts */ - if (!dev->start) - return &adapter->stats; - - /* send a get statistics command to the board */ - adapter->tx_pcb.command = CMD_NETWORK_STATISTICS; - adapter->tx_pcb.length = 0; - adapter->got[CMD_NETWORK_STATISTICS] = 0; - if (!send_pcb(dev, &adapter->tx_pcb)) - printk("%s: couldn't send get statistics command\n", dev->name); - else { - int timeout = jiffies + TIMEOUT; - while (adapter->got[CMD_NETWORK_STATISTICS] == 0 && jiffies < timeout) - ; - if (jiffies >= timeout) { - TIMEOUT_MSG(__LINE__); - return &adapter->stats; - } - } - - /* statistics are now up to date */ - return &adapter->stats; -} - -/****************************************************** - * - * close the board - * - ******************************************************/ - -static int -elp_close (struct device *dev) -{ - elp_device * adapter; - - CHECK_NULL(dev); - adapter = dev->priv; - CHECK_NULL(adapter); - - if (elp_debug >= 3) - printk("%s: request to close device\n", dev->name); - - /* Someone may request the device statistic information even when - * the interface is closed. The following will update the statistics - * structure in the driver, so we'll be able to give current statistics. - */ - (void) elp_get_stats(dev); - - /* - * disable interrupts on the board - */ - outb_control(0x00, dev->base_addr); - - /* - * flag transmitter as busy (i.e. not available) - */ - dev->tbusy = 1; - - /* - * indicate device is closed - */ - dev->start = 0; - - /* - * release the IRQ - */ - free_irq(dev->irq); - - /* - * and we no longer have to map irq to dev either - */ - irq2dev_map[dev->irq] = 0; - - MOD_DEC_USE_COUNT; - - return 0; -} - - -/************************************************************ - * - * Set multicast list - * num_addrs==0: clear mc_list - * num_addrs==-1: set promiscuous mode - * num_addrs>0: set mc_list - * - ************************************************************/ - -static void -elp_set_mc_list (struct device *dev) -{ - elp_device *adapter = (elp_device *) dev->priv; - struct dev_mc_list *dmi=dev->mc_list; - int i; - - if (elp_debug >= 3) - printk("%s: request to set multicast list\n", dev->name); - - if (!(dev->flags&(IFF_PROMISC|IFF_ALLMULTI))) - { - /* send a "load multicast list" command to the board, max 10 addrs/cmd */ - /* if num_addrs==0 the list will be cleared */ - adapter->tx_pcb.command = CMD_LOAD_MULTICAST_LIST; - adapter->tx_pcb.length = 6*dev->mc_count; - for (i=0;i<dev->mc_count;i++) - { - memcpy(adapter->tx_pcb.data.multicast[i], dmi->dmi_addr,6); - dmi=dmi->next; - } - adapter->got[CMD_LOAD_MULTICAST_LIST] = 0; - if (!send_pcb(dev, &adapter->tx_pcb)) - printk("%s: couldn't send set_multicast command\n", dev->name); - else { - int timeout = jiffies + TIMEOUT; - while (adapter->got[CMD_LOAD_MULTICAST_LIST] == 0 && jiffies < timeout) - ; - if (jiffies >= timeout) { - TIMEOUT_MSG(__LINE__); - } - } - if (dev->mc_count) - adapter->tx_pcb.data.configure = NO_LOOPBACK | RECV_BROAD | RECV_MULTI; - else /* num_addrs == 0 */ - adapter->tx_pcb.data.configure = NO_LOOPBACK | RECV_BROAD; - } - else - adapter->tx_pcb.data.configure = NO_LOOPBACK | RECV_PROMISC; - /* - * configure adapter to receive messages (as specified above) - * and wait for response - */ - if (elp_debug >= 3) - printk("%s: sending 82586 configure command\n", dev->name); - adapter->tx_pcb.command = CMD_CONFIGURE_82586; - adapter->tx_pcb.length = 2; - adapter->got[CMD_CONFIGURE_82586] = 0; - if (!send_pcb(dev, &adapter->tx_pcb)) - printk("%s: couldn't send 82586 configure command\n", dev->name); - else { - int timeout = jiffies + TIMEOUT; - while (adapter->got[CMD_CONFIGURE_82586] == 0 && jiffies < timeout) - ; - if (jiffies >= timeout) - TIMEOUT_MSG(__LINE__); - } -} - -/****************************************************** - * - * initialise Etherlink Plus board - * - ******************************************************/ - -static void -elp_init (struct device *dev) -{ - elp_device * adapter; - - CHECK_NULL(dev); - - /* - * set ptrs to various functions - */ - dev->open = elp_open; /* local */ - dev->stop = elp_close; /* local */ - dev->get_stats = elp_get_stats; /* local */ - dev->hard_start_xmit = elp_start_xmit; /* local */ - dev->set_multicast_list = elp_set_mc_list; /* local */ - - /* Setup the generic properties */ - ether_setup(dev); - - /* - * setup ptr to adapter specific information - */ - adapter = (elp_device *)(dev->priv = kmalloc(sizeof(elp_device), GFP_KERNEL)); - CHECK_NULL(adapter); - if (adapter == NULL) - return; - memset(&(adapter->stats), 0, sizeof(struct enet_statistics)); - - /* - * memory information - */ - dev->mem_start = dev->mem_end = dev->rmem_end = dev->rmem_start = 0; -} - -/************************************************************ - * - * A couple of tests to see if there's 3C505 or not - * Called only by elp_autodetect - ************************************************************/ - -static int -elp_sense (struct device * dev) -{ - int timeout; - int addr=dev->base_addr; - const char *name=dev->name; - long flags; - byte orig_HCR, orig_HSR; - - if (check_region(addr, 0xf)) - return -1; - - orig_HCR=inb_control(addr); - orig_HSR=inb_status(addr); - - if (elp_debug > 0) - printk(search_msg, name, addr); - - if (((orig_HCR==0xff) && (orig_HSR==0xff)) || - ((orig_HCR & DIR) != (orig_HSR & DIR))) { - if (elp_debug > 0) - printk(notfound_msg, 1); - return -1; /* It can't be 3c505 if HCR.DIR != HSR.DIR */ - } - - /* Enable interrupts - we need timers! */ - save_flags(flags); - sti(); - - /* Wait for a while; the adapter may still be booting up */ - if (elp_debug > 0) - printk(stilllooking_msg); - for (timeout = jiffies + (100 * 15); jiffies <= timeout; ) - if (GET_ASF(addr) != ASF_PCB_END) - break; - - if (orig_HCR & DIR) { - /* If HCR.DIR is up, we pull it down. HSR.DIR should follow. */ - outb_control(orig_HCR & ~DIR,addr); - timeout = jiffies+30; - while (jiffies < timeout) - ; - restore_flags(flags); - if (inb_status(addr) & DIR) { - outb_control(orig_HCR,addr); - if (elp_debug > 0) - printk(notfound_msg, 2); - return -1; - } - } else { - /* If HCR.DIR is down, we pull it up. HSR.DIR should follow. */ - outb_control(orig_HCR | DIR,addr); - timeout = jiffies+300; - while (jiffies < timeout) - ; - restore_flags(flags); - if (!(inb_status(addr) & DIR)) { - outb_control(orig_HCR,addr); - if (elp_debug > 0) - printk(notfound_msg, 3); - return -1; - } - } - /* - * It certainly looks like a 3c505. If it has DMA enabled, it needs - * a hard reset. Also, do a hard reset if selected at the compile time. - */ - if (elp_debug > 0) - printk(found_msg); - - if (((orig_HCR==0x35) && (orig_HSR==0x5b)) || ELP_NEED_HARD_RESET) - adapter_hard_reset(dev); - return 0; -} - -/************************************************************* - * - * Search through addr_list[] and try to find a 3C505 - * Called only by eplus_probe - *************************************************************/ - -static int -elp_autodetect (struct device * dev) -{ - int idx=0; - - /* if base address set, then only check that address - otherwise, run through the table */ - if (dev->base_addr != 0) { /* dev->base_addr == 0 ==> plain autodetect */ - if (elp_sense(dev) == 0) - return dev->base_addr; - } else while ( (dev->base_addr=addr_list[idx++]) ) { - if (elp_sense(dev) == 0) - return dev->base_addr; - } - - /* could not find an adapter */ - if (elp_debug > 0) - printk(couldnot_msg, dev->name); - - return 0; /* Because of this, the layer above will return -ENODEV */ -} - -/****************************************************** - * - * probe for an Etherlink Plus board at the specified address - * - ******************************************************/ - -int -elplus_probe (struct device *dev) -{ - elp_device adapter; - int i; - - CHECK_NULL(dev); - - /* - * setup adapter structure - */ - - dev->base_addr = elp_autodetect(dev); - if ( !(dev->base_addr) ) - return -ENODEV; - - /* - * As we enter here from bootup, the adapter should have IRQs enabled, - * but we can as well enable them anyway. - */ - outb_control(inb_control(dev->base_addr) | CMDE, dev->base_addr); - autoirq_setup(0); - - /* - * use ethernet address command to probe for board in polled mode - * (this also makes us the IRQ that we need for automatic detection) - */ - adapter.tx_pcb.command = CMD_STATION_ADDRESS; - adapter.tx_pcb.length = 0; - if (!send_pcb (dev, &adapter.tx_pcb) || - !receive_pcb(dev, &adapter.rx_pcb) || - (adapter.rx_pcb.command != CMD_ADDRESS_RESPONSE) || - (adapter.rx_pcb.length != 6)) { - printk("%s: not responding to first PCB\n", dev->name); - return -ENODEV; - } - - if (dev->irq) { /* Is there a preset IRQ? */ - if (dev->irq != autoirq_report(0)) { - printk("%s: Detected IRQ doesn't match user-defined one.\n",dev->name); - return -ENODEV; - } - /* if dev->irq == autoirq_report(0), all is well */ - } else /* No preset IRQ; just use what we can detect */ - dev->irq=autoirq_report(0); - switch (dev->irq) { /* Legal, sane? */ - case 0: - printk("%s: No IRQ reported by autoirq_report().\n",dev->name); - printk("%s: Check the jumpers of your 3c505 board.\n",dev->name); - return -ENODEV; - case 1: - case 6: - case 8: - case 13: - printk("%s: Impossible IRQ %d reported by autoirq_report().\n", - dev->name, dev->irq); - return -ENODEV; - } - /* - * Now we have the IRQ number so we can disable the interrupts from - * the board until the board is opened. - */ - outb_control(inb_control(dev->base_addr) & ~CMDE, dev->base_addr); - - /* - * copy ethernet address into structure - */ - for (i = 0; i < 6; i++) - dev->dev_addr[i] = adapter.rx_pcb.data.eth_addr[i]; - - /* - * print remainder of startup message - */ - printk("%s: 3c505 card found at I/O %#lx using IRQ%d" - " has address %02x:%02x:%02x:%02x:%02x:%02x\n", - dev->name, dev->base_addr, dev->irq, - dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], - dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); - - /* - * and reserve the address region - */ - request_region(dev->base_addr, ELP_IO_EXTENT, "3c505"); - - /* - * initialise the device - */ - elp_init(dev); - return 0; -} - -#ifdef MODULE -static char devicename[9] = { 0, }; -static struct device dev_3c505 = { - devicename, /* device name is inserted by linux/drivers/net/net_init.c */ - 0, 0, 0, 0, - 0, 0, - 0, 0, 0, NULL, elplus_probe }; - -int io = 0x300; -int irq = 0; - -int init_module(void) -{ - if (io == 0) - printk("3c505: You should not use auto-probing with insmod!\n"); - dev_3c505.base_addr = io; - dev_3c505.irq = irq; - if (register_netdev(&dev_3c505) != 0) { - printk("3c505: register_netdev() returned non-zero.\n"); - return -EIO; - } - return 0; -} - -void -cleanup_module(void) -{ - unregister_netdev(&dev_3c505); - kfree(dev_3c505.priv); - dev_3c505.priv = NULL; - - /* If we don't do this, we can't re-insmod it later. */ - release_region(dev_3c505.base_addr, ELP_IO_EXTENT); -} -#endif /* MODULE */ diff --git a/i386/i386at/gpl/linux/net/3c505.h b/i386/i386at/gpl/linux/net/3c505.h deleted file mode 100644 index f7d28368..00000000 --- a/i386/i386at/gpl/linux/net/3c505.h +++ /dev/null @@ -1,245 +0,0 @@ -/***************************************************************** - * - * defines for 3Com Etherlink Plus adapter - * - *****************************************************************/ - -/* - * I/O register offsets - */ -#define PORT_COMMAND 0x00 /* read/write, 8-bit */ -#define PORT_STATUS 0x02 /* read only, 8-bit */ -#define PORT_AUXDMA 0x02 /* write only, 8-bit */ -#define PORT_DATA 0x04 /* read/write, 16-bit */ -#define PORT_CONTROL 0x06 /* read/write, 8-bit */ - -#define ELP_IO_EXTENT 0x10 /* size of used IO registers */ - -/* - * host control registers bits - */ -#define ATTN 0x80 /* attention */ -#define FLSH 0x40 /* flush data register */ -#define DMAE 0x20 /* DMA enable */ -#define DIR 0x10 /* direction */ -#define TCEN 0x08 /* terminal count interrupt enable */ -#define CMDE 0x04 /* command register interrupt enable */ -#define HSF2 0x02 /* host status flag 2 */ -#define HSF1 0x01 /* host status flag 1 */ - -/* - * combinations of HSF flags used for PCB transmission - */ -#define HSF_PCB_ACK HSF1 -#define HSF_PCB_NAK HSF2 -#define HSF_PCB_END (HSF2|HSF1) -#define HSF_PCB_MASK (HSF2|HSF1) - -/* - * host status register bits - */ -#define HRDY 0x80 /* data register ready */ -#define HCRE 0x40 /* command register empty */ -#define ACRF 0x20 /* adapter command register full */ -/* #define DIR 0x10 direction - same as in control register */ -#define DONE 0x08 /* DMA done */ -#define ASF3 0x04 /* adapter status flag 3 */ -#define ASF2 0x02 /* adapter status flag 2 */ -#define ASF1 0x01 /* adapter status flag 1 */ - -/* - * combinations of ASF flags used for PCB reception - */ -#define ASF_PCB_ACK ASF1 -#define ASF_PCB_NAK ASF2 -#define ASF_PCB_END (ASF2|ASF1) -#define ASF_PCB_MASK (ASF2|ASF1) - -/* - * host aux DMA register bits - */ -#define DMA_BRST 0x01 /* DMA burst */ - -/* - * maximum amount of data data allowed in a PCB - */ -#define MAX_PCB_DATA 62 - -/***************************************************************** - * - * timeout value - * this is a rough value used for loops to stop them from - * locking up the whole machine in the case of failure or - * error conditions - * - *****************************************************************/ - -#define TIMEOUT 300 - -/***************************************************************** - * - * PCB commands - * - *****************************************************************/ - -enum { - /* - * host PCB commands - */ - CMD_CONFIGURE_ADAPTER_MEMORY = 0x01, - CMD_CONFIGURE_82586 = 0x02, - CMD_STATION_ADDRESS = 0x03, - CMD_DMA_DOWNLOAD = 0x04, - CMD_DMA_UPLOAD = 0x05, - CMD_PIO_DOWNLOAD = 0x06, - CMD_PIO_UPLOAD = 0x07, - CMD_RECEIVE_PACKET = 0x08, - CMD_TRANSMIT_PACKET = 0x09, - CMD_NETWORK_STATISTICS = 0x0a, - CMD_LOAD_MULTICAST_LIST = 0x0b, - CMD_CLEAR_PROGRAM = 0x0c, - CMD_DOWNLOAD_PROGRAM = 0x0d, - CMD_EXECUTE_PROGRAM = 0x0e, - CMD_SELF_TEST = 0x0f, - CMD_SET_STATION_ADDRESS = 0x10, - CMD_ADAPTER_INFO = 0x11, - NUM_TRANSMIT_CMDS, - - /* - * adapter PCB commands - */ - CMD_CONFIGURE_ADAPTER_RESPONSE = 0x31, - CMD_CONFIGURE_82586_RESPONSE = 0x32, - CMD_ADDRESS_RESPONSE = 0x33, - CMD_DOWNLOAD_DATA_REQUEST = 0x34, - CMD_UPLOAD_DATA_REQUEST = 0x35, - CMD_RECEIVE_PACKET_COMPLETE = 0x38, - CMD_TRANSMIT_PACKET_COMPLETE = 0x39, - CMD_NETWORK_STATISTICS_RESPONSE = 0x3a, - CMD_LOAD_MULTICAST_RESPONSE = 0x3b, - CMD_CLEAR_PROGRAM_RESPONSE = 0x3c, - CMD_DOWNLOAD_PROGRAM_RESPONSE = 0x3d, - CMD_EXECUTE_RESPONSE = 0x3e, - CMD_SELF_TEST_RESPONSE = 0x3f, - CMD_SET_ADDRESS_RESPONSE = 0x40, - CMD_ADAPTER_INFO_RESPONSE = 0x41 -}; - -/* Definitions for the PCB data structure */ - -/* Data units */ -typedef unsigned char byte; -typedef unsigned short int word; -typedef unsigned long int dword; - -/* Data structures */ -struct Memconf { - word cmd_q, - rcv_q, - mcast, - frame, - rcv_b, - progs; -}; - -struct Rcv_pkt { - word buf_ofs, - buf_seg, - buf_len, - timeout; -}; - -struct Xmit_pkt { - word buf_ofs, - buf_seg, - pkt_len; -}; - -struct Rcv_resp { - word buf_ofs, - buf_seg, - buf_len, - pkt_len, - timeout, - status; - dword timetag; -}; - -struct Xmit_resp { - word buf_ofs, - buf_seg, - c_stat, - status; -}; - - -struct Netstat { - dword tot_recv, - tot_xmit; - word err_CRC, - err_align, - err_res, - err_ovrrun; -}; - - -struct Selftest { - word error; - union { - word ROM_cksum; - struct { - word ofs, seg; - } RAM; - word i82586; - } failure; -}; - -struct Info { - byte minor_vers, - major_vers; - word ROM_cksum, - RAM_sz, - free_ofs, - free_seg; -}; - -struct Memdump { - word size, - off, - seg; -}; - -/* -Primary Command Block. The most important data structure. All communication -between the host and the adapter is done with these. (Except for the actual -ethernet data, which has different packaging.) -*/ -typedef struct { - byte command; - byte length; - union { - struct Memconf memconf; - word configure; - struct Rcv_pkt rcv_pkt; - struct Xmit_pkt xmit_pkt; - byte multicast[10][6]; - byte eth_addr[6]; - byte failed; - struct Rcv_resp rcv_resp; - struct Xmit_resp xmit_resp; - struct Netstat netstat; - struct Selftest selftest; - struct Info info; - struct Memdump memdump; - byte raw[62]; - } data; -} pcb_struct; - -/* These defines for 'configure' */ -#define RECV_STATION 0x00 -#define RECV_BROAD 0x01 -#define RECV_MULTI 0x02 -#define RECV_PROMISC 0x04 -#define NO_LOOPBACK 0x00 -#define INT_LOOPBACK 0x08 -#define EXT_LOOPBACK 0x10 diff --git a/i386/i386at/gpl/linux/net/3c507.c b/i386/i386at/gpl/linux/net/3c507.c deleted file mode 100644 index f18bc0a3..00000000 --- a/i386/i386at/gpl/linux/net/3c507.c +++ /dev/null @@ -1,923 +0,0 @@ -/* 3c507.c: An EtherLink16 device driver for Linux. */ -/* - Written 1993,1994 by Donald Becker. - - Copyright 1993 United States Government as represented by the - Director, National Security Agency. - - This software may be used and distributed according to the terms - of the GNU Public License, incorporated herein by reference. - - The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O - Center of Excellence in Space Data and Information Sciences - Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771 - - Thanks go to jennings@Montrouge.SMR.slb.com ( Patrick Jennings) - and jrs@world.std.com (Rick Sladkey) for testing and bugfixes. - Mark Salazar <leslie@access.digex.net> made the changes for cards with - only 16K packet buffers. - - Things remaining to do: - Verify that the tx and rx buffers don't have fencepost errors. - Move the theory of operation and memory map documentation. - The statistics need to be updated correctly. -*/ - -static const char *version = - "3c507.c:v1.10 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n"; - - -#include <linux/module.h> - -/* - Sources: - This driver wouldn't have been written with the availability of the - Crynwr driver source code. It provided a known-working implementation - that filled in the gaping holes of the Intel documentation. Three cheers - for Russ Nelson. - - Intel Microcommunications Databook, Vol. 1, 1990. It provides just enough - info that the casual reader might think that it documents the i82586 :-<. -*/ - -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/types.h> -#include <linux/fcntl.h> -#include <linux/interrupt.h> -#include <linux/ptrace.h> -#include <linux/ioport.h> -#include <linux/in.h> -#include <linux/string.h> -#include <asm/system.h> -#include <asm/bitops.h> -#include <asm/io.h> -#include <asm/dma.h> -#include <linux/errno.h> - -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> -#include <linux/malloc.h> - - -/* use 0 for production, 1 for verification, 2..7 for debug */ -#ifndef NET_DEBUG -#define NET_DEBUG 1 -#endif -static unsigned int net_debug = NET_DEBUG; - -/* A zero-terminated list of common I/O addresses to be probed. */ -static unsigned int netcard_portlist[] = - { 0x300, 0x320, 0x340, 0x280, 0}; - -/* - Details of the i82586. - - You'll really need the databook to understand the details of this part, - but the outline is that the i82586 has two separate processing units. - Both are started from a list of three configuration tables, of which only - the last, the System Control Block (SCB), is used after reset-time. The SCB - has the following fields: - Status word - Command word - Tx/Command block addr. - Rx block addr. - The command word accepts the following controls for the Tx and Rx units: - */ - -#define CUC_START 0x0100 -#define CUC_RESUME 0x0200 -#define CUC_SUSPEND 0x0300 -#define RX_START 0x0010 -#define RX_RESUME 0x0020 -#define RX_SUSPEND 0x0030 - -/* The Rx unit uses a list of frame descriptors and a list of data buffer - descriptors. We use full-sized (1518 byte) data buffers, so there is - a one-to-one pairing of frame descriptors to buffer descriptors. - - The Tx ("command") unit executes a list of commands that look like: - Status word Written by the 82586 when the command is done. - Command word Command in lower 3 bits, post-command action in upper 3 - Link word The address of the next command. - Parameters (as needed). - - Some definitions related to the Command Word are: - */ -#define CMD_EOL 0x8000 /* The last command of the list, stop. */ -#define CMD_SUSP 0x4000 /* Suspend after doing cmd. */ -#define CMD_INTR 0x2000 /* Interrupt after doing cmd. */ - -enum commands { - CmdNOp = 0, CmdSASetup = 1, CmdConfigure = 2, CmdMulticastList = 3, - CmdTx = 4, CmdTDR = 5, CmdDump = 6, CmdDiagnose = 7}; - -/* Information that need to be kept for each board. */ -struct net_local { - struct enet_statistics stats; - int last_restart; - ushort rx_head; - ushort rx_tail; - ushort tx_head; - ushort tx_cmd_link; - ushort tx_reap; -}; - -/* - Details of the EtherLink16 Implementation - The 3c507 is a generic shared-memory i82586 implementation. - The host can map 16K, 32K, 48K, or 64K of the 64K memory into - 0x0[CD][08]0000, or all 64K into 0xF[02468]0000. - */ - -/* Offsets from the base I/O address. */ -#define SA_DATA 0 /* Station address data, or 3Com signature. */ -#define MISC_CTRL 6 /* Switch the SA_DATA banks, and bus config bits. */ -#define RESET_IRQ 10 /* Reset the latched IRQ line. */ -#define SIGNAL_CA 11 /* Frob the 82586 Channel Attention line. */ -#define ROM_CONFIG 13 -#define MEM_CONFIG 14 -#define IRQ_CONFIG 15 -#define EL16_IO_EXTENT 16 - -/* The ID port is used at boot-time to locate the ethercard. */ -#define ID_PORT 0x100 - -/* Offsets to registers in the mailbox (SCB). */ -#define iSCB_STATUS 0x8 -#define iSCB_CMD 0xA -#define iSCB_CBL 0xC /* Command BLock offset. */ -#define iSCB_RFA 0xE /* Rx Frame Area offset. */ - -/* Since the 3c507 maps the shared memory window so that the last byte is - at 82586 address FFFF, the first byte is at 82586 address 0, 16K, 32K, or - 48K corresponding to window sizes of 64K, 48K, 32K and 16K respectively. - We can account for this be setting the 'SBC Base' entry in the ISCP table - below for all the 16 bit offset addresses, and also adding the 'SCB Base' - value to all 24 bit physical addresses (in the SCP table and the TX and RX - Buffer Descriptors). - -Mark - */ -#define SCB_BASE ((unsigned)64*1024 - (dev->mem_end - dev->mem_start)) - -/* - What follows in 'init_words[]' is the "program" that is downloaded to the - 82586 memory. It's mostly tables and command blocks, and starts at the - reset address 0xfffff6. This is designed to be similar to the EtherExpress, - thus the unusual location of the SCB at 0x0008. - - Even with the additional "don't care" values, doing it this way takes less - program space than initializing the individual tables, and I feel it's much - cleaner. - - The databook is particularly useless for the first two structures, I had - to use the Crynwr driver as an example. - - The memory setup is as follows: - */ - -#define CONFIG_CMD 0x0018 -#define SET_SA_CMD 0x0024 -#define SA_OFFSET 0x002A -#define IDLELOOP 0x30 -#define TDR_CMD 0x38 -#define TDR_TIME 0x3C -#define DUMP_CMD 0x40 -#define DIAG_CMD 0x48 -#define SET_MC_CMD 0x4E -#define DUMP_DATA 0x56 /* A 170 byte buffer for dump and Set-MC into. */ - -#define TX_BUF_START 0x0100 -#define NUM_TX_BUFS 4 -#define TX_BUF_SIZE (1518+14+20+16) /* packet+header+TBD */ - -#define RX_BUF_START 0x2000 -#define RX_BUF_SIZE (1518+14+18) /* packet+header+RBD */ -#define RX_BUF_END (dev->mem_end - dev->mem_start) - -/* - That's it: only 86 bytes to set up the beast, including every extra - command available. The 170 byte buffer at DUMP_DATA is shared between the - Dump command (called only by the diagnostic program) and the SetMulticastList - command. - - To complete the memory setup you only have to write the station address at - SA_OFFSET and create the Tx & Rx buffer lists. - - The Tx command chain and buffer list is setup as follows: - A Tx command table, with the data buffer pointing to... - A Tx data buffer descriptor. The packet is in a single buffer, rather than - chaining together several smaller buffers. - A NoOp command, which initially points to itself, - And the packet data. - - A transmit is done by filling in the Tx command table and data buffer, - re-writing the NoOp command, and finally changing the offset of the last - command to point to the current Tx command. When the Tx command is finished, - it jumps to the NoOp, when it loops until the next Tx command changes the - "link offset" in the NoOp. This way the 82586 never has to go through the - slow restart sequence. - - The Rx buffer list is set up in the obvious ring structure. We have enough - memory (and low enough interrupt latency) that we can avoid the complicated - Rx buffer linked lists by alway associating a full-size Rx data buffer with - each Rx data frame. - - I current use four transmit buffers starting at TX_BUF_START (0x0100), and - use the rest of memory, from RX_BUF_START to RX_BUF_END, for Rx buffers. - - */ - -unsigned short init_words[] = { - /* System Configuration Pointer (SCP). */ - 0x0000, /* Set bus size to 16 bits. */ - 0,0, /* pad words. */ - 0x0000,0x0000, /* ISCP phys addr, set in init_82586_mem(). */ - - /* Intermediate System Configuration Pointer (ISCP). */ - 0x0001, /* Status word that's cleared when init is done. */ - 0x0008,0,0, /* SCB offset, (skip, skip) */ - - /* System Control Block (SCB). */ - 0,0xf000|RX_START|CUC_START, /* SCB status and cmd. */ - CONFIG_CMD, /* Command list pointer, points to Configure. */ - RX_BUF_START, /* Rx block list. */ - 0,0,0,0, /* Error count: CRC, align, buffer, overrun. */ - - /* 0x0018: Configure command. Change to put MAC data with packet. */ - 0, CmdConfigure, /* Status, command. */ - SET_SA_CMD, /* Next command is Set Station Addr. */ - 0x0804, /* "4" bytes of config data, 8 byte FIFO. */ - 0x2e40, /* Magic values, including MAC data location. */ - 0, /* Unused pad word. */ - - /* 0x0024: Setup station address command. */ - 0, CmdSASetup, - SET_MC_CMD, /* Next command. */ - 0xaa00,0xb000,0x0bad, /* Station address (to be filled in) */ - - /* 0x0030: NOP, looping back to itself. Point to first Tx buffer to Tx. */ - 0, CmdNOp, IDLELOOP, 0 /* pad */, - - /* 0x0038: A unused Time-Domain Reflectometer command. */ - 0, CmdTDR, IDLELOOP, 0, - - /* 0x0040: An unused Dump State command. */ - 0, CmdDump, IDLELOOP, DUMP_DATA, - - /* 0x0048: An unused Diagnose command. */ - 0, CmdDiagnose, IDLELOOP, - - /* 0x004E: An empty set-multicast-list command. */ - 0, CmdMulticastList, IDLELOOP, 0, -}; - -/* Index to functions, as function prototypes. */ - -extern int el16_probe(struct device *dev); /* Called from Space.c */ - -static int el16_probe1(struct device *dev, int ioaddr); -static int el16_open(struct device *dev); -static int el16_send_packet(struct sk_buff *skb, struct device *dev); -static void el16_interrupt(int irq, struct pt_regs *regs); -static void el16_rx(struct device *dev); -static int el16_close(struct device *dev); -static struct enet_statistics *el16_get_stats(struct device *dev); - -static void hardware_send_packet(struct device *dev, void *buf, short length); -void init_82586_mem(struct device *dev); - - -#ifdef HAVE_DEVLIST -struct netdev_entry netcard_drv = -{"3c507", el16_probe1, EL16_IO_EXTENT, netcard_portlist}; -#endif - -/* Check for a network adaptor of this type, and return '0' iff one exists. - If dev->base_addr == 0, probe all likely locations. - If dev->base_addr == 1, always return failure. - If dev->base_addr == 2, (detachable devices only) allocate space for the - device and return success. - */ -int -el16_probe(struct device *dev) -{ - int base_addr = dev ? dev->base_addr : 0; - int i; - - if (base_addr > 0x1ff) /* Check a single specified location. */ - return el16_probe1(dev, base_addr); - else if (base_addr != 0) - return ENXIO; /* Don't probe at all. */ - - for (i = 0; netcard_portlist[i]; i++) { - int ioaddr = netcard_portlist[i]; - if (check_region(ioaddr, EL16_IO_EXTENT)) - continue; - if (el16_probe1(dev, ioaddr) == 0) - return 0; - } - - return ENODEV; -} - -int el16_probe1(struct device *dev, int ioaddr) -{ - static unsigned char init_ID_done = 0, version_printed = 0; - int i, irq, irqval; - - if (init_ID_done == 0) { - ushort lrs_state = 0xff; - /* Send the ID sequence to the ID_PORT to enable the board(s). */ - outb(0x00, ID_PORT); - for(i = 0; i < 255; i++) { - outb(lrs_state, ID_PORT); - lrs_state <<= 1; - if (lrs_state & 0x100) - lrs_state ^= 0xe7; - } - outb(0x00, ID_PORT); - init_ID_done = 1; - } - - if (inb(ioaddr) == '*' && inb(ioaddr+1) == '3' - && inb(ioaddr+2) == 'C' && inb(ioaddr+3) == 'O') - ; - else - return ENODEV; - - /* Allocate a new 'dev' if needed. */ - if (dev == NULL) - dev = init_etherdev(0, sizeof(struct net_local)); - - if (net_debug && version_printed++ == 0) - printk(version); - - printk("%s: 3c507 at %#x,", dev->name, ioaddr); - - /* We should make a few more checks here, like the first three octets of - the S.A. for the manufacturer's code. */ - - irq = inb(ioaddr + IRQ_CONFIG) & 0x0f; - - irqval = request_irq(irq, &el16_interrupt, 0, "3c507"); - if (irqval) { - printk ("unable to get IRQ %d (irqval=%d).\n", irq, irqval); - return EAGAIN; - } - - /* We've committed to using the board, and can start filling in *dev. */ - request_region(ioaddr, EL16_IO_EXTENT, "3c507"); - dev->base_addr = ioaddr; - - outb(0x01, ioaddr + MISC_CTRL); - for (i = 0; i < 6; i++) { - dev->dev_addr[i] = inb(ioaddr + i); - printk(" %02x", dev->dev_addr[i]); - } - - if ((dev->mem_start & 0xf) > 0) - net_debug = dev->mem_start & 7; - -#ifdef MEM_BASE - dev->mem_start = MEM_BASE; - dev->mem_end = dev->mem_start + 0x10000; -#else - { - int base; - int size; - char mem_config = inb(ioaddr + MEM_CONFIG); - if (mem_config & 0x20) { - size = 64*1024; - base = 0xf00000 + (mem_config & 0x08 ? 0x080000 - : ((mem_config & 3) << 17)); - } else { - size = ((mem_config & 3) + 1) << 14; - base = 0x0c0000 + ( (mem_config & 0x18) << 12); - } - dev->mem_start = base; - dev->mem_end = base + size; - } -#endif - - dev->if_port = (inb(ioaddr + ROM_CONFIG) & 0x80) ? 1 : 0; - dev->irq = inb(ioaddr + IRQ_CONFIG) & 0x0f; - - printk(", IRQ %d, %sternal xcvr, memory %#lx-%#lx.\n", dev->irq, - dev->if_port ? "ex" : "in", dev->mem_start, dev->mem_end-1); - - if (net_debug) - printk(version); - - /* Initialize the device structure. */ - dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL); - if (dev->priv == NULL) - return -ENOMEM; - memset(dev->priv, 0, sizeof(struct net_local)); - - dev->open = el16_open; - dev->stop = el16_close; - dev->hard_start_xmit = el16_send_packet; - dev->get_stats = el16_get_stats; - - ether_setup(dev); /* Generic ethernet behaviour */ - - dev->flags&=~IFF_MULTICAST; /* Multicast doesn't work */ - - return 0; -} - - - -static int -el16_open(struct device *dev) -{ - irq2dev_map[dev->irq] = dev; - - /* Initialize the 82586 memory and start it. */ - init_82586_mem(dev); - - dev->tbusy = 0; - dev->interrupt = 0; - dev->start = 1; - - MOD_INC_USE_COUNT; - - return 0; -} - -static int -el16_send_packet(struct sk_buff *skb, struct device *dev) -{ - struct net_local *lp = (struct net_local *)dev->priv; - int ioaddr = dev->base_addr; - short *shmem = (short*)dev->mem_start; - - if (dev->tbusy) { - /* If we get here, some higher level has decided we are broken. - There should really be a "kick me" function call instead. */ - int tickssofar = jiffies - dev->trans_start; - if (tickssofar < 5) - return 1; - if (net_debug > 1) - printk("%s: transmit timed out, %s? ", dev->name, - shmem[iSCB_STATUS>>1] & 0x8000 ? "IRQ conflict" : - "network cable problem"); - /* Try to restart the adaptor. */ - if (lp->last_restart == lp->stats.tx_packets) { - if (net_debug > 1) printk("Resetting board.\n"); - /* Completely reset the adaptor. */ - init_82586_mem(dev); - } else { - /* Issue the channel attention signal and hope it "gets better". */ - if (net_debug > 1) printk("Kicking board.\n"); - shmem[iSCB_CMD>>1] = 0xf000|CUC_START|RX_START; - outb(0, ioaddr + SIGNAL_CA); /* Issue channel-attn. */ - lp->last_restart = lp->stats.tx_packets; - } - dev->tbusy=0; - dev->trans_start = jiffies; - } - - /* If some higher layer thinks we've missed an tx-done interrupt - we are passed NULL. Caution: dev_tint() handles the cli()/sti() - itself. */ - if (skb == NULL) { - dev_tint(dev); - return 0; - } - - /* Block a timer-based transmit from overlapping. */ - if (set_bit(0, (void*)&dev->tbusy) != 0) - printk("%s: Transmitter access conflict.\n", dev->name); - else { - short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; - unsigned char *buf = skb->data; - - /* Disable the 82586's input to the interrupt line. */ - outb(0x80, ioaddr + MISC_CTRL); - hardware_send_packet(dev, buf, length); - dev->trans_start = jiffies; - /* Enable the 82586 interrupt input. */ - outb(0x84, ioaddr + MISC_CTRL); - } - - dev_kfree_skb (skb, FREE_WRITE); - - /* You might need to clean up and record Tx statistics here. */ - - return 0; -} - -/* The typical workload of the driver: - Handle the network interface interrupts. */ -static void -el16_interrupt(int irq, struct pt_regs *regs) -{ - struct device *dev = (struct device *)(irq2dev_map[irq]); - struct net_local *lp; - int ioaddr, status, boguscount = 0; - ushort ack_cmd = 0; - ushort *shmem; - - if (dev == NULL) { - printk ("net_interrupt(): irq %d for unknown device.\n", irq); - return; - } - dev->interrupt = 1; - - ioaddr = dev->base_addr; - lp = (struct net_local *)dev->priv; - shmem = ((ushort*)dev->mem_start); - - status = shmem[iSCB_STATUS>>1]; - - if (net_debug > 4) { - printk("%s: 3c507 interrupt, status %4.4x.\n", dev->name, status); - } - - /* Disable the 82586's input to the interrupt line. */ - outb(0x80, ioaddr + MISC_CTRL); - - /* Reap the Tx packet buffers. */ - while (lp->tx_reap != lp->tx_head) { - unsigned short tx_status = shmem[lp->tx_reap>>1]; - - if (tx_status == 0) { - if (net_debug > 5) printk("Couldn't reap %#x.\n", lp->tx_reap); - break; - } - if (tx_status & 0x2000) { - lp->stats.tx_packets++; - lp->stats.collisions += tx_status & 0xf; - dev->tbusy = 0; - mark_bh(NET_BH); /* Inform upper layers. */ - } else { - lp->stats.tx_errors++; - if (tx_status & 0x0600) lp->stats.tx_carrier_errors++; - if (tx_status & 0x0100) lp->stats.tx_fifo_errors++; - if (!(tx_status & 0x0040)) lp->stats.tx_heartbeat_errors++; - if (tx_status & 0x0020) lp->stats.tx_aborted_errors++; - } - if (net_debug > 5) - printk("Reaped %x, Tx status %04x.\n" , lp->tx_reap, tx_status); - lp->tx_reap += TX_BUF_SIZE; - if (lp->tx_reap > RX_BUF_START - TX_BUF_SIZE) - lp->tx_reap = TX_BUF_START; - if (++boguscount > 4) - break; - } - - if (status & 0x4000) { /* Packet received. */ - if (net_debug > 5) - printk("Received packet, rx_head %04x.\n", lp->rx_head); - el16_rx(dev); - } - - /* Acknowledge the interrupt sources. */ - ack_cmd = status & 0xf000; - - if ((status & 0x0700) != 0x0200 && dev->start) { - if (net_debug) - printk("%s: Command unit stopped, status %04x, restarting.\n", - dev->name, status); - /* If this ever occurs we should really re-write the idle loop, reset - the Tx list, and do a complete restart of the command unit. - For now we rely on the Tx timeout if the resume doesn't work. */ - ack_cmd |= CUC_RESUME; - } - - if ((status & 0x0070) != 0x0040 && dev->start) { - static void init_rx_bufs(struct device *); - /* The Rx unit is not ready, it must be hung. Restart the receiver by - initializing the rx buffers, and issuing an Rx start command. */ - if (net_debug) - printk("%s: Rx unit stopped, status %04x, restarting.\n", - dev->name, status); - init_rx_bufs(dev); - shmem[iSCB_RFA >> 1] = RX_BUF_START; - ack_cmd |= RX_START; - } - - shmem[iSCB_CMD>>1] = ack_cmd; - outb(0, ioaddr + SIGNAL_CA); /* Issue channel-attn. */ - - /* Clear the latched interrupt. */ - outb(0, ioaddr + RESET_IRQ); - - /* Enable the 82586's interrupt input. */ - outb(0x84, ioaddr + MISC_CTRL); - - return; -} - -static int -el16_close(struct device *dev) -{ - int ioaddr = dev->base_addr; - ushort *shmem = (short*)dev->mem_start; - - dev->tbusy = 1; - dev->start = 0; - - /* Flush the Tx and disable Rx. */ - shmem[iSCB_CMD >> 1] = RX_SUSPEND | CUC_SUSPEND; - outb(0, ioaddr + SIGNAL_CA); - - /* Disable the 82586's input to the interrupt line. */ - outb(0x80, ioaddr + MISC_CTRL); - - /* We always physically use the IRQ line, so we don't do free_irq(). - We do remove ourselves from the map. */ - - irq2dev_map[dev->irq] = 0; - - /* Update the statistics here. */ - - MOD_DEC_USE_COUNT; - - return 0; -} - -/* Get the current statistics. This may be called with the card open or - closed. */ -static struct enet_statistics * -el16_get_stats(struct device *dev) -{ - struct net_local *lp = (struct net_local *)dev->priv; - - /* ToDo: decide if there are any useful statistics from the SCB. */ - - return &lp->stats; -} - -/* Initialize the Rx-block list. */ -static void -init_rx_bufs(struct device *dev) -{ - struct net_local *lp = (struct net_local *)dev->priv; - unsigned short *write_ptr; - unsigned short SCB_base = SCB_BASE; - - int cur_rxbuf = lp->rx_head = RX_BUF_START; - - /* Initialize each Rx frame + data buffer. */ - do { /* While there is room for one more. */ - - write_ptr = (unsigned short *)(dev->mem_start + cur_rxbuf); - - *write_ptr++ = 0x0000; /* Status */ - *write_ptr++ = 0x0000; /* Command */ - *write_ptr++ = cur_rxbuf + RX_BUF_SIZE; /* Link */ - *write_ptr++ = cur_rxbuf + 22; /* Buffer offset */ - *write_ptr++ = 0x0000; /* Pad for dest addr. */ - *write_ptr++ = 0x0000; - *write_ptr++ = 0x0000; - *write_ptr++ = 0x0000; /* Pad for source addr. */ - *write_ptr++ = 0x0000; - *write_ptr++ = 0x0000; - *write_ptr++ = 0x0000; /* Pad for protocol. */ - - *write_ptr++ = 0x0000; /* Buffer: Actual count */ - *write_ptr++ = -1; /* Buffer: Next (none). */ - *write_ptr++ = cur_rxbuf + 0x20 + SCB_base; /* Buffer: Address low */ - *write_ptr++ = 0x0000; - /* Finally, the number of bytes in the buffer. */ - *write_ptr++ = 0x8000 + RX_BUF_SIZE-0x20; - - lp->rx_tail = cur_rxbuf; - cur_rxbuf += RX_BUF_SIZE; - } while (cur_rxbuf <= RX_BUF_END - RX_BUF_SIZE); - - /* Terminate the list by setting the EOL bit, and wrap the pointer to make - the list a ring. */ - write_ptr = (unsigned short *) - (dev->mem_start + lp->rx_tail + 2); - *write_ptr++ = 0xC000; /* Command, mark as last. */ - *write_ptr++ = lp->rx_head; /* Link */ - -} - -void -init_82586_mem(struct device *dev) -{ - struct net_local *lp = (struct net_local *)dev->priv; - short ioaddr = dev->base_addr; - ushort *shmem = (short*)dev->mem_start; - - /* Enable loopback to protect the wire while starting up, - and hold the 586 in reset during the memory initialization. */ - outb(0x20, ioaddr + MISC_CTRL); - - /* Fix the ISCP address and base. */ - init_words[3] = SCB_BASE; - init_words[7] = SCB_BASE; - - /* Write the words at 0xfff6 (address-aliased to 0xfffff6). */ - memcpy((void*)dev->mem_end-10, init_words, 10); - - /* Write the words at 0x0000. */ - memcpy((char*)dev->mem_start, init_words + 5, sizeof(init_words) - 10); - - /* Fill in the station address. */ - memcpy((char*)dev->mem_start+SA_OFFSET, dev->dev_addr, - sizeof(dev->dev_addr)); - - /* The Tx-block list is written as needed. We just set up the values. */ - lp->tx_cmd_link = IDLELOOP + 4; - lp->tx_head = lp->tx_reap = TX_BUF_START; - - init_rx_bufs(dev); - - /* Start the 586 by releasing the reset line, but leave loopback. */ - outb(0xA0, ioaddr + MISC_CTRL); - - /* This was time consuming to track down: you need to give two channel - attention signals to reliably start up the i82586. */ - outb(0, ioaddr + SIGNAL_CA); - - { - int boguscnt = 50; - while (shmem[iSCB_STATUS>>1] == 0) - if (--boguscnt == 0) { - printk("%s: i82586 initialization timed out with status %04x," - "cmd %04x.\n", dev->name, - shmem[iSCB_STATUS>>1], shmem[iSCB_CMD>>1]); - break; - } - /* Issue channel-attn -- the 82586 won't start. */ - outb(0, ioaddr + SIGNAL_CA); - } - - /* Disable loopback and enable interrupts. */ - outb(0x84, ioaddr + MISC_CTRL); - if (net_debug > 4) - printk("%s: Initialized 82586, status %04x.\n", dev->name, - shmem[iSCB_STATUS>>1]); - return; -} - -static void -hardware_send_packet(struct device *dev, void *buf, short length) -{ - struct net_local *lp = (struct net_local *)dev->priv; - short ioaddr = dev->base_addr; - ushort tx_block = lp->tx_head; - ushort *write_ptr = (ushort *)(dev->mem_start + tx_block); - - /* Set the write pointer to the Tx block, and put out the header. */ - *write_ptr++ = 0x0000; /* Tx status */ - *write_ptr++ = CMD_INTR|CmdTx; /* Tx command */ - *write_ptr++ = tx_block+16; /* Next command is a NoOp. */ - *write_ptr++ = tx_block+8; /* Data Buffer offset. */ - - /* Output the data buffer descriptor. */ - *write_ptr++ = length | 0x8000; /* Byte count parameter. */ - *write_ptr++ = -1; /* No next data buffer. */ - *write_ptr++ = tx_block+22+SCB_BASE;/* Buffer follows the NoOp command. */ - *write_ptr++ = 0x0000; /* Buffer address high bits (always zero). */ - - /* Output the Loop-back NoOp command. */ - *write_ptr++ = 0x0000; /* Tx status */ - *write_ptr++ = CmdNOp; /* Tx command */ - *write_ptr++ = tx_block+16; /* Next is myself. */ - - /* Output the packet at the write pointer. */ - memcpy(write_ptr, buf, length); - - /* Set the old command link pointing to this send packet. */ - *(ushort*)(dev->mem_start + lp->tx_cmd_link) = tx_block; - lp->tx_cmd_link = tx_block + 20; - - /* Set the next free tx region. */ - lp->tx_head = tx_block + TX_BUF_SIZE; - if (lp->tx_head > RX_BUF_START - TX_BUF_SIZE) - lp->tx_head = TX_BUF_START; - - if (net_debug > 4) { - printk("%s: 3c507 @%x send length = %d, tx_block %3x, next %3x.\n", - dev->name, ioaddr, length, tx_block, lp->tx_head); - } - - if (lp->tx_head != lp->tx_reap) - dev->tbusy = 0; -} - -static void -el16_rx(struct device *dev) -{ - struct net_local *lp = (struct net_local *)dev->priv; - short *shmem = (short*)dev->mem_start; - ushort rx_head = lp->rx_head; - ushort rx_tail = lp->rx_tail; - ushort boguscount = 10; - short frame_status; - - while ((frame_status = shmem[rx_head>>1]) < 0) { /* Command complete */ - ushort *read_frame = (short *)(dev->mem_start + rx_head); - ushort rfd_cmd = read_frame[1]; - ushort next_rx_frame = read_frame[2]; - ushort data_buffer_addr = read_frame[3]; - ushort *data_frame = (short *)(dev->mem_start + data_buffer_addr); - ushort pkt_len = data_frame[0]; - - if (rfd_cmd != 0 || data_buffer_addr != rx_head + 22 - || (pkt_len & 0xC000) != 0xC000) { - printk("%s: Rx frame at %#x corrupted, status %04x cmd %04x" - "next %04x data-buf @%04x %04x.\n", dev->name, rx_head, - frame_status, rfd_cmd, next_rx_frame, data_buffer_addr, - pkt_len); - } else if ((frame_status & 0x2000) == 0) { - /* Frame Rxed, but with error. */ - lp->stats.rx_errors++; - if (frame_status & 0x0800) lp->stats.rx_crc_errors++; - if (frame_status & 0x0400) lp->stats.rx_frame_errors++; - if (frame_status & 0x0200) lp->stats.rx_fifo_errors++; - if (frame_status & 0x0100) lp->stats.rx_over_errors++; - if (frame_status & 0x0080) lp->stats.rx_length_errors++; - } else { - /* Malloc up new buffer. */ - struct sk_buff *skb; - - pkt_len &= 0x3fff; - skb = dev_alloc_skb(pkt_len+2); - if (skb == NULL) { - printk("%s: Memory squeeze, dropping packet.\n", dev->name); - lp->stats.rx_dropped++; - break; - } - - skb_reserve(skb,2); - skb->dev = dev; - - /* 'skb->data' points to the start of sk_buff data area. */ - memcpy(skb_put(skb,pkt_len), data_frame + 5, pkt_len); - - skb->protocol=eth_type_trans(skb,dev); - netif_rx(skb); - lp->stats.rx_packets++; - } - - /* Clear the status word and set End-of-List on the rx frame. */ - read_frame[0] = 0; - read_frame[1] = 0xC000; - /* Clear the end-of-list on the prev. RFD. */ - *(short*)(dev->mem_start + rx_tail + 2) = 0x0000; - - rx_tail = rx_head; - rx_head = next_rx_frame; - if (--boguscount == 0) - break; - } - - lp->rx_head = rx_head; - lp->rx_tail = rx_tail; -} -#ifdef MODULE -static char devicename[9] = { 0, }; -static struct device dev_3c507 = { - devicename, /* device name is inserted by linux/drivers/net/net_init.c */ - 0, 0, 0, 0, - 0, 0, - 0, 0, 0, NULL, el16_probe -}; - -static int io = 0x300; -static int irq = 0; - -int init_module(void) -{ - if (io == 0) - printk("3c507: You should not use auto-probing with insmod!\n"); - dev_3c507.base_addr = io; - dev_3c507.irq = irq; - if (register_netdev(&dev_3c507) != 0) { - printk("3c507: register_netdev() returned non-zero.\n"); - return -EIO; - } - return 0; -} - -void -cleanup_module(void) -{ - unregister_netdev(&dev_3c507); - kfree(dev_3c507.priv); - dev_3c507.priv = NULL; - - /* If we don't do this, we can't re-insmod it later. */ - free_irq(dev_3c507.irq); - release_region(dev_3c507.base_addr, EL16_IO_EXTENT); -} -#endif /* MODULE */ - -/* - * Local variables: - * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -I/usr/src/linux/drivers/net -Wall -Wstrict-prototypes -O6 -m486 -c 3c507.c" - * version-control: t - * kept-new-versions: 5 - * tab-width: 4 - * c-indent-level: 4 - * End: - */ diff --git a/i386/i386at/gpl/linux/net/3c509.c b/i386/i386at/gpl/linux/net/3c509.c deleted file mode 100644 index 5e7dce4f..00000000 --- a/i386/i386at/gpl/linux/net/3c509.c +++ /dev/null @@ -1,739 +0,0 @@ -/* 3c509.c: A 3c509 EtherLink3 ethernet driver for linux. */ -/* - Written 1993,1994 by Donald Becker. - - Copyright 1994 by Donald Becker. - Copyright 1993 United States Government as represented by the - Director, National Security Agency. This software may be used and - distributed according to the terms of the GNU Public License, - incorporated herein by reference. - - This driver is for the 3Com EtherLinkIII series. - - The author may be reached as becker@cesdis.gsfc.nasa.gov or - C/O Center of Excellence in Space Data and Information Sciences - Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771 - - Known limitations: - Because of the way 3c509 ISA detection works it's difficult to predict - a priori which of several ISA-mode cards will be detected first. - - This driver does not use predictive interrupt mode, resulting in higher - packet latency but lower overhead. If interrupts are disabled for an - unusually long time it could also result in missed packets, but in - practice this rarely happens. -*/ - -static const char *version = "3c509.c:1.03 10/8/94 becker@cesdis.gsfc.nasa.gov\n"; - -#include <linux/module.h> - -#include <linux/config.h> -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/string.h> -#include <linux/interrupt.h> -#include <linux/ptrace.h> -#include <linux/errno.h> -#include <linux/in.h> -#include <linux/malloc.h> -#include <linux/ioport.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> -#include <linux/config.h> /* for CONFIG_MCA */ - -#include <asm/bitops.h> -#include <asm/io.h> - - -#ifdef EL3_DEBUG -int el3_debug = EL3_DEBUG; -#else -int el3_debug = 2; -#endif - -/* To minimize the size of the driver source I only define operating - constants if they are used several times. You'll need the manual - if you want to understand driver details. */ -/* Offsets from base I/O address. */ -#define EL3_DATA 0x00 -#define EL3_CMD 0x0e -#define EL3_STATUS 0x0e -#define ID_PORT 0x100 -#define EEPROM_READ 0x80 - -#define EL3_IO_EXTENT 16 - -#define EL3WINDOW(win_num) outw(SelectWindow + (win_num), ioaddr + EL3_CMD) - - -/* The top five bits written to EL3_CMD are a command, the lower - 11 bits are the parameter, if applicable. */ -enum c509cmd { - TotalReset = 0<<11, SelectWindow = 1<<11, StartCoax = 2<<11, - RxDisable = 3<<11, RxEnable = 4<<11, RxReset = 5<<11, RxDiscard = 8<<11, - TxEnable = 9<<11, TxDisable = 10<<11, TxReset = 11<<11, - FakeIntr = 12<<11, AckIntr = 13<<11, SetIntrMask = 14<<11, - SetReadZero = 15<<11, SetRxFilter = 16<<11, SetRxThreshold = 17<<11, - SetTxThreshold = 18<<11, SetTxStart = 19<<11, StatsEnable = 21<<11, - StatsDisable = 22<<11, StopCoax = 23<<11,}; - -/* The SetRxFilter command accepts the following classes: */ -enum RxFilter { - RxStation = 1, RxMulticast = 2, RxBroadcast = 4, RxProm = 8 }; - -/* Register window 1 offsets, the window used in normal operation. */ -#define TX_FIFO 0x00 -#define RX_FIFO 0x00 -#define RX_STATUS 0x08 -#define TX_STATUS 0x0B -#define TX_FREE 0x0C /* Remaining free bytes in Tx buffer. */ - -#define WN0_IRQ 0x08 /* Window 0: Set IRQ line in bits 12-15. */ -#define WN4_MEDIA 0x0A /* Window 4: Various transcvr/media bits. */ -#define MEDIA_TP 0x00C0 /* Enable link beat and jabber for 10baseT. */ - -struct el3_private { - struct enet_statistics stats; -}; - -static ushort id_read_eeprom(int index); -static ushort read_eeprom(short ioaddr, int index); -static int el3_open(struct device *dev); -static int el3_start_xmit(struct sk_buff *skb, struct device *dev); -static void el3_interrupt(int irq, struct pt_regs *regs); -static void update_stats(int addr, struct device *dev); -static struct enet_statistics *el3_get_stats(struct device *dev); -static int el3_rx(struct device *dev); -static int el3_close(struct device *dev); -static void set_multicast_list(struct device *dev); - - - -int el3_probe(struct device *dev) -{ - short lrs_state = 0xff, i; - ushort ioaddr, irq, if_port; - short *phys_addr = (short *)dev->dev_addr; - static int current_tag = 0; - - /* First check all slots of the EISA bus. The next slot address to - probe is kept in 'eisa_addr' to support multiple probe() calls. */ - if (EISA_bus) { - static int eisa_addr = 0x1000; - while (eisa_addr < 0x9000) { - ioaddr = eisa_addr; - eisa_addr += 0x1000; - - /* Check the standard EISA ID register for an encoded '3Com'. */ - if (inw(ioaddr + 0xC80) != 0x6d50) - continue; - - /* Change the register set to the configuration window 0. */ - outw(SelectWindow | 0, ioaddr + 0xC80 + EL3_CMD); - - irq = inw(ioaddr + WN0_IRQ) >> 12; - if_port = inw(ioaddr + 6)>>14; - for (i = 0; i < 3; i++) - phys_addr[i] = htons(read_eeprom(ioaddr, i)); - - /* Restore the "Product ID" to the EEPROM read register. */ - read_eeprom(ioaddr, 3); - - /* Was the EISA code an add-on hack? Nahhhhh... */ - goto found; - } - } - -#ifdef CONFIG_MCA - if (MCA_bus) { - mca_adaptor_select_mode(1); - for (i = 0; i < 8; i++) - if ((mca_adaptor_id(i) | 1) == 0x627c) { - ioaddr = mca_pos_base_addr(i); - irq = inw(ioaddr + WN0_IRQ) >> 12; - if_port = inw(ioaddr + 6)>>14; - for (i = 0; i < 3; i++) - phys_addr[i] = htons(read_eeprom(ioaddr, i)); - - mca_adaptor_select_mode(0); - goto found; - } - mca_adaptor_select_mode(0); - - } -#endif - - /* Next check for all ISA bus boards by sending the ID sequence to the - ID_PORT. We find cards past the first by setting the 'current_tag' - on cards as they are found. Cards with their tag set will not - respond to subsequent ID sequences. */ - - if (check_region(ID_PORT,1)) { - static int once = 1; - if (once) printk("3c509: Somebody has reserved 0x%x, can't do ID_PORT lookup, nor card auto-probing\n",ID_PORT); - once = 0; - return -ENODEV; - } - - outb(0x00, ID_PORT); - outb(0x00, ID_PORT); - for(i = 0; i < 255; i++) { - outb(lrs_state, ID_PORT); - lrs_state <<= 1; - lrs_state = lrs_state & 0x100 ? lrs_state ^ 0xcf : lrs_state; - } - - /* For the first probe, clear all board's tag registers. */ - if (current_tag == 0) - outb(0xd0, ID_PORT); - else /* Otherwise kill off already-found boards. */ - outb(0xd8, ID_PORT); - - if (id_read_eeprom(7) != 0x6d50) { - return -ENODEV; - } - - /* Read in EEPROM data, which does contention-select. - Only the lowest address board will stay "on-line". - 3Com got the byte order backwards. */ - for (i = 0; i < 3; i++) { - phys_addr[i] = htons(id_read_eeprom(i)); - } - - { - unsigned short iobase = id_read_eeprom(8); - if_port = iobase >> 14; - ioaddr = 0x200 + ((iobase & 0x1f) << 4); - } - irq = id_read_eeprom(9) >> 12; - - if (dev->base_addr != 0 - && dev->base_addr != (unsigned short)ioaddr) { - return -ENODEV; - } - - /* Set the adaptor tag so that the next card can be found. */ - outb(0xd0 + ++current_tag, ID_PORT); - - /* Activate the adaptor at the EEPROM location. */ - outb(0xff, ID_PORT); - - EL3WINDOW(0); - if (inw(ioaddr) != 0x6d50) - return -ENODEV; - - /* Free the interrupt so that some other card can use it. */ - outw(0x0f00, ioaddr + WN0_IRQ); - found: - dev->base_addr = ioaddr; - dev->irq = irq; - dev->if_port = if_port; - request_region(dev->base_addr, EL3_IO_EXTENT, "3c509"); - - { - const char *if_names[] = {"10baseT", "AUI", "undefined", "BNC"}; - printk("%s: 3c509 at %#3.3lx tag %d, %s port, address ", - dev->name, dev->base_addr, current_tag, if_names[dev->if_port]); - } - - /* Read in the station address. */ - for (i = 0; i < 6; i++) - printk(" %2.2x", dev->dev_addr[i]); - printk(", IRQ %d.\n", dev->irq); - - /* Make up a EL3-specific-data structure. */ - dev->priv = kmalloc(sizeof(struct el3_private), GFP_KERNEL); - if (dev->priv == NULL) - return -ENOMEM; - memset(dev->priv, 0, sizeof(struct el3_private)); - - if (el3_debug > 0) - printk(version); - - /* The EL3-specific entries in the device structure. */ - dev->open = &el3_open; - dev->hard_start_xmit = &el3_start_xmit; - dev->stop = &el3_close; - dev->get_stats = &el3_get_stats; - dev->set_multicast_list = &set_multicast_list; - - /* Fill in the generic fields of the device structure. */ - ether_setup(dev); - return 0; -} - -/* Read a word from the EEPROM using the regular EEPROM access register. - Assume that we are in register window zero. - */ -static ushort read_eeprom(short ioaddr, int index) -{ - int timer; - - outw(EEPROM_READ + index, ioaddr + 10); - /* Pause for at least 162 us. for the read to take place. */ - for (timer = 0; timer < 162*4 + 400; timer++) - SLOW_DOWN_IO; - return inw(ioaddr + 12); -} - -/* Read a word from the EEPROM when in the ISA ID probe state. */ -static ushort id_read_eeprom(int index) -{ - int timer, bit, word = 0; - - /* Issue read command, and pause for at least 162 us. for it to complete. - Assume extra-fast 16Mhz bus. */ - outb(EEPROM_READ + index, ID_PORT); - - /* This should really be done by looking at one of the timer channels. */ - for (timer = 0; timer < 162*4 + 400; timer++) - SLOW_DOWN_IO; - - for (bit = 15; bit >= 0; bit--) - word = (word << 1) + (inb(ID_PORT) & 0x01); - - if (el3_debug > 3) - printk(" 3c509 EEPROM word %d %#4.4x.\n", index, word); - - return word; -} - - - -static int -el3_open(struct device *dev) -{ - int ioaddr = dev->base_addr; - int i; - - outw(TxReset, ioaddr + EL3_CMD); - outw(RxReset, ioaddr + EL3_CMD); - outw(SetReadZero | 0x00, ioaddr + EL3_CMD); - - if (request_irq(dev->irq, &el3_interrupt, 0, "3c509")) { - return -EAGAIN; - } - - EL3WINDOW(0); - if (el3_debug > 3) - printk("%s: Opening, IRQ %d status@%x %4.4x.\n", dev->name, - dev->irq, ioaddr + EL3_STATUS, inw(ioaddr + EL3_STATUS)); - - /* Activate board: this is probably unnecessary. */ - outw(0x0001, ioaddr + 4); - - irq2dev_map[dev->irq] = dev; - - /* Set the IRQ line. */ - outw((dev->irq << 12) | 0x0f00, ioaddr + WN0_IRQ); - - /* Set the station address in window 2 each time opened. */ - EL3WINDOW(2); - - for (i = 0; i < 6; i++) - outb(dev->dev_addr[i], ioaddr + i); - - if (dev->if_port == 3) - /* Start the thinnet transceiver. We should really wait 50ms...*/ - outw(StartCoax, ioaddr + EL3_CMD); - else if (dev->if_port == 0) { - /* 10baseT interface, enabled link beat and jabber check. */ - EL3WINDOW(4); - outw(inw(ioaddr + WN4_MEDIA) | MEDIA_TP, ioaddr + WN4_MEDIA); - } - - /* Switch to the stats window, and clear all stats by reading. */ - outw(StatsDisable, ioaddr + EL3_CMD); - EL3WINDOW(6); - for (i = 0; i < 9; i++) - inb(ioaddr + i); - inb(ioaddr + 10); - inb(ioaddr + 12); - - /* Switch to register set 1 for normal use. */ - EL3WINDOW(1); - - /* Accept b-case and phys addr only. */ - outw(SetRxFilter | RxStation | RxBroadcast, ioaddr + EL3_CMD); - outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */ - - dev->interrupt = 0; - dev->tbusy = 0; - dev->start = 1; - - outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */ - outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */ - /* Allow status bits to be seen. */ - outw(SetReadZero | 0xff, ioaddr + EL3_CMD); - outw(AckIntr | 0x69, ioaddr + EL3_CMD); /* Ack IRQ */ - outw(SetIntrMask | 0x98, ioaddr + EL3_CMD); /* Set interrupt mask. */ - - if (el3_debug > 3) - printk("%s: Opened 3c509 IRQ %d status %4.4x.\n", - dev->name, dev->irq, inw(ioaddr + EL3_STATUS)); - - MOD_INC_USE_COUNT; - return 0; /* Always succeed */ -} - -static int -el3_start_xmit(struct sk_buff *skb, struct device *dev) -{ - struct el3_private *lp = (struct el3_private *)dev->priv; - int ioaddr = dev->base_addr; - - /* Transmitter timeout, serious problems. */ - if (dev->tbusy) { - int tickssofar = jiffies - dev->trans_start; - if (tickssofar < 10) - return 1; - printk("%s: transmit timed out, tx_status %2.2x status %4.4x.\n", - dev->name, inb(ioaddr + TX_STATUS), inw(ioaddr + EL3_STATUS)); - dev->trans_start = jiffies; - /* Issue TX_RESET and TX_START commands. */ - outw(TxReset, ioaddr + EL3_CMD); - outw(TxEnable, ioaddr + EL3_CMD); - dev->tbusy = 0; - } - - if (skb == NULL) { - dev_tint(dev); - return 0; - } - - if (skb->len <= 0) - return 0; - - if (el3_debug > 4) { - printk("%s: el3_start_xmit(length = %ld) called, status %4.4x.\n", - dev->name, skb->len, inw(ioaddr + EL3_STATUS)); - } -#ifndef final_version - { /* Error-checking code, delete for 1.30. */ - ushort status = inw(ioaddr + EL3_STATUS); - if (status & 0x0001 /* IRQ line active, missed one. */ - && inw(ioaddr + EL3_STATUS) & 1) { /* Make sure. */ - printk("%s: Missed interrupt, status then %04x now %04x" - " Tx %2.2x Rx %4.4x.\n", dev->name, status, - inw(ioaddr + EL3_STATUS), inb(ioaddr + TX_STATUS), - inw(ioaddr + RX_STATUS)); - /* Fake interrupt trigger by masking, acknowledge interrupts. */ - outw(SetReadZero | 0x00, ioaddr + EL3_CMD); - outw(AckIntr | 0x69, ioaddr + EL3_CMD); /* Ack IRQ */ - outw(SetReadZero | 0xff, ioaddr + EL3_CMD); - } - } -#endif - - /* Avoid timer-based retransmission conflicts. */ - if (set_bit(0, (void*)&dev->tbusy) != 0) - printk("%s: Transmitter access conflict.\n", dev->name); - else { - /* Put out the doubleword header... */ - outw(skb->len, ioaddr + TX_FIFO); - outw(0x00, ioaddr + TX_FIFO); - /* ... and the packet rounded to a doubleword. */ - outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2); - - dev->trans_start = jiffies; - if (inw(ioaddr + TX_FREE) > 1536) { - dev->tbusy = 0; - } else - /* Interrupt us when the FIFO has room for max-sized packet. */ - outw(SetTxThreshold + 1536, ioaddr + EL3_CMD); - } - - dev_kfree_skb (skb, FREE_WRITE); - - /* Clear the Tx status stack. */ - { - short tx_status; - int i = 4; - - while (--i > 0 && (tx_status = inb(ioaddr + TX_STATUS)) > 0) { - if (tx_status & 0x38) lp->stats.tx_aborted_errors++; - if (tx_status & 0x30) outw(TxReset, ioaddr + EL3_CMD); - if (tx_status & 0x3C) outw(TxEnable, ioaddr + EL3_CMD); - outb(0x00, ioaddr + TX_STATUS); /* Pop the status stack. */ - } - } - return 0; -} - -/* The EL3 interrupt handler. */ -static void -el3_interrupt(int irq, struct pt_regs *regs) -{ - struct device *dev = (struct device *)(irq2dev_map[irq]); - int ioaddr, status; - int i = 0; - - if (dev == NULL) { - printk ("el3_interrupt(): irq %d for unknown device.\n", irq); - return; - } - - if (dev->interrupt) - printk("%s: Re-entering the interrupt handler.\n", dev->name); - dev->interrupt = 1; - - ioaddr = dev->base_addr; - status = inw(ioaddr + EL3_STATUS); - - if (el3_debug > 4) - printk("%s: interrupt, status %4.4x.\n", dev->name, status); - - while ((status = inw(ioaddr + EL3_STATUS)) & 0x91) { - - if (status & 0x10) - el3_rx(dev); - - if (status & 0x08) { - if (el3_debug > 5) - printk(" TX room bit was handled.\n"); - /* There's room in the FIFO for a full-sized packet. */ - outw(AckIntr | 0x08, ioaddr + EL3_CMD); - dev->tbusy = 0; - mark_bh(NET_BH); - } - if (status & 0x80) /* Statistics full. */ - update_stats(ioaddr, dev); - - if (++i > 10) { - printk("%s: Infinite loop in interrupt, status %4.4x.\n", - dev->name, status); - /* Clear all interrupts. */ - outw(AckIntr | 0xFF, ioaddr + EL3_CMD); - break; - } - /* Acknowledge the IRQ. */ - outw(AckIntr | 0x41, ioaddr + EL3_CMD); /* Ack IRQ */ - - } - - if (el3_debug > 4) { - printk("%s: exiting interrupt, status %4.4x.\n", dev->name, - inw(ioaddr + EL3_STATUS)); - } - - dev->interrupt = 0; - return; -} - - -static struct enet_statistics * -el3_get_stats(struct device *dev) -{ - struct el3_private *lp = (struct el3_private *)dev->priv; - unsigned long flags; - - save_flags(flags); - cli(); - update_stats(dev->base_addr, dev); - restore_flags(flags); - return &lp->stats; -} - -/* Update statistics. We change to register window 6, so this should be run - single-threaded if the device is active. This is expected to be a rare - operation, and it's simpler for the rest of the driver to assume that - window 1 is always valid rather than use a special window-state variable. - */ -static void update_stats(int ioaddr, struct device *dev) -{ - struct el3_private *lp = (struct el3_private *)dev->priv; - - if (el3_debug > 5) - printk(" Updating the statistics.\n"); - /* Turn off statistics updates while reading. */ - outw(StatsDisable, ioaddr + EL3_CMD); - /* Switch to the stats window, and read everything. */ - EL3WINDOW(6); - lp->stats.tx_carrier_errors += inb(ioaddr + 0); - lp->stats.tx_heartbeat_errors += inb(ioaddr + 1); - /* Multiple collisions. */ inb(ioaddr + 2); - lp->stats.collisions += inb(ioaddr + 3); - lp->stats.tx_window_errors += inb(ioaddr + 4); - lp->stats.rx_fifo_errors += inb(ioaddr + 5); - lp->stats.tx_packets += inb(ioaddr + 6); - /* Rx packets */ inb(ioaddr + 7); - /* Tx deferrals */ inb(ioaddr + 8); - inw(ioaddr + 10); /* Total Rx and Tx octets. */ - inw(ioaddr + 12); - - /* Back to window 1, and turn statistics back on. */ - EL3WINDOW(1); - outw(StatsEnable, ioaddr + EL3_CMD); - return; -} - -static int -el3_rx(struct device *dev) -{ - struct el3_private *lp = (struct el3_private *)dev->priv; - int ioaddr = dev->base_addr; - short rx_status; - - if (el3_debug > 5) - printk(" In rx_packet(), status %4.4x, rx_status %4.4x.\n", - inw(ioaddr+EL3_STATUS), inw(ioaddr+RX_STATUS)); - while ((rx_status = inw(ioaddr + RX_STATUS)) > 0) { - if (rx_status & 0x4000) { /* Error, update stats. */ - short error = rx_status & 0x3800; - lp->stats.rx_errors++; - switch (error) { - case 0x0000: lp->stats.rx_over_errors++; break; - case 0x0800: lp->stats.rx_length_errors++; break; - case 0x1000: lp->stats.rx_frame_errors++; break; - case 0x1800: lp->stats.rx_length_errors++; break; - case 0x2000: lp->stats.rx_frame_errors++; break; - case 0x2800: lp->stats.rx_crc_errors++; break; - } - } else { - short pkt_len = rx_status & 0x7ff; - struct sk_buff *skb; - - skb = dev_alloc_skb(pkt_len+5); - if (el3_debug > 4) - printk("Receiving packet size %d status %4.4x.\n", - pkt_len, rx_status); - if (skb != NULL) { - skb->dev = dev; - skb_reserve(skb,2); /* Align IP on 16 byte boundaries */ - - /* 'skb->data' points to the start of sk_buff data area. */ - insl(ioaddr+RX_FIFO, skb_put(skb,pkt_len), - (pkt_len + 3) >> 2); - - skb->protocol=eth_type_trans(skb,dev); - netif_rx(skb); - outw(RxDiscard, ioaddr + EL3_CMD); /* Pop top Rx packet. */ - lp->stats.rx_packets++; - continue; - } else if (el3_debug) - printk("%s: Couldn't allocate a sk_buff of size %d.\n", - dev->name, pkt_len); - } - lp->stats.rx_dropped++; - outw(RxDiscard, ioaddr + EL3_CMD); - while (inw(ioaddr + EL3_STATUS) & 0x1000) - printk(" Waiting for 3c509 to discard packet, status %x.\n", - inw(ioaddr + EL3_STATUS) ); - } - - return 0; -} - -/* - * Set or clear the multicast filter for this adaptor. - */ - -static void set_multicast_list(struct device *dev) -{ - short ioaddr = dev->base_addr; - if (el3_debug > 1) { - static int old = 0; - if (old != dev->mc_count) { - old = dev->mc_count; - printk("%s: Setting Rx mode to %d addresses.\n", dev->name, dev->mc_count); - } - } - if (dev->flags&IFF_PROMISC) - { - outw(SetRxFilter | RxStation | RxMulticast | RxBroadcast | RxProm, - ioaddr + EL3_CMD); - } - else if (dev->mc_count || (dev->flags&IFF_ALLMULTI)) - { - outw(SetRxFilter|RxStation|RxMulticast|RxBroadcast, ioaddr + EL3_CMD); - } - else - outw(SetRxFilter | RxStation | RxBroadcast, ioaddr + EL3_CMD); -} - -static int -el3_close(struct device *dev) -{ - int ioaddr = dev->base_addr; - - if (el3_debug > 2) - printk("%s: Shutting down ethercard.\n", dev->name); - - dev->tbusy = 1; - dev->start = 0; - - /* Turn off statistics ASAP. We update lp->stats below. */ - outw(StatsDisable, ioaddr + EL3_CMD); - - /* Disable the receiver and transmitter. */ - outw(RxDisable, ioaddr + EL3_CMD); - outw(TxDisable, ioaddr + EL3_CMD); - - if (dev->if_port == 3) - /* Turn off thinnet power. Green! */ - outw(StopCoax, ioaddr + EL3_CMD); - else if (dev->if_port == 0) { - /* Disable link beat and jabber, if_port may change ere next open(). */ - EL3WINDOW(4); - outw(inw(ioaddr + WN4_MEDIA) & ~MEDIA_TP, ioaddr + WN4_MEDIA); - } - - free_irq(dev->irq); - /* Switching back to window 0 disables the IRQ. */ - EL3WINDOW(0); - /* But we explicitly zero the IRQ line select anyway. */ - outw(0x0f00, ioaddr + WN0_IRQ); - - - irq2dev_map[dev->irq] = 0; - - update_stats(ioaddr, dev); - MOD_DEC_USE_COUNT; - return 0; -} - -#ifdef MODULE -static char devicename[9] = { 0, }; -static struct device dev_3c509 = { - devicename, /* device name is inserted by linux/drivers/net/net_init.c */ - 0, 0, 0, 0, - 0, 0, - 0, 0, 0, NULL, el3_probe }; - -static int io = 0; -static int irq = 0; - -int -init_module(void) -{ - dev_3c509.base_addr = io; - dev_3c509.irq = irq; - if (!EISA_bus) { - printk("3c509: WARNING! Module load-time probing works reliably only for EISA-bus!\n"); - } - if (register_netdev(&dev_3c509) != 0) - return -EIO; - return 0; -} - -void -cleanup_module(void) -{ - unregister_netdev(&dev_3c509); - kfree_s(dev_3c509.priv,sizeof(struct el3_private)); - dev_3c509.priv=NULL; - /* If we don't do this, we can't re-insmod it later. */ - release_region(dev_3c509.base_addr, EL3_IO_EXTENT); -} -#endif /* MODULE */ - -/* - * Local variables: - * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c 3c509.c" - * version-control: t - * kept-new-versions: 5 - * tab-width: 4 - * End: - */ diff --git a/i386/i386at/gpl/linux/net/3c59x.c b/i386/i386at/gpl/linux/net/3c59x.c deleted file mode 100644 index b5c4d5b7..00000000 --- a/i386/i386at/gpl/linux/net/3c59x.c +++ /dev/null @@ -1,1066 +0,0 @@ -/* 3c59x.c: A 3Com 3c590/3c595 "Vortex" ethernet driver for linux. */ -/* - Written 1995 by Donald Becker. - - This software may be used and distributed according to the terms - of the GNU Public License, incorporated herein by reference. - - This driver is for the 3Com "Vortex" series ethercards. Members of - the series include the 3c590 PCI EtherLink III and 3c595-Tx PCI Fast - EtherLink. It also works with the 10Mbs-only 3c590 PCI EtherLink III. - - The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O - Center of Excellence in Space Data and Information Sciences - Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771 -*/ - -static char *version = "3c59x.c:v0.13 2/13/96 becker@cesdis.gsfc.nasa.gov\n"; - -/* "Knobs" that turn on special features. */ -/* Allow the use of bus master transfers instead of programmed-I/O for the - Tx process. Bus master transfers are always disabled by default, but - iff this is set they may be turned on using 'options'. */ -#define VORTEX_BUS_MASTER - -/* Put out somewhat more debugging messages. (0 - no msg, 1 minimal msgs). */ -#define VORTEX_DEBUG 1 - -#include <linux/module.h> - -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/string.h> -#include <linux/ptrace.h> -#include <linux/errno.h> -#include <linux/in.h> -#include <linux/ioport.h> -#include <linux/malloc.h> -#include <linux/interrupt.h> -#include <linux/pci.h> -#include <linux/bios32.h> -#include <linux/timer.h> -#include <asm/bitops.h> -#include <asm/io.h> - -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> - -#ifdef HAVE_SHARED_IRQ -#define USE_SHARED_IRQ -#include <linux/shared_irq.h> -#endif - -/* The total size is twice that of the original EtherLinkIII series: the - runtime register window, window 1, is now always mapped in. */ -#define VORTEX_TOTAL_SIZE 0x20 - -#ifdef HAVE_DEVLIST -struct netdev_entry tc59x_drv = -{"Vortex", vortex_pci_probe, VORTEX_TOTAL_SIZE, NULL}; -#endif - -#ifdef VORTEX_DEBUG -int vortex_debug = VORTEX_DEBUG; -#else -int vortex_debug = 1; -#endif - -static int product_ids[] = {0x5900, 0x5950, 0x5951, 0x5952, 0, 0}; -static const char *product_names[] = { - "3c590 Vortex 10Mbps", - "3c595 Vortex 100baseTX", - "3c595 Vortex 100baseT4", - "3c595 Vortex 100base-MII", - "EISA Vortex 3c597", -}; -#define DEMON_INDEX 5 /* Caution! Must be consistent with above! */ - -/* - Theory of Operation - -I. Board Compatibility - -This device driver is designed for the 3Com FastEtherLink, 3Com's PCI to -10/100baseT adapter. It also works with the 3c590, a similar product -with only a 10Mbs interface. - -II. Board-specific settings - -PCI bus devices are configured by the system at boot time, so no jumpers -need to be set on the board. The system BIOS should be set to assign the -PCI INTA signal to an otherwise unused system IRQ line. While it's -physically possible to shared PCI interrupt lines, the 1.2.0 kernel doesn't -support it. - -III. Driver operation - -The 3c59x series use an interface that's very similar to the previous 3c5x9 -series. The primary interface is two programmed-I/O FIFOs, with an -alternate single-contiguous-region bus-master transfer (see next). - -One extension that is advertised in a very large font is that the adapters -are capable of being bus masters. Unfortunately this capability is only for -a single contiguous region making it less useful than the list of transfer -regions available with the DEC Tulip or AMD PCnet. Given the significant -performance impact of taking an extra interrupt for each transfer, using -DMA transfers is a win only with large blocks. - -IIIC. Synchronization -The driver runs as two independent, single-threaded flows of control. One -is the send-packet routine, which enforces single-threaded use by the -dev->tbusy flag. The other thread is the interrupt handler, which is single -threaded by the hardware and other software. - -IV. Notes - -Thanks to Cameron Spitzer and Terry Murphy of 3Com for providing both -3c590 and 3c595 boards. -The name "Vortex" is the internal 3Com project name for the PCI ASIC, and -the not-yet-released (3/95) EISA version is called "Demon". According to -Terry these names come from rides at the local amusement park. - -The new chips support both ethernet (1.5K) and FDDI (4.5K) packet sizes! -This driver only supports ethernet packets because of the skbuff allocation -limit of 4K. -*/ - -#define TCOM_VENDOR_ID 0x10B7 /* 3Com's manufacturer's ID. */ - -/* Operational defintions. - These are not used by other compilation units and thus are not - exported in a ".h" file. - - First the windows. There are eight register windows, with the command - and status registers available in each. - */ -#define EL3WINDOW(win_num) outw(SelectWindow + (win_num), ioaddr + EL3_CMD) -#define EL3_CMD 0x0e -#define EL3_STATUS 0x0e - -/* The top five bits written to EL3_CMD are a command, the lower - 11 bits are the parameter, if applicable. - Note that 11 parameters bits was fine for ethernet, but the new chip - can handle FDDI lenght frames (~4500 octets) and now parameters count - 32-bit 'Dwords' rather than octets. */ - -enum vortex_cmd { - TotalReset = 0<<11, SelectWindow = 1<<11, StartCoax = 2<<11, - RxDisable = 3<<11, RxEnable = 4<<11, RxReset = 5<<11, RxDiscard = 8<<11, - TxEnable = 9<<11, TxDisable = 10<<11, TxReset = 11<<11, - FakeIntr = 12<<11, AckIntr = 13<<11, SetIntrEnb = 14<<11, - SetStatusEnb = 15<<11, SetRxFilter = 16<<11, SetRxThreshold = 17<<11, - SetTxThreshold = 18<<11, SetTxStart = 19<<11, - StartDMAUp = 20<<11, StartDMADown = (20<<11)+1, StatsEnable = 21<<11, - StatsDisable = 22<<11, StopCoax = 23<<11,}; - -/* The SetRxFilter command accepts the following classes: */ -enum RxFilter { - RxStation = 1, RxMulticast = 2, RxBroadcast = 4, RxProm = 8 }; - -/* Bits in the general status register. */ -enum vortex_status { - IntLatch = 0x0001, AdapterFailure = 0x0002, TxComplete = 0x0004, - TxAvailable = 0x0008, RxComplete = 0x0010, RxEarly = 0x0020, - IntReq = 0x0040, StatsFull = 0x0080, DMADone = 1<<8, - DMAInProgress = 1<<11, /* DMA controller is still busy.*/ - CmdInProgress = 1<<12, /* EL3_CMD is still busy.*/ -}; - -/* Register window 1 offsets, the window used in normal operation. - On the Vortex this window is always mapped at offsets 0x10-0x1f. */ -enum Window1 { - TX_FIFO = 0x10, RX_FIFO = 0x10, RxErrors = 0x14, - RxStatus = 0x18, Timer=0x1A, TxStatus = 0x1B, - TxFree = 0x1C, /* Remaining free bytes in Tx buffer. */ -}; -enum Window0 { - Wn0EepromCmd = 10, /* Window 0: EEPROM command register. */ -}; -enum Win0_EEPROM_bits { - EEPROM_Read = 0x80, EEPROM_WRITE = 0x40, EEPROM_ERASE = 0xC0, - EEPROM_EWENB = 0x30, /* Enable erasing/writing for 10 msec. */ - EEPROM_EWDIS = 0x00, /* Disable EWENB before 10 msec timeout. */ -}; -/* EEPROM locations. */ -enum eeprom_offset { - PhysAddr01=0, PhysAddr23=1, PhysAddr45=2, ModelID=3, - EtherLink3ID=7, IFXcvrIO=8, IRQLine=9, - NodeAddr01=10, NodeAddr23=11, NodeAddr45=12, - DriverTune=13, Checksum=15}; - -enum Window3 { /* Window 3: MAC/config bits. */ - Wn3_Config=0, Wn3_MAC_Ctrl=6, Wn3_Options=8, -}; -union wn3_config { - int i; - struct w3_config_fields { - unsigned int ram_size:3, ram_width:1, ram_speed:2, rom_size:2; - int pad8:8; - unsigned int ram_split:2, pad18:2, xcvr:3, pad21:1, autoselect:1; - int pad24:8; - } u; -}; - -enum Window4 { - Wn4_Media = 0x0A, /* Window 4: Various transcvr/media bits. */ -}; -enum Win4_Media_bits { - Media_TP = 0x00C0, /* Enable link beat and jabber for 10baseT. */ -}; -enum Window7 { /* Window 7: Bus Master control. */ - Wn7_MasterAddr = 0, Wn7_MasterLen = 6, Wn7_MasterStatus = 12, -}; - -struct vortex_private { - char devname[8]; /* "ethN" string, also for kernel debug. */ - const char *product_name; - struct device *next_module; - struct enet_statistics stats; -#ifdef VORTEX_BUS_MASTER - struct sk_buff *tx_skb; /* Packet being eaten by bus master ctrl. */ -#endif - struct timer_list timer; /* Media selection timer. */ - int options; /* User-settable driver options (none yet). */ - unsigned int media_override:3, full_duplex:1, bus_master:1, autoselect:1; -}; - -static char *if_names[] = { - "10baseT", "10Mbs AUI", "undefined", "10base2", - "100baseTX", "100baseFX", "MII", "undefined"}; - -static int vortex_scan(struct device *dev); -static int vortex_found_device(struct device *dev, int ioaddr, int irq, - int product_index, int options); -static int vortex_probe1(struct device *dev); -static int vortex_open(struct device *dev); -static void vortex_timer(unsigned long arg); -static int vortex_start_xmit(struct sk_buff *skb, struct device *dev); -static int vortex_rx(struct device *dev); -static void vortex_interrupt(int irq, struct pt_regs *regs); -static int vortex_close(struct device *dev); -static void update_stats(int addr, struct device *dev); -static struct enet_statistics *vortex_get_stats(struct device *dev); -static void set_multicast_list(struct device *dev); - - -/* Unlike the other PCI cards the 59x cards don't need a large contiguous - memory region, so making the driver a loadable module is feasible. - - Unfortuneately maximizing the shared code between the integrated and - module version of the driver results in a complicated set of initialization - procedures. - init_module() -- modules / tc59x_init() -- built-in - The wrappers for vortex_scan() - vortex_scan() The common routine that scans for PCI and EISA cards - vortex_found_device() Allocate a device structure when we find a card. - Different versions exist for modules and built-in. - vortex_probe1() Fill in the device structure -- this is seperated - so that the modules code can put it in dev->init. -*/ -/* This driver uses 'options' to pass the media type, full-duplex flag, etc. */ -/* Note: this is the only limit on the number of cards supported!! */ -int options[8] = { -1, -1, -1, -1, -1, -1, -1, -1,}; - -#ifdef MODULE -static int debug = -1; -/* A list of all installed Vortex devices, for removing the driver module. */ -static struct device *root_vortex_dev = NULL; - -int -init_module(void) -{ - int cards_found; - - if (debug >= 0) - vortex_debug = debug; - if (vortex_debug) - printk(version); - - root_vortex_dev = NULL; - cards_found = vortex_scan(0); - return cards_found < 0 ? cards_found : 0; -} - -#else -unsigned long tc59x_probe(struct device *dev) -{ - int cards_found = 0; - - cards_found = vortex_scan(dev); - - if (vortex_debug > 0 && cards_found) - printk(version); - - return cards_found ? 0 : -ENODEV; -} -#endif /* not MODULE */ - -static int vortex_scan(struct device *dev) -{ - int cards_found = 0; - - if (pcibios_present()) { - static int pci_index = 0; - for (; pci_index < 8; pci_index++) { - unsigned char pci_bus, pci_device_fn, pci_irq_line, pci_latency; - unsigned int pci_ioaddr; - unsigned short pci_command; - int index; - - for (index = 0; product_ids[index]; index++) { - if ( ! pcibios_find_device(TCOM_VENDOR_ID, product_ids[index], - pci_index, &pci_bus, - &pci_device_fn)) - break; - } - if ( ! product_ids[index]) - break; - - pcibios_read_config_byte(pci_bus, pci_device_fn, - PCI_INTERRUPT_LINE, &pci_irq_line); - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_0, &pci_ioaddr); - /* Remove I/O space marker in bit 0. */ - pci_ioaddr &= ~3; - -#ifdef VORTEX_BUS_MASTER - /* Get and check the bus-master and latency values. - Some PCI BIOSes fail to set the master-enable bit, and - the latency timer must be set to the maximum value to avoid - data corruption that occurs when the timer expires during - a transfer. Yes, it's a bug. */ - pcibios_read_config_word(pci_bus, pci_device_fn, - PCI_COMMAND, &pci_command); - if ( ! (pci_command & PCI_COMMAND_MASTER)) { - printk(" PCI Master Bit has not been set! Setting...\n"); - pci_command |= PCI_COMMAND_MASTER; - pcibios_write_config_word(pci_bus, pci_device_fn, - PCI_COMMAND, pci_command); - } - pcibios_read_config_byte(pci_bus, pci_device_fn, - PCI_LATENCY_TIMER, &pci_latency); - if (pci_latency != 255) { - printk(" Overriding PCI latency timer (CFLT) setting of %d, new value is 255.\n", pci_latency); - pcibios_write_config_byte(pci_bus, pci_device_fn, - PCI_LATENCY_TIMER, 255); - } -#endif /* VORTEX_BUS_MASTER */ - vortex_found_device(dev, pci_ioaddr, pci_irq_line, index, - dev && dev->mem_start ? dev->mem_start - : options[cards_found]); - dev = 0; - cards_found++; - } - } - - /* Now check all slots of the EISA bus. */ - if (EISA_bus) { - static int ioaddr = 0x1000; - for (ioaddr = 0x1000; ioaddr < 0x9000; ioaddr += 0x1000) { - /* Check the standard EISA ID register for an encoded '3Com'. */ - if (inw(ioaddr + 0xC80) != 0x6d50) - continue; - /* Check for a product that we support. */ - if ((inw(ioaddr + 0xC82) & 0xFFF0) != 0x5970 - && (inw(ioaddr + 0xC82) & 0xFFF0) != 0x5920) - continue; - vortex_found_device(dev, ioaddr, inw(ioaddr + 0xC88) >> 12, - DEMON_INDEX, dev && dev->mem_start - ? dev->mem_start : options[cards_found]); - dev = 0; - cards_found++; - } - } - - return cards_found; -} - -static int vortex_found_device(struct device *dev, int ioaddr, int irq, - int product_index, int options) -{ - struct vortex_private *vp; - -#ifdef MODULE - /* Allocate and fill new device structure. */ - int dev_size = sizeof(struct device) + - sizeof(struct vortex_private); - - dev = (struct device *) kmalloc(dev_size, GFP_KERNEL); - memset(dev, 0, dev_size); - dev->priv = ((void *)dev) + sizeof(struct device); - vp = (struct vortex_private *)dev->priv; - dev->name = vp->devname; /* An empty string. */ - dev->base_addr = ioaddr; - dev->irq = irq; - dev->init = vortex_probe1; - vp->product_name = product_names[product_index]; - vp->options = options; - if (options >= 0) { - vp->media_override = ((options & 7) == 2) ? 0 : options & 7; - vp->full_duplex = (options & 8) ? 1 : 0; - vp->bus_master = (options & 16) ? 1 : 0; - } else { - vp->media_override = 7; - vp->full_duplex = 0; - vp->bus_master = 0; - } - ether_setup(dev); - vp->next_module = root_vortex_dev; - root_vortex_dev = dev; - if (register_netdev(dev) != 0) - return -EIO; -#else /* not a MODULE */ - if (dev) { - dev->priv = kmalloc(sizeof (struct vortex_private), GFP_KERNEL); - memset(dev->priv, 0, sizeof (struct vortex_private)); - } - dev = init_etherdev(dev, sizeof(struct vortex_private)); - dev->base_addr = ioaddr; - dev->irq = irq; - vp = (struct vortex_private *)dev->priv; - vp->product_name = product_names[product_index]; - vp->options = options; - if (options >= 0) { - vp->media_override = ((options & 7) == 2) ? 0 : options & 7; - vp->full_duplex = (options & 8) ? 1 : 0; - vp->bus_master = (options & 16) ? 1 : 0; - } else { - vp->media_override = 7; - vp->full_duplex = 0; - vp->bus_master = 0; - } - - vortex_probe1(dev); -#endif /* MODULE */ - return 0; -} - -static int vortex_probe1(struct device *dev) -{ - int ioaddr = dev->base_addr; - struct vortex_private *vp = (struct vortex_private *)dev->priv; - int i; - - printk("%s: 3Com %s at %#3x,", dev->name, - vp->product_name, ioaddr); - - /* Read the station address from the EEPROM. */ - EL3WINDOW(0); - for (i = 0; i < 3; i++) { - short *phys_addr = (short *)dev->dev_addr; - int timer; - outw(EEPROM_Read + PhysAddr01 + i, ioaddr + Wn0EepromCmd); - /* Pause for at least 162 us. for the read to take place. */ - for (timer = 0; timer < 162*4 + 400; timer++) { - SLOW_DOWN_IO; - if ((inw(ioaddr + Wn0EepromCmd) & 0x8000) == 0) - break; - } - phys_addr[i] = htons(inw(ioaddr + 12)); - } - for (i = 0; i < 6; i++) - printk("%c%2.2x", i ? ':' : ' ', dev->dev_addr[i]); - printk(", IRQ %d\n", dev->irq); - /* Tell them about an invalid IRQ. */ - if (vortex_debug && (dev->irq <= 0 || dev->irq > 15)) - printk(" *** Warning: this IRQ is unlikely to work!\n"); - - { - char *ram_split[] = {"5:3", "3:1", "1:1", "invalid"}; - union wn3_config config; - EL3WINDOW(3); - config.i = inl(ioaddr + Wn3_Config); - if (vortex_debug > 1) - printk(" Internal config register is %4.4x, transceivers %#x.\n", - config.i, inw(ioaddr + Wn3_Options)); - printk(" %dK %s-wide RAM %s Rx:Tx split, %s%s interface.\n", - 8 << config.u.ram_size, - config.u.ram_width ? "word" : "byte", - ram_split[config.u.ram_split], - config.u.autoselect ? "autoselect/" : "", - if_names[config.u.xcvr]); - dev->if_port = config.u.xcvr; - vp->autoselect = config.u.autoselect; - } - - /* We do a request_region() only to register /proc/ioports info. */ - request_region(ioaddr, VORTEX_TOTAL_SIZE, vp->product_name); - - /* The 3c59x-specific entries in the device structure. */ - dev->open = &vortex_open; - dev->hard_start_xmit = &vortex_start_xmit; - dev->stop = &vortex_close; - dev->get_stats = &vortex_get_stats; - dev->set_multicast_list = &set_multicast_list; -#if defined (HAVE_SET_MAC_ADDR) && 0 - dev->set_mac_address = &set_mac_address; -#endif - - return 0; -} - - -static int -vortex_open(struct device *dev) -{ - int ioaddr = dev->base_addr; - struct vortex_private *vp = (struct vortex_private *)dev->priv; - union wn3_config config; - int i; - - /* Before initializing select the active media port. */ - EL3WINDOW(3); - if (vp->full_duplex) - outb(0x20, ioaddr + Wn3_MAC_Ctrl); /* Set the full-duplex bit. */ - config.i = inl(ioaddr + Wn3_Config); - - if (vp->media_override != 7) { - if (vortex_debug > 1) - printk("%s: Media override to transceiver %d (%s).\n", - dev->name, vp->media_override, if_names[vp->media_override]); - config.u.xcvr = vp->media_override; - dev->if_port = vp->media_override; - outl(config.i, ioaddr + Wn3_Config); - } - - if (vortex_debug > 1) { - printk("%s: vortex_open() InternalConfig %8.8x.\n", - dev->name, config.i); - } - - outw(TxReset, ioaddr + EL3_CMD); - for (i = 20; i >= 0 ; i--) - if ( ! inw(ioaddr + EL3_STATUS) & CmdInProgress) - break; - - outw(RxReset, ioaddr + EL3_CMD); - /* Wait a few ticks for the RxReset command to complete. */ - for (i = 20; i >= 0 ; i--) - if ( ! inw(ioaddr + EL3_STATUS) & CmdInProgress) - break; - - outw(SetStatusEnb | 0x00, ioaddr + EL3_CMD); - -#ifdef USE_SHARED_IRQ - i = request_shared_irq(dev->irq, &vortex_interrupt, dev, vp->product_name); - if (i) /* Error */ - return i; -#else - if (dev->irq == 0 || irq2dev_map[dev->irq] != NULL) - return -EAGAIN; - irq2dev_map[dev->irq] = dev; - if (request_irq(dev->irq, &vortex_interrupt, 0, vp->product_name)) { - irq2dev_map[dev->irq] = NULL; - return -EAGAIN; - } -#endif - - if (vortex_debug > 1) { - EL3WINDOW(4); - printk("%s: vortex_open() irq %d media status %4.4x.\n", - dev->name, dev->irq, inw(ioaddr + Wn4_Media)); - } - - /* Set the station address and mask in window 2 each time opened. */ - EL3WINDOW(2); - for (i = 0; i < 6; i++) - outb(dev->dev_addr[i], ioaddr + i); - for (; i < 12; i+=2) - outw(0, ioaddr + i); - - if (dev->if_port == 3) - /* Start the thinnet transceiver. We should really wait 50ms...*/ - outw(StartCoax, ioaddr + EL3_CMD); - else if (dev->if_port == 0) { - /* 10baseT interface, enabled link beat and jabber check. */ - EL3WINDOW(4); - outw(inw(ioaddr + Wn4_Media) | Media_TP, ioaddr + Wn4_Media); - } - - /* Switch to the stats window, and clear all stats by reading. */ - outw(StatsDisable, ioaddr + EL3_CMD); - EL3WINDOW(6); - for (i = 0; i < 10; i++) - inb(ioaddr + i); - inw(ioaddr + 10); - inw(ioaddr + 12); - /* New: On the Vortex we must also clear the BadSSD counter. */ - EL3WINDOW(4); - inb(ioaddr + 12); - - /* Switch to register set 7 for normal use. */ - EL3WINDOW(7); - - /* Accept b-case and phys addr only. */ - outw(SetRxFilter | RxStation | RxBroadcast, ioaddr + EL3_CMD); - outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */ - - dev->tbusy = 0; - dev->interrupt = 0; - dev->start = 1; - - outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */ - outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */ - /* Allow status bits to be seen. */ - outw(SetStatusEnb | 0xff, ioaddr + EL3_CMD); - /* Ack all pending events, and set active indicator mask. */ - outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq, - ioaddr + EL3_CMD); - outw(SetIntrEnb | IntLatch | TxAvailable | RxComplete | StatsFull - | DMADone, ioaddr + EL3_CMD); - -#ifdef MODULE - MOD_INC_USE_COUNT; -#endif - - if (vp->autoselect) { - init_timer(&vp->timer); - vp->timer.expires = (14*HZ)/10; /* 1.4 sec. */ - vp->timer.data = (unsigned long)dev; - vp->timer.function = &vortex_timer; /* timer handler */ - add_timer(&vp->timer); - } - return 0; -} - -static void vortex_timer(unsigned long data) -{ - struct device *dev = (struct device *)data; - if (vortex_debug > 2) - printk("%s: Media selection timer tick happened.\n", dev->name); - /* ToDo: active media selection here! */ -} - -static int -vortex_start_xmit(struct sk_buff *skb, struct device *dev) -{ - struct vortex_private *vp = (struct vortex_private *)dev->priv; - int ioaddr = dev->base_addr; - - /* Transmitter timeout, serious problems. */ - if (dev->tbusy) { - int tickssofar = jiffies - dev->trans_start; - if (tickssofar < 40) - return 1; - printk("%s: transmit timed out, tx_status %2.2x status %4.4x.\n", - dev->name, inb(ioaddr + TxStatus), inw(ioaddr + EL3_STATUS)); - vp->stats.tx_errors++; - /* Issue TX_RESET and TX_START commands. */ - outw(TxReset, ioaddr + EL3_CMD); - { - int i; - for (i = 20; i >= 0 ; i--) - if ( ! inw(ioaddr + EL3_STATUS) & CmdInProgress) - break; - } - outw(TxEnable, ioaddr + EL3_CMD); - dev->trans_start = jiffies; - dev->tbusy = 0; - return 0; - } - - if (skb == NULL || skb->len <= 0) { - printk("%s: Obsolete driver layer request made: skbuff==NULL.\n", - dev->name); - dev_tint(dev); - return 0; - } - - /* Block a timer-based transmit from overlapping. This could better be - done with atomic_swap(1, dev->tbusy), but set_bit() works as well. - If this ever occurs the queue layer is doing something evil! */ - if (set_bit(0, (void*)&dev->tbusy) != 0) { - printk("%s: Transmitter access conflict.\n", dev->name); - return 1; - } - - /* Put out the doubleword header... */ - outl(skb->len, ioaddr + TX_FIFO); -#ifdef VORTEX_BUS_MASTER - if (vp->bus_master) { - /* Set the bus-master controller to transfer the packet. */ - outl((int)(skb->data), ioaddr + Wn7_MasterAddr); - outw((skb->len + 3) & ~3, ioaddr + Wn7_MasterLen); - vp->tx_skb = skb; - outw(StartDMADown, ioaddr + EL3_CMD); - } else { - /* ... and the packet rounded to a doubleword. */ - outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2); - dev_kfree_skb (skb, FREE_WRITE); - if (inw(ioaddr + TxFree) > 1536) { - dev->tbusy = 0; - } else - /* Interrupt us when the FIFO has room for max-sized packet. */ - outw(SetTxThreshold + 1536, ioaddr + EL3_CMD); - } -#else - /* ... and the packet rounded to a doubleword. */ - outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2); - dev_kfree_skb (skb, FREE_WRITE); - if (inw(ioaddr + TxFree) > 1536) { - dev->tbusy = 0; - } else - /* Interrupt us when the FIFO has room for max-sized packet. */ - outw(SetTxThreshold + 1536, ioaddr + EL3_CMD); -#endif /* bus master */ - - dev->trans_start = jiffies; - - /* Clear the Tx status stack. */ - { - short tx_status; - int i = 4; - - while (--i > 0 && (tx_status = inb(ioaddr + TxStatus)) > 0) { - if (tx_status & 0x3C) { /* A Tx-disabling error occured. */ - if (vortex_debug > 2) - printk("%s: Tx error, status %2.2x.\n", - dev->name, tx_status); - if (tx_status & 0x04) vp->stats.tx_fifo_errors++; - if (tx_status & 0x38) vp->stats.tx_aborted_errors++; - if (tx_status & 0x30) { - int j; - outw(TxReset, ioaddr + EL3_CMD); - for (j = 20; j >= 0 ; j--) - if ( ! inw(ioaddr + EL3_STATUS) & CmdInProgress) - break; - } - outw(TxEnable, ioaddr + EL3_CMD); - } - outb(0x00, ioaddr + TxStatus); /* Pop the status stack. */ - } - } - return 0; -} - -/* The interrupt handler does all of the Rx thread work and cleans up - after the Tx thread. */ -static void vortex_interrupt(int irq, struct pt_regs *regs) -{ -#ifdef USE_SHARED_IRQ - struct device *dev = (struct device *)(irq == 0 ? regs : irq2dev_map[irq]); -#else - struct device *dev = (struct device *)(irq2dev_map[irq]); -#endif - struct vortex_private *lp; - int ioaddr, status; - int latency; - int i = 0; - - if (dev == NULL) { - printk ("vortex_interrupt(): irq %d for unknown device.\n", irq); - return; - } - - if (dev->interrupt) - printk("%s: Re-entering the interrupt handler.\n", dev->name); - dev->interrupt = 1; - - ioaddr = dev->base_addr; - latency = inb(ioaddr + Timer); - lp = (struct vortex_private *)dev->priv; - - status = inw(ioaddr + EL3_STATUS); - - if (vortex_debug > 4) - printk("%s: interrupt, status %4.4x, timer %d.\n", dev->name, - status, latency); - if ((status & 0xE000) != 0xE000) { - static int donedidthis=0; - /* Some interrupt controllers store a bogus interrupt from boot-time. - Ignore a single early interrupt, but don't hang the machine for - other interrupt problems. */ - if (donedidthis++ > 1) { - printk("%s: Bogus interrupt, bailing. Status %4.4x, start=%d.\n", - dev->name, status, dev->start); - free_irq(dev->irq); - } - } - - do { - if (vortex_debug > 5) - printk("%s: In interrupt loop, status %4.4x.\n", - dev->name, status); - if (status & RxComplete) - vortex_rx(dev); - - if (status & TxAvailable) { - if (vortex_debug > 5) - printk(" TX room bit was handled.\n"); - /* There's room in the FIFO for a full-sized packet. */ - outw(AckIntr | TxAvailable, ioaddr + EL3_CMD); - dev->tbusy = 0; - mark_bh(NET_BH); - } -#ifdef VORTEX_BUS_MASTER - if (status & DMADone) { - outw(0x1000, ioaddr + Wn7_MasterStatus); /* Ack the event. */ - dev->tbusy = 0; - mark_bh(NET_BH); - } -#endif - if (status & (AdapterFailure | RxEarly | StatsFull)) { - /* Handle all uncommon interrupts at once. */ - if (status & RxEarly) { /* Rx early is unused. */ - vortex_rx(dev); - outw(AckIntr | RxEarly, ioaddr + EL3_CMD); - } - if (status & StatsFull) { /* Empty statistics. */ - static int DoneDidThat = 0; - if (vortex_debug > 4) - printk("%s: Updating stats.\n", dev->name); - update_stats(ioaddr, dev); - /* DEBUG HACK: Disable statistics as an interrupt source. */ - /* This occurs when we have the wrong media type! */ - if (DoneDidThat == 0 && - inw(ioaddr + EL3_STATUS) & StatsFull) { - int win, reg; - printk("%s: Updating stats failed, disabling stats as an" - " interrupt source.\n", dev->name); - for (win = 0; win < 8; win++) { - EL3WINDOW(win); - printk("\n Vortex window %d:", win); - for (reg = 0; reg < 16; reg++) - printk(" %2.2x", inb(ioaddr+reg)); - } - EL3WINDOW(7); - outw(SetIntrEnb | 0x18, ioaddr + EL3_CMD); - DoneDidThat++; - } - } - if (status & AdapterFailure) { - /* Adapter failure requires Rx reset and reinit. */ - outw(RxReset, ioaddr + EL3_CMD); - /* Set the Rx filter to the current state. */ - outw(SetRxFilter | RxStation | RxBroadcast - | (dev->flags & IFF_ALLMULTI ? RxMulticast : 0) - | (dev->flags & IFF_PROMISC ? RxProm : 0), - ioaddr + EL3_CMD); - outw(RxEnable, ioaddr + EL3_CMD); /* Re-enable the receiver. */ - outw(AckIntr | AdapterFailure, ioaddr + EL3_CMD); - } - } - - if (++i > 10) { - printk("%s: Infinite loop in interrupt, status %4.4x. " - "Disabling functions (%4.4x).\n", - dev->name, status, SetStatusEnb | ((~status) & 0xFE)); - /* Disable all pending interrupts. */ - outw(SetStatusEnb | ((~status) & 0xFE), ioaddr + EL3_CMD); - outw(AckIntr | 0xFF, ioaddr + EL3_CMD); - break; - } - /* Acknowledge the IRQ. */ - outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD); - - } while ((status = inw(ioaddr + EL3_STATUS)) & (IntLatch | RxComplete)); - - if (vortex_debug > 4) - printk("%s: exiting interrupt, status %4.4x.\n", dev->name, status); - - dev->interrupt = 0; - return; -} - -static int -vortex_rx(struct device *dev) -{ - struct vortex_private *vp = (struct vortex_private *)dev->priv; - int ioaddr = dev->base_addr; - int i; - short rx_status; - - if (vortex_debug > 5) - printk(" In rx_packet(), status %4.4x, rx_status %4.4x.\n", - inw(ioaddr+EL3_STATUS), inw(ioaddr+RxStatus)); - while ((rx_status = inw(ioaddr + RxStatus)) > 0) { - if (rx_status & 0x4000) { /* Error, update stats. */ - unsigned char rx_error = inb(ioaddr + RxErrors); - if (vortex_debug > 4) - printk(" Rx error: status %2.2x.\n", rx_error); - vp->stats.rx_errors++; - if (rx_error & 0x01) vp->stats.rx_over_errors++; - if (rx_error & 0x02) vp->stats.rx_length_errors++; - if (rx_error & 0x04) vp->stats.rx_frame_errors++; - if (rx_error & 0x08) vp->stats.rx_crc_errors++; - if (rx_error & 0x10) vp->stats.rx_length_errors++; - } else { - /* The packet length: up to 4.5K!. */ - short pkt_len = rx_status & 0x1fff; - struct sk_buff *skb; - - skb = dev_alloc_skb(pkt_len + 5); - if (vortex_debug > 4) - printk("Receiving packet size %d status %4.4x.\n", - pkt_len, rx_status); - if (skb != NULL) { - skb->dev = dev; - skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ - /* 'skb_put()' points to the start of sk_buff data area. */ - insl(ioaddr + RX_FIFO, skb_put(skb, pkt_len), - (pkt_len + 3) >> 2); - skb->protocol = eth_type_trans(skb, dev); - netif_rx(skb); - outw(RxDiscard, ioaddr + EL3_CMD); /* Pop top Rx packet. */ - /* Wait a limited time to go to next packet. */ - for (i = 200; i >= 0; i--) - if ( ! inw(ioaddr + EL3_STATUS) & CmdInProgress) - break; - vp->stats.rx_packets++; - continue; - } else if (vortex_debug) - printk("%s: Couldn't allocate a sk_buff of size %d.\n", - dev->name, pkt_len); - } - vp->stats.rx_dropped++; - outw(RxDiscard, ioaddr + EL3_CMD); - /* Wait a limited time to skip this packet. */ - for (i = 200; i >= 0; i--) - if ( ! inw(ioaddr + EL3_STATUS) & CmdInProgress) - break; - } - - return 0; -} - -static int -vortex_close(struct device *dev) -{ - int ioaddr = dev->base_addr; - - dev->start = 0; - dev->tbusy = 1; - - if (vortex_debug > 1) - printk("%s: vortex_close() status %4.4x, Tx status %2.2x.\n", - dev->name, inw(ioaddr + EL3_STATUS), inb(ioaddr + TxStatus)); - - /* Turn off statistics ASAP. We update lp->stats below. */ - outw(StatsDisable, ioaddr + EL3_CMD); - - /* Disable the receiver and transmitter. */ - outw(RxDisable, ioaddr + EL3_CMD); - outw(TxDisable, ioaddr + EL3_CMD); - - if (dev->if_port == 3) - /* Turn off thinnet power. Green! */ - outw(StopCoax, ioaddr + EL3_CMD); - else if (dev->if_port == 0) { - /* Disable link beat and jabber, if_port may change ere next open(). */ - EL3WINDOW(4); - outw(inw(ioaddr + Wn4_Media) & ~Media_TP, ioaddr + Wn4_Media); - } - -#ifdef USE_SHARED_IRQ - free_shared_irq(dev->irq, dev); -#else - free_irq(dev->irq); - /* Mmmm, we should diable all interrupt sources here. */ - irq2dev_map[dev->irq] = 0; -#endif - - update_stats(ioaddr, dev); -#ifdef MODULE - MOD_DEC_USE_COUNT; -#endif - - return 0; -} - -static struct enet_statistics * -vortex_get_stats(struct device *dev) -{ - struct vortex_private *vp = (struct vortex_private *)dev->priv; - unsigned long flags; - - save_flags(flags); - cli(); - update_stats(dev->base_addr, dev); - restore_flags(flags); - return &vp->stats; -} - -/* Update statistics. - Unlike with the EL3 we need not worry about interrupts changing - the window setting from underneath us, but we must still guard - against a race condition with a StatsUpdate interrupt updating the - table. This is done by checking that the ASM (!) code generated uses - atomic updates with '+='. - */ -static void update_stats(int ioaddr, struct device *dev) -{ - struct vortex_private *vp = (struct vortex_private *)dev->priv; - - /* Unlike the 3c5x9 we need not turn off stats updates while reading. */ - /* Switch to the stats window, and read everything. */ - EL3WINDOW(6); - vp->stats.tx_carrier_errors += inb(ioaddr + 0); - vp->stats.tx_heartbeat_errors += inb(ioaddr + 1); - /* Multiple collisions. */ inb(ioaddr + 2); - vp->stats.collisions += inb(ioaddr + 3); - vp->stats.tx_window_errors += inb(ioaddr + 4); - vp->stats.rx_fifo_errors += inb(ioaddr + 5); - vp->stats.tx_packets += inb(ioaddr + 6); - vp->stats.tx_packets += (inb(ioaddr + 9)&0x30) << 4; - /* Rx packets */ inb(ioaddr + 7); /* Must read to clear */ - /* Tx deferrals */ inb(ioaddr + 8); - /* Don't bother with register 9, an extention of registers 6&7. - If we do use the 6&7 values the atomic update assumption above - is invalid. */ - inw(ioaddr + 10); /* Total Rx and Tx octets. */ - inw(ioaddr + 12); - /* New: On the Vortex we must also clear the BadSSD counter. */ - EL3WINDOW(4); - inb(ioaddr + 12); - - /* We change back to window 7 (not 1) with the Vortex. */ - EL3WINDOW(7); - return; -} - -/* There are two version of set_multicast_list() to support both v1.2 and - v1.4 kernels. */ -static void -set_multicast_list(struct device *dev) -{ - short ioaddr = dev->base_addr; - - if ((dev->mc_list) || (dev->flags & IFF_ALLMULTI)) { - outw(SetRxFilter|RxStation|RxMulticast|RxBroadcast, ioaddr + EL3_CMD); - if (vortex_debug > 3) { - printk("%s: Setting Rx multicast mode, %d addresses.\n", - dev->name, dev->mc_count); - } - } else if (dev->flags & IFF_PROMISC) { - outw(SetRxFilter | RxStation | RxMulticast | RxBroadcast | RxProm, - ioaddr + EL3_CMD); - } else - outw(SetRxFilter | RxStation | RxBroadcast, ioaddr + EL3_CMD); -} - - -#ifdef MODULE -void -cleanup_module(void) -{ - struct device *next_dev; - - /* No need to check MOD_IN_USE, as sys_delete_module() checks. */ - while (root_vortex_dev) { - next_dev = ((struct vortex_private *)root_vortex_dev->priv)->next_module; - unregister_netdev(root_vortex_dev); - release_region(root_vortex_dev->base_addr, VORTEX_TOTAL_SIZE); - kfree(root_vortex_dev); - root_vortex_dev = next_dev; - } -} -#endif /* MODULE */ - -/* - * Local variables: - * compile-command: "gcc -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c 3c59x.c -o 3c59x.o" - * c-indent-level: 4 - * tab-width: 4 - * End: - */ diff --git a/i386/i386at/gpl/linux/net/8390.c b/i386/i386at/gpl/linux/net/8390.c deleted file mode 100644 index 7962413c..00000000 --- a/i386/i386at/gpl/linux/net/8390.c +++ /dev/null @@ -1,727 +0,0 @@ -/* 8390.c: A general NS8390 ethernet driver core for linux. */ -/* - Written 1992-94 by Donald Becker. - - Copyright 1993 United States Government as represented by the - Director, National Security Agency. - - This software may be used and distributed according to the terms - of the GNU Public License, incorporated herein by reference. - - The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O - Center of Excellence in Space Data and Information Sciences - Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771 - - This is the chip-specific code for many 8390-based ethernet adaptors. - This is not a complete driver, it must be combined with board-specific - code such as ne.c, wd.c, 3c503.c, etc. - - Changelog: - - Paul Gortmaker : remove set_bit lock, other cleanups. - Paul Gortmaker : add ei_get_8390_hdr() so we can pass skb's to - ei_block_input() for eth_io_copy_and_sum(). - - */ - -static const char *version = - "8390.c:v1.10 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n"; - -/* - Braindamage remaining: - Much of this code should have been cleaned up, but every attempt - has broken some clone part. - - Sources: - The National Semiconductor LAN Databook, and the 3Com 3c503 databook. - */ - -#include <linux/module.h> - -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/fs.h> -#include <linux/types.h> -#include <linux/ptrace.h> -#include <linux/string.h> -#include <asm/system.h> -#include <asm/segment.h> -#include <asm/bitops.h> -#include <asm/io.h> -#include <linux/errno.h> -#include <linux/fcntl.h> -#include <linux/in.h> -#include <linux/interrupt.h> - -#include <linux/netdevice.h> -#include <linux/etherdevice.h> - -#include "8390.h" - -/* These are the operational function interfaces to board-specific - routines. - void reset_8390(struct device *dev) - Resets the board associated with DEV, including a hardware reset of - the 8390. This is only called when there is a transmit timeout, and - it is always followed by 8390_init(). - void block_output(struct device *dev, int count, const unsigned char *buf, - int start_page) - Write the COUNT bytes of BUF to the packet buffer at START_PAGE. The - "page" value uses the 8390's 256-byte pages. - void get_8390_hdr(struct device *dev, struct e8390_hdr *hdr, int ring_page) - Read the 4 byte, page aligned 8390 header. *If* there is a - subsequent read, it will be of the rest of the packet. - void block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset) - Read COUNT bytes from the packet buffer into the skb data area. Start - reading from RING_OFFSET, the address as the 8390 sees it. This will always - follow the read of the 8390 header. -*/ -#define ei_reset_8390 (ei_local->reset_8390) -#define ei_block_output (ei_local->block_output) -#define ei_block_input (ei_local->block_input) -#define ei_get_8390_hdr (ei_local->get_8390_hdr) - -/* use 0 for production, 1 for verification, >2 for debug */ -#ifdef EI_DEBUG -int ei_debug = EI_DEBUG; -#else -int ei_debug = 0; -#endif -#ifdef EI_PINGPONG -static int ei_pingpong = 1; -#else -static int ei_pingpong = 0; -#endif - -/* Max number of packets received at one Intr. - Currently this may only be examined by a kernel debugger. */ -static int high_water_mark = 0; - -/* Index to functions. */ -static void ei_tx_intr(struct device *dev); -static void ei_receive(struct device *dev); -static void ei_rx_overrun(struct device *dev); - -/* Routines generic to NS8390-based boards. */ -static void NS8390_trigger_send(struct device *dev, unsigned int length, - int start_page); -static void set_multicast_list(struct device *dev); - - -/* Open/initialize the board. This routine goes all-out, setting everything - up anew at each open, even though many of these registers should only - need to be set once at boot. - */ -int ei_open(struct device *dev) -{ - struct ei_device *ei_local = (struct ei_device *) dev->priv; - - /* This can't happen unless somebody forgot to call ethdev_init(). */ - if (ei_local == NULL) { - printk(KERN_EMERG "%s: ei_open passed a non-existent device!\n", dev->name); - return -ENXIO; - } - - irq2dev_map[dev->irq] = dev; - NS8390_init(dev, 1); - dev->start = 1; - ei_local->irqlock = 0; - return 0; -} - -/* Opposite of above. Only used when "ifconfig <devname> down" is done. */ -int ei_close(struct device *dev) -{ - NS8390_init(dev, 0); - dev->start = 0; - return 0; -} - -static int ei_start_xmit(struct sk_buff *skb, struct device *dev) -{ - int e8390_base = dev->base_addr; - struct ei_device *ei_local = (struct ei_device *) dev->priv; - int length, send_length; - -/* - * We normally shouldn't be called if dev->tbusy is set, but the - * existing code does anyway. If it has been too long since the - * last Tx, we assume the board has died and kick it. - */ - - if (dev->tbusy) { /* Do timeouts, just like the 8003 driver. */ - int txsr = inb(e8390_base+EN0_TSR), isr; - int tickssofar = jiffies - dev->trans_start; - if (tickssofar < TX_TIMEOUT || (tickssofar < (TX_TIMEOUT+5) && ! (txsr & ENTSR_PTX))) { - return 1; - } - isr = inb(e8390_base+EN0_ISR); - if (dev->start == 0) { - printk("%s: xmit on stopped card\n", dev->name); - return 1; - } - - printk(KERN_DEBUG "%s: Tx timed out, %s TSR=%#2x, ISR=%#2x, t=%d.\n", - dev->name, (txsr & ENTSR_ABT) ? "excess collisions." : - (isr) ? "lost interrupt?" : "cable problem?", txsr, isr, tickssofar); - - if (!isr && !ei_local->stat.tx_packets) { - /* The 8390 probably hasn't gotten on the cable yet. */ - ei_local->interface_num ^= 1; /* Try a different xcvr. */ - } - - /* Try to restart the card. Perhaps the user has fixed something. */ - ei_reset_8390(dev); - NS8390_init(dev, 1); - dev->trans_start = jiffies; - } - - /* Sending a NULL skb means some higher layer thinks we've missed an - tx-done interrupt. Caution: dev_tint() handles the cli()/sti() - itself. */ - if (skb == NULL) { - dev_tint(dev); - return 0; - } - - length = skb->len; - if (skb->len <= 0) - return 0; - - /* Mask interrupts from the ethercard. */ - outb_p(0x00, e8390_base + EN0_IMR); - if (dev->interrupt) { - printk("%s: Tx request while isr active.\n",dev->name); - outb_p(ENISR_ALL, e8390_base + EN0_IMR); - return 1; - } - ei_local->irqlock = 1; - - send_length = ETH_ZLEN < length ? length : ETH_ZLEN; - - if (ei_local->pingpong) { - int output_page; - if (ei_local->tx1 == 0) { - output_page = ei_local->tx_start_page; - ei_local->tx1 = send_length; - if (ei_debug && ei_local->tx2 > 0) - printk("%s: idle transmitter tx2=%d, lasttx=%d, txing=%d.\n", - dev->name, ei_local->tx2, ei_local->lasttx, - ei_local->txing); - } else if (ei_local->tx2 == 0) { - output_page = ei_local->tx_start_page + 6; - ei_local->tx2 = send_length; - if (ei_debug && ei_local->tx1 > 0) - printk("%s: idle transmitter, tx1=%d, lasttx=%d, txing=%d.\n", - dev->name, ei_local->tx1, ei_local->lasttx, - ei_local->txing); - } else { /* We should never get here. */ - if (ei_debug) - printk("%s: No Tx buffers free. irq=%d tx1=%d tx2=%d last=%d\n", - dev->name, dev->interrupt, ei_local->tx1, - ei_local->tx2, ei_local->lasttx); - ei_local->irqlock = 0; - dev->tbusy = 1; - outb_p(ENISR_ALL, e8390_base + EN0_IMR); - return 1; - } - ei_block_output(dev, length, skb->data, output_page); - if (! ei_local->txing) { - ei_local->txing = 1; - NS8390_trigger_send(dev, send_length, output_page); - dev->trans_start = jiffies; - if (output_page == ei_local->tx_start_page) - ei_local->tx1 = -1, ei_local->lasttx = -1; - else - ei_local->tx2 = -1, ei_local->lasttx = -2; - } else - ei_local->txqueue++; - - dev->tbusy = (ei_local->tx1 && ei_local->tx2); - } else { /* No pingpong, just a single Tx buffer. */ - ei_block_output(dev, length, skb->data, ei_local->tx_start_page); - ei_local->txing = 1; - NS8390_trigger_send(dev, send_length, ei_local->tx_start_page); - dev->trans_start = jiffies; - dev->tbusy = 1; - } - - /* Turn 8390 interrupts back on. */ - ei_local->irqlock = 0; - outb_p(ENISR_ALL, e8390_base + EN0_IMR); - - dev_kfree_skb (skb, FREE_WRITE); - - return 0; -} - -/* The typical workload of the driver: - Handle the ether interface interrupts. */ -void ei_interrupt(int irq, struct pt_regs * regs) -{ - struct device *dev = (struct device *)(irq2dev_map[irq]); - int e8390_base; - int interrupts, nr_serviced = 0; - struct ei_device *ei_local; - - if (dev == NULL) { - printk ("net_interrupt(): irq %d for unknown device.\n", irq); - return; - } - e8390_base = dev->base_addr; - ei_local = (struct ei_device *) dev->priv; - if (dev->interrupt || ei_local->irqlock) { - /* The "irqlock" check is only for testing. */ - printk(ei_local->irqlock - ? "%s: Interrupted while interrupts are masked! isr=%#2x imr=%#2x.\n" - : "%s: Reentering the interrupt handler! isr=%#2x imr=%#2x.\n", - dev->name, inb_p(e8390_base + EN0_ISR), - inb_p(e8390_base + EN0_IMR)); - return; - } - - dev->interrupt = 1; - - /* Change to page 0 and read the intr status reg. */ - outb_p(E8390_NODMA+E8390_PAGE0, e8390_base + E8390_CMD); - if (ei_debug > 3) - printk("%s: interrupt(isr=%#2.2x).\n", dev->name, - inb_p(e8390_base + EN0_ISR)); - - /* !!Assumption!! -- we stay in page 0. Don't break this. */ - while ((interrupts = inb_p(e8390_base + EN0_ISR)) != 0 - && ++nr_serviced < MAX_SERVICE) { - if (dev->start == 0) { - printk("%s: interrupt from stopped card\n", dev->name); - interrupts = 0; - break; - } - if (interrupts & ENISR_OVER) { - ei_rx_overrun(dev); - } else if (interrupts & (ENISR_RX+ENISR_RX_ERR)) { - /* Got a good (?) packet. */ - ei_receive(dev); - } - /* Push the next to-transmit packet through. */ - if (interrupts & ENISR_TX) { - ei_tx_intr(dev); - } else if (interrupts & ENISR_COUNTERS) { - ei_local->stat.rx_frame_errors += inb_p(e8390_base + EN0_COUNTER0); - ei_local->stat.rx_crc_errors += inb_p(e8390_base + EN0_COUNTER1); - ei_local->stat.rx_missed_errors+= inb_p(e8390_base + EN0_COUNTER2); - outb_p(ENISR_COUNTERS, e8390_base + EN0_ISR); /* Ack intr. */ - } - - /* Ignore the transmit errs and reset intr for now. */ - if (interrupts & ENISR_TX_ERR) { - outb_p(ENISR_TX_ERR, e8390_base + EN0_ISR); /* Ack intr. */ - } - - /* Ignore any RDC interrupts that make it back to here. */ - if (interrupts & ENISR_RDC) { - outb_p(ENISR_RDC, e8390_base + EN0_ISR); - } - - outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base + E8390_CMD); - } - - if (interrupts && ei_debug) { - outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base + E8390_CMD); - if (nr_serviced >= MAX_SERVICE) { - printk("%s: Too much work at interrupt, status %#2.2x\n", - dev->name, interrupts); - outb_p(ENISR_ALL, e8390_base + EN0_ISR); /* Ack. most intrs. */ - } else { - printk("%s: unknown interrupt %#2x\n", dev->name, interrupts); - outb_p(0xff, e8390_base + EN0_ISR); /* Ack. all intrs. */ - } - } - dev->interrupt = 0; - return; -} - -/* We have finished a transmit: check for errors and then trigger the next - packet to be sent. */ -static void ei_tx_intr(struct device *dev) -{ - int e8390_base = dev->base_addr; - int status = inb(e8390_base + EN0_TSR); - struct ei_device *ei_local = (struct ei_device *) dev->priv; - - outb_p(ENISR_TX, e8390_base + EN0_ISR); /* Ack intr. */ - - if (ei_local->pingpong) { - ei_local->txqueue--; - if (ei_local->tx1 < 0) { - if (ei_local->lasttx != 1 && ei_local->lasttx != -1) - printk("%s: bogus last_tx_buffer %d, tx1=%d.\n", - ei_local->name, ei_local->lasttx, ei_local->tx1); - ei_local->tx1 = 0; - dev->tbusy = 0; - if (ei_local->tx2 > 0) { - ei_local->txing = 1; - NS8390_trigger_send(dev, ei_local->tx2, ei_local->tx_start_page + 6); - dev->trans_start = jiffies; - ei_local->tx2 = -1, - ei_local->lasttx = 2; - } else - ei_local->lasttx = 20, ei_local->txing = 0; - } else if (ei_local->tx2 < 0) { - if (ei_local->lasttx != 2 && ei_local->lasttx != -2) - printk("%s: bogus last_tx_buffer %d, tx2=%d.\n", - ei_local->name, ei_local->lasttx, ei_local->tx2); - ei_local->tx2 = 0; - dev->tbusy = 0; - if (ei_local->tx1 > 0) { - ei_local->txing = 1; - NS8390_trigger_send(dev, ei_local->tx1, ei_local->tx_start_page); - dev->trans_start = jiffies; - ei_local->tx1 = -1; - ei_local->lasttx = 1; - } else - ei_local->lasttx = 10, ei_local->txing = 0; - } else - printk("%s: unexpected TX-done interrupt, lasttx=%d.\n", - dev->name, ei_local->lasttx); - } else { - ei_local->txing = 0; - dev->tbusy = 0; - } - - /* Minimize Tx latency: update the statistics after we restart TXing. */ - if (status & ENTSR_COL) ei_local->stat.collisions++; - if (status & ENTSR_PTX) - ei_local->stat.tx_packets++; - else { - ei_local->stat.tx_errors++; - if (status & ENTSR_ABT) ei_local->stat.tx_aborted_errors++; - if (status & ENTSR_CRS) ei_local->stat.tx_carrier_errors++; - if (status & ENTSR_FU) ei_local->stat.tx_fifo_errors++; - if (status & ENTSR_CDH) ei_local->stat.tx_heartbeat_errors++; - if (status & ENTSR_OWC) ei_local->stat.tx_window_errors++; - } - - mark_bh (NET_BH); -} - -/* We have a good packet(s), get it/them out of the buffers. */ - -static void ei_receive(struct device *dev) -{ - int e8390_base = dev->base_addr; - struct ei_device *ei_local = (struct ei_device *) dev->priv; - int rxing_page, this_frame, next_frame, current_offset; - int rx_pkt_count = 0; - struct e8390_pkt_hdr rx_frame; - int num_rx_pages = ei_local->stop_page-ei_local->rx_start_page; - - while (++rx_pkt_count < 10) { - int pkt_len; - - /* Get the rx page (incoming packet pointer). */ - outb_p(E8390_NODMA+E8390_PAGE1, e8390_base + E8390_CMD); - rxing_page = inb_p(e8390_base + EN1_CURPAG); - outb_p(E8390_NODMA+E8390_PAGE0, e8390_base + E8390_CMD); - - /* Remove one frame from the ring. Boundary is always a page behind. */ - this_frame = inb_p(e8390_base + EN0_BOUNDARY) + 1; - if (this_frame >= ei_local->stop_page) - this_frame = ei_local->rx_start_page; - - /* Someday we'll omit the previous, iff we never get this message. - (There is at least one clone claimed to have a problem.) */ - if (ei_debug > 0 && this_frame != ei_local->current_page) - printk("%s: mismatched read page pointers %2x vs %2x.\n", - dev->name, this_frame, ei_local->current_page); - - if (this_frame == rxing_page) /* Read all the frames? */ - break; /* Done for now */ - - current_offset = this_frame << 8; - ei_get_8390_hdr(dev, &rx_frame, this_frame); - - pkt_len = rx_frame.count - sizeof(struct e8390_pkt_hdr); - - next_frame = this_frame + 1 + ((pkt_len+4)>>8); - - /* Check for bogosity warned by 3c503 book: the status byte is never - written. This happened a lot during testing! This code should be - cleaned up someday. */ - if (rx_frame.next != next_frame - && rx_frame.next != next_frame + 1 - && rx_frame.next != next_frame - num_rx_pages - && rx_frame.next != next_frame + 1 - num_rx_pages) { - ei_local->current_page = rxing_page; - outb(ei_local->current_page-1, e8390_base+EN0_BOUNDARY); - ei_local->stat.rx_errors++; - continue; - } - - if (pkt_len < 60 || pkt_len > 1518) { - if (ei_debug) - printk("%s: bogus packet size: %d, status=%#2x nxpg=%#2x.\n", - dev->name, rx_frame.count, rx_frame.status, - rx_frame.next); - ei_local->stat.rx_errors++; - } else if ((rx_frame.status & 0x0F) == ENRSR_RXOK) { - struct sk_buff *skb; - - skb = dev_alloc_skb(pkt_len+2); - if (skb == NULL) { - if (ei_debug > 1) - printk("%s: Couldn't allocate a sk_buff of size %d.\n", - dev->name, pkt_len); - ei_local->stat.rx_dropped++; - break; - } else { - skb_reserve(skb,2); /* IP headers on 16 byte boundaries */ - skb->dev = dev; - skb_put(skb, pkt_len); /* Make room */ - ei_block_input(dev, pkt_len, skb, current_offset + sizeof(rx_frame)); - skb->protocol=eth_type_trans(skb,dev); - netif_rx(skb); - ei_local->stat.rx_packets++; - } - } else { - int errs = rx_frame.status; - if (ei_debug) - printk("%s: bogus packet: status=%#2x nxpg=%#2x size=%d\n", - dev->name, rx_frame.status, rx_frame.next, - rx_frame.count); - if (errs & ENRSR_FO) - ei_local->stat.rx_fifo_errors++; - } - next_frame = rx_frame.next; - - /* This _should_ never happen: it's here for avoiding bad clones. */ - if (next_frame >= ei_local->stop_page) { - printk("%s: next frame inconsistency, %#2x\n", dev->name, - next_frame); - next_frame = ei_local->rx_start_page; - } - ei_local->current_page = next_frame; - outb_p(next_frame-1, e8390_base+EN0_BOUNDARY); - } - /* If any worth-while packets have been received, netif_rx() - has done a mark_bh(NET_BH) for us and will work on them - when we get to the bottom-half routine. */ - - /* Record the maximum Rx packet queue. */ - if (rx_pkt_count > high_water_mark) - high_water_mark = rx_pkt_count; - - /* We used to also ack ENISR_OVER here, but that would sometimes mask - a real overrun, leaving the 8390 in a stopped state with rec'vr off. */ - outb_p(ENISR_RX+ENISR_RX_ERR, e8390_base+EN0_ISR); - return; -} - -/* We have a receiver overrun: we have to kick the 8390 to get it started - again.*/ -static void ei_rx_overrun(struct device *dev) -{ - int e8390_base = dev->base_addr; - int reset_start_time = jiffies; - struct ei_device *ei_local = (struct ei_device *) dev->priv; - - /* We should already be stopped and in page0. Remove after testing. */ - outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD); - - if (ei_debug > 1) - printk("%s: Receiver overrun.\n", dev->name); - ei_local->stat.rx_over_errors++; - - /* The old Biro driver does dummy = inb_p( RBCR[01] ); at this point. - It might mean something -- magic to speed up a reset? A 8390 bug?*/ - - /* Wait for the reset to complete. This should happen almost instantly, - but could take up to 1.5msec in certain rare instances. There is no - easy way of timing something in that range, so we use 'jiffies' as - a sanity check. */ - while ((inb_p(e8390_base+EN0_ISR) & ENISR_RESET) == 0) - if (jiffies - reset_start_time > 2*HZ/100) { - printk("%s: reset did not complete at ei_rx_overrun.\n", - dev->name); - NS8390_init(dev, 1); - return; - } - - /* Remove packets right away. */ - ei_receive(dev); - - outb_p(ENISR_OVER, e8390_base+EN0_ISR); - /* Generic 8390 insns to start up again, same as in open_8390(). */ - outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START, e8390_base + E8390_CMD); - outb_p(E8390_TXCONFIG, e8390_base + EN0_TXCR); /* xmit on. */ -} - -static struct enet_statistics *get_stats(struct device *dev) -{ - short ioaddr = dev->base_addr; - struct ei_device *ei_local = (struct ei_device *) dev->priv; - - /* If the card is stopped, just return the present stats. */ - if (dev->start == 0) return &ei_local->stat; - - /* Read the counter registers, assuming we are in page 0. */ - ei_local->stat.rx_frame_errors += inb_p(ioaddr + EN0_COUNTER0); - ei_local->stat.rx_crc_errors += inb_p(ioaddr + EN0_COUNTER1); - ei_local->stat.rx_missed_errors+= inb_p(ioaddr + EN0_COUNTER2); - - return &ei_local->stat; -} - -/* - * Set or clear the multicast filter for this adaptor. - */ - -static void set_multicast_list(struct device *dev) -{ - short ioaddr = dev->base_addr; - - if(dev->flags&IFF_PROMISC) - { - outb_p(E8390_RXCONFIG | 0x18, ioaddr + EN0_RXCR); - } - else if((dev->flags&IFF_ALLMULTI)||dev->mc_list) - { - /* The multicast-accept list is initialized to accept-all, and we - rely on higher-level filtering for now. */ - outb_p(E8390_RXCONFIG | 0x08, ioaddr + EN0_RXCR); - } - else - outb_p(E8390_RXCONFIG, ioaddr + EN0_RXCR); -} - -/* Initialize the rest of the 8390 device structure. */ -int ethdev_init(struct device *dev) -{ - if (ei_debug > 1) - printk(version); - - if (dev->priv == NULL) { - struct ei_device *ei_local; - - dev->priv = kmalloc(sizeof(struct ei_device), GFP_KERNEL); - if (dev->priv == NULL) - return -ENOMEM; - memset(dev->priv, 0, sizeof(struct ei_device)); - ei_local = (struct ei_device *)dev->priv; - ei_local->pingpong = ei_pingpong; - } - - dev->hard_start_xmit = &ei_start_xmit; - dev->get_stats = get_stats; - dev->set_multicast_list = &set_multicast_list; - - ether_setup(dev); - - return 0; -} - - -/* This page of functions should be 8390 generic */ -/* Follow National Semi's recommendations for initializing the "NIC". */ -void NS8390_init(struct device *dev, int startp) -{ - int e8390_base = dev->base_addr; - struct ei_device *ei_local = (struct ei_device *) dev->priv; - int i; - int endcfg = ei_local->word16 ? (0x48 | ENDCFG_WTS) : 0x48; - unsigned long flags; - - /* Follow National Semi's recommendations for initing the DP83902. */ - outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base); /* 0x21 */ - outb_p(endcfg, e8390_base + EN0_DCFG); /* 0x48 or 0x49 */ - /* Clear the remote byte count registers. */ - outb_p(0x00, e8390_base + EN0_RCNTLO); - outb_p(0x00, e8390_base + EN0_RCNTHI); - /* Set to monitor and loopback mode -- this is vital!. */ - outb_p(E8390_RXOFF, e8390_base + EN0_RXCR); /* 0x20 */ - outb_p(E8390_TXOFF, e8390_base + EN0_TXCR); /* 0x02 */ - /* Set the transmit page and receive ring. */ - outb_p(ei_local->tx_start_page, e8390_base + EN0_TPSR); - ei_local->tx1 = ei_local->tx2 = 0; - outb_p(ei_local->rx_start_page, e8390_base + EN0_STARTPG); - outb_p(ei_local->stop_page-1, e8390_base + EN0_BOUNDARY); /* 3c503 says 0x3f,NS0x26*/ - ei_local->current_page = ei_local->rx_start_page; /* assert boundary+1 */ - outb_p(ei_local->stop_page, e8390_base + EN0_STOPPG); - /* Clear the pending interrupts and mask. */ - outb_p(0xFF, e8390_base + EN0_ISR); - outb_p(0x00, e8390_base + EN0_IMR); - - /* Copy the station address into the DS8390 registers, - and set the multicast hash bitmap to receive all multicasts. */ - save_flags(flags); - cli(); - outb_p(E8390_NODMA + E8390_PAGE1 + E8390_STOP, e8390_base); /* 0x61 */ - for(i = 0; i < 6; i++) { - outb_p(dev->dev_addr[i], e8390_base + EN1_PHYS + i); - } - /* Initialize the multicast list to accept-all. If we enable multicast - the higher levels can do the filtering. */ - for(i = 0; i < 8; i++) - outb_p(0xff, e8390_base + EN1_MULT + i); - - outb_p(ei_local->rx_start_page, e8390_base + EN1_CURPAG); - outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base); - restore_flags(flags); - dev->tbusy = 0; - dev->interrupt = 0; - ei_local->tx1 = ei_local->tx2 = 0; - ei_local->txing = 0; - if (startp) { - outb_p(0xff, e8390_base + EN0_ISR); - outb_p(ENISR_ALL, e8390_base + EN0_IMR); - outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base); - outb_p(E8390_TXCONFIG, e8390_base + EN0_TXCR); /* xmit on. */ - /* 3c503 TechMan says rxconfig only after the NIC is started. */ - outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR); /* rx on, */ - dev->set_multicast_list(dev); /* Get the multicast status right if this - was a reset. */ - } - return; -} - -/* Trigger a transmit start, assuming the length is valid. */ -static void NS8390_trigger_send(struct device *dev, unsigned int length, - int start_page) -{ - int e8390_base = dev->base_addr; - - outb_p(E8390_NODMA+E8390_PAGE0, e8390_base); - - if (inb_p(e8390_base) & E8390_TRANS) { - printk("%s: trigger_send() called with the transmitter busy.\n", - dev->name); - return; - } - outb_p(length & 0xff, e8390_base + EN0_TCNTLO); - outb_p(length >> 8, e8390_base + EN0_TCNTHI); - outb_p(start_page, e8390_base + EN0_TPSR); - outb_p(E8390_NODMA+E8390_TRANS+E8390_START, e8390_base); - return; -} - -#ifdef MODULE - -int init_module(void) -{ - return 0; -} - -void -cleanup_module(void) -{ -} -#endif /* MODULE */ - -/* - * Local variables: - * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c 8390.c" - * version-control: t - * kept-new-versions: 5 - * c-indent-level: 4 - * tab-width: 4 - * End: - */ diff --git a/i386/i386at/gpl/linux/net/8390.h b/i386/i386at/gpl/linux/net/8390.h deleted file mode 100644 index 17b8cdb5..00000000 --- a/i386/i386at/gpl/linux/net/8390.h +++ /dev/null @@ -1,168 +0,0 @@ -/* Generic NS8390 register definitions. */ -/* This file is part of Donald Becker's 8390 drivers, and is distributed - under the same license. - Some of these names and comments originated from the Crynwr - packet drivers, which are distributed under the GPL. */ - -#ifndef _8390_h -#define _8390_h - -#include <linux/if_ether.h> -#include <linux/ioport.h> -#include <linux/skbuff.h> - -#define TX_2X_PAGES 12 -#define TX_1X_PAGES 6 -#define TX_PAGES (ei_status.pingpong ? TX_2X_PAGES : TX_1X_PAGES) - -#define ETHER_ADDR_LEN 6 - -/* The 8390 specific per-packet-header format. */ -struct e8390_pkt_hdr { - unsigned char status; /* status */ - unsigned char next; /* pointer to next packet. */ - unsigned short count; /* header + packet length in bytes */ -}; - -/* From 8390.c */ -extern int ei_debug; -extern struct sigaction ei_sigaction; - -extern int ethif_init(struct device *dev); -extern int ethdev_init(struct device *dev); -extern void NS8390_init(struct device *dev, int startp); -extern int ei_open(struct device *dev); -extern int ei_close(struct device *dev); -extern void ei_interrupt(int irq, struct pt_regs *regs); - -#ifndef HAVE_AUTOIRQ -/* From auto_irq.c */ -extern struct device *irq2dev_map[16]; -extern int autoirq_setup(int waittime); -extern int autoirq_report(int waittime); -#endif - -/* Most of these entries should be in 'struct device' (or most of the - things in there should be here!) */ -/* You have one of these per-board */ -struct ei_device { - const char *name; - void (*reset_8390)(struct device *); - void (*get_8390_hdr)(struct device *, struct e8390_pkt_hdr *, int); - void (*block_output)(struct device *, int, const unsigned char *, int); - void (*block_input)(struct device *, int, struct sk_buff *, int); - unsigned open:1; - unsigned word16:1; /* We have the 16-bit (vs 8-bit) version of the card. */ - unsigned txing:1; /* Transmit Active */ - unsigned irqlock:1; /* 8390's intrs disabled when '1'. */ - unsigned dmaing:1; /* Remote DMA Active */ - unsigned pingpong:1; /* Using the ping-pong driver */ - unsigned char tx_start_page, rx_start_page, stop_page; - unsigned char current_page; /* Read pointer in buffer */ - unsigned char interface_num; /* Net port (AUI, 10bT.) to use. */ - unsigned char txqueue; /* Tx Packet buffer queue length. */ - short tx1, tx2; /* Packet lengths for ping-pong tx. */ - short lasttx; /* Alpha version consistency check. */ - unsigned char reg0; /* Register '0' in a WD8013 */ - unsigned char reg5; /* Register '5' in a WD8013 */ - unsigned char saved_irq; /* Original dev->irq value. */ - /* The new statistics table. */ - struct enet_statistics stat; -}; - -/* The maximum number of 8390 interrupt service routines called per IRQ. */ -#define MAX_SERVICE 12 - -/* The maximum time waited (in jiffies) before assuming a Tx failed. (20ms) */ -#define TX_TIMEOUT (20*HZ/100) - -#define ei_status (*(struct ei_device *)(dev->priv)) - -/* Some generic ethernet register configurations. */ -#define E8390_TX_IRQ_MASK 0xa /* For register EN0_ISR */ -#define E8390_RX_IRQ_MASK 0x5 -#define E8390_RXCONFIG 0x4 /* EN0_RXCR: broadcasts, no multicast,errors */ -#define E8390_RXOFF 0x20 /* EN0_RXCR: Accept no packets */ -#define E8390_TXCONFIG 0x00 /* EN0_TXCR: Normal transmit mode */ -#define E8390_TXOFF 0x02 /* EN0_TXCR: Transmitter off */ - -/* Register accessed at EN_CMD, the 8390 base addr. */ -#define E8390_STOP 0x01 /* Stop and reset the chip */ -#define E8390_START 0x02 /* Start the chip, clear reset */ -#define E8390_TRANS 0x04 /* Transmit a frame */ -#define E8390_RREAD 0x08 /* Remote read */ -#define E8390_RWRITE 0x10 /* Remote write */ -#define E8390_NODMA 0x20 /* Remote DMA */ -#define E8390_PAGE0 0x00 /* Select page chip registers */ -#define E8390_PAGE1 0x40 /* using the two high-order bits */ -#define E8390_PAGE2 0x80 /* Page 3 is invalid. */ - -#define E8390_CMD 0x00 /* The command register (for all pages) */ -/* Page 0 register offsets. */ -#define EN0_CLDALO 0x01 /* Low byte of current local dma addr RD */ -#define EN0_STARTPG 0x01 /* Starting page of ring bfr WR */ -#define EN0_CLDAHI 0x02 /* High byte of current local dma addr RD */ -#define EN0_STOPPG 0x02 /* Ending page +1 of ring bfr WR */ -#define EN0_BOUNDARY 0x03 /* Boundary page of ring bfr RD WR */ -#define EN0_TSR 0x04 /* Transmit status reg RD */ -#define EN0_TPSR 0x04 /* Transmit starting page WR */ -#define EN0_NCR 0x05 /* Number of collision reg RD */ -#define EN0_TCNTLO 0x05 /* Low byte of tx byte count WR */ -#define EN0_FIFO 0x06 /* FIFO RD */ -#define EN0_TCNTHI 0x06 /* High byte of tx byte count WR */ -#define EN0_ISR 0x07 /* Interrupt status reg RD WR */ -#define EN0_CRDALO 0x08 /* low byte of current remote dma address RD */ -#define EN0_RSARLO 0x08 /* Remote start address reg 0 */ -#define EN0_CRDAHI 0x09 /* high byte, current remote dma address RD */ -#define EN0_RSARHI 0x09 /* Remote start address reg 1 */ -#define EN0_RCNTLO 0x0a /* Remote byte count reg WR */ -#define EN0_RCNTHI 0x0b /* Remote byte count reg WR */ -#define EN0_RSR 0x0c /* rx status reg RD */ -#define EN0_RXCR 0x0c /* RX configuration reg WR */ -#define EN0_TXCR 0x0d /* TX configuration reg WR */ -#define EN0_COUNTER0 0x0d /* Rcv alignment error counter RD */ -#define EN0_DCFG 0x0e /* Data configuration reg WR */ -#define EN0_COUNTER1 0x0e /* Rcv CRC error counter RD */ -#define EN0_IMR 0x0f /* Interrupt mask reg WR */ -#define EN0_COUNTER2 0x0f /* Rcv missed frame error counter RD */ - -/* Bits in EN0_ISR - Interrupt status register */ -#define ENISR_RX 0x01 /* Receiver, no error */ -#define ENISR_TX 0x02 /* Transmitter, no error */ -#define ENISR_RX_ERR 0x04 /* Receiver, with error */ -#define ENISR_TX_ERR 0x08 /* Transmitter, with error */ -#define ENISR_OVER 0x10 /* Receiver overwrote the ring */ -#define ENISR_COUNTERS 0x20 /* Counters need emptying */ -#define ENISR_RDC 0x40 /* remote dma complete */ -#define ENISR_RESET 0x80 /* Reset completed */ -#define ENISR_ALL 0x3f /* Interrupts we will enable */ - -/* Bits in EN0_DCFG - Data config register */ -#define ENDCFG_WTS 0x01 /* word transfer mode selection */ - -/* Page 1 register offsets. */ -#define EN1_PHYS 0x01 /* This board's physical enet addr RD WR */ -#define EN1_CURPAG 0x07 /* Current memory page RD WR */ -#define EN1_MULT 0x08 /* Multicast filter mask array (8 bytes) RD WR */ - -/* Bits in received packet status byte and EN0_RSR*/ -#define ENRSR_RXOK 0x01 /* Received a good packet */ -#define ENRSR_CRC 0x02 /* CRC error */ -#define ENRSR_FAE 0x04 /* frame alignment error */ -#define ENRSR_FO 0x08 /* FIFO overrun */ -#define ENRSR_MPA 0x10 /* missed pkt */ -#define ENRSR_PHY 0x20 /* physical/multicase address */ -#define ENRSR_DIS 0x40 /* receiver disable. set in monitor mode */ -#define ENRSR_DEF 0x80 /* deferring */ - -/* Transmitted packet status, EN0_TSR. */ -#define ENTSR_PTX 0x01 /* Packet transmitted without error */ -#define ENTSR_ND 0x02 /* The transmit wasn't deferred. */ -#define ENTSR_COL 0x04 /* The transmit collided at least once. */ -#define ENTSR_ABT 0x08 /* The transmit collided 16 times, and was deferred. */ -#define ENTSR_CRS 0x10 /* The carrier sense was lost. */ -#define ENTSR_FU 0x20 /* A "FIFO underrun" occurred during transmit. */ -#define ENTSR_CDH 0x40 /* The collision detect "heartbeat" signal was lost. */ -#define ENTSR_OWC 0x80 /* There was an out-of-window collision. */ - -#endif /* _8390_h */ diff --git a/i386/i386at/gpl/linux/net/Space.c b/i386/i386at/gpl/linux/net/Space.c deleted file mode 100644 index a05507d3..00000000 --- a/i386/i386at/gpl/linux/net/Space.c +++ /dev/null @@ -1,400 +0,0 @@ -/* - * INET An implementation of the TCP/IP protocol suite for the LINUX - * operating system. INET is implemented using the BSD Socket - * interface as the means of communication with the user level. - * - * Holds initial configuration information for devices. - * - * NOTE: This file is a nice idea, but its current format does not work - * well for drivers that support multiple units, like the SLIP - * driver. We should actually have only one pointer to a driver - * here, with the driver knowing how many units it supports. - * Currently, the SLIP driver abuses the "base_addr" integer - * field of the 'device' structure to store the unit number... - * -FvK - * - * Version: @(#)Space.c 1.0.7 08/12/93 - * - * Authors: Ross Biro, <bir7@leland.Stanford.Edu> - * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> - * Donald J. Becker, <becker@super.org> - * - * FIXME: - * Sort the device chain fastest first. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ -#include <linux/config.h> -#include <linux/netdevice.h> -#include <linux/errno.h> - -#define NEXT_DEV NULL - - -/* A unified ethernet device probe. This is the easiest way to have every - ethernet adaptor have the name "eth[0123...]". - */ - -extern int hp100_probe(struct device *dev); -extern int ultra_probe(struct device *dev); -extern int wd_probe(struct device *dev); -extern int el2_probe(struct device *dev); -extern int ne_probe(struct device *dev); -extern int hp_probe(struct device *dev); -extern int hp_plus_probe(struct device *dev); -extern int znet_probe(struct device *); -extern int express_probe(struct device *); -extern int eepro_probe(struct device *); -extern int el3_probe(struct device *); -extern int at1500_probe(struct device *); -extern int at1700_probe(struct device *); -extern int eth16i_probe(struct device *); -extern int depca_probe(struct device *); -extern int apricot_probe(struct device *); -extern int ewrk3_probe(struct device *); -extern int de4x5_probe(struct device *); -extern int el1_probe(struct device *); -#if defined(CONFIG_WAVELAN) -extern int wavelan_probe(struct device *); -#endif /* defined(CONFIG_WAVELAN) */ -extern int el16_probe(struct device *); -extern int elplus_probe(struct device *); -extern int ac3200_probe(struct device *); -extern int e2100_probe(struct device *); -extern int ni52_probe(struct device *); -extern int ni65_probe(struct device *); -extern int SK_init(struct device *); -extern int seeq8005_probe(struct device *); -extern int tc59x_probe(struct device *); - -/* Detachable devices ("pocket adaptors") */ -extern int atp_init(struct device *); -extern int de600_probe(struct device *); -extern int de620_probe(struct device *); - -static int -ethif_probe(struct device *dev) -{ - u_long base_addr = dev->base_addr; - - if ((base_addr == 0xffe0) || (base_addr == 1)) - return 1; /* ENXIO */ - - if (1 -#if defined(CONFIG_VORTEX) - && tc59x_probe(dev) -#endif -#if defined(CONFIG_SEEQ8005) - && seeq8005_probe(dev) -#endif -#if defined(CONFIG_HP100) - && hp100_probe(dev) -#endif -#if defined(CONFIG_ULTRA) - && ultra_probe(dev) -#endif -#if defined(CONFIG_WD80x3) || defined(WD80x3) - - && wd_probe(dev) -#endif -#if defined(CONFIG_EL2) || defined(EL2) /* 3c503 */ - && el2_probe(dev) -#endif -#if defined(CONFIG_HPLAN) || defined(HPLAN) - && hp_probe(dev) -#endif -#if 0 -#if defined(CONFIG_HPLAN_PLUS) - && hp_plus_probe(dev) -#endif -#endif -#ifdef CONFIG_AC3200 /* Ansel Communications EISA 3200. */ - && ac3200_probe(dev) -#endif -#ifdef CONFIG_E2100 /* Cabletron E21xx series. */ - && e2100_probe(dev) -#endif -#if defined(CONFIG_NE2000) || defined(NE2000) - && ne_probe(dev) -#endif -#ifdef CONFIG_AT1500 - && at1500_probe(dev) -#endif -#ifdef CONFIG_AT1700 - && at1700_probe(dev) -#endif -#ifdef CONFIG_ETH16I - && eth16i_probe(dev) /* ICL EtherTeam 16i/32 */ -#endif -#ifdef CONFIG_EL3 /* 3c509 */ - && el3_probe(dev) -#endif -#ifdef CONFIG_ZNET /* Zenith Z-Note and some IBM Thinkpads. */ - && znet_probe(dev) -#endif -#ifdef CONFIG_EEXPRESS /* Intel EtherExpress */ - && express_probe(dev) -#endif -#ifdef CONFIG_EEXPRESS_PRO /* Intel EtherExpress Pro/10 */ - && eepro_probe(dev) -#endif -#ifdef CONFIG_DEPCA /* DEC DEPCA */ - && depca_probe(dev) -#endif -#ifdef CONFIG_EWRK3 /* DEC EtherWORKS 3 */ - && ewrk3_probe(dev) -#endif -#ifdef CONFIG_DE4X5 /* DEC DE425, DE434, DE435 adapters */ - && de4x5_probe(dev) -#endif -#ifdef CONFIG_APRICOT /* Apricot I82596 */ - && apricot_probe(dev) -#endif -#ifdef CONFIG_EL1 /* 3c501 */ - && el1_probe(dev) -#endif -#if defined(CONFIG_WAVELAN) /* WaveLAN */ - && wavelan_probe(dev) -#endif /* defined(CONFIG_WAVELAN) */ -#ifdef CONFIG_EL16 /* 3c507 */ - && el16_probe(dev) -#endif -#ifdef CONFIG_ELPLUS /* 3c505 */ - && elplus_probe(dev) -#endif -#ifdef CONFIG_DE600 /* D-Link DE-600 adapter */ - && de600_probe(dev) -#endif -#ifdef CONFIG_DE620 /* D-Link DE-620 adapter */ - && de620_probe(dev) -#endif -#if defined(CONFIG_SK_G16) - && SK_init(dev) -#endif -#ifdef CONFIG_NI52 - && ni52_probe(dev) -#endif -#ifdef CONFIG_NI65 - && ni65_probe(dev) -#endif - && 1 ) { - return 1; /* -ENODEV or -EAGAIN would be more accurate. */ - } - return 0; -} - - -#ifdef CONFIG_NETROM - extern int nr_init(struct device *); - - static struct device nr3_dev = { "nr3", 0, 0, 0, 0, 0, 0, 0, 0, 0, NEXT_DEV, nr_init, }; - static struct device nr2_dev = { "nr2", 0, 0, 0, 0, 0, 0, 0, 0, 0, &nr3_dev, nr_init, }; - static struct device nr1_dev = { "nr1", 0, 0, 0, 0, 0, 0, 0, 0, 0, &nr2_dev, nr_init, }; - static struct device nr0_dev = { "nr0", 0, 0, 0, 0, 0, 0, 0, 0, 0, &nr1_dev, nr_init, }; - -# undef NEXT_DEV -# define NEXT_DEV (&nr0_dev) -#endif - -/* Run-time ATtachable (Pocket) devices have a different (not "eth#") name. */ -#ifdef CONFIG_ATP /* AT-LAN-TEC (RealTek) pocket adaptor. */ -static struct device atp_dev = { - "atp0", 0, 0, 0, 0, 0, 0, 0, 0, 0, NEXT_DEV, atp_init, /* ... */ }; -# undef NEXT_DEV -# define NEXT_DEV (&atp_dev) -#endif - -#ifdef CONFIG_ARCNET - extern int arcnet_probe(struct device *dev); - static struct device arcnet_dev = { - "arc0", 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NEXT_DEV, arcnet_probe, }; -# undef NEXT_DEV -# define NEXT_DEV (&arcnet_dev) -#endif - -/* In Mach, by default allow at least 2 interfaces. */ -#ifdef MACH -#ifndef ETH1_ADDR -# define ETH1_ADDR 0 -#endif -#ifndef ETH1_IRQ -# define ETH1_IRQ 0 -#endif -#endif - -/* The first device defaults to I/O base '0', which means autoprobe. */ -#ifndef ETH0_ADDR -# define ETH0_ADDR 0 -#endif -#ifndef ETH0_IRQ -# define ETH0_IRQ 0 -#endif -/* "eth0" defaults to autoprobe (== 0), other use a base of 0xffe0 (== -0x20), - which means "don't probe". These entries exist to only to provide empty - slots which may be enabled at boot-time. */ - -static struct device eth3_dev = { - "eth3", 0,0,0,0,0xffe0 /* I/O base*/, 0,0,0,0, NEXT_DEV, ethif_probe }; -static struct device eth2_dev = { - "eth2", 0,0,0,0,0xffe0 /* I/O base*/, 0,0,0,0, ð3_dev, ethif_probe }; -#ifdef MACH -static struct device eth1_dev = { - "eth1", 0,0,0,0,ETH1_ADDR, ETH1_IRQ,0,0,0, ð2_dev, ethif_probe }; -#else -static struct device eth1_dev = { - "eth1", 0,0,0,0,0xffe0 /* I/O base*/, 0,0,0,0, ð2_dev, ethif_probe }; -#endif -static struct device eth0_dev = { - "eth0", 0, 0, 0, 0, ETH0_ADDR, ETH0_IRQ, 0, 0, 0, ð1_dev, ethif_probe }; - -# undef NEXT_DEV -# define NEXT_DEV (ð0_dev) - -#if defined(PLIP) || defined(CONFIG_PLIP) - extern int plip_init(struct device *); - static struct device plip2_dev = { - "plip2", 0, 0, 0, 0, 0x278, 2, 0, 0, 0, NEXT_DEV, plip_init, }; - static struct device plip1_dev = { - "plip1", 0, 0, 0, 0, 0x378, 7, 0, 0, 0, &plip2_dev, plip_init, }; - static struct device plip0_dev = { - "plip0", 0, 0, 0, 0, 0x3BC, 5, 0, 0, 0, &plip1_dev, plip_init, }; -# undef NEXT_DEV -# define NEXT_DEV (&plip0_dev) -#endif /* PLIP */ - -#if defined(SLIP) || defined(CONFIG_SLIP) - /* To be exact, this node just hooks the initialization - routines to the device structures. */ -extern int slip_init_ctrl_dev(struct device *); -static struct device slip_bootstrap = { - "slip_proto", 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NEXT_DEV, slip_init_ctrl_dev, }; -#undef NEXT_DEV -#define NEXT_DEV (&slip_bootstrap) -#endif /* SLIP */ - -#if defined(CONFIG_PPP) -extern int ppp_init(struct device *); -static struct device ppp_bootstrap = { - "ppp_proto", 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NEXT_DEV, ppp_init, }; -#undef NEXT_DEV -#define NEXT_DEV (&ppp_bootstrap) -#endif /* PPP */ - -#ifdef CONFIG_DUMMY - extern int dummy_init(struct device *dev); - static struct device dummy_dev = { - "dummy", 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NEXT_DEV, dummy_init, }; -# undef NEXT_DEV -# define NEXT_DEV (&dummy_dev) -#endif - -#ifdef CONFIG_EQUALIZER -extern int eql_init(struct device *dev); -struct device eql_dev = { - "eql", /* Master device for IP traffic load - balancing */ - 0x0, 0x0, 0x0, 0x0, /* recv end/start; mem end/start */ - 0, /* base I/O address */ - 0, /* IRQ */ - 0, 0, 0, /* flags */ - NEXT_DEV, /* next device */ - eql_init /* set up the rest */ -}; -# undef NEXT_DEV -# define NEXT_DEV (&eql_dev) -#endif - -#ifdef CONFIG_IBMTR - - extern int tok_probe(struct device *dev); - static struct device ibmtr_dev1 = { - "tr1", /* IBM Token Ring (Non-DMA) Interface */ - 0x0, /* recv memory end */ - 0x0, /* recv memory start */ - 0x0, /* memory end */ - 0x0, /* memory start */ - 0xa24, /* base I/O address */ - 0, /* IRQ */ - 0, 0, 0, /* flags */ - NEXT_DEV, /* next device */ - tok_probe /* ??? Token_init should set up the rest */ - }; -# undef NEXT_DEV -# define NEXT_DEV (&ibmtr_dev1) - - - static struct device ibmtr_dev0 = { - "tr0", /* IBM Token Ring (Non-DMA) Interface */ - 0x0, /* recv memory end */ - 0x0, /* recv memory start */ - 0x0, /* memory end */ - 0x0, /* memory start */ - 0xa20, /* base I/O address */ - 0, /* IRQ */ - 0, 0, 0, /* flags */ - NEXT_DEV, /* next device */ - tok_probe /* ??? Token_init should set up the rest */ - }; -# undef NEXT_DEV -# define NEXT_DEV (&ibmtr_dev0) - -#endif -#ifdef CONFIG_NET_IPIP -#ifdef CONFIG_IP_FORWARD - extern int tunnel_init(struct device *); - - static struct device tunnel_dev1 = - { - "tunl1", /* IPIP tunnel */ - 0x0, /* recv memory end */ - 0x0, /* recv memory start */ - 0x0, /* memory end */ - 0x0, /* memory start */ - 0x0, /* base I/O address */ - 0, /* IRQ */ - 0, 0, 0, /* flags */ - NEXT_DEV, /* next device */ - tunnel_init /* Fill in the details */ - }; - - static struct device tunnel_dev0 = - { - "tunl0", /* IPIP tunnel */ - 0x0, /* recv memory end */ - 0x0, /* recv memory start */ - 0x0, /* memory end */ - 0x0, /* memory start */ - 0x0, /* base I/O address */ - 0, /* IRQ */ - 0, 0, 0, /* flags */ - &tunnel_dev1, /* next device */ - tunnel_init /* Fill in the details */ - }; -# undef NEXT_DEV -# define NEXT_DEV (&tunnel_dev0) - -#endif -#endif - -#ifdef MACH -struct device *dev_base = ð0_dev; -#else -extern int loopback_init(struct device *dev); -struct device loopback_dev = { - "lo", /* Software Loopback interface */ - 0x0, /* recv memory end */ - 0x0, /* recv memory start */ - 0x0, /* memory end */ - 0x0, /* memory start */ - 0, /* base I/O address */ - 0, /* IRQ */ - 0, 0, 0, /* flags */ - NEXT_DEV, /* next device */ - loopback_init /* loopback_init should set up the rest */ -}; - -struct device *dev_base = &loopback_dev; -#endif diff --git a/i386/i386at/gpl/linux/net/ac3200.c b/i386/i386at/gpl/linux/net/ac3200.c deleted file mode 100644 index 054af13a..00000000 --- a/i386/i386at/gpl/linux/net/ac3200.c +++ /dev/null @@ -1,385 +0,0 @@ -/* ac3200.c: A driver for the Ansel Communications EISA ethernet adaptor. */ -/* - Written 1993, 1994 by Donald Becker. - Copyright 1993 United States Government as represented by the Director, - National Security Agency. This software may only be used and distributed - according to the terms of the GNU Public License as modified by SRC, - incorporated herein by reference. - - The author may be reached as becker@cesdis.gsfc.nasa.gov, or - C/O Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771 - - This is driver for the Ansel Communications Model 3200 EISA Ethernet LAN - Adapter. The programming information is from the users manual, as related - by glee@ardnassak.math.clemson.edu. - */ - -static const char *version = - "ac3200.c:v1.01 7/1/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n"; - -#include <linux/module.h> - -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/errno.h> -#include <linux/string.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> - -#include <asm/system.h> -#include <asm/io.h> - -#include "8390.h" - -/* Offsets from the base address. */ -#define AC_NIC_BASE 0x00 -#define AC_SA_PROM 0x16 /* The station address PROM. */ -#define AC_ADDR0 0x00 /* Prefix station address values. */ -#define AC_ADDR1 0x40 /* !!!!These are just guesses!!!! */ -#define AC_ADDR2 0x90 -#define AC_ID_PORT 0xC80 -#define AC_EISA_ID 0x0110d305 -#define AC_RESET_PORT 0xC84 -#define AC_RESET 0x00 -#define AC_ENABLE 0x01 -#define AC_CONFIG 0xC90 /* The configuration port. */ - -#define AC_IO_EXTENT 0x10 /* IS THIS REALLY TRUE ??? */ - /* Actually accessed is: - * AC_NIC_BASE (0-15) - * AC_SA_PROM (0-5) - * AC_ID_PORT (0-3) - * AC_RESET_PORT - * AC_CONFIG - */ - -/* Decoding of the configuration register. */ -static unsigned char config2irqmap[8] = {15, 12, 11, 10, 9, 7, 5, 3}; -static int addrmap[8] = -{0xFF0000, 0xFE0000, 0xFD0000, 0xFFF0000, 0xFFE0000, 0xFFC0000, 0xD0000, 0 }; -static const char *port_name[4] = { "10baseT", "invalid", "AUI", "10base2"}; - -#define config2irq(configval) config2irqmap[((configval) >> 3) & 7] -#define config2mem(configval) addrmap[(configval) & 7] -#define config2name(configval) port_name[((configval) >> 6) & 3] - -/* First and last 8390 pages. */ -#define AC_START_PG 0x00 /* First page of 8390 TX buffer */ -#define AC_STOP_PG 0x80 /* Last page +1 of the 8390 RX ring */ - -int ac3200_probe(struct device *dev); -static int ac_probe1(int ioaddr, struct device *dev); - -static int ac_open(struct device *dev); -static void ac_reset_8390(struct device *dev); -static void ac_block_input(struct device *dev, int count, - struct sk_buff *skb, int ring_offset); -static void ac_block_output(struct device *dev, const int count, - const unsigned char *buf, const int start_page); -static void ac_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, - int ring_page); - -static int ac_close_card(struct device *dev); - - -/* Probe for the AC3200. - - The AC3200 can be identified by either the EISA configuration registers, - or the unique value in the station address PROM. - */ - -int ac3200_probe(struct device *dev) -{ - unsigned short ioaddr = dev->base_addr; - - if (ioaddr > 0x1ff) /* Check a single specified location. */ - return ac_probe1(ioaddr, dev); - else if (ioaddr > 0) /* Don't probe at all. */ - return ENXIO; - - /* If you have a pre 0.99pl15 machine you should delete this line. */ - if ( ! EISA_bus) - return ENXIO; - - for (ioaddr = 0x1000; ioaddr < 0x9000; ioaddr += 0x1000) { - if (check_region(ioaddr, AC_IO_EXTENT)) - continue; - if (ac_probe1(ioaddr, dev) == 0) - return 0; - } - - return ENODEV; -} - -static int ac_probe1(int ioaddr, struct device *dev) -{ - int i; - -#ifndef final_version - printk("AC3200 ethercard probe at %#3x:", ioaddr); - - for(i = 0; i < 6; i++) - printk(" %02x", inb(ioaddr + AC_SA_PROM + i)); -#endif - - /* !!!!The values of AC_ADDRn (see above) should be corrected when we - find out the correct station address prefix!!!! */ - if (inb(ioaddr + AC_SA_PROM + 0) != AC_ADDR0 - || inb(ioaddr + AC_SA_PROM + 1) != AC_ADDR1 - || inb(ioaddr + AC_SA_PROM + 2) != AC_ADDR2 ) { -#ifndef final_version - printk(" not found (invalid prefix).\n"); -#endif - return ENODEV; - } - - /* The correct probe method is to check the EISA ID. */ - for (i = 0; i < 4; i++) - if (inl(ioaddr + AC_ID_PORT) != AC_EISA_ID) { - printk("EISA ID mismatch, %8x vs %8x.\n", - inl(ioaddr + AC_EISA_ID), AC_EISA_ID); - return ENODEV; - } - - - /* We should have a "dev" from Space.c or the static module table. */ - if (dev == NULL) { - printk("ac3200.c: Passed a NULL device.\n"); - dev = init_etherdev(0, 0); - } - - for(i = 0; i < ETHER_ADDR_LEN; i++) - dev->dev_addr[i] = inb(ioaddr + AC_SA_PROM + i); - -#ifndef final_version - printk("\nAC3200 ethercard configuration register is %#02x," - " EISA ID %02x %02x %02x %02x.\n", inb(ioaddr + AC_CONFIG), - inb(ioaddr + AC_ID_PORT + 0), inb(ioaddr + AC_ID_PORT + 1), - inb(ioaddr + AC_ID_PORT + 2), inb(ioaddr + AC_ID_PORT + 3)); -#endif - - /* Assign and allocate the interrupt now. */ - if (dev->irq == 0) - dev->irq = config2irq(inb(ioaddr + AC_CONFIG)); - else if (dev->irq == 2) - dev->irq = 9; - - if (request_irq(dev->irq, ei_interrupt, 0, "ac3200")) { - printk (" unable to get IRQ %d.\n", dev->irq); - return EAGAIN; - } - - /* Allocate dev->priv and fill in 8390 specific dev fields. */ - if (ethdev_init(dev)) { - printk (" unable to allocate memory for dev->priv.\n"); - free_irq(dev->irq); - return -ENOMEM; - } - - request_region(ioaddr, AC_IO_EXTENT, "ac3200"); - - dev->base_addr = ioaddr; - -#ifdef notyet - if (dev->mem_start) { /* Override the value from the board. */ - for (i = 0; i < 7; i++) - if (addrmap[i] == dev->mem_start) - break; - if (i >= 7) - i = 0; - outb((inb(ioaddr + AC_CONFIG) & ~7) | i, ioaddr + AC_CONFIG); - } -#endif - - dev->if_port = inb(ioaddr + AC_CONFIG) >> 6; - dev->mem_start = config2mem(inb(ioaddr + AC_CONFIG)); - dev->rmem_start = dev->mem_start + TX_PAGES*256; - dev->mem_end = dev->rmem_end = dev->mem_start - + (AC_STOP_PG - AC_START_PG)*256; - - ei_status.name = "AC3200"; - ei_status.tx_start_page = AC_START_PG; - ei_status.rx_start_page = AC_START_PG + TX_PAGES; - ei_status.stop_page = AC_STOP_PG; - ei_status.word16 = 1; - - printk("\n%s: AC3200 at %#x, IRQ %d, %s port, shared memory %#lx-%#lx.\n", - dev->name, ioaddr, dev->irq, port_name[dev->if_port], - dev->mem_start, dev->mem_end-1); - - if (ei_debug > 0) - printk(version); - - ei_status.reset_8390 = &ac_reset_8390; - ei_status.block_input = &ac_block_input; - ei_status.block_output = &ac_block_output; - ei_status.get_8390_hdr = &ac_get_8390_hdr; - - dev->open = &ac_open; - dev->stop = &ac_close_card; - NS8390_init(dev, 0); - return 0; -} - -static int ac_open(struct device *dev) -{ -#ifdef notyet - /* Someday we may enable the IRQ and shared memory here. */ - int ioaddr = dev->base_addr; - - if (request_irq(dev->irq, ei_interrupt, 0, "ac3200")) - return -EAGAIN; -#endif - - ei_open(dev); - - MOD_INC_USE_COUNT; - - return 0; -} - -static void ac_reset_8390(struct device *dev) -{ - ushort ioaddr = dev->base_addr; - - outb(AC_RESET, ioaddr + AC_RESET_PORT); - if (ei_debug > 1) printk("resetting AC3200, t=%ld...", jiffies); - - ei_status.txing = 0; - outb(AC_ENABLE, ioaddr + AC_RESET_PORT); - if (ei_debug > 1) printk("reset done\n"); - - return; -} - -/* Grab the 8390 specific header. Similar to the block_input routine, but - we don't need to be concerned with ring wrap as the header will be at - the start of a page, so we optimize accordingly. */ - -static void -ac_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page) -{ - unsigned long hdr_start = dev->mem_start + ((ring_page - AC_START_PG)<<8); - memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr)); -} - -/* Block input and output are easy on shared memory ethercards, the only - complication is when the ring buffer wraps. */ - -static void ac_block_input(struct device *dev, int count, struct sk_buff *skb, - int ring_offset) -{ - unsigned long xfer_start = dev->mem_start + ring_offset - (AC_START_PG<<8); - - if (xfer_start + count > dev->rmem_end) { - /* We must wrap the input move. */ - int semi_count = dev->rmem_end - xfer_start; - memcpy_fromio(skb->data, xfer_start, semi_count); - count -= semi_count; - memcpy_fromio(skb->data + semi_count, dev->rmem_start, count); - } else { - /* Packet is in one chunk -- we can copy + cksum. */ - eth_io_copy_and_sum(skb, xfer_start, count, 0); - } -} - -static void ac_block_output(struct device *dev, int count, - const unsigned char *buf, int start_page) -{ - unsigned long shmem = dev->mem_start + ((start_page - AC_START_PG)<<8); - - memcpy_toio(shmem, buf, count); -} - -static int ac_close_card(struct device *dev) -{ - dev->start = 0; - dev->tbusy = 1; - - if (ei_debug > 1) - printk("%s: Shutting down ethercard.\n", dev->name); - -#ifdef notyet - /* We should someday disable shared memory and interrupts. */ - outb(0x00, ioaddr + 6); /* Disable interrupts. */ - free_irq(dev->irq); - irq2dev_map[dev->irq] = 0; -#endif - - ei_close(dev); - - MOD_DEC_USE_COUNT; - - return 0; -} - -#ifdef MODULE -#define MAX_AC32_CARDS 4 /* Max number of AC32 cards per module */ -#define NAMELEN 8 /* # of chars for storing dev->name */ -static char namelist[NAMELEN * MAX_AC32_CARDS] = { 0, }; -static struct device dev_ac32[MAX_AC32_CARDS] = { - { - NULL, /* assign a chunk of namelist[] below */ - 0, 0, 0, 0, - 0, 0, - 0, 0, 0, NULL, NULL - }, -}; - -static int io[MAX_AC32_CARDS] = { 0, }; -static int irq[MAX_AC32_CARDS] = { 0, }; -static int mem[MAX_AC32_CARDS] = { 0, }; - -int -init_module(void) -{ - int this_dev, found = 0; - - for (this_dev = 0; this_dev < MAX_AC32_CARDS; this_dev++) { - struct device *dev = &dev_ac32[this_dev]; - dev->name = namelist+(NAMELEN*this_dev); - dev->irq = irq[this_dev]; - dev->base_addr = io[this_dev]; - dev->mem_start = mem[this_dev]; /* Currently ignored by driver */ - dev->init = ac3200_probe; - /* Default is to only install one card. */ - if (io[this_dev] == 0 && this_dev != 0) break; - if (register_netdev(dev) != 0) { - printk(KERN_WARNING "ac3200.c: No ac3200 card found (i/o = 0x%x).\n", io[this_dev]); - if (found != 0) return 0; /* Got at least one. */ - return -ENXIO; - } - found++; - } - - return 0; -} - -void -cleanup_module(void) -{ - int this_dev; - - for (this_dev = 0; this_dev < MAX_AC32_CARDS; this_dev++) { - struct device *dev = &dev_ac32[this_dev]; - if (dev->priv != NULL) { - kfree(dev->priv); - dev->priv = NULL; - /* Someday free_irq + irq2dev may be in ac_close_card() */ - free_irq(dev->irq); - irq2dev_map[dev->irq] = NULL; - release_region(dev->base_addr, AC_IO_EXTENT); - unregister_netdev(dev); - } - } -} -#endif /* MODULE */ - -/* - * Local variables: - * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c ac3200.c" - * version-control: t - * kept-new-versions: 5 - * tab-width: 4 - * End: - */ diff --git a/i386/i386at/gpl/linux/net/apricot.c b/i386/i386at/gpl/linux/net/apricot.c deleted file mode 100644 index 130d7759..00000000 --- a/i386/i386at/gpl/linux/net/apricot.c +++ /dev/null @@ -1,1046 +0,0 @@ -/* apricot.c: An Apricot 82596 ethernet driver for linux. */ -/* - Apricot - Written 1994 by Mark Evans. - This driver is for the Apricot 82596 bus-master interface - - Modularised 12/94 Mark Evans - - Driver skeleton - Written 1993 by Donald Becker. - Copyright 1993 United States Government as represented by the Director, - National Security Agency. This software may only be used and distributed - according to the terms of the GNU Public License as modified by SRC, - incorporated herein by reference. - - The author may be reached as becker@super.org or - C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715 - - -*/ - -static const char *version = "apricot.c:v0.2 05/12/94\n"; - -#include <linux/module.h> - -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/string.h> -#include <linux/ptrace.h> -#include <linux/errno.h> -#include <linux/ioport.h> -#include <linux/malloc.h> -#include <linux/interrupt.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> - -#include <asm/bitops.h> -#include <asm/io.h> -#include <asm/dma.h> - -#ifndef HAVE_PORTRESERVE -#define check_region(addr, size) 0 -#define request_region(addr, size,name) do ; while(0) -#endif - -#ifndef HAVE_ALLOC_SKB -#define alloc_skb(size, priority) (struct sk_buff *) kmalloc(size,priority) -#define kfree_skbmem(buff, size) kfree_s(buff,size) -#endif - -#define APRICOT_DEBUG 1 - -#ifdef APRICOT_DEBUG -int i596_debug = APRICOT_DEBUG; -#else -int i596_debug = 1; -#endif - -#define APRICOT_TOTAL_SIZE 17 - -#define I596_NULL -1 - -#define CMD_EOL 0x8000 /* The last command of the list, stop. */ -#define CMD_SUSP 0x4000 /* Suspend after doing cmd. */ -#define CMD_INTR 0x2000 /* Interrupt after doing cmd. */ - -#define CMD_FLEX 0x0008 /* Enable flexible memory model */ - -enum commands { - CmdNOp = 0, CmdSASetup = 1, CmdConfigure = 2, CmdMulticastList = 3, - CmdTx = 4, CmdTDR = 5, CmdDump = 6, CmdDiagnose = 7}; - -#define STAT_C 0x8000 /* Set to 0 after execution */ -#define STAT_B 0x4000 /* Command being executed */ -#define STAT_OK 0x2000 /* Command executed ok */ -#define STAT_A 0x1000 /* Command aborted */ - -#define CUC_START 0x0100 -#define CUC_RESUME 0x0200 -#define CUC_SUSPEND 0x0300 -#define CUC_ABORT 0x0400 -#define RX_START 0x0010 -#define RX_RESUME 0x0020 -#define RX_SUSPEND 0x0030 -#define RX_ABORT 0x0040 - -struct i596_cmd { - unsigned short status; - unsigned short command; - struct i596_cmd *next; -}; - -#define EOF 0x8000 -#define SIZE_MASK 0x3fff - -struct i596_tbd { - unsigned short size; - unsigned short pad; - struct i596_tbd *next; - char *data; -}; - -struct tx_cmd { - struct i596_cmd cmd; - struct i596_tbd *tbd; - unsigned short size; - unsigned short pad; -}; - -struct i596_rfd { - unsigned short stat; - unsigned short cmd; - struct i596_rfd *next; - long rbd; - unsigned short count; - unsigned short size; - char data[1532]; -}; - -#define RX_RING_SIZE 8 - -struct i596_scb { - unsigned short status; - unsigned short command; - struct i596_cmd *cmd; - struct i596_rfd *rfd; - unsigned long crc_err; - unsigned long align_err; - unsigned long resource_err; - unsigned long over_err; - unsigned long rcvdt_err; - unsigned long short_err; - unsigned short t_on; - unsigned short t_off; -}; - -struct i596_iscp { - unsigned long stat; - struct i596_scb *scb; -}; - -struct i596_scp { - unsigned long sysbus; - unsigned long pad; - struct i596_iscp *iscp; -}; - -struct i596_private { - struct i596_scp scp; - struct i596_iscp iscp; - struct i596_scb scb; - struct i596_cmd set_add; - char eth_addr[8]; - struct i596_cmd set_conf; - char i596_config[16]; - struct i596_cmd tdr; - unsigned long stat; - int last_restart; - struct i596_rfd *rx_tail; - struct i596_cmd *cmd_tail; - struct i596_cmd *cmd_head; - int cmd_backlog; - unsigned long last_cmd; - struct enet_statistics stats; -}; - -char init_setup[] = { - 0x8E, /* length, prefetch on */ - 0xC8, /* fifo to 8, monitor off */ - 0x80, /* don't save bad frames */ - 0x2E, /* No source address insertion, 8 byte preamble */ - 0x00, /* priority and backoff defaults */ - 0x60, /* interframe spacing */ - 0x00, /* slot time LSB */ - 0xf2, /* slot time and retries */ - 0x00, /* promiscuous mode */ - 0x00, /* collision detect */ - 0x40, /* minimum frame length */ - 0xff, - 0x00, - 0x7f /* *multi IA */ }; - -static int i596_open(struct device *dev); -static int i596_start_xmit(struct sk_buff *skb, struct device *dev); -static void i596_interrupt(int irq, struct pt_regs *regs); -static int i596_close(struct device *dev); -static struct enet_statistics *i596_get_stats(struct device *dev); -static void i596_add_cmd(struct device *dev, struct i596_cmd *cmd); -static void print_eth(char *); -static void set_multicast_list(struct device *dev); - - -static inline int -init_rx_bufs(struct device *dev, int num) -{ - struct i596_private *lp = (struct i596_private *)dev->priv; - int i; - struct i596_rfd *rfd; - - lp->scb.rfd = (struct i596_rfd *)I596_NULL; - - if (i596_debug > 1) printk ("%s: init_rx_bufs %d.\n", dev->name, num); - - for (i = 0; i < num; i++) - { - if (!(rfd = (struct i596_rfd *)kmalloc(sizeof(struct i596_rfd), GFP_KERNEL))) - break; - - rfd->stat = 0x0000; - rfd->rbd = I596_NULL; - rfd->count = 0; - rfd->size = 1532; - if (i == 0) - { - rfd->cmd = CMD_EOL; - lp->rx_tail = rfd; - } - else - rfd->cmd = 0x0000; - - rfd->next = lp->scb.rfd; - lp->scb.rfd = rfd; - } - - if (i != 0) - lp->rx_tail->next = lp->scb.rfd; - - return (i); -} - -static inline void -remove_rx_bufs(struct device *dev) -{ - struct i596_private *lp = (struct i596_private *)dev->priv; - struct i596_rfd *rfd = lp->scb.rfd; - - lp->rx_tail->next = (struct i596_rfd *)I596_NULL; - - do - { - lp->scb.rfd = rfd->next; - kfree_s(rfd, sizeof(struct i596_rfd)); - rfd = lp->scb.rfd; - } - while (rfd != lp->rx_tail); -} - -static inline void -init_i596_mem(struct device *dev) -{ - struct i596_private *lp = (struct i596_private *)dev->priv; - short ioaddr = dev->base_addr; - int boguscnt = 100; - - /* change the scp address */ - outw(0, ioaddr); - outw(0, ioaddr); - outb(4, ioaddr+0xf); - outw(((((int)&lp->scp) & 0xffff) | 2), ioaddr); - outw((((int)&lp->scp)>>16) & 0xffff, ioaddr); - - lp->last_cmd = jiffies; - - lp->scp.sysbus = 0x00440000; - lp->scp.iscp = &(lp->iscp); - lp->iscp.scb = &(lp->scb); - lp->iscp.stat = 0x0001; - lp->cmd_backlog = 0; - - lp->cmd_head = lp->scb.cmd = (struct i596_cmd *) I596_NULL; - - if (i596_debug > 2) printk("%s: starting i82596.\n", dev->name); - - (void) inb (ioaddr+0x10); - outb(4, ioaddr+0xf); - outw(0, ioaddr+4); - - while (lp->iscp.stat) - if (--boguscnt == 0) - { - printk("%s: i82596 initialization timed out with status %4.4x, cmd %4.4x.\n", - dev->name, lp->scb.status, lp->scb.command); - break; - } - - lp->scb.command = 0; - - memcpy (lp->i596_config, init_setup, 14); - lp->set_conf.command = CmdConfigure; - i596_add_cmd(dev, &lp->set_conf); - - memcpy (lp->eth_addr, dev->dev_addr, 6); - lp->set_add.command = CmdSASetup; - i596_add_cmd(dev, &lp->set_add); - - lp->tdr.command = CmdTDR; - i596_add_cmd(dev, &lp->tdr); - - boguscnt = 200; - while (lp->scb.status, lp->scb.command) - if (--boguscnt == 0) - { - printk("%s: receive unit start timed out with status %4.4x, cmd %4.4x.\n", - dev->name, lp->scb.status, lp->scb.command); - break; - } - - lp->scb.command = RX_START; - outw(0, ioaddr+4); - - boguscnt = 200; - while (lp->scb.status, lp->scb.command) - if (--boguscnt == 0) - { - printk("i82596 init timed out with status %4.4x, cmd %4.4x.\n", - lp->scb.status, lp->scb.command); - break; - } - - return; -} - -static inline int -i596_rx(struct device *dev) -{ - struct i596_private *lp = (struct i596_private *)dev->priv; - int frames = 0; - - if (i596_debug > 3) printk ("i596_rx()\n"); - - while ((lp->scb.rfd->stat) & STAT_C) - { - if (i596_debug >2) print_eth(lp->scb.rfd->data); - - if ((lp->scb.rfd->stat) & STAT_OK) - { - /* a good frame */ - int pkt_len = lp->scb.rfd->count & 0x3fff; - struct sk_buff *skb = dev_alloc_skb(pkt_len); - - frames++; - - if (skb == NULL) - { - printk ("%s: i596_rx Memory squeeze, dropping packet.\n", dev->name); - lp->stats.rx_dropped++; - break; - } - - skb->dev = dev; - memcpy(skb_put(skb,pkt_len), lp->scb.rfd->data, pkt_len); - - skb->protocol=eth_type_trans(skb,dev); - netif_rx(skb); - lp->stats.rx_packets++; - - if (i596_debug > 4) print_eth(skb->data); - } - else - { - lp->stats.rx_errors++; - if ((lp->scb.rfd->stat) & 0x0001) lp->stats.collisions++; - if ((lp->scb.rfd->stat) & 0x0080) lp->stats.rx_length_errors++; - if ((lp->scb.rfd->stat) & 0x0100) lp->stats.rx_over_errors++; - if ((lp->scb.rfd->stat) & 0x0200) lp->stats.rx_fifo_errors++; - if ((lp->scb.rfd->stat) & 0x0400) lp->stats.rx_frame_errors++; - if ((lp->scb.rfd->stat) & 0x0800) lp->stats.rx_crc_errors++; - if ((lp->scb.rfd->stat) & 0x1000) lp->stats.rx_length_errors++; - } - - lp->scb.rfd->stat = 0; - lp->rx_tail->cmd = 0; - lp->rx_tail = lp->scb.rfd; - lp->scb.rfd = lp->scb.rfd->next; - lp->rx_tail->count = 0; - lp->rx_tail->cmd = CMD_EOL; - - } - - if (i596_debug > 3) printk ("frames %d\n", frames); - - return 0; -} - -static inline void -i596_cleanup_cmd(struct i596_private *lp) -{ - struct i596_cmd *ptr; - int boguscnt = 100; - - if (i596_debug > 4) printk ("i596_cleanup_cmd\n"); - - while (lp->cmd_head != (struct i596_cmd *) I596_NULL) - { - ptr = lp->cmd_head; - - lp->cmd_head = lp->cmd_head->next; - lp->cmd_backlog--; - - switch ((ptr->command) & 0x7) - { - case CmdTx: - { - struct tx_cmd *tx_cmd = (struct tx_cmd *) ptr; - struct sk_buff *skb = ((struct sk_buff *)(tx_cmd->tbd->data)) -1; - - dev_kfree_skb(skb, FREE_WRITE); - - lp->stats.tx_errors++; - lp->stats.tx_aborted_errors++; - - ptr->next = (struct i596_cmd * ) I596_NULL; - kfree_s((unsigned char *)tx_cmd, (sizeof (struct tx_cmd) + sizeof (struct i596_tbd))); - break; - } - case CmdMulticastList: - { - unsigned short count = *((unsigned short *) (ptr + 1)); - - ptr->next = (struct i596_cmd * ) I596_NULL; - kfree_s((unsigned char *)ptr, (sizeof (struct i596_cmd) + count + 2)); - break; - } - default: - ptr->next = (struct i596_cmd * ) I596_NULL; - } - } - - while (lp->scb.status, lp->scb.command) - if (--boguscnt == 0) - { - printk("i596_cleanup_cmd timed out with status %4.4x, cmd %4.4x.\n", - lp->scb.status, lp->scb.command); - break; - } - - lp->scb.cmd = lp->cmd_head; -} - -static inline void -i596_reset(struct device *dev, struct i596_private *lp, int ioaddr) -{ - int boguscnt = 100; - - if (i596_debug > 4) printk ("i596_reset\n"); - - while (lp->scb.status, lp->scb.command) - if (--boguscnt == 0) - { - printk("i596_reset timed out with status %4.4x, cmd %4.4x.\n", - lp->scb.status, lp->scb.command); - break; - } - - dev->start = 0; - dev->tbusy = 1; - - lp->scb.command = CUC_ABORT|RX_ABORT; - outw(0, ioaddr+4); - - /* wait for shutdown */ - boguscnt = 400; - - while ((lp->scb.status, lp->scb.command) || lp->scb.command) - if (--boguscnt == 0) - { - printk("i596_reset 2 timed out with status %4.4x, cmd %4.4x.\n", - lp->scb.status, lp->scb.command); - break; - } - - i596_cleanup_cmd(lp); - i596_rx(dev); - - dev->start = 1; - dev->tbusy = 0; - dev->interrupt = 0; - init_i596_mem(dev); -} - -static void i596_add_cmd(struct device *dev, struct i596_cmd *cmd) -{ - struct i596_private *lp = (struct i596_private *)dev->priv; - int ioaddr = dev->base_addr; - unsigned long flags; - int boguscnt = 100; - - if (i596_debug > 4) printk ("i596_add_cmd\n"); - - cmd->status = 0; - cmd->command |= (CMD_EOL|CMD_INTR); - cmd->next = (struct i596_cmd *) I596_NULL; - - save_flags(flags); - cli(); - if (lp->cmd_head != (struct i596_cmd *) I596_NULL) - lp->cmd_tail->next = cmd; - else - { - lp->cmd_head = cmd; - while (lp->scb.status, lp->scb.command) - if (--boguscnt == 0) - { - printk("i596_add_cmd timed out with status %4.4x, cmd %4.4x.\n", - lp->scb.status, lp->scb.command); - break; - } - - lp->scb.cmd = cmd; - lp->scb.command = CUC_START; - outw (0, ioaddr+4); - } - lp->cmd_tail = cmd; - lp->cmd_backlog++; - - lp->cmd_head = lp->scb.cmd; - restore_flags(flags); - - if (lp->cmd_backlog > 16) - { - int tickssofar = jiffies - lp->last_cmd; - - if (tickssofar < 25) return; - - printk("%s: command unit timed out, status resetting.\n", dev->name); - - i596_reset(dev, lp, ioaddr); - } -} - -static int -i596_open(struct device *dev) -{ - int i; - - if (i596_debug > 1) - printk("%s: i596_open() irq %d.\n", dev->name, dev->irq); - - if (request_irq(dev->irq, &i596_interrupt, 0, "apricot")) - return -EAGAIN; - - irq2dev_map[dev->irq] = dev; - - i = init_rx_bufs(dev, RX_RING_SIZE); - - if ((i = init_rx_bufs(dev, RX_RING_SIZE)) < RX_RING_SIZE) - printk("%s: only able to allocate %d receive buffers\n", dev->name, i); - - if (i < 4) - { - free_irq(dev->irq); - irq2dev_map[dev->irq] = 0; - return -EAGAIN; - } - - dev->tbusy = 0; - dev->interrupt = 0; - dev->start = 1; - MOD_INC_USE_COUNT; - - /* Initialize the 82596 memory */ - init_i596_mem(dev); - - return 0; /* Always succeed */ -} - -static int -i596_start_xmit(struct sk_buff *skb, struct device *dev) -{ - struct i596_private *lp = (struct i596_private *)dev->priv; - int ioaddr = dev->base_addr; - struct tx_cmd *tx_cmd; - - if (i596_debug > 2) printk ("%s: Apricot start xmit\n", dev->name); - - /* Transmitter timeout, serious problems. */ - if (dev->tbusy) { - int tickssofar = jiffies - dev->trans_start; - if (tickssofar < 5) - return 1; - printk("%s: transmit timed out, status resetting.\n", - dev->name); - lp->stats.tx_errors++; - /* Try to restart the adaptor */ - if (lp->last_restart == lp->stats.tx_packets) { - if (i596_debug > 1) printk ("Resetting board.\n"); - - /* Shutdown and restart */ - i596_reset(dev,lp, ioaddr); - } else { - /* Issue a channel attention signal */ - if (i596_debug > 1) printk ("Kicking board.\n"); - - lp->scb.command = CUC_START|RX_START; - outw(0, ioaddr+4); - - lp->last_restart = lp->stats.tx_packets; - } - dev->tbusy = 0; - dev->trans_start = jiffies; - } - - /* If some higher level thinks we've misses a tx-done interrupt - we are passed NULL. n.b. dev_tint handles the cli()/sti() - itself. */ - if (skb == NULL) { - dev_tint(dev); - return 0; - } - - /* shouldn't happen */ - if (skb->len <= 0) return 0; - - if (i596_debug > 3) printk("%s: i596_start_xmit() called\n", dev->name); - - /* Block a timer-based transmit from overlapping. This could better be - done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ - if (set_bit(0, (void*)&dev->tbusy) != 0) - printk("%s: Transmitter access conflict.\n", dev->name); - else - { - short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; - dev->trans_start = jiffies; - - tx_cmd = (struct tx_cmd *) kmalloc ((sizeof (struct tx_cmd) + sizeof (struct i596_tbd)), GFP_ATOMIC); - if (tx_cmd == NULL) - { - printk ("%s: i596_xmit Memory squeeze, dropping packet.\n", dev->name); - lp->stats.tx_dropped++; - - dev_kfree_skb(skb, FREE_WRITE); - } - else - { - tx_cmd->tbd = (struct i596_tbd *) (tx_cmd + 1); - tx_cmd->tbd->next = (struct i596_tbd *) I596_NULL; - - tx_cmd->cmd.command = CMD_FLEX|CmdTx; - - tx_cmd->pad = 0; - tx_cmd->size = 0; - tx_cmd->tbd->pad = 0; - tx_cmd->tbd->size = EOF | length; - - tx_cmd->tbd->data = skb->data; - - if (i596_debug > 3) print_eth(skb->data); - - i596_add_cmd(dev, (struct i596_cmd *)tx_cmd); - - lp->stats.tx_packets++; - } - } - - dev->tbusy = 0; - - return 0; -} - - -static void print_eth(char *add) -{ - int i; - - printk ("Dest "); - for (i = 0; i < 6; i++) - printk(" %2.2X", (unsigned char)add[i]); - printk ("\n"); - - printk ("Source"); - for (i = 0; i < 6; i++) - printk(" %2.2X", (unsigned char)add[i+6]); - printk ("\n"); - printk ("type %2.2X%2.2X\n", (unsigned char)add[12], (unsigned char)add[13]); -} - -int apricot_probe(struct device *dev) -{ - int i; - struct i596_private *lp; - int checksum = 0; - int ioaddr = 0x300; - char eth_addr[6]; - - /* this is easy the ethernet interface can only be at 0x300 */ - /* first check nothing is already registered here */ - - if (check_region(ioaddr, APRICOT_TOTAL_SIZE)) - return ENODEV; - - for (i = 0; i < 8; i++) - { - eth_addr[i] = inb(ioaddr+8+i); - checksum += eth_addr[i]; - } - - /* checksum is a multiple of 0x100, got this wrong first time - some machines have 0x100, some 0x200. The DOS driver doesn't - even bother with the checksum */ - - if (checksum % 0x100) return ENODEV; - - /* Some other boards trip the checksum.. but then appear as ether - address 0. Trap these - AC */ - - if(memcmp(eth_addr,"\x00\x00\x49",3)!= 0) - return ENODEV; - - request_region(ioaddr, APRICOT_TOTAL_SIZE, "apricot"); - - dev->base_addr = ioaddr; - ether_setup(dev); - printk("%s: Apricot 82596 at %#3x,", dev->name, ioaddr); - - for (i = 0; i < 6; i++) - printk(" %2.2X", dev->dev_addr[i] = eth_addr[i]); - - dev->base_addr = ioaddr; - dev->irq = 10; - printk(" IRQ %d.\n", dev->irq); - - if (i596_debug > 0) printk(version); - - /* The APRICOT-specific entries in the device structure. */ - dev->open = &i596_open; - dev->stop = &i596_close; - dev->hard_start_xmit = &i596_start_xmit; - dev->get_stats = &i596_get_stats; - dev->set_multicast_list = &set_multicast_list; - - dev->mem_start = (int)kmalloc(sizeof(struct i596_private)+ 0x0f, GFP_KERNEL); - /* align for scp */ - dev->priv = (void *)((dev->mem_start + 0xf) & 0xfffffff0); - - lp = (struct i596_private *)dev->priv; - memset((void *)lp, 0, sizeof(struct i596_private)); - lp->scb.command = 0; - lp->scb.cmd = (struct i596_cmd *) I596_NULL; - lp->scb.rfd = (struct i596_rfd *)I596_NULL; - - return 0; -} - -static void -i596_interrupt(int irq, struct pt_regs *regs) -{ - struct device *dev = (struct device *)(irq2dev_map[irq]); - struct i596_private *lp; - short ioaddr; - int boguscnt = 200; - unsigned short status, ack_cmd = 0; - - if (dev == NULL) { - printk ("i596_interrupt(): irq %d for unknown device.\n", irq); - return; - } - - if (i596_debug > 3) printk ("%s: i596_interrupt(): irq %d\n",dev->name, irq); - - if (dev->interrupt) - printk("%s: Re-entering the interrupt handler.\n", dev->name); - - dev->interrupt = 1; - - ioaddr = dev->base_addr; - - lp = (struct i596_private *)dev->priv; - - while (lp->scb.status, lp->scb.command) - if (--boguscnt == 0) - { - printk("%s: i596 interrupt, timeout status %4.4x command %4.4x.\n", dev->name, lp->scb.status, lp->scb.command); - break; - } - status = lp->scb.status; - - if (i596_debug > 4) - printk("%s: i596 interrupt, status %4.4x.\n", dev->name, status); - - ack_cmd = status & 0xf000; - - if ((status & 0x8000) || (status & 0x2000)) - { - struct i596_cmd *ptr; - - if ((i596_debug > 4) && (status & 0x8000)) - printk("%s: i596 interrupt completed command.\n", dev->name); - if ((i596_debug > 4) && (status & 0x2000)) - printk("%s: i596 interrupt command unit inactive %x.\n", dev->name, status & 0x0700); - - while ((lp->cmd_head != (struct i596_cmd *) I596_NULL) && (lp->cmd_head->status & STAT_C)) - { - ptr = lp->cmd_head; - - lp->cmd_head = lp->cmd_head->next; - lp->cmd_backlog--; - - switch ((ptr->command) & 0x7) - { - case CmdTx: - { - struct tx_cmd *tx_cmd = (struct tx_cmd *) ptr; - struct sk_buff *skb = ((struct sk_buff *)(tx_cmd->tbd->data)) -1; - - dev_kfree_skb(skb, FREE_WRITE); - - if ((ptr->status) & STAT_OK) - { - if (i596_debug >2) print_eth(skb->data); - } - else - { - lp->stats.tx_errors++; - if ((ptr->status) & 0x0020) lp->stats.collisions++; - if (!((ptr->status) & 0x0040)) lp->stats.tx_heartbeat_errors++; - if ((ptr->status) & 0x0400) lp->stats.tx_carrier_errors++; - if ((ptr->status) & 0x0800) lp->stats.collisions++; - if ((ptr->status) & 0x1000) lp->stats.tx_aborted_errors++; - } - - - ptr->next = (struct i596_cmd * ) I596_NULL; - kfree_s((unsigned char *)tx_cmd, (sizeof (struct tx_cmd) + sizeof (struct i596_tbd))); - break; - } - case CmdMulticastList: - { - unsigned short count = *((unsigned short *) (ptr + 1)); - - ptr->next = (struct i596_cmd * ) I596_NULL; - kfree_s((unsigned char *)ptr, (sizeof (struct i596_cmd) + count + 2)); - break; - } - case CmdTDR: - { - unsigned long status = *((unsigned long *) (ptr + 1)); - - if (status & 0x8000) - { - if (i596_debug > 3) - printk("%s: link ok.\n", dev->name); - } - else - { - if (status & 0x4000) - printk("%s: Transceiver problem.\n", dev->name); - if (status & 0x2000) - printk("%s: Termination problem.\n", dev->name); - if (status & 0x1000) - printk("%s: Short circuit.\n", dev->name); - - printk("%s: Time %ld.\n", dev->name, status & 0x07ff); - } - } - default: - ptr->next = (struct i596_cmd * ) I596_NULL; - - lp->last_cmd = jiffies; - } - } - - ptr = lp->cmd_head; - while ((ptr != (struct i596_cmd *) I596_NULL) && (ptr != lp->cmd_tail)) - { - ptr->command &= 0x1fff; - ptr = ptr->next; - } - - if ((lp->cmd_head != (struct i596_cmd *) I596_NULL) && (dev->start)) ack_cmd |= CUC_START; - lp->scb.cmd = lp->cmd_head; - } - - if ((status & 0x1000) || (status & 0x4000)) - { - if ((i596_debug > 4) && (status & 0x4000)) - printk("%s: i596 interrupt received a frame.\n", dev->name); - if ((i596_debug > 4) && (status & 0x1000)) - printk("%s: i596 interrupt receive unit inactive %x.\n", dev->name, status & 0x0070); - - i596_rx(dev); - - if (dev->start) ack_cmd |= RX_START; - } - - /* acknowledge the interrupt */ - -/* - if ((lp->scb.cmd != (struct i596_cmd *) I596_NULL) && (dev->start)) ack_cmd | = CUC_START; -*/ - boguscnt = 100; - while (lp->scb.status, lp->scb.command) - if (--boguscnt == 0) - { - printk("%s: i596 interrupt, timeout status %4.4x command %4.4x.\n", dev->name, lp->scb.status, lp->scb.command); - break; - } - lp->scb.command = ack_cmd; - - (void) inb (ioaddr+0x10); - outb (4, ioaddr+0xf); - outw (0, ioaddr+4); - - if (i596_debug > 4) - printk("%s: exiting interrupt.\n", dev->name); - - dev->interrupt = 0; - return; -} - -static int -i596_close(struct device *dev) -{ - int ioaddr = dev->base_addr; - struct i596_private *lp = (struct i596_private *)dev->priv; - int boguscnt = 200; - - dev->start = 0; - dev->tbusy = 1; - - if (i596_debug > 1) - printk("%s: Shutting down ethercard, status was %4.4x.\n", - dev->name, lp->scb.status); - - lp->scb.command = CUC_ABORT|RX_ABORT; - outw(0, ioaddr+4); - - i596_cleanup_cmd(lp); - - while (lp->scb.status, lp->scb.command) - if (--boguscnt == 0) - { - printk("%s: close timed timed out with status %4.4x, cmd %4.4x.\n", - dev->name, lp->scb.status, lp->scb.command); - break; - } - free_irq(dev->irq); - irq2dev_map[dev->irq] = 0; - remove_rx_bufs(dev); - MOD_DEC_USE_COUNT; - - return 0; -} - -static struct enet_statistics * -i596_get_stats(struct device *dev) -{ - struct i596_private *lp = (struct i596_private *)dev->priv; - - return &lp->stats; -} - -/* - * Set or clear the multicast filter for this adaptor. - */ - -static void set_multicast_list(struct device *dev) -{ - struct i596_private *lp = (struct i596_private *)dev->priv; - struct i596_cmd *cmd; - - if (i596_debug > 1) - printk ("%s: set multicast list %d\n", dev->name, dev->mc_count); - - if (dev->mc_count > 0) - { - struct dev_mc_list *dmi; - char *cp; - cmd = (struct i596_cmd *) kmalloc(sizeof(struct i596_cmd)+2+dev->mc_count*6, GFP_ATOMIC); - if (cmd == NULL) - { - printk ("%s: set_multicast Memory squeeze.\n", dev->name); - return; - } - cmd->command = CmdMulticastList; - *((unsigned short *) (cmd + 1)) = dev->mc_count * 6; - cp=((char *)(cmd + 1))+2; - for(dmi=dev->mc_list;dmi!=NULL;dmi=dmi->next) - { - memcpy(cp, dmi,6); - cp+=6; - } - print_eth (((char *)(cmd + 1)) + 2); - i596_add_cmd(dev, cmd); - } - else - { - if (lp->set_conf.next != (struct i596_cmd * ) I596_NULL) - return; - if (dev->mc_count == 0 && !(dev->flags&(IFF_PROMISC|IFF_ALLMULTI))) - { - if(dev->flags&IFF_ALLMULTI) - dev->flags|=IFF_PROMISC; - lp->i596_config[8] &= ~0x01; - } - else - lp->i596_config[8] |= 0x01; - - i596_add_cmd(dev, &lp->set_conf); - } -} - -#ifdef HAVE_DEVLIST -static unsigned int apricot_portlist[] = {0x300, 0}; -struct netdev_entry apricot_drv = -{"apricot", apricot_probe, APRICOT_TOTAL_SIZE, apricot_portlist}; -#endif - -#ifdef MODULE -static char devicename[9] = { 0, }; -static struct device dev_apricot = { - devicename, /* device name inserted by /linux/drivers/net/net_init.c */ - 0, 0, 0, 0, - 0x300, 10, - 0, 0, 0, NULL, apricot_probe }; - -static int io = 0x300; -static int irq = 10; - -int -init_module(void) -{ - dev_apricot.base_addr = io; - dev_apricot.irq = irq; - if (register_netdev(&dev_apricot) != 0) - return -EIO; - return 0; -} - -void -cleanup_module(void) -{ - unregister_netdev(&dev_apricot); - kfree_s((void *)dev_apricot.mem_start, sizeof(struct i596_private) + 0xf); - dev_apricot.priv = NULL; - - /* If we don't do this, we can't re-insmod it later. */ - release_region(dev_apricot.base_addr, APRICOT_TOTAL_SIZE); -} -#endif /* MODULE */ - -/* - * Local variables: - * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c apricot.c" - * End: - */ diff --git a/i386/i386at/gpl/linux/net/at1700.c b/i386/i386at/gpl/linux/net/at1700.c deleted file mode 100644 index 3d684c0a..00000000 --- a/i386/i386at/gpl/linux/net/at1700.c +++ /dev/null @@ -1,677 +0,0 @@ -/* at1700.c: A network device driver for the Allied Telesis AT1700. - - Written 1993-94 by Donald Becker. - - Copyright 1993 United States Government as represented by the - Director, National Security Agency. - - This software may be used and distributed according to the terms - of the GNU Public License, incorporated herein by reference. - - The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O - Center of Excellence in Space Data and Information Sciences - Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771 - - This is a device driver for the Allied Telesis AT1700, which is a - straight-forward Fujitsu MB86965 implementation. - - Sources: - The Fujitsu MB86965 datasheet. - - After the initial version of this driver was written Gerry Sawkins of - ATI provided their EEPROM configuration code header file. - Thanks to NIIBE Yutaka <gniibe@mri.co.jp> for bug fixes. - - Bugs: - The MB86965 has a design flaw that makes all probes unreliable. Not - only is it difficult to detect, it also moves around in I/O space in - response to inb()s from other device probes! -*/ - -static const char *version = - "at1700.c:v1.12 1/18/95 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n"; - -#include <linux/module.h> - -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/types.h> -#include <linux/fcntl.h> -#include <linux/interrupt.h> -#include <linux/ptrace.h> -#include <linux/ioport.h> -#include <linux/in.h> -#include <linux/malloc.h> -#include <linux/string.h> -#include <asm/system.h> -#include <asm/bitops.h> -#include <asm/io.h> -#include <asm/dma.h> -#include <linux/errno.h> - -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> - -/* This unusual address order is used to verify the CONFIG register. */ -static int at1700_probe_list[] = -{0x260, 0x280, 0x2a0, 0x240, 0x340, 0x320, 0x380, 0x300, 0}; - -/* use 0 for production, 1 for verification, >2 for debug */ -#ifndef NET_DEBUG -#define NET_DEBUG 1 -#endif -static unsigned int net_debug = NET_DEBUG; - -typedef unsigned char uchar; - -/* Information that need to be kept for each board. */ -struct net_local { - struct enet_statistics stats; - uint tx_started:1; /* Number of packet on the Tx queue. */ - uchar tx_queue; /* Number of packet on the Tx queue. */ - ushort tx_queue_len; /* Current length of the Tx queue. */ -}; - - -/* Offsets from the base address. */ -#define STATUS 0 -#define TX_STATUS 0 -#define RX_STATUS 1 -#define TX_INTR 2 /* Bit-mapped interrupt enable registers. */ -#define RX_INTR 3 -#define TX_MODE 4 -#define RX_MODE 5 -#define CONFIG_0 6 /* Misc. configuration settings. */ -#define CONFIG_1 7 -/* Run-time register bank 2 definitions. */ -#define DATAPORT 8 /* Word-wide DMA or programmed-I/O dataport. */ -#define TX_START 10 -#define MODE13 13 -#define EEPROM_Ctrl 16 -#define EEPROM_Data 17 -#define IOCONFIG 19 -#define RESET 31 /* Write to reset some parts of the chip. */ -#define AT1700_IO_EXTENT 32 - -/* EEPROM_Ctrl bits. */ -#define EE_SHIFT_CLK 0x40 /* EEPROM shift clock, in reg. 16. */ -#define EE_CS 0x20 /* EEPROM chip select, in reg. 16. */ -#define EE_DATA_WRITE 0x80 /* EEPROM chip data in, in reg. 17. */ -#define EE_DATA_READ 0x80 /* EEPROM chip data out, in reg. 17. */ - -/* Delay between EEPROM clock transitions. */ -#define eeprom_delay() do { int _i = 40; while (--_i > 0) { __SLOW_DOWN_IO; }} while (0) - -/* The EEPROM commands include the alway-set leading bit. */ -#define EE_WRITE_CMD (5 << 6) -#define EE_READ_CMD (6 << 6) -#define EE_ERASE_CMD (7 << 6) - - -/* Index to functions, as function prototypes. */ - -extern int at1700_probe(struct device *dev); - -static int at1700_probe1(struct device *dev, short ioaddr); -static int read_eeprom(int ioaddr, int location); -static int net_open(struct device *dev); -static int net_send_packet(struct sk_buff *skb, struct device *dev); -static void net_interrupt(int irq, struct pt_regs *regs); -static void net_rx(struct device *dev); -static int net_close(struct device *dev); -static struct enet_statistics *net_get_stats(struct device *dev); -static void set_multicast_list(struct device *dev); - - -/* Check for a network adaptor of this type, and return '0' iff one exists. - If dev->base_addr == 0, probe all likely locations. - If dev->base_addr == 1, always return failure. - If dev->base_addr == 2, allocate space for the device and return success - (detachable devices only). - */ -#ifdef HAVE_DEVLIST -/* Support for a alternate probe manager, which will eliminate the - boilerplate below. */ -struct netdev_entry at1700_drv = -{"at1700", at1700_probe1, AT1700_IO_EXTENT, at1700_probe_list}; -#else -int -at1700_probe(struct device *dev) -{ - int i; - int base_addr = dev ? dev->base_addr : 0; - - if (base_addr > 0x1ff) /* Check a single specified location. */ - return at1700_probe1(dev, base_addr); - else if (base_addr != 0) /* Don't probe at all. */ - return ENXIO; - - for (i = 0; at1700_probe_list[i]; i++) { - int ioaddr = at1700_probe_list[i]; - if (check_region(ioaddr, AT1700_IO_EXTENT)) - continue; - if (at1700_probe1(dev, ioaddr) == 0) - return 0; - } - - return ENODEV; -} -#endif - -/* The Fujitsu datasheet suggests that the NIC be probed for by checking its - "signature", the default bit pattern after a reset. This *doesn't* work -- - there is no way to reset the bus interface without a complete power-cycle! - - It turns out that ATI came to the same conclusion I did: the only thing - that can be done is checking a few bits and then diving right into an - EEPROM read. */ - -int at1700_probe1(struct device *dev, short ioaddr) -{ - char irqmap[8] = {3, 4, 5, 9, 10, 11, 14, 15}; - unsigned int i, irq; - - /* Resetting the chip doesn't reset the ISA interface, so don't bother. - That means we have to be careful with the register values we probe for. - */ -#ifdef notdef - printk("at1700 probe at %#x, eeprom is %4.4x %4.4x %4.4x ctrl %4.4x.\n", - ioaddr, read_eeprom(ioaddr, 4), read_eeprom(ioaddr, 5), - read_eeprom(ioaddr, 6), inw(ioaddr + EEPROM_Ctrl)); -#endif - if (at1700_probe_list[inb(ioaddr + IOCONFIG) & 0x07] != ioaddr - || read_eeprom(ioaddr, 4) != 0x0000 - || (read_eeprom(ioaddr, 5) & 0xff00) != 0xF400) - return -ENODEV; - - /* Reset the internal state machines. */ - outb(0, ioaddr + RESET); - - irq = irqmap[(read_eeprom(ioaddr, 12)&0x04) - | (read_eeprom(ioaddr, 0)>>14)]; - - /* Snarf the interrupt vector now. */ - if (request_irq(irq, &net_interrupt, 0, "at1700")) { - printk ("AT1700 found at %#3x, but it's unusable due to a conflict on" - "IRQ %d.\n", ioaddr, irq); - return EAGAIN; - } - - /* Allocate a new 'dev' if needed. */ - if (dev == NULL) - dev = init_etherdev(0, sizeof(struct net_local)); - - /* Grab the region so that we can find another board if the IRQ request - fails. */ - request_region(ioaddr, AT1700_IO_EXTENT, "at1700"); - - printk("%s: AT1700 found at %#3x, IRQ %d, address ", dev->name, - ioaddr, irq); - - dev->base_addr = ioaddr; - dev->irq = irq; - irq2dev_map[irq] = dev; - - for(i = 0; i < 3; i++) { - unsigned short eeprom_val = read_eeprom(ioaddr, 4+i); - printk("%04x", eeprom_val); - ((unsigned short *)dev->dev_addr)[i] = ntohs(eeprom_val); - } - - /* The EEPROM word 12 bit 0x0400 means use regular 100 ohm 10baseT signals, - rather than 150 ohm shielded twisted pair compensation. - 0x0000 == auto-sense the interface - 0x0800 == use TP interface - 0x1800 == use coax interface - */ - { - const char *porttype[] = {"auto-sense", "10baseT", "auto-sense", "10base2"}; - ushort setup_value = read_eeprom(ioaddr, 12); - - dev->if_port = setup_value >> 8; - printk(" %s interface.\n", porttype[(dev->if_port>>3) & 3]); - } - - /* Set the station address in bank zero. */ - outb(0xe0, ioaddr + 7); - for (i = 0; i < 6; i++) - outb(dev->dev_addr[i], ioaddr + 8 + i); - - /* Switch to bank 1 and set the multicast table to accept none. */ - outb(0xe4, ioaddr + 7); - for (i = 0; i < 8; i++) - outb(0x00, ioaddr + 8 + i); - - /* Set the configuration register 0 to 32K 100ns. byte-wide memory, 16 bit - bus access, two 4K Tx queues, and disabled Tx and Rx. */ - outb(0xda, ioaddr + CONFIG_0); - - /* Switch to bank 2 and lock our I/O address. */ - outb(0xe8, ioaddr + 7); - outb(dev->if_port, MODE13); - - /* Power-down the chip. Aren't we green! */ - outb(0x00, ioaddr + CONFIG_1); - - if (net_debug) - printk(version); - - /* Initialize the device structure. */ - dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL); - if (dev->priv == NULL) - return -ENOMEM; - memset(dev->priv, 0, sizeof(struct net_local)); - - dev->open = net_open; - dev->stop = net_close; - dev->hard_start_xmit = net_send_packet; - dev->get_stats = net_get_stats; - dev->set_multicast_list = &set_multicast_list; - - /* Fill in the fields of 'dev' with ethernet-generic values. */ - - ether_setup(dev); - return 0; -} - -static int read_eeprom(int ioaddr, int location) -{ - int i; - unsigned short retval = 0; - short ee_addr = ioaddr + EEPROM_Ctrl; - short ee_daddr = ioaddr + EEPROM_Data; - int read_cmd = location | EE_READ_CMD; - short ctrl_val = EE_CS; - - outb(ctrl_val, ee_addr); - - /* Shift the read command bits out. */ - for (i = 9; i >= 0; i--) { - short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - outb(dataval, ee_daddr); - outb(EE_CS | EE_SHIFT_CLK, ee_addr); /* EEPROM clock tick. */ - eeprom_delay(); - outb(EE_CS, ee_addr); /* Finish EEPROM a clock tick. */ - eeprom_delay(); - } - outb(EE_CS, ee_addr); - - for (i = 16; i > 0; i--) { - outb(EE_CS | EE_SHIFT_CLK, ee_addr); - eeprom_delay(); - retval = (retval << 1) | ((inb(ee_daddr) & EE_DATA_READ) ? 1 : 0); - outb(EE_CS, ee_addr); - eeprom_delay(); - } - - /* Terminate the EEPROM access. */ - ctrl_val &= ~EE_CS; - outb(ctrl_val | EE_SHIFT_CLK, ee_addr); - eeprom_delay(); - outb(ctrl_val, ee_addr); - eeprom_delay(); - return retval; -} - - - -static int net_open(struct device *dev) -{ - struct net_local *lp = (struct net_local *)dev->priv; - int ioaddr = dev->base_addr; - int i; - - /* Powerup the chip, initialize config register 1, and select bank 0. */ - outb(0xe0, ioaddr + CONFIG_1); - - /* Set the station address in bank zero. */ - for (i = 0; i < 6; i++) - outb(dev->dev_addr[i], ioaddr + 8 + i); - - /* Switch to bank 1 and set the multicast table to accept none. */ - outb(0xe4, ioaddr + 7); - for (i = 0; i < 8; i++) - outb(0x00, ioaddr + 8 + i); - - /* Set the configuration register 0 to 32K 100ns. byte-wide memory, 16 bit - bus access, and two 4K Tx queues. */ - outb(0xda, ioaddr + CONFIG_0); - - /* Same config 0, except enable the Rx and Tx. */ - outb(0x5a, ioaddr + CONFIG_0); - /* Switch to register bank 2 for the run-time registers. */ - outb(0xe8, ioaddr + CONFIG_1); - - lp->tx_started = 0; - lp->tx_queue = 0; - lp->tx_queue_len = 0; - - /* Turn on Rx interrupts, leave Tx interrupts off until packet Tx. */ - outb(0x00, ioaddr + TX_INTR); - outb(0x81, ioaddr + RX_INTR); - - dev->tbusy = 0; - dev->interrupt = 0; - dev->start = 1; - - MOD_INC_USE_COUNT; - - return 0; -} - -static int -net_send_packet(struct sk_buff *skb, struct device *dev) -{ - struct net_local *lp = (struct net_local *)dev->priv; - int ioaddr = dev->base_addr; - - if (dev->tbusy) { - /* If we get here, some higher level has decided we are broken. - There should really be a "kick me" function call instead. */ - int tickssofar = jiffies - dev->trans_start; - if (tickssofar < 10) - return 1; - printk("%s: transmit timed out with status %04x, %s?\n", dev->name, - inw(ioaddr + STATUS), inb(ioaddr + TX_STATUS) & 0x80 - ? "IRQ conflict" : "network cable problem"); - printk("%s: timeout registers: %04x %04x %04x %04x %04x %04x %04x %04x.\n", - dev->name, inw(ioaddr + 0), inw(ioaddr + 2), inw(ioaddr + 4), - inw(ioaddr + 6), inw(ioaddr + 8), inw(ioaddr + 10), - inw(ioaddr + 12), inw(ioaddr + 14)); - lp->stats.tx_errors++; - /* ToDo: We should try to restart the adaptor... */ - outw(0xffff, ioaddr + 24); - outw(0xffff, ioaddr + TX_STATUS); - outw(0xe85a, ioaddr + CONFIG_0); - outw(0x8100, ioaddr + TX_INTR); - dev->tbusy=0; - dev->trans_start = jiffies; - lp->tx_started = 0; - lp->tx_queue = 0; - lp->tx_queue_len = 0; - } - - /* If some higher layer thinks we've missed an tx-done interrupt - we are passed NULL. Caution: dev_tint() handles the cli()/sti() - itself. */ - if (skb == NULL) { - dev_tint(dev); - return 0; - } - - /* Block a timer-based transmit from overlapping. This could better be - done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ - if (set_bit(0, (void*)&dev->tbusy) != 0) - printk("%s: Transmitter access conflict.\n", dev->name); - else { - short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; - unsigned char *buf = skb->data; - - /* Turn off the possible Tx interrupts. */ - outb(0x00, ioaddr + TX_INTR); - - outw(length, ioaddr + DATAPORT); - outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1); - - lp->tx_queue++; - lp->tx_queue_len += length + 2; - - if (lp->tx_started == 0) { - /* If the Tx is idle, always trigger a transmit. */ - outb(0x80 | lp->tx_queue, ioaddr + TX_START); - lp->tx_queue = 0; - lp->tx_queue_len = 0; - dev->trans_start = jiffies; - lp->tx_started = 1; - dev->tbusy = 0; - } else if (lp->tx_queue_len < 4096 - 1502) - /* Yes, there is room for one more packet. */ - dev->tbusy = 0; - - /* Turn on Tx interrupts back on. */ - outb(0x82, ioaddr + TX_INTR); - } - dev_kfree_skb (skb, FREE_WRITE); - - return 0; -} - -/* The typical workload of the driver: - Handle the network interface interrupts. */ -static void -net_interrupt(int irq, struct pt_regs *regs) -{ - struct device *dev = (struct device *)(irq2dev_map[irq]); - struct net_local *lp; - int ioaddr, status; - - if (dev == NULL) { - printk ("at1700_interrupt(): irq %d for unknown device.\n", irq); - return; - } - dev->interrupt = 1; - - ioaddr = dev->base_addr; - lp = (struct net_local *)dev->priv; - status = inw(ioaddr + TX_STATUS); - outw(status, ioaddr + TX_STATUS); - - if (net_debug > 4) - printk("%s: Interrupt with status %04x.\n", dev->name, status); - if (status & 0xff00 - || (inb(ioaddr + RX_MODE) & 0x40) == 0) { /* Got a packet(s). */ - net_rx(dev); - } - if (status & 0x00ff) { - if (status & 0x80) { - lp->stats.tx_packets++; - if (lp->tx_queue) { - outb(0x80 | lp->tx_queue, ioaddr + TX_START); - lp->tx_queue = 0; - lp->tx_queue_len = 0; - dev->trans_start = jiffies; - dev->tbusy = 0; - mark_bh(NET_BH); /* Inform upper layers. */ - } else { - lp->tx_started = 0; - /* Turn on Tx interrupts off. */ - outb(0x00, ioaddr + TX_INTR); - dev->tbusy = 0; - mark_bh(NET_BH); /* Inform upper layers. */ - } - } - } - - dev->interrupt = 0; - return; -} - -/* We have a good packet(s), get it/them out of the buffers. */ -static void -net_rx(struct device *dev) -{ - struct net_local *lp = (struct net_local *)dev->priv; - int ioaddr = dev->base_addr; - int boguscount = 5; - - while ((inb(ioaddr + RX_MODE) & 0x40) == 0) { - ushort status = inw(ioaddr + DATAPORT); - ushort pkt_len = inw(ioaddr + DATAPORT); - - if (net_debug > 4) - printk("%s: Rxing packet mode %02x status %04x.\n", - dev->name, inb(ioaddr + RX_MODE), status); -#ifndef final_version - if (status == 0) { - outb(0x05, ioaddr + 14); - break; - } -#endif - - if ((status & 0xF0) != 0x20) { /* There was an error. */ - lp->stats.rx_errors++; - if (status & 0x08) lp->stats.rx_length_errors++; - if (status & 0x04) lp->stats.rx_frame_errors++; - if (status & 0x02) lp->stats.rx_crc_errors++; - if (status & 0x01) lp->stats.rx_over_errors++; - } else { - /* Malloc up new buffer. */ - struct sk_buff *skb; - - if (pkt_len > 1550) { - printk("%s: The AT1700 claimed a very large packet, size %d.\n", - dev->name, pkt_len); - /* Prime the FIFO and then flush the packet. */ - inw(ioaddr + DATAPORT); inw(ioaddr + DATAPORT); - outb(0x05, ioaddr + 14); - lp->stats.rx_errors++; - break; - } - skb = dev_alloc_skb(pkt_len+3); - if (skb == NULL) { - printk("%s: Memory squeeze, dropping packet (len %d).\n", - dev->name, pkt_len); - /* Prime the FIFO and then flush the packet. */ - inw(ioaddr + DATAPORT); inw(ioaddr + DATAPORT); - outb(0x05, ioaddr + 14); - lp->stats.rx_dropped++; - break; - } - skb->dev = dev; - skb_reserve(skb,2); - - insw(ioaddr + DATAPORT, skb_put(skb,pkt_len), (pkt_len + 1) >> 1); - skb->protocol=eth_type_trans(skb, dev); - netif_rx(skb); - lp->stats.rx_packets++; - } - if (--boguscount <= 0) - break; - } - - /* If any worth-while packets have been received, dev_rint() - has done a mark_bh(NET_BH) for us and will work on them - when we get to the bottom-half routine. */ - { - int i; - for (i = 0; i < 20; i++) { - if ((inb(ioaddr + RX_MODE) & 0x40) == 0x40) - break; - inw(ioaddr + DATAPORT); /* dummy status read */ - outb(0x05, ioaddr + 14); - } - - if (net_debug > 5) - printk("%s: Exint Rx packet with mode %02x after %d ticks.\n", - dev->name, inb(ioaddr + RX_MODE), i); - } - return; -} - -/* The inverse routine to net_open(). */ -static int net_close(struct device *dev) -{ - int ioaddr = dev->base_addr; - - dev->tbusy = 1; - dev->start = 0; - - /* Set configuration register 0 to disable Tx and Rx. */ - outb(0xda, ioaddr + CONFIG_0); - - /* Update the statistics -- ToDo. */ - - /* Power-down the chip. Green, green, green! */ - outb(0x00, ioaddr + CONFIG_1); - - MOD_DEC_USE_COUNT; - - return 0; -} - -/* Get the current statistics. This may be called with the card open or - closed. */ -static struct enet_statistics * -net_get_stats(struct device *dev) -{ - struct net_local *lp = (struct net_local *)dev->priv; - - cli(); - /* ToDo: Update the statistics from the device registers. */ - sti(); - - return &lp->stats; -} - -/* Set or clear the multicast filter for this adaptor. - num_addrs == -1 Promiscuous mode, receive all packets - num_addrs == 0 Normal mode, clear multicast list - num_addrs > 0 Multicast mode, receive normal and MC packets, and do - best-effort filtering. - */ -static void -set_multicast_list(struct device *dev) -{ - short ioaddr = dev->base_addr; - if (dev->mc_count || dev->flags&(IFF_PROMISC|IFF_ALLMULTI)) - { - /* - * We must make the kernel realise we had to move - * into promisc mode or we start all out war on - * the cable. - AC - */ - dev->flags|=IFF_PROMISC; - - outb(3, ioaddr + RX_MODE); /* Enable promiscuous mode */ - } - else - outb(2, ioaddr + RX_MODE); /* Disable promiscuous, use normal mode */ -} -#ifdef MODULE -static char devicename[9] = { 0, }; -static struct device dev_at1700 = { - devicename, /* device name is inserted by linux/drivers/net/net_init.c */ - 0, 0, 0, 0, - 0, 0, - 0, 0, 0, NULL, at1700_probe }; - -static int io = 0x260; -static int irq = 0; - -int init_module(void) -{ - if (io == 0) - printk("at1700: You should not use auto-probing with insmod!\n"); - dev_at1700.base_addr = io; - dev_at1700.irq = irq; - if (register_netdev(&dev_at1700) != 0) { - printk("at1700: register_netdev() returned non-zero.\n"); - return -EIO; - } - return 0; -} - -void -cleanup_module(void) -{ - unregister_netdev(&dev_at1700); - kfree(dev_at1700.priv); - dev_at1700.priv = NULL; - - /* If we don't do this, we can't re-insmod it later. */ - free_irq(dev_at1700.irq); - irq2dev_map[dev_at1700.irq] = NULL; - release_region(dev_at1700.base_addr, AT1700_IO_EXTENT); -} -#endif /* MODULE */ - -/* - * Local variables: - * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c at1700.c" - * version-control: t - * kept-new-versions: 5 - * tab-width: 4 - * c-indent-level: 4 - * End: - */ diff --git a/i386/i386at/gpl/linux/net/atp.c b/i386/i386at/gpl/linux/net/atp.c deleted file mode 100644 index 62aa04ef..00000000 --- a/i386/i386at/gpl/linux/net/atp.c +++ /dev/null @@ -1,787 +0,0 @@ -/* atp.c: Attached (pocket) ethernet adapter driver for linux. */ -/* - This is a driver for a commonly OEMed pocket (parallel port) - ethernet adapter. - - Written 1993,1994,1995 by Donald Becker. - - Copyright 1993 United States Government as represented by the - Director, National Security Agency. - - This software may be used and distributed according to the terms - of the GNU Public License, incorporated herein by reference. - - The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O - Center of Excellence in Space Data and Information Sciences - Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771 - - The timer-based reset code was written by Bill Carlson, wwc@super.org. -*/ - -static const char *version = - "atp.c:v1.01 1/18/95 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n"; - -/* - This file is a device driver for the RealTek (aka AT-Lan-Tec) pocket - ethernet adapter. This is a common low-cost OEM pocket ethernet - adapter, sold under many names. - - Sources: - This driver was written from the packet driver assembly code provided by - Vincent Bono of AT-Lan-Tec. Ever try to figure out how a complicated - device works just from the assembly code? It ain't pretty. The following - description is written based on guesses and writing lots of special-purpose - code to test my theorized operation. - - Theory of Operation - - The RTL8002 adapter seems to be built around a custom spin of the SEEQ - controller core. It probably has a 16K or 64K internal packet buffer, of - which the first 4K is devoted to transmit and the rest to receive. - The controller maintains the queue of received packet and the packet buffer - access pointer internally, with only 'reset to beginning' and 'skip to next - packet' commands visible. The transmit packet queue holds two (or more?) - packets: both 'retransmit this packet' (due to collision) and 'transmit next - packet' commands must be started by hand. - - The station address is stored in a standard bit-serial EEPROM which must be - read (ughh) by the device driver. (Provisions have been made for - substituting a 74S288 PROM, but I haven't gotten reports of any models - using it.) Unlike built-in devices, a pocket adapter can temporarily lose - power without indication to the device driver. The major effect is that - the station address, receive filter (promiscuous, etc.) and transceiver - must be reset. - - The controller itself has 16 registers, some of which use only the lower - bits. The registers are read and written 4 bits at a time. The four bit - register address is presented on the data lines along with a few additional - timing and control bits. The data is then read from status port or written - to the data port. - - Since the bulk data transfer of the actual packets through the slow - parallel port dominates the driver's running time, four distinct data - (non-register) transfer modes are provided by the adapter, two in each - direction. In the first mode timing for the nibble transfers is - provided through the data port. In the second mode the same timing is - provided through the control port. In either case the data is read from - the status port and written to the data port, just as it is accessing - registers. - - In addition to the basic data transfer methods, several more are modes are - created by adding some delay by doing multiple reads of the data to allow - it to stabilize. This delay seems to be needed on most machines. - - The data transfer mode is stored in the 'dev->if_port' field. Its default - value is '4'. It may be overridden at boot-time using the third parameter - to the "ether=..." initialization. - - The header file <atp.h> provides inline functions that encapsulate the - register and data access methods. These functions are hand-tuned to - generate reasonable object code. This header file also documents my - interpretations of the device registers. -*/ - -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/types.h> -#include <linux/fcntl.h> -#include <linux/interrupt.h> -#include <linux/ptrace.h> -#include <linux/ioport.h> -#include <linux/in.h> -#include <linux/malloc.h> -#include <linux/string.h> -#include <asm/system.h> -#include <asm/bitops.h> -#include <asm/io.h> -#include <asm/dma.h> -#include <linux/errno.h> - -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> - -#include "atp.h" - -/* use 0 for production, 1 for verification, >2 for debug */ -#ifndef NET_DEBUG -#define NET_DEBUG 1 -#endif -static unsigned int net_debug = NET_DEBUG; - -/* The number of low I/O ports used by the ethercard. */ -#define ETHERCARD_TOTAL_SIZE 3 - -/* This code, written by wwc@super.org, resets the adapter every - TIMED_CHECKER ticks. This recovers from an unknown error which - hangs the device. */ -#define TIMED_CHECKER (HZ/4) -#ifdef TIMED_CHECKER -#include <linux/timer.h> -static void atp_timed_checker(unsigned long ignored); -static struct device *atp_timed_dev; -static struct timer_list atp_timer = {NULL, NULL, 0, 0, atp_timed_checker}; -#endif - -/* Index to functions, as function prototypes. */ - -extern int atp_probe(struct device *dev); - -static int atp_probe1(struct device *dev, short ioaddr); -static void get_node_ID(struct device *dev); -static unsigned short eeprom_op(short ioaddr, unsigned int cmd); -static int net_open(struct device *dev); -static void hardware_init(struct device *dev); -static void write_packet(short ioaddr, int length, unsigned char *packet, int mode); -static void trigger_send(short ioaddr, int length); -static int net_send_packet(struct sk_buff *skb, struct device *dev); -static void net_interrupt(int irq, struct pt_regs *regs); -static void net_rx(struct device *dev); -static void read_block(short ioaddr, int length, unsigned char *buffer, int data_mode); -static int net_close(struct device *dev); -static struct enet_statistics *net_get_stats(struct device *dev); -static void set_multicast_list(struct device *dev); - - -/* Check for a network adapter of this type, and return '0' iff one exists. - If dev->base_addr == 0, probe all likely locations. - If dev->base_addr == 1, always return failure. - If dev->base_addr == 2, allocate space for the device and return success - (detachable devices only). - */ -int -atp_init(struct device *dev) -{ - int *port, ports[] = {0x378, 0x278, 0x3bc, 0}; - int base_addr = dev->base_addr; - - if (base_addr > 0x1ff) /* Check a single specified location. */ - return atp_probe1(dev, base_addr); - else if (base_addr == 1) /* Don't probe at all. */ - return ENXIO; - - for (port = ports; *port; port++) { - int ioaddr = *port; - outb(0x57, ioaddr + PAR_DATA); - if (inb(ioaddr + PAR_DATA) != 0x57) - continue; - if (atp_probe1(dev, ioaddr) == 0) - return 0; - } - - return ENODEV; -} - -static int atp_probe1(struct device *dev, short ioaddr) -{ - int saved_ctrl_reg, status; - - outb(0xff, ioaddr + PAR_DATA); - /* Save the original value of the Control register, in case we guessed - wrong. */ - saved_ctrl_reg = inb(ioaddr + PAR_CONTROL); - /* IRQEN=0, SLCTB=high INITB=high, AUTOFDB=high, STBB=high. */ - outb(0x04, ioaddr + PAR_CONTROL); - write_reg_high(ioaddr, CMR1, CMR1h_RESET); - eeprom_delay(2048); - status = read_nibble(ioaddr, CMR1); - - if ((status & 0x78) != 0x08) { - /* The pocket adapter probe failed, restore the control register. */ - outb(saved_ctrl_reg, ioaddr + PAR_CONTROL); - return 1; - } - status = read_nibble(ioaddr, CMR2_h); - if ((status & 0x78) != 0x10) { - outb(saved_ctrl_reg, ioaddr + PAR_CONTROL); - return 1; - } - /* Find the IRQ used by triggering an interrupt. */ - write_reg_byte(ioaddr, CMR2, 0x01); /* No accept mode, IRQ out. */ - write_reg_high(ioaddr, CMR1, CMR1h_RxENABLE | CMR1h_TxENABLE); /* Enable Tx and Rx. */ - - /* Omit autoIRQ routine for now. Use "table lookup" instead. Uhgggh. */ - if (ioaddr == 0x378) - dev->irq = 7; - else - dev->irq = 5; - write_reg_high(ioaddr, CMR1, CMR1h_TxRxOFF); /* Disable Tx and Rx units. */ - write_reg(ioaddr, CMR2, CMR2_NULL); - - dev->base_addr = ioaddr; - - /* Read the station address PROM. */ - get_node_ID(dev); - - printk("%s: Pocket adapter found at %#3lx, IRQ %d, SAPROM " - "%02X:%02X:%02X:%02X:%02X:%02X.\n", dev->name, dev->base_addr, - dev->irq, dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], - dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); - - /* Leave the hardware in a reset state. */ - write_reg_high(ioaddr, CMR1, CMR1h_RESET); - - if (net_debug) - printk(version); - - /* Initialize the device structure. */ - ether_setup(dev); - dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL); - if (dev->priv == NULL) - return -ENOMEM; - memset(dev->priv, 0, sizeof(struct net_local)); - - - { - struct net_local *lp = (struct net_local *)dev->priv; - lp->addr_mode = CMR2h_Normal; - } - - /* For the ATP adapter the "if_port" is really the data transfer mode. */ - dev->if_port = (dev->mem_start & 0xf) ? dev->mem_start & 0x7 : 4; - if (dev->mem_end & 0xf) - net_debug = dev->mem_end & 7; - - dev->open = net_open; - dev->stop = net_close; - dev->hard_start_xmit = net_send_packet; - dev->get_stats = net_get_stats; - dev->set_multicast_list = &set_multicast_list; - -#ifdef TIMED_CHECKER - del_timer(&atp_timer); - atp_timer.expires = jiffies + TIMED_CHECKER; - atp_timed_dev = dev; - add_timer(&atp_timer); -#endif - return 0; -} - -/* Read the station address PROM, usually a word-wide EEPROM. */ -static void get_node_ID(struct device *dev) -{ - short ioaddr = dev->base_addr; - int sa_offset = 0; - int i; - - write_reg(ioaddr, CMR2, CMR2_EEPROM); /* Point to the EEPROM control registers. */ - - /* Some adapters have the station address at offset 15 instead of offset - zero. Check for it, and fix it if needed. */ - if (eeprom_op(ioaddr, EE_READ(0)) == 0xffff) - sa_offset = 15; - - for (i = 0; i < 3; i++) - ((unsigned short *)dev->dev_addr)[i] = - ntohs(eeprom_op(ioaddr, EE_READ(sa_offset + i))); - - write_reg(ioaddr, CMR2, CMR2_NULL); -} - -/* - An EEPROM read command starts by shifting out 0x60+address, and then - shifting in the serial data. See the NatSemi databook for details. - * ________________ - * CS : __| - * ___ ___ - * CLK: ______| |___| | - * __ _______ _______ - * DI : __X_______X_______X - * DO : _________X_______X - */ - -static unsigned short eeprom_op(short ioaddr, unsigned int cmd) -{ - unsigned eedata_out = 0; - int num_bits = EE_CMD_SIZE; - - while (--num_bits >= 0) { - char outval = test_bit(num_bits, &cmd) ? EE_DATA_WRITE : 0; - write_reg_high(ioaddr, PROM_CMD, outval | EE_CLK_LOW); - eeprom_delay(5); - write_reg_high(ioaddr, PROM_CMD, outval | EE_CLK_HIGH); - eedata_out <<= 1; - if (read_nibble(ioaddr, PROM_DATA) & EE_DATA_READ) - eedata_out++; - eeprom_delay(5); - } - write_reg_high(ioaddr, PROM_CMD, EE_CLK_LOW & ~EE_CS); - return eedata_out; -} - - -/* Open/initialize the board. This is called (in the current kernel) - sometime after booting when the 'ifconfig' program is run. - - This routine sets everything up anew at each open, even - registers that "should" only need to be set once at boot, so that - there is non-reboot way to recover if something goes wrong. - - This is an attachable device: if there is no dev->priv entry then it wasn't - probed for at boot-time, and we need to probe for it again. - */ -static int net_open(struct device *dev) -{ - - /* The interrupt line is turned off (tri-stated) when the device isn't in - use. That's especially important for "attached" interfaces where the - port or interrupt may be shared. */ - if (irq2dev_map[dev->irq] != 0 - || (irq2dev_map[dev->irq] = dev) == 0 - || request_irq(dev->irq, &net_interrupt, 0, "ATP")) { - return -EAGAIN; - } - - hardware_init(dev); - dev->start = 1; - return 0; -} - -/* This routine resets the hardware. We initialize everything, assuming that - the hardware may have been temporarily detached. */ -static void hardware_init(struct device *dev) -{ - struct net_local *lp = (struct net_local *)dev->priv; - int ioaddr = dev->base_addr; - int i; - - write_reg_high(ioaddr, CMR1, CMR1h_RESET); - - for (i = 0; i < 6; i++) - write_reg_byte(ioaddr, PAR0 + i, dev->dev_addr[i]); - - write_reg_high(ioaddr, CMR2, lp->addr_mode); - - if (net_debug > 2) { - printk("%s: Reset: current Rx mode %d.\n", dev->name, - (read_nibble(ioaddr, CMR2_h) >> 3) & 0x0f); - } - - write_reg(ioaddr, CMR2, CMR2_IRQOUT); - write_reg_high(ioaddr, CMR1, CMR1h_RxENABLE | CMR1h_TxENABLE); - - /* Enable the interrupt line from the serial port. */ - outb(Ctrl_SelData + Ctrl_IRQEN, ioaddr + PAR_CONTROL); - - /* Unmask the interesting interrupts. */ - write_reg(ioaddr, IMR, ISR_RxOK | ISR_TxErr | ISR_TxOK); - write_reg_high(ioaddr, IMR, ISRh_RxErr); - - lp->tx_unit_busy = 0; - lp->pac_cnt_in_tx_buf = 0; - lp->saved_tx_size = 0; - - dev->tbusy = 0; - dev->interrupt = 0; -} - -static void trigger_send(short ioaddr, int length) -{ - write_reg_byte(ioaddr, TxCNT0, length & 0xff); - write_reg(ioaddr, TxCNT1, length >> 8); - write_reg(ioaddr, CMR1, CMR1_Xmit); -} - -static void write_packet(short ioaddr, int length, unsigned char *packet, int data_mode) -{ - length = (length + 1) & ~1; /* Round up to word length. */ - outb(EOC+MAR, ioaddr + PAR_DATA); - if ((data_mode & 1) == 0) { - /* Write the packet out, starting with the write addr. */ - outb(WrAddr+MAR, ioaddr + PAR_DATA); - do { - write_byte_mode0(ioaddr, *packet++); - } while (--length > 0) ; - } else { - /* Write the packet out in slow mode. */ - unsigned char outbyte = *packet++; - - outb(Ctrl_LNibWrite + Ctrl_IRQEN, ioaddr + PAR_CONTROL); - outb(WrAddr+MAR, ioaddr + PAR_DATA); - - outb((outbyte & 0x0f)|0x40, ioaddr + PAR_DATA); - outb(outbyte & 0x0f, ioaddr + PAR_DATA); - outbyte >>= 4; - outb(outbyte & 0x0f, ioaddr + PAR_DATA); - outb(Ctrl_HNibWrite + Ctrl_IRQEN, ioaddr + PAR_CONTROL); - while (--length > 0) - write_byte_mode1(ioaddr, *packet++); - } - /* Terminate the Tx frame. End of write: ECB. */ - outb(0xff, ioaddr + PAR_DATA); - outb(Ctrl_HNibWrite | Ctrl_SelData | Ctrl_IRQEN, ioaddr + PAR_CONTROL); -} - -static int -net_send_packet(struct sk_buff *skb, struct device *dev) -{ - struct net_local *lp = (struct net_local *)dev->priv; - int ioaddr = dev->base_addr; - - if (dev->tbusy) { - /* If we get here, some higher level has decided we are broken. - There should really be a "kick me" function call instead. */ - int tickssofar = jiffies - dev->trans_start; - if (tickssofar < 5) - return 1; - printk("%s: transmit timed out, %s?\n", dev->name, - inb(ioaddr + PAR_CONTROL) & 0x10 ? "network cable problem" - : "IRQ conflict"); - lp->stats.tx_errors++; - /* Try to restart the adapter. */ - hardware_init(dev); - dev->tbusy=0; - dev->trans_start = jiffies; - } - - /* If some higher layer thinks we've missed an tx-done interrupt - we are passed NULL. Caution: dev_tint() handles the cli()/sti() - itself. */ - if (skb == NULL) { - dev_tint(dev); - return 0; - } - - /* Block a timer-based transmit from overlapping. This could better be - done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ - if (set_bit(0, (void*)&dev->tbusy) != 0) - printk("%s: Transmitter access conflict.\n", dev->name); - else { - short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; - unsigned char *buf = skb->data; - int flags; - - /* Disable interrupts by writing 0x00 to the Interrupt Mask Register. - This sequence must not be interrupted by an incoming packet. */ - save_flags(flags); - cli(); - write_reg(ioaddr, IMR, 0); - write_reg_high(ioaddr, IMR, 0); - restore_flags(flags); - - write_packet(ioaddr, length, buf, dev->if_port); - - lp->pac_cnt_in_tx_buf++; - if (lp->tx_unit_busy == 0) { - trigger_send(ioaddr, length); - lp->saved_tx_size = 0; /* Redundant */ - lp->re_tx = 0; - lp->tx_unit_busy = 1; - } else - lp->saved_tx_size = length; - - dev->trans_start = jiffies; - /* Re-enable the LPT interrupts. */ - write_reg(ioaddr, IMR, ISR_RxOK | ISR_TxErr | ISR_TxOK); - write_reg_high(ioaddr, IMR, ISRh_RxErr); - } - - dev_kfree_skb (skb, FREE_WRITE); - - return 0; -} - -/* The typical workload of the driver: - Handle the network interface interrupts. */ -static void -net_interrupt(int irq, struct pt_regs * regs) -{ - struct device *dev = (struct device *)(irq2dev_map[irq]); - struct net_local *lp; - int ioaddr, status, boguscount = 20; - static int num_tx_since_rx = 0; - - if (dev == NULL) { - printk ("ATP_interrupt(): irq %d for unknown device.\n", irq); - return; - } - dev->interrupt = 1; - - ioaddr = dev->base_addr; - lp = (struct net_local *)dev->priv; - - /* Disable additional spurious interrupts. */ - outb(Ctrl_SelData, ioaddr + PAR_CONTROL); - - /* The adapter's output is currently the IRQ line, switch it to data. */ - write_reg(ioaddr, CMR2, CMR2_NULL); - write_reg(ioaddr, IMR, 0); - - if (net_debug > 5) printk("%s: In interrupt ", dev->name); - while (--boguscount > 0) { - status = read_nibble(ioaddr, ISR); - if (net_debug > 5) printk("loop status %02x..", status); - - if (status & (ISR_RxOK<<3)) { - write_reg(ioaddr, ISR, ISR_RxOK); /* Clear the Rx interrupt. */ - do { - int read_status = read_nibble(ioaddr, CMR1); - if (net_debug > 6) - printk("handling Rx packet %02x..", read_status); - /* We acknowledged the normal Rx interrupt, so if the interrupt - is still outstanding we must have a Rx error. */ - if (read_status & (CMR1_IRQ << 3)) { /* Overrun. */ - lp->stats.rx_over_errors++; - /* Set to no-accept mode long enough to remove a packet. */ - write_reg_high(ioaddr, CMR2, CMR2h_OFF); - net_rx(dev); - /* Clear the interrupt and return to normal Rx mode. */ - write_reg_high(ioaddr, ISR, ISRh_RxErr); - write_reg_high(ioaddr, CMR2, lp->addr_mode); - } else if ((read_status & (CMR1_BufEnb << 3)) == 0) { - net_rx(dev); - dev->last_rx = jiffies; - num_tx_since_rx = 0; - } else - break; - } while (--boguscount > 0); - } else if (status & ((ISR_TxErr + ISR_TxOK)<<3)) { - if (net_debug > 6) printk("handling Tx done.."); - /* Clear the Tx interrupt. We should check for too many failures - and reinitialize the adapter. */ - write_reg(ioaddr, ISR, ISR_TxErr + ISR_TxOK); - if (status & (ISR_TxErr<<3)) { - lp->stats.collisions++; - if (++lp->re_tx > 15) { - lp->stats.tx_aborted_errors++; - hardware_init(dev); - break; - } - /* Attempt to retransmit. */ - if (net_debug > 6) printk("attempting to ReTx"); - write_reg(ioaddr, CMR1, CMR1_ReXmit + CMR1_Xmit); - } else { - /* Finish up the transmit. */ - lp->stats.tx_packets++; - lp->pac_cnt_in_tx_buf--; - if ( lp->saved_tx_size) { - trigger_send(ioaddr, lp->saved_tx_size); - lp->saved_tx_size = 0; - lp->re_tx = 0; - } else - lp->tx_unit_busy = 0; - dev->tbusy = 0; - mark_bh(NET_BH); /* Inform upper layers. */ - } - num_tx_since_rx++; - } else if (num_tx_since_rx > 8 - && jiffies > dev->last_rx + 100) { - if (net_debug > 2) - printk("%s: Missed packet? No Rx after %d Tx and %ld jiffies" - " status %02x CMR1 %02x.\n", dev->name, - num_tx_since_rx, jiffies - dev->last_rx, status, - (read_nibble(ioaddr, CMR1) >> 3) & 15); - lp->stats.rx_missed_errors++; - hardware_init(dev); - num_tx_since_rx = 0; - break; - } else - break; - } - - /* This following code fixes a rare (and very difficult to track down) - problem where the adapter forgets its ethernet address. */ - { - int i; - for (i = 0; i < 6; i++) - write_reg_byte(ioaddr, PAR0 + i, dev->dev_addr[i]); -#ifdef TIMED_CHECKER - del_timer(&atp_timer); - atp_timer.expires = jiffies + TIMED_CHECKER; - add_timer(&atp_timer); -#endif - } - - /* Tell the adapter that it can go back to using the output line as IRQ. */ - write_reg(ioaddr, CMR2, CMR2_IRQOUT); - /* Enable the physical interrupt line, which is sure to be low until.. */ - outb(Ctrl_SelData + Ctrl_IRQEN, ioaddr + PAR_CONTROL); - /* .. we enable the interrupt sources. */ - write_reg(ioaddr, IMR, ISR_RxOK | ISR_TxErr | ISR_TxOK); - write_reg_high(ioaddr, IMR, ISRh_RxErr); /* Hmmm, really needed? */ - - if (net_debug > 5) printk("exiting interrupt.\n"); - - dev->interrupt = 0; - - return; -} - -#ifdef TIMED_CHECKER -/* This following code fixes a rare (and very difficult to track down) - problem where the adapter forgets its ethernet address. */ -static void atp_timed_checker(unsigned long ignored) -{ - int i; - int ioaddr = atp_timed_dev->base_addr; - - if (!atp_timed_dev->interrupt) - { - for (i = 0; i < 6; i++) -#if 0 - if (read_cmd_byte(ioaddr, PAR0 + i) != atp_timed_dev->dev_addr[i]) - { - struct net_local *lp = (struct net_local *)atp_timed_dev->priv; - write_reg_byte(ioaddr, PAR0 + i, atp_timed_dev->dev_addr[i]); - if (i == 2) - lp->stats.tx_errors++; - else if (i == 3) - lp->stats.tx_dropped++; - else if (i == 4) - lp->stats.collisions++; - else - lp->stats.rx_errors++; - } -#else - write_reg_byte(ioaddr, PAR0 + i, atp_timed_dev->dev_addr[i]); -#endif - } - del_timer(&atp_timer); - atp_timer.expires = jiffies + TIMED_CHECKER; - add_timer(&atp_timer); -} -#endif - -/* We have a good packet(s), get it/them out of the buffers. */ -static void net_rx(struct device *dev) -{ - struct net_local *lp = (struct net_local *)dev->priv; - int ioaddr = dev->base_addr; -#ifdef notdef - ushort header[4]; -#else - struct rx_header rx_head; -#endif - - /* Process the received packet. */ - outb(EOC+MAR, ioaddr + PAR_DATA); - read_block(ioaddr, 8, (unsigned char*)&rx_head, dev->if_port); - if (net_debug > 5) - printk(" rx_count %04x %04x %04x %04x..", rx_head.pad, - rx_head.rx_count, rx_head.rx_status, rx_head.cur_addr); - if ((rx_head.rx_status & 0x77) != 0x01) { - lp->stats.rx_errors++; - /* Ackkk! I don't have any documentation on what the error bits mean! - The best I can do is slap the device around a bit. */ - if (net_debug > 3) printk("%s: Unknown ATP Rx error %04x.\n", - dev->name, rx_head.rx_status); - hardware_init(dev); - return; - } else { - /* Malloc up new buffer. */ - int pkt_len = (rx_head.rx_count & 0x7ff) - 4; /* The "-4" is omits the FCS (CRC). */ - struct sk_buff *skb; - - skb = dev_alloc_skb(pkt_len); - if (skb == NULL) { - printk("%s: Memory squeeze, dropping packet.\n", dev->name); - lp->stats.rx_dropped++; - goto done; - } - skb->dev = dev; - - read_block(ioaddr, pkt_len, skb_put(skb,pkt_len), dev->if_port); - - if (net_debug > 6) { - unsigned char *data = skb->data; - printk(" data %02x%02x%02x %02x%02x%02x %02x%02x%02x" - "%02x%02x%02x %02x%02x..", - data[0], data[1], data[2], data[3], data[4], data[5], - data[6], data[7], data[8], data[9], data[10], data[11], - data[12], data[13]); - } - - skb->protocol=eth_type_trans(skb,dev); - netif_rx(skb); - lp->stats.rx_packets++; - } - done: - write_reg(ioaddr, CMR1, CMR1_NextPkt); - return; -} - -static void read_block(short ioaddr, int length, unsigned char *p, int data_mode) -{ - - if (data_mode <= 3) { /* Mode 0 or 1 */ - outb(Ctrl_LNibRead, ioaddr + PAR_CONTROL); - outb(length == 8 ? RdAddr | HNib | MAR : RdAddr | MAR, - ioaddr + PAR_DATA); - if (data_mode <= 1) { /* Mode 0 or 1 */ - do *p++ = read_byte_mode0(ioaddr); while (--length > 0); - } else /* Mode 2 or 3 */ - do *p++ = read_byte_mode2(ioaddr); while (--length > 0); - } else if (data_mode <= 5) - do *p++ = read_byte_mode4(ioaddr); while (--length > 0); - else - do *p++ = read_byte_mode6(ioaddr); while (--length > 0); - - outb(EOC+HNib+MAR, ioaddr + PAR_DATA); - outb(Ctrl_SelData, ioaddr + PAR_CONTROL); -} - -/* The inverse routine to net_open(). */ -static int -net_close(struct device *dev) -{ - struct net_local *lp = (struct net_local *)dev->priv; - int ioaddr = dev->base_addr; - - dev->tbusy = 1; - dev->start = 0; - - /* Flush the Tx and disable Rx here. */ - lp->addr_mode = CMR2h_OFF; - write_reg_high(ioaddr, CMR2, CMR2h_OFF); - - /* Free the IRQ line. */ - outb(0x00, ioaddr + PAR_CONTROL); - free_irq(dev->irq); - irq2dev_map[dev->irq] = 0; - - /* Leave the hardware in a reset state. */ - write_reg_high(ioaddr, CMR1, CMR1h_RESET); - - return 0; -} - -/* Get the current statistics. This may be called with the card open or - closed. */ -static struct enet_statistics * -net_get_stats(struct device *dev) -{ - struct net_local *lp = (struct net_local *)dev->priv; - return &lp->stats; -} - -/* - * Set or clear the multicast filter for this adapter. - */ - -static void set_multicast_list(struct device *dev) -{ - struct net_local *lp = (struct net_local *)dev->priv; - short ioaddr = dev->base_addr; - int num_addrs=dev->mc_list; - - if(dev->flags&(IFF_ALLMULTI|IFF_PROMISC)) - num_addrs=1; - /* - * We must make the kernel realise we had to move - * into promisc mode or we start all out war on - * the cable. - AC - */ - if(num_addrs) - dev->flags|=IFF_PROMISC; - lp->addr_mode = num_addrs ? CMR2h_PROMISC : CMR2h_Normal; - write_reg_high(ioaddr, CMR2, lp->addr_mode); -} - -/* - * Local variables: - * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c atp.c" - * version-control: t - * kept-new-versions: 5 - * tab-width: 4 - * End: - */ diff --git a/i386/i386at/gpl/linux/net/atp.h b/i386/i386at/gpl/linux/net/atp.h deleted file mode 100644 index e58f8c10..00000000 --- a/i386/i386at/gpl/linux/net/atp.h +++ /dev/null @@ -1,264 +0,0 @@ -#include <linux/if_ether.h> -#include <linux/types.h> -#include <asm/io.h> - -struct net_local { -#ifdef __KERNEL__ - struct enet_statistics stats; -#endif - ushort saved_tx_size; - unsigned char - re_tx, /* Number of packet retransmissions. */ - tx_unit_busy, - addr_mode, /* Current Rx filter e.g. promiscuous, etc. */ - pac_cnt_in_tx_buf; -}; - -struct rx_header { - ushort pad; /* The first read is always corrupted. */ - ushort rx_count; - ushort rx_status; /* Unknown bit assignments :-<. */ - ushort cur_addr; /* Apparently the current buffer address(?) */ -}; - -#define PAR_DATA 0 -#define PAR_STATUS 1 -#define PAR_CONTROL 2 - -#define Ctrl_LNibRead 0x08 /* LP_PSELECP */ -#define Ctrl_HNibRead 0 -#define Ctrl_LNibWrite 0x08 /* LP_PSELECP */ -#define Ctrl_HNibWrite 0 -#define Ctrl_SelData 0x04 /* LP_PINITP */ -#define Ctrl_IRQEN 0x10 /* LP_PINTEN */ - -#define EOW 0xE0 -#define EOC 0xE0 -#define WrAddr 0x40 /* Set address of EPLC read, write register. */ -#define RdAddr 0xC0 -#define HNib 0x10 - -enum page0_regs -{ - /* The first six registers hold the ethernet physical station address. */ - PAR0 = 0, PAR1 = 1, PAR2 = 2, PAR3 = 3, PAR4 = 4, PAR5 = 5, - TxCNT0 = 6, TxCNT1 = 7, /* The transmit byte count. */ - TxSTAT = 8, RxSTAT = 9, /* Tx and Rx status. */ - ISR = 10, IMR = 11, /* Interrupt status and mask. */ - CMR1 = 12, /* Command register 1. */ - CMR2 = 13, /* Command register 2. */ - MAR = 14, /* Memory address register. */ - CMR2_h = 0x1d, }; - -enum eepage_regs -{ PROM_CMD = 6, PROM_DATA = 7 }; /* Note that PROM_CMD is in the "high" bits. */ - - -#define ISR_TxOK 0x01 -#define ISR_RxOK 0x04 -#define ISR_TxErr 0x02 -#define ISRh_RxErr 0x11 /* ISR, high nibble */ - -#define CMR1h_RESET 0x04 /* Reset. */ -#define CMR1h_RxENABLE 0x02 /* Rx unit enable. */ -#define CMR1h_TxENABLE 0x01 /* Tx unit enable. */ -#define CMR1h_TxRxOFF 0x00 -#define CMR1_ReXmit 0x08 /* Trigger a retransmit. */ -#define CMR1_Xmit 0x04 /* Trigger a transmit. */ -#define CMR1_IRQ 0x02 /* Interrupt active. */ -#define CMR1_BufEnb 0x01 /* Enable the buffer(?). */ -#define CMR1_NextPkt 0x01 /* Enable the buffer(?). */ - -#define CMR2_NULL 8 -#define CMR2_IRQOUT 9 -#define CMR2_RAMTEST 10 -#define CMR2_EEPROM 12 /* Set to page 1, for reading the EEPROM. */ - -#define CMR2h_OFF 0 /* No accept mode. */ -#define CMR2h_Physical 1 /* Accept a physical address match only. */ -#define CMR2h_Normal 2 /* Accept physical and broadcast address. */ -#define CMR2h_PROMISC 3 /* Promiscuous mode. */ - -/* An inline function used below: it differs from inb() by explicitly return an unsigned - char, saving a truncation. */ -extern inline unsigned char inbyte(unsigned short port) -{ - unsigned char _v; - __asm__ __volatile__ ("inb %w1,%b0" :"=a" (_v):"d" (port)); - return _v; -} - -/* Read register OFFSET. - This command should always be terminated with read_end(). */ -extern inline unsigned char read_nibble(short port, unsigned char offset) -{ - unsigned char retval; - outb(EOC+offset, port + PAR_DATA); - outb(RdAddr+offset, port + PAR_DATA); - inbyte(port + PAR_STATUS); /* Settling time delay */ - retval = inbyte(port + PAR_STATUS); - outb(EOC+offset, port + PAR_DATA); - - return retval; -} - -/* Functions for bulk data read. The interrupt line is always disabled. */ -/* Get a byte using read mode 0, reading data from the control lines. */ -extern inline unsigned char read_byte_mode0(short ioaddr) -{ - unsigned char low_nib; - - outb(Ctrl_LNibRead, ioaddr + PAR_CONTROL); - inbyte(ioaddr + PAR_STATUS); - low_nib = (inbyte(ioaddr + PAR_STATUS) >> 3) & 0x0f; - outb(Ctrl_HNibRead, ioaddr + PAR_CONTROL); - inbyte(ioaddr + PAR_STATUS); /* Settling time delay -- needed! */ - inbyte(ioaddr + PAR_STATUS); /* Settling time delay -- needed! */ - return low_nib | ((inbyte(ioaddr + PAR_STATUS) << 1) & 0xf0); -} - -/* The same as read_byte_mode0(), but does multiple inb()s for stability. */ -extern inline unsigned char read_byte_mode2(short ioaddr) -{ - unsigned char low_nib; - - outb(Ctrl_LNibRead, ioaddr + PAR_CONTROL); - inbyte(ioaddr + PAR_STATUS); - low_nib = (inbyte(ioaddr + PAR_STATUS) >> 3) & 0x0f; - outb(Ctrl_HNibRead, ioaddr + PAR_CONTROL); - inbyte(ioaddr + PAR_STATUS); /* Settling time delay -- needed! */ - return low_nib | ((inbyte(ioaddr + PAR_STATUS) << 1) & 0xf0); -} - -/* Read a byte through the data register. */ -extern inline unsigned char read_byte_mode4(short ioaddr) -{ - unsigned char low_nib; - - outb(RdAddr | MAR, ioaddr + PAR_DATA); - low_nib = (inbyte(ioaddr + PAR_STATUS) >> 3) & 0x0f; - outb(RdAddr | HNib | MAR, ioaddr + PAR_DATA); - return low_nib | ((inbyte(ioaddr + PAR_STATUS) << 1) & 0xf0); -} - -/* Read a byte through the data register, double reading to allow settling. */ -extern inline unsigned char read_byte_mode6(short ioaddr) -{ - unsigned char low_nib; - - outb(RdAddr | MAR, ioaddr + PAR_DATA); - inbyte(ioaddr + PAR_STATUS); - low_nib = (inbyte(ioaddr + PAR_STATUS) >> 3) & 0x0f; - outb(RdAddr | HNib | MAR, ioaddr + PAR_DATA); - inbyte(ioaddr + PAR_STATUS); - return low_nib | ((inbyte(ioaddr + PAR_STATUS) << 1) & 0xf0); -} - -extern inline void -write_reg(short port, unsigned char reg, unsigned char value) -{ - unsigned char outval; - outb(EOC | reg, port + PAR_DATA); - outval = WrAddr | reg; - outb(outval, port + PAR_DATA); - outb(outval, port + PAR_DATA); /* Double write for PS/2. */ - - outval &= 0xf0; - outval |= value; - outb(outval, port + PAR_DATA); - outval &= 0x1f; - outb(outval, port + PAR_DATA); - outb(outval, port + PAR_DATA); - - outb(EOC | outval, port + PAR_DATA); -} - -extern inline void -write_reg_high(short port, unsigned char reg, unsigned char value) -{ - unsigned char outval = EOC | HNib | reg; - - outb(outval, port + PAR_DATA); - outval &= WrAddr | HNib | 0x0f; - outb(outval, port + PAR_DATA); - outb(outval, port + PAR_DATA); /* Double write for PS/2. */ - - outval = WrAddr | HNib | value; - outb(outval, port + PAR_DATA); - outval &= HNib | 0x0f; /* HNib | value */ - outb(outval, port + PAR_DATA); - outb(outval, port + PAR_DATA); - - outb(EOC | HNib | outval, port + PAR_DATA); -} - -/* Write a byte out using nibble mode. The low nibble is written first. */ -extern inline void -write_reg_byte(short port, unsigned char reg, unsigned char value) -{ - unsigned char outval; - outb(EOC | reg, port + PAR_DATA); /* Reset the address register. */ - outval = WrAddr | reg; - outb(outval, port + PAR_DATA); - outb(outval, port + PAR_DATA); /* Double write for PS/2. */ - - outb((outval & 0xf0) | (value & 0x0f), port + PAR_DATA); - outb(value & 0x0f, port + PAR_DATA); - value >>= 4; - outb(value, port + PAR_DATA); - outb(0x10 | value, port + PAR_DATA); - outb(0x10 | value, port + PAR_DATA); - - outb(EOC | value, port + PAR_DATA); /* Reset the address register. */ -} - -/* - * Bulk data writes to the packet buffer. The interrupt line remains enabled. - * The first, faster method uses only the dataport (data modes 0, 2 & 4). - * The second (backup) method uses data and control regs (modes 1, 3 & 5). - * It should only be needed when there is skew between the individual data - * lines. - */ -extern inline void write_byte_mode0(short ioaddr, unsigned char value) -{ - outb(value & 0x0f, ioaddr + PAR_DATA); - outb((value>>4) | 0x10, ioaddr + PAR_DATA); -} - -extern inline void write_byte_mode1(short ioaddr, unsigned char value) -{ - outb(value & 0x0f, ioaddr + PAR_DATA); - outb(Ctrl_IRQEN | Ctrl_LNibWrite, ioaddr + PAR_CONTROL); - outb((value>>4) | 0x10, ioaddr + PAR_DATA); - outb(Ctrl_IRQEN | Ctrl_HNibWrite, ioaddr + PAR_CONTROL); -} - -/* Write 16bit VALUE to the packet buffer: the same as above just doubled. */ -extern inline void write_word_mode0(short ioaddr, unsigned short value) -{ - outb(value & 0x0f, ioaddr + PAR_DATA); - value >>= 4; - outb((value & 0x0f) | 0x10, ioaddr + PAR_DATA); - value >>= 4; - outb(value & 0x0f, ioaddr + PAR_DATA); - value >>= 4; - outb((value & 0x0f) | 0x10, ioaddr + PAR_DATA); -} - -/* EEPROM_Ctrl bits. */ -#define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */ -#define EE_CS 0x02 /* EEPROM chip select. */ -#define EE_CLK_HIGH 0x12 -#define EE_CLK_LOW 0x16 -#define EE_DATA_WRITE 0x01 /* EEPROM chip data in. */ -#define EE_DATA_READ 0x08 /* EEPROM chip data out. */ - -/* Delay between EEPROM clock transitions. */ -#define eeprom_delay(ticks) \ -do { int _i = 40; while (--_i > 0) { __SLOW_DOWN_IO; }} while (0) - -/* The EEPROM commands include the alway-set leading bit. */ -#define EE_WRITE_CMD(offset) (((5 << 6) + (offset)) << 17) -#define EE_READ(offset) (((6 << 6) + (offset)) << 17) -#define EE_ERASE(offset) (((7 << 6) + (offset)) << 17) -#define EE_CMD_SIZE 27 /* The command+address+data size. */ diff --git a/i386/i386at/gpl/linux/net/de4x5.c b/i386/i386at/gpl/linux/net/de4x5.c deleted file mode 100644 index 249887a6..00000000 --- a/i386/i386at/gpl/linux/net/de4x5.c +++ /dev/null @@ -1,2788 +0,0 @@ -/* de4x5.c: A DIGITAL DE425/DE434/DE435/DE500 ethernet driver for Linux. - - Copyright 1994, 1995 Digital Equipment Corporation. - - This software may be used and distributed according to the terms of - the GNU Public License, incorporated herein by reference. - - This driver is written for the Digital Equipment Corporation series - of EtherWORKS ethernet cards: - - DE425 TP/COAX EISA - DE434 TP PCI - DE435 TP/COAX/AUI PCI - DE500 10/100 PCI Fasternet - - The driver has been tested on a relatively busy network using the DE425, - DE434, DE435 and DE500 cards and benchmarked with 'ttcp': it transferred - 16M of data to a DECstation 5000/200 as follows: - - TCP UDP - TX RX TX RX - DE425 1030k 997k 1170k 1128k - DE434 1063k 995k 1170k 1125k - DE435 1063k 995k 1170k 1125k - DE500 1063k 998k 1170k 1125k in 10Mb/s mode - - All values are typical (in kBytes/sec) from a sample of 4 for each - measurement. Their error is +/-20k on a quiet (private) network and also - depend on what load the CPU has. - - The author may be reached as davies@wanton.lkg.dec.com or Digital - Equipment Corporation, 550 King Street, Littleton MA 01460. - - ========================================================================= - This driver has been written substantially from scratch, although its - inheritance of style and stack interface from 'ewrk3.c' and in turn from - Donald Becker's 'lance.c' should be obvious. - - Upto 15 EISA cards can be supported under this driver, limited primarily - by the available IRQ lines. I have checked different configurations of - multiple depca, EtherWORKS 3 cards and de4x5 cards and have not found a - problem yet (provided you have at least depca.c v0.38) ... - - PCI support has been added to allow the driver to work with the DE434 - and DE435 cards. The I/O accesses are a bit of a kludge due to the - differences in the EISA and PCI CSR address offsets from the base - address. - - The ability to load this driver as a loadable module has been included - and used extensively during the driver development (to save those long - reboot sequences). Loadable module support under PCI has been achieved - by letting any I/O address less than 0x1000 be assigned as: - - 0xghh - - where g is the bus number (usually 0 until the BIOS's get fixed) - hh is the device number (max is 32 per bus). - - Essentially, the I/O address and IRQ information are ignored and filled - in later by the PCI BIOS during the PCI probe. Note that the board - should be in the system at boot time so that its I/O address and IRQ are - allocated by the PCI BIOS automatically. The special case of device 0 on - bus 0 is not allowed as the probe will think you're autoprobing a - module. - - To utilise this ability, you have to do 8 things: - - 0) have a copy of the loadable modules code installed on your system. - 1) copy de4x5.c from the /linux/drivers/net directory to your favourite - temporary directory. - 2) edit the source code near line 2762 to reflect the I/O address and - IRQ you're using, or assign these when loading by: - - insmod de4x5.o irq=x io=y - - 3) compile de4x5.c, but include -DMODULE in the command line to ensure - that the correct bits are compiled (see end of source code). - 4) if you are wanting to add a new card, goto 5. Otherwise, recompile a - kernel with the de4x5 configuration turned off and reboot. - 5) insmod de4x5.o - 6) run the net startup bits for your new eth?? interface manually - (usually /etc/rc.inet[12] at boot time). - 7) enjoy! - - Note that autoprobing is not allowed in loadable modules - the system is - already up and running and you're messing with interrupts. - - To unload a module, turn off the associated interface - 'ifconfig eth?? down' then 'rmmod de4x5'. - - Automedia detection is included so that in principal you can disconnect - from, e.g. TP, reconnect to BNC and things will still work (after a - pause whilst the driver figures out where its media went). My tests - using ping showed that it appears to work.... - - A compile time switch to allow Znyx recognition has been added. This - "feature" is in no way supported nor tested in this driver and the user - may use it at his/her sole discretion. I have had 2 conflicting reports - that my driver will or won't work with Znyx. Try Donald Becker's - 'tulip.c' if this driver doesn't work for you. I will not be supporting - Znyx cards since I have no information on them and can't test them in a - system. - - TO DO: - ------ - - - Revision History - ---------------- - - Version Date Description - - 0.1 17-Nov-94 Initial writing. ALPHA code release. - 0.2 13-Jan-95 Added PCI support for DE435's. - 0.21 19-Jan-95 Added auto media detection. - 0.22 10-Feb-95 Fix interrupt handler call <chris@cosy.sbg.ac.at>. - Fix recognition bug reported by <bkm@star.rl.ac.uk>. - Add request/release_region code. - Add loadable modules support for PCI. - Clean up loadable modules support. - 0.23 28-Feb-95 Added DC21041 and DC21140 support. - Fix missed frame counter value and initialisation. - Fixed EISA probe. - 0.24 11-Apr-95 Change delay routine to use <linux/udelay>. - Change TX_BUFFS_AVAIL macro. - Change media autodetection to allow manual setting. - Completed DE500 (DC21140) support. - 0.241 18-Apr-95 Interim release without DE500 Autosense Algorithm. - 0.242 10-May-95 Minor changes - 0.30 12-Jun-95 Timer fix for DC21140 - Portability changes. - Add ALPHA changes from <jestabro@ant.tay1.dec.com>. - Add DE500 semi automatic autosense. - Add Link Fail interrupt TP failure detection. - Add timer based link change detection. - Plugged a memory leak in de4x5_queue_pkt(). - 0.31 13-Jun-95 Fixed PCI stuff for 1.3.1 - 0.32 26-Jun-95 Added verify_area() calls in de4x5_ioctl() from - suggestion by <heiko@colossus.escape.de> - - ========================================================================= -*/ - -static const char *version = "de4x5.c:v0.32 6/26/95 davies@wanton.lkg.dec.com\n"; - -#include <linux/module.h> - -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/string.h> -#include <linux/interrupt.h> -#include <linux/ptrace.h> -#include <linux/errno.h> -#include <linux/ioport.h> -#include <linux/malloc.h> -#include <linux/bios32.h> -#include <linux/pci.h> -#include <linux/delay.h> -#include <asm/bitops.h> -#include <asm/io.h> -#include <asm/dma.h> -#include <asm/segment.h> - -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> - -#include <linux/time.h> -#include <linux/types.h> -#include <linux/unistd.h> - -#include "de4x5.h" - -#ifdef DE4X5_DEBUG -static int de4x5_debug = DE4X5_DEBUG; -#else -static int de4x5_debug = 1; -#endif - -#ifdef DE4X5_AUTOSENSE /* Should be done on a per adapter basis */ -static int de4x5_autosense = DE4X5_AUTOSENSE; -#else -static int de4x5_autosense = AUTO; /* Do auto media/mode sensing */ -#endif - -#ifdef DE4X5_FULL_DUPLEX /* Should be done on a per adapter basis */ -static s32 de4x5_full_duplex = 1; -#else -static s32 de4x5_full_duplex = 0; -#endif - -#define DE4X5_NDA 0xffe0 /* No Device (I/O) Address */ - -/* -** Ethernet PROM defines -*/ -#define PROBE_LENGTH 32 -#define ETH_PROM_SIG 0xAA5500FFUL - -/* -** Ethernet Info -*/ -#define PKT_BUF_SZ 1536 /* Buffer size for each Tx/Rx buffer */ -#define MAX_PKT_SZ 1514 /* Maximum ethernet packet length */ -#define MAX_DAT_SZ 1500 /* Maximum ethernet data length */ -#define MIN_DAT_SZ 1 /* Minimum ethernet data length */ -#define PKT_HDR_LEN 14 /* Addresses and data length info */ -#define FAKE_FRAME_LEN (MAX_PKT_SZ + 1) -#define QUEUE_PKT_TIMEOUT (3*HZ) /* 3 second timeout */ - - -#define CRC_POLYNOMIAL_BE 0x04c11db7UL /* Ethernet CRC, big endian */ -#define CRC_POLYNOMIAL_LE 0xedb88320UL /* Ethernet CRC, little endian */ - -/* -** EISA bus defines -*/ -#define DE4X5_EISA_IO_PORTS 0x0c00 /* I/O port base address, slot 0 */ -#define DE4X5_EISA_TOTAL_SIZE 0xfff /* I/O address extent */ - -#define MAX_EISA_SLOTS 16 -#define EISA_SLOT_INC 0x1000 - -#define DE4X5_SIGNATURE {"DE425",""} -#define DE4X5_NAME_LENGTH 8 - -/* -** PCI Bus defines -*/ -#define PCI_MAX_BUS_NUM 8 -#define DE4X5_PCI_TOTAL_SIZE 0x80 /* I/O address extent */ -#define DE4X5_CLASS_CODE 0x00020000 /* Network controller, Ethernet */ - -/* -** Memory Alignment. Each descriptor is 4 longwords long. To force a -** particular alignment on the TX descriptor, adjust DESC_SKIP_LEN and -** DESC_ALIGN. ALIGN aligns the start address of the private memory area -** and hence the RX descriptor ring's first entry. -*/ -#define ALIGN4 ((u_long)4 - 1) /* 1 longword align */ -#define ALIGN8 ((u_long)8 - 1) /* 2 longword align */ -#define ALIGN16 ((u_long)16 - 1) /* 4 longword align */ -#define ALIGN32 ((u_long)32 - 1) /* 8 longword align */ -#define ALIGN64 ((u_long)64 - 1) /* 16 longword align */ -#define ALIGN128 ((u_long)128 - 1) /* 32 longword align */ - -#define ALIGN ALIGN32 /* Keep the DC21040 happy... */ -#define CACHE_ALIGN CAL_16LONG -#define DESC_SKIP_LEN DSL_0 /* Must agree with DESC_ALIGN */ -/*#define DESC_ALIGN u32 dummy[4]; / * Must agree with DESC_SKIP_LEN */ -#define DESC_ALIGN - -#ifdef MACH -#define IS_NOT_DEC -#endif - -#ifndef IS_NOT_DEC /* See README.de4x5 for using this */ -static int is_not_dec = 0; -#else -static int is_not_dec = 1; -#endif - -/* -** DE4X5 IRQ ENABLE/DISABLE -*/ -#define ENABLE_IRQs { \ - imr |= lp->irq_en;\ - outl(imr, DE4X5_IMR); /* Enable the IRQs */\ -} - -#define DISABLE_IRQs {\ - imr = inl(DE4X5_IMR);\ - imr &= ~lp->irq_en;\ - outl(imr, DE4X5_IMR); /* Disable the IRQs */\ -} - -#define UNMASK_IRQs {\ - imr |= lp->irq_mask;\ - outl(imr, DE4X5_IMR); /* Unmask the IRQs */\ -} - -#define MASK_IRQs {\ - imr = inl(DE4X5_IMR);\ - imr &= ~lp->irq_mask;\ - outl(imr, DE4X5_IMR); /* Mask the IRQs */\ -} - -/* -** DE4X5 START/STOP -*/ -#define START_DE4X5 {\ - omr = inl(DE4X5_OMR);\ - omr |= OMR_ST | OMR_SR;\ - outl(omr, DE4X5_OMR); /* Enable the TX and/or RX */\ -} - -#define STOP_DE4X5 {\ - omr = inl(DE4X5_OMR);\ - omr &= ~(OMR_ST|OMR_SR);\ - outl(omr, DE4X5_OMR); /* Disable the TX and/or RX */ \ -} - -/* -** DE4X5 SIA RESET -*/ -#define RESET_SIA outl(0, DE4X5_SICR); /* Reset SIA connectivity regs */ - -/* -** DE500 AUTOSENSE TIMER INTERVAL (MILLISECS) -*/ -#define DE4X5_AUTOSENSE_MS 250 - -/* -** SROM Structure -*/ -struct de4x5_srom { - char reserved[18]; - char version; - char num_adapters; - char ieee_addr[6]; - char info[100]; - short chksum; -}; - -/* -** DE4X5 Descriptors. Make sure that all the RX buffers are contiguous -** and have sizes of both a power of 2 and a multiple of 4. -** A size of 256 bytes for each buffer could be chosen because over 90% of -** all packets in our network are <256 bytes long and 64 longword alignment -** is possible. 1536 showed better 'ttcp' performance. Take your pick. 32 TX -** descriptors are needed for machines with an ALPHA CPU. -*/ -#define NUM_RX_DESC 8 /* Number of RX descriptors */ -#define NUM_TX_DESC 32 /* Number of TX descriptors */ -#define BUFF_ALLOC_RETRIES 10 /* In case of memory shortage */ -#define RX_BUFF_SZ 1536 /* Power of 2 for kmalloc and */ - /* Multiple of 4 for DC21040 */ -struct de4x5_desc { - volatile s32 status; - u32 des1; - u32 buf; - u32 next; - DESC_ALIGN -}; - -/* -** The DE4X5 private structure -*/ -#define DE4X5_PKT_STAT_SZ 16 -#define DE4X5_PKT_BIN_SZ 128 /* Should be >=100 unless you - increase DE4X5_PKT_STAT_SZ */ - -struct de4x5_private { - char adapter_name[80]; /* Adapter name */ - struct de4x5_desc rx_ring[NUM_RX_DESC]; /* RX descriptor ring */ - struct de4x5_desc tx_ring[NUM_TX_DESC]; /* TX descriptor ring */ - struct sk_buff *skb[NUM_TX_DESC]; /* TX skb for freeing when sent */ - int rx_new, rx_old; /* RX descriptor ring pointers */ - int tx_new, tx_old; /* TX descriptor ring pointers */ - char setup_frame[SETUP_FRAME_LEN]; /* Holds MCA and PA info. */ - struct enet_statistics stats; /* Public stats */ - struct { - u_int bins[DE4X5_PKT_STAT_SZ]; /* Private stats counters */ - u_int unicast; - u_int multicast; - u_int broadcast; - u_int excessive_collisions; - u_int tx_underruns; - u_int excessive_underruns; - } pktStats; - char rxRingSize; - char txRingSize; - int bus; /* EISA or PCI */ - int bus_num; /* PCI Bus number */ - int chipset; /* DC21040, DC21041 or DC21140 */ - s32 irq_mask; /* Interrupt Mask (Enable) bits */ - s32 irq_en; /* Summary interrupt bits */ - int media; /* Media (eg TP), mode (eg 100B)*/ - int linkProb; /* Possible Link Problem */ - int autosense; /* Allow/disallow autosensing */ - int tx_enable; /* Enable descriptor polling */ - int lostMedia; /* Possibly lost media */ - int setup_f; /* Setup frame filtering type */ -}; - - -/* -** The transmit ring full condition is described by the tx_old and tx_new -** pointers by: -** tx_old = tx_new Empty ring -** tx_old = tx_new+1 Full ring -** tx_old+txRingSize = tx_new+1 Full ring (wrapped condition) -*/ -#define TX_BUFFS_AVAIL ((lp->tx_old<=lp->tx_new)?\ - lp->tx_old+lp->txRingSize-lp->tx_new-1:\ - lp->tx_old -lp->tx_new-1) - -/* -** Public Functions -*/ -static int de4x5_open(struct device *dev); -static int de4x5_queue_pkt(struct sk_buff *skb, struct device *dev); -static void de4x5_interrupt(int irq, struct pt_regs *regs); -static int de4x5_close(struct device *dev); -static struct enet_statistics *de4x5_get_stats(struct device *dev); -static void set_multicast_list(struct device *dev); -static int de4x5_ioctl(struct device *dev, struct ifreq *rq, int cmd); - -/* -** Private functions -*/ -static int de4x5_hw_init(struct device *dev, u_long iobase); -static int de4x5_init(struct device *dev); -static int de4x5_rx(struct device *dev); -static int de4x5_tx(struct device *dev); -static int de4x5_ast(struct device *dev); - -static int autoconf_media(struct device *dev); -static void create_packet(struct device *dev, char *frame, int len); -static void dce_us_delay(u32 usec); -static void dce_ms_delay(u32 msec); -static void load_packet(struct device *dev, char *buf, u32 flags, struct sk_buff *skb); -static void dc21040_autoconf(struct device *dev); -static void dc21041_autoconf(struct device *dev); -static void dc21140_autoconf(struct device *dev); -static int test_media(struct device *dev, s32 irqs, s32 irq_mask, s32 csr13, s32 csr14, s32 csr15, s32 msec); -/*static int test_sym_link(struct device *dev, u32 msec);*/ -static int ping_media(struct device *dev); -static void reset_init_sia(struct device *dev, s32 sicr, s32 strr, s32 sigr); -static int test_ans(struct device *dev, s32 irqs, s32 irq_mask, s32 msec); -static void load_ms_timer(struct device *dev, u32 msec); -static int EISA_signature(char *name, s32 eisa_id); -static int DevicePresent(u_long iobase); -static short srom_rd(u_long address, u_char offset); -static void srom_latch(u_int command, u_long address); -static void srom_command(u_int command, u_long address); -static void srom_address(u_int command, u_long address, u_char offset); -static short srom_data(u_int command, u_long address); -/*static void srom_busy(u_int command, u_long address);*/ -static void sendto_srom(u_int command, u_long addr); -static int getfrom_srom(u_long addr); -static void SetMulticastFilter(struct device *dev); -static int get_hw_addr(struct device *dev); - -static void eisa_probe(struct device *dev, u_long iobase); -static void pci_probe(struct device *dev, u_long iobase); -static struct device *alloc_device(struct device *dev, u_long iobase); -static char *build_setup_frame(struct device *dev, int mode); -static void disable_ast(struct device *dev); -static void enable_ast(struct device *dev, u32 time_out); -static void kick_tx(struct device *dev); - -#ifdef MODULE -int init_module(void); -void cleanup_module(void); -static int autoprobed = 1, loading_module = 1; -# else -static unsigned char de4x5_irq[] = {5,9,10,11}; -static int autoprobed = 0, loading_module = 0; -#endif /* MODULE */ - -static char name[DE4X5_NAME_LENGTH + 1]; -static int num_de4x5s = 0, num_eth = 0; - -/* -** Kludge to get around the fact that the CSR addresses have different -** offsets in the PCI and EISA boards. Also note that the ethernet address -** PROM is accessed differently. -*/ -static struct bus_type { - int bus; - int bus_num; - int device; - int chipset; - struct de4x5_srom srom; - int autosense; -} bus; - -/* -** Miscellaneous defines... -*/ -#define RESET_DE4X5 {\ - int i;\ - i=inl(DE4X5_BMR);\ - dce_ms_delay(1);\ - outl(i | BMR_SWR, DE4X5_BMR);\ - dce_ms_delay(1);\ - outl(i, DE4X5_BMR);\ - dce_ms_delay(1);\ - for (i=0;i<5;i++) {inl(DE4X5_BMR); dce_ms_delay(1);}\ - dce_ms_delay(1);\ -} - - - -int de4x5_probe(struct device *dev) -{ - int tmp = num_de4x5s, status = -ENODEV; - u_long iobase = dev->base_addr; - - if ((iobase == 0) && loading_module){ - printk("Autoprobing is not supported when loading a module based driver.\n"); - status = -EIO; - } else { - eisa_probe(dev, iobase); - pci_probe(dev, iobase); - - if ((tmp == num_de4x5s) && (iobase != 0) && loading_module) { - printk("%s: de4x5_probe() cannot find device at 0x%04lx.\n", dev->name, - iobase); - } - - /* - ** Walk the device list to check that at least one device - ** initialised OK - */ - for (; (dev->priv == NULL) && (dev->next != NULL); dev = dev->next); - - if (dev->priv) status = 0; - if (iobase == 0) autoprobed = 1; - } - - return status; -} - -static int -de4x5_hw_init(struct device *dev, u_long iobase) -{ - struct bus_type *lp = &bus; - int tmpbus, tmpchs, i, j, status=0; - char *tmp; - - /* Ensure we're not sleeping */ - if (lp->chipset == DC21041) { - outl(0, PCI_CFDA); - dce_ms_delay(10); - } - - RESET_DE4X5; - - if ((inl(DE4X5_STS) & (STS_TS | STS_RS)) == 0) { - /* - ** Now find out what kind of DC21040/DC21041/DC21140 board we have. - */ - if (lp->bus == PCI) { - if (!is_not_dec) { - if ((lp->chipset == DC21040) || (lp->chipset == DC21041)) { - strcpy(name, "DE435"); - } else if (lp->chipset == DC21140) { - strcpy(name, "DE500"); /* Must read the SROM here! */ - } - } else { - strcpy(name, "UNKNOWN"); - } - } else { - EISA_signature(name, EISA_ID0); - } - - if (*name != '\0') { /* found a board signature */ - dev->base_addr = iobase; - if (lp->bus == EISA) { - printk("%s: %s at %04lx (EISA slot %ld)", - dev->name, name, iobase, ((iobase>>12)&0x0f)); - } else { /* PCI port address */ - printk("%s: %s at %04lx (PCI bus %d, device %d)", dev->name, name, - iobase, lp->bus_num, lp->device); - } - - printk(", h/w address "); - status = get_hw_addr(dev); - for (i = 0; i < ETH_ALEN - 1; i++) { /* get the ethernet addr. */ - printk("%2.2x:", dev->dev_addr[i]); - } - printk("%2.2x,\n", dev->dev_addr[i]); - - tmpbus = lp->bus; - tmpchs = lp->chipset; - - if (status == 0) { - struct de4x5_private *lp; - - /* - ** Reserve a section of kernel memory for the adapter - ** private area and the TX/RX descriptor rings. - */ - dev->priv = (void *) kmalloc(sizeof(struct de4x5_private) + ALIGN, - GFP_KERNEL); - if (dev->priv == NULL) - return -ENOMEM; - /* - ** Align to a longword boundary - */ - dev->priv = (void *)(((u_long)dev->priv + ALIGN) & ~ALIGN); - lp = (struct de4x5_private *)dev->priv; - memset(dev->priv, 0, sizeof(struct de4x5_private)); - lp->bus = tmpbus; - lp->chipset = tmpchs; - - /* - ** Choose autosensing - */ - if (de4x5_autosense & AUTO) { - lp->autosense = AUTO; - } else { - if (lp->chipset != DC21140) { - if ((lp->chipset == DC21040) && (de4x5_autosense & TP_NW)) { - de4x5_autosense = TP; - } - if ((lp->chipset == DC21041) && (de4x5_autosense & BNC_AUI)) { - de4x5_autosense = BNC; - } - lp->autosense = de4x5_autosense & 0x001f; - } else { - lp->autosense = de4x5_autosense & 0x00c0; - } - } - - sprintf(lp->adapter_name,"%s (%s)", name, dev->name); - request_region(iobase, (lp->bus == PCI ? DE4X5_PCI_TOTAL_SIZE : - DE4X5_EISA_TOTAL_SIZE), - lp->adapter_name); - - /* - ** Allocate contiguous receive buffers, long word aligned. - ** This could be a possible memory leak if the private area - ** is ever hosed. - */ - for (tmp=NULL, j=0; (j<BUFF_ALLOC_RETRIES) && (tmp==NULL); j++) { - if ((tmp = (void *)kmalloc(RX_BUFF_SZ * NUM_RX_DESC + ALIGN, - GFP_KERNEL)) != NULL) { - tmp = (char *)(((u_long) tmp + ALIGN) & ~ALIGN); - for (i=0; i<NUM_RX_DESC; i++) { - lp->rx_ring[i].status = 0; - lp->rx_ring[i].des1 = RX_BUFF_SZ; - lp->rx_ring[i].buf = virt_to_bus(tmp + i * RX_BUFF_SZ); - lp->rx_ring[i].next = (u32)NULL; - } - barrier(); - } - } - - if (tmp != NULL) { - lp->rxRingSize = NUM_RX_DESC; - lp->txRingSize = NUM_TX_DESC; - - /* Write the end of list marker to the descriptor lists */ - lp->rx_ring[lp->rxRingSize - 1].des1 |= RD_RER; - lp->tx_ring[lp->txRingSize - 1].des1 |= TD_TER; - - /* Tell the adapter where the TX/RX rings are located. */ - outl(virt_to_bus(lp->rx_ring), DE4X5_RRBA); - outl(virt_to_bus(lp->tx_ring), DE4X5_TRBA); - - /* Initialise the IRQ mask and Enable/Disable */ - lp->irq_mask = IMR_RIM | IMR_TIM | IMR_TUM ; - lp->irq_en = IMR_NIM | IMR_AIM; - - lp->tx_enable = TRUE; - - if (dev->irq < 2) { -#ifndef MODULE - unsigned char irqnum; - s32 omr; - autoirq_setup(0); - - omr = inl(DE4X5_OMR); - outl(IMR_AIM|IMR_RUM, DE4X5_IMR); /* Unmask RUM interrupt */ - outl(OMR_SR | omr, DE4X5_OMR); /* Start RX w/no descriptors */ - - irqnum = autoirq_report(1); - if (!irqnum) { - printk(" and failed to detect IRQ line.\n"); - status = -ENXIO; - } else { - for (dev->irq=0,i=0; (i<sizeof(de4x5_irq)) && (!dev->irq); i++) { - if (irqnum == de4x5_irq[i]) { - dev->irq = irqnum; - printk(" and uses IRQ%d.\n", dev->irq); - } - } - - if (!dev->irq) { - printk(" but incorrect IRQ line detected.\n"); - status = -ENXIO; - } - } - - outl(0, DE4X5_IMR); /* Re-mask RUM interrupt */ - -#endif /* MODULE */ - } else { - printk(" and requires IRQ%d (not probed).\n", dev->irq); - } - } else { - printk("%s: Kernel could not allocate RX buffer memory.\n", - dev->name); - status = -ENXIO; - } - if (status) release_region(iobase, (lp->bus == PCI ? - DE4X5_PCI_TOTAL_SIZE : - DE4X5_EISA_TOTAL_SIZE)); - } else { - printk(" which has an Ethernet PROM CRC error.\n"); - status = -ENXIO; - } - } else { - status = -ENXIO; - } - } else { - status = -ENXIO; - } - - if (!status) { - if (de4x5_debug > 0) { - printk(version); - } - - /* The DE4X5-specific entries in the device structure. */ - dev->open = &de4x5_open; - dev->hard_start_xmit = &de4x5_queue_pkt; - dev->stop = &de4x5_close; - dev->get_stats = &de4x5_get_stats; - dev->set_multicast_list = &set_multicast_list; - dev->do_ioctl = &de4x5_ioctl; - - dev->mem_start = 0; - - /* Fill in the generic field of the device structure. */ - ether_setup(dev); - - /* Let the adapter sleep to save power */ - if (lp->chipset == DC21041) { - outl(0, DE4X5_SICR); - outl(CFDA_PSM, PCI_CFDA); - } - } else { /* Incorrectly initialised hardware */ - struct de4x5_private *lp = (struct de4x5_private *)dev->priv; - if (lp) { - kfree_s(bus_to_virt(lp->rx_ring[0].buf), - RX_BUFF_SZ * NUM_RX_DESC + ALIGN); - } - if (dev->priv) { - kfree_s(dev->priv, sizeof(struct de4x5_private) + ALIGN); - dev->priv = NULL; - } - } - - return status; -} - - -static int -de4x5_open(struct device *dev) -{ - struct de4x5_private *lp = (struct de4x5_private *)dev->priv; - u_long iobase = dev->base_addr; - int i, status = 0; - s32 imr, omr, sts; - - /* - ** Wake up the adapter - */ - if (lp->chipset == DC21041) { - outl(0, PCI_CFDA); - dce_ms_delay(10); - } - - if (request_irq(dev->irq, (void *)de4x5_interrupt, 0, lp->adapter_name)) { - printk("de4x5_open(): Requested IRQ%d is busy\n",dev->irq); - status = -EAGAIN; - } else { - - irq2dev_map[dev->irq] = dev; - /* - ** Re-initialize the DE4X5... - */ - status = de4x5_init(dev); - - if (de4x5_debug > 1){ - printk("%s: de4x5 open with irq %d\n",dev->name,dev->irq); - printk("\tphysical address: "); - for (i=0;i<6;i++){ - printk("%2.2x:",(short)dev->dev_addr[i]); - } - printk("\n"); - printk("Descriptor head addresses:\n"); - printk("\t0x%8.8lx 0x%8.8lx\n",(u_long)lp->rx_ring,(u_long)lp->tx_ring); - printk("Descriptor addresses:\nRX: "); - for (i=0;i<lp->rxRingSize-1;i++){ - if (i < 3) { - printk("0x%8.8lx ",(u_long)&lp->rx_ring[i].status); - } - } - printk("...0x%8.8lx\n",(u_long)&lp->rx_ring[i].status); - printk("TX: "); - for (i=0;i<lp->txRingSize-1;i++){ - if (i < 3) { - printk("0x%8.8lx ", (u_long)&lp->tx_ring[i].status); - } - } - printk("...0x%8.8lx\n", (u_long)&lp->tx_ring[i].status); - printk("Descriptor buffers:\nRX: "); - for (i=0;i<lp->rxRingSize-1;i++){ - if (i < 3) { - printk("0x%8.8x ",lp->rx_ring[i].buf); - } - } - printk("...0x%8.8x\n",lp->rx_ring[i].buf); - printk("TX: "); - for (i=0;i<lp->txRingSize-1;i++){ - if (i < 3) { - printk("0x%8.8x ", lp->tx_ring[i].buf); - } - } - printk("...0x%8.8x\n", lp->tx_ring[i].buf); - printk("Ring size: \nRX: %d\nTX: %d\n", - (short)lp->rxRingSize, - (short)lp->txRingSize); - printk("\tstatus: %d\n", status); - } - - if (!status) { - dev->tbusy = 0; - dev->start = 1; - dev->interrupt = UNMASK_INTERRUPTS; - dev->trans_start = jiffies; - - START_DE4X5; - - /* Unmask and enable DE4X5 board interrupts */ - imr = 0; - UNMASK_IRQs; - - /* Reset any pending (stale) interrupts */ - sts = inl(DE4X5_STS); - outl(sts, DE4X5_STS); - - ENABLE_IRQs; - } - if (de4x5_debug > 1) { - printk("\tsts: 0x%08x\n", inl(DE4X5_STS)); - printk("\tbmr: 0x%08x\n", inl(DE4X5_BMR)); - printk("\timr: 0x%08x\n", inl(DE4X5_IMR)); - printk("\tomr: 0x%08x\n", inl(DE4X5_OMR)); - printk("\tsisr: 0x%08x\n", inl(DE4X5_SISR)); - printk("\tsicr: 0x%08x\n", inl(DE4X5_SICR)); - printk("\tstrr: 0x%08x\n", inl(DE4X5_STRR)); - printk("\tsigr: 0x%08x\n", inl(DE4X5_SIGR)); - } - } - - MOD_INC_USE_COUNT; - - return status; -} - -/* -** Initialize the DE4X5 operating conditions. NB: a chip problem with the -** DC21140 requires using perfect filtering mode for that chip. Since I can't -** see why I'd want > 14 multicast addresses, I may change all chips to use -** the perfect filtering mode. Keep the DMA burst length at 8: there seems -** to be data corruption problems if it is larger (UDP errors seen from a -** ttcp source). -*/ -static int -de4x5_init(struct device *dev) -{ - struct de4x5_private *lp = (struct de4x5_private *)dev->priv; - u_long iobase = dev->base_addr; - int i, j, status = 0; - s32 bmr, omr; - - /* Lock out other processes whilst setting up the hardware */ - set_bit(0, (void *)&dev->tbusy); - - RESET_DE4X5; - - bmr = inl(DE4X5_BMR); - bmr |= PBL_8 | DESC_SKIP_LEN | CACHE_ALIGN; - outl(bmr, DE4X5_BMR); - - if (lp->chipset != DC21140) { - omr = TR_96; - lp->setup_f = HASH_PERF; - } else { - omr = OMR_SDP | OMR_SF; - lp->setup_f = PERFECT; - } - outl(virt_to_bus(lp->rx_ring), DE4X5_RRBA); - outl(virt_to_bus(lp->tx_ring), DE4X5_TRBA); - - lp->rx_new = lp->rx_old = 0; - lp->tx_new = lp->tx_old = 0; - - for (i = 0; i < lp->rxRingSize; i++) { - lp->rx_ring[i].status = R_OWN; - } - - for (i = 0; i < lp->txRingSize; i++) { - lp->tx_ring[i].status = 0; - } - - barrier(); - - /* Build the setup frame depending on filtering mode */ - SetMulticastFilter(dev); - - if (lp->chipset != DC21140) { - load_packet(dev, lp->setup_frame, HASH_F|TD_SET|SETUP_FRAME_LEN, NULL); - } else { - load_packet(dev, lp->setup_frame, PERFECT_F|TD_SET|SETUP_FRAME_LEN, NULL); - } - outl(omr|OMR_ST, DE4X5_OMR); - - /* Poll for completion of setup frame (interrupts are disabled for now) */ - for (j=0, i=jiffies;(i<=jiffies+HZ/100) && (j==0);) { - if (lp->tx_ring[lp->tx_new].status >= 0) j=1; - } - outl(omr, DE4X5_OMR); /* Stop everything! */ - - if (j == 0) { - printk("%s: Setup frame timed out, status %08x\n", dev->name, - inl(DE4X5_STS)); - status = -EIO; - } - - lp->tx_new = (++lp->tx_new) % lp->txRingSize; - lp->tx_old = lp->tx_new; - - /* Autoconfigure the connected port */ - if (autoconf_media(dev) == 0) { - status = -EIO; - } - - return 0; -} - -/* -** Writes a socket buffer address to the next available transmit descriptor -*/ -static int -de4x5_queue_pkt(struct sk_buff *skb, struct device *dev) -{ - struct de4x5_private *lp = (struct de4x5_private *)dev->priv; - u_long iobase = dev->base_addr; - int i, status = 0; - s32 imr, omr, sts; - - /* - ** Clean out the TX ring asynchronously to interrupts - sometimes the - ** interrupts are lost by delayed descriptor status updates relative to - ** the irq assertion, especially with a busy PCI bus. - */ - if (set_bit(0, (void*)&dev->tbusy) == 0) { - cli(); - de4x5_tx(dev); - dev->tbusy = 0; - sti(); - } - - /* - ** Transmitter timeout, possibly serious problems. - ** The 'lostMedia' threshold accounts for transient errors that - ** were noticed when switching media. - */ - if (dev->tbusy || (lp->lostMedia > LOST_MEDIA_THRESHOLD)) { - u_long tickssofar = jiffies - dev->trans_start; - if ((tickssofar < QUEUE_PKT_TIMEOUT) && - (lp->lostMedia <= LOST_MEDIA_THRESHOLD)) { - status = -1; - } else { - if (de4x5_debug >= 1) { - printk("%s: transmit timed out, status %08x, tbusy:%ld, lostMedia:%d tickssofar:%ld, resetting.\n",dev->name, inl(DE4X5_STS), dev->tbusy, lp->lostMedia, tickssofar); - } - - /* Stop and reset the TX and RX... */ - STOP_DE4X5; - - /* Re-queue any skb's. */ - for (i=lp->tx_old; i!=lp->tx_new; i=(++i)%lp->txRingSize) { - if (lp->skb[i] != NULL) { - if (lp->skb[i]->len != FAKE_FRAME_LEN) { - if (lp->tx_ring[i].status == T_OWN) { - dev_queue_xmit(lp->skb[i], dev, SOPRI_NORMAL); - } else { /* already sent */ - dev_kfree_skb(lp->skb[i], FREE_WRITE); - } - } else { - dev_kfree_skb(lp->skb[i], FREE_WRITE); - } - lp->skb[i] = NULL; - } - } - if (skb->len != FAKE_FRAME_LEN) { - dev_queue_xmit(skb, dev, SOPRI_NORMAL); - } else { - dev_kfree_skb(skb, FREE_WRITE); - } - - /* Initialise the hardware */ - status = de4x5_init(dev); - - /* Unmask DE4X5 board interrupts */ - if (!status) { - /* Start here to clean stale interrupts later */ - dev->interrupt = UNMASK_INTERRUPTS; - dev->start = 1; - dev->tbusy = 0; - dev->trans_start = jiffies; - - START_DE4X5; - - /* Unmask DE4X5 board interrupts */ - imr = 0; - UNMASK_IRQs; - - /* Clear any pending (stale) interrupts */ - sts = inl(DE4X5_STS); - outl(sts, DE4X5_STS); - - ENABLE_IRQs; - } else { - printk("%s: hardware initialisation failure, status %08x.\n", - dev->name, inl(DE4X5_STS)); - } - } - } else if (skb == NULL) { - dev_tint(dev); - } else if (skb->len == FAKE_FRAME_LEN) { /* Don't TX a fake frame! */ - dev_kfree_skb(skb, FREE_WRITE); - } else if (skb->len > 0) { - /* Enforce 1 process per h/w access */ - if (set_bit(0, (void*)&dev->tbusy) != 0) { - printk("%s: Transmitter access conflict.\n", dev->name); - status = -1; /* Re-queue packet */ - } else { - cli(); - if (TX_BUFFS_AVAIL) { /* Fill in a Tx ring entry */ - load_packet(dev, skb->data, TD_IC | TD_LS | TD_FS | skb->len, skb); - if (lp->tx_enable) { - outl(POLL_DEMAND, DE4X5_TPD); /* Start the TX */ - } - - lp->tx_new = (++lp->tx_new) % lp->txRingSize; /* Ensure a wrap */ - dev->trans_start = jiffies; - - if (TX_BUFFS_AVAIL) { - dev->tbusy = 0; /* Another pkt may be queued */ - } - } else { /* Ring full - re-queue */ - status = -1; - } - sti(); - } - } - - return status; -} - -/* -** The DE4X5 interrupt handler. -** -** I/O Read/Writes through intermediate PCI bridges are never 'posted', -** so that the asserted interrupt always has some real data to work with - -** if these I/O accesses are ever changed to memory accesses, ensure the -** STS write is read immediately to complete the transaction if the adapter -** is not on bus 0. Lost interrupts can still occur when the PCI bus load -** is high and descriptor status bits cannot be set before the associated -** interrupt is asserted and this routine entered. -*/ -static void -de4x5_interrupt(int irq, struct pt_regs *regs) -{ - struct device *dev = (struct device *)(irq2dev_map[irq]); - struct de4x5_private *lp; - s32 imr, omr, sts; - u_long iobase; - - if (dev == NULL) { - printk ("de4x5_interrupt(): irq %d for unknown device.\n", irq); - } else { - lp = (struct de4x5_private *)dev->priv; - iobase = dev->base_addr; - - if (dev->interrupt) - printk("%s: Re-entering the interrupt handler.\n", dev->name); - - DISABLE_IRQs; /* Ensure non re-entrancy */ - dev->interrupt = MASK_INTERRUPTS; - - while ((sts = inl(DE4X5_STS)) & lp->irq_mask) { /* Read IRQ status */ - outl(sts, DE4X5_STS); /* Reset the board interrupts */ - - if (sts & (STS_RI | STS_RU)) /* Rx interrupt (packet[s] arrived) */ - de4x5_rx(dev); - - if (sts & (STS_TI | STS_TU)) /* Tx interrupt (packet sent) */ - de4x5_tx(dev); - - if (sts & STS_TM) /* Autosense tick */ - de4x5_ast(dev); - - if (sts & STS_LNF) { /* TP Link has failed */ - lp->lostMedia = LOST_MEDIA_THRESHOLD + 1; - lp->irq_mask &= ~IMR_LFM; - kick_tx(dev); - } - - if (sts & STS_SE) { /* Bus Error */ - STOP_DE4X5; - printk("%s: Fatal bus error occured, sts=%#8x, device stopped.\n", - dev->name, sts); - } - } - - if (TX_BUFFS_AVAIL && dev->tbusy) {/* Any resources available? */ - dev->tbusy = 0; /* Clear TX busy flag */ - mark_bh(NET_BH); - } - - dev->interrupt = UNMASK_INTERRUPTS; - ENABLE_IRQs; - } - - return; -} - -static int -de4x5_rx(struct device *dev) -{ - struct de4x5_private *lp = (struct de4x5_private *)dev->priv; - int i, entry; - s32 status; - char *buf; - - for (entry = lp->rx_new; lp->rx_ring[entry].status >= 0;entry = lp->rx_new) { - status = lp->rx_ring[entry].status; - - if (status & RD_FS) { /* Remember the start of frame */ - lp->rx_old = entry; - } - - if (status & RD_LS) { /* Valid frame status */ - if (status & RD_ES) { /* There was an error. */ - lp->stats.rx_errors++; /* Update the error stats. */ - if (status & (RD_RF | RD_TL)) lp->stats.rx_frame_errors++; - if (status & RD_CE) lp->stats.rx_crc_errors++; - if (status & RD_OF) lp->stats.rx_fifo_errors++; - } else { /* A valid frame received */ - struct sk_buff *skb; - short pkt_len = (short)(lp->rx_ring[entry].status >> 16) - 4; - - if ((skb = dev_alloc_skb(pkt_len+2)) != NULL) { - skb->dev = dev; - - skb_reserve(skb,2); /* Align */ - if (entry < lp->rx_old) { /* Wrapped buffer */ - short len = (lp->rxRingSize - lp->rx_old) * RX_BUFF_SZ; - memcpy(skb_put(skb,len), bus_to_virt(lp->rx_ring[lp->rx_old].buf), len); - memcpy(skb_put(skb,pkt_len-len), bus_to_virt(lp->rx_ring[0].buf), pkt_len - len); - } else { /* Linear buffer */ - memcpy(skb_put(skb,pkt_len), bus_to_virt(lp->rx_ring[lp->rx_old].buf), pkt_len); - } - - /* Push up the protocol stack */ - skb->protocol=eth_type_trans(skb,dev); - netif_rx(skb); - - /* Update stats */ - lp->stats.rx_packets++; - for (i=1; i<DE4X5_PKT_STAT_SZ-1; i++) { - if (pkt_len < (i*DE4X5_PKT_BIN_SZ)) { - lp->pktStats.bins[i]++; - i = DE4X5_PKT_STAT_SZ; - } - } - buf = skb->data; /* Look at the dest addr */ - if (buf[0] & 0x01) { /* Multicast/Broadcast */ - if ((*(s32 *)&buf[0] == -1) && (*(s16 *)&buf[4] == -1)) { - lp->pktStats.broadcast++; - } else { - lp->pktStats.multicast++; - } - } else if ((*(s32 *)&buf[0] == *(s32 *)&dev->dev_addr[0]) && - (*(s16 *)&buf[4] == *(s16 *)&dev->dev_addr[4])) { - lp->pktStats.unicast++; - } - - lp->pktStats.bins[0]++; /* Duplicates stats.rx_packets */ - if (lp->pktStats.bins[0] == 0) { /* Reset counters */ - memset((char *)&lp->pktStats, 0, sizeof(lp->pktStats)); - } - } else { - printk("%s: Insufficient memory; nuking packet.\n", dev->name); - lp->stats.rx_dropped++; /* Really, deferred. */ - break; - } - } - - /* Change buffer ownership for this last frame, back to the adapter */ - for (; lp->rx_old!=entry; lp->rx_old=(++lp->rx_old)%lp->rxRingSize) { - lp->rx_ring[lp->rx_old].status = R_OWN; - barrier(); - } - lp->rx_ring[entry].status = R_OWN; - barrier(); - } - - /* - ** Update entry information - */ - lp->rx_new = (++lp->rx_new) % lp->rxRingSize; - } - - return 0; -} - -/* -** Buffer sent - check for TX buffer errors. -*/ -static int -de4x5_tx(struct device *dev) -{ - struct de4x5_private *lp = (struct de4x5_private *)dev->priv; - u_long iobase = dev->base_addr; - int entry; - s32 status; - - for (entry = lp->tx_old; entry != lp->tx_new; entry = lp->tx_old) { - status = lp->tx_ring[entry].status; - if (status < 0) { /* Buffer not sent yet */ - break; - } else if (status & TD_ES) { /* An error happened */ - lp->stats.tx_errors++; - if (status & TD_NC) lp->stats.tx_carrier_errors++; - if (status & TD_LC) lp->stats.tx_window_errors++; - if (status & TD_UF) lp->stats.tx_fifo_errors++; - if (status & TD_LC) lp->stats.collisions++; - if (status & TD_EC) lp->pktStats.excessive_collisions++; - if (status & TD_DE) lp->stats.tx_aborted_errors++; - - if ((status != 0x7fffffff) && /* Not setup frame */ - (status & (TD_LO | TD_NC | TD_EC | TD_LF))) { - lp->lostMedia++; - if (lp->lostMedia > LOST_MEDIA_THRESHOLD) { /* Trip autosense */ - kick_tx(dev); - } - } else { - outl(POLL_DEMAND, DE4X5_TPD); /* Restart a stalled TX */ - } - } else { /* Packet sent */ - lp->stats.tx_packets++; - lp->lostMedia = 0; /* Remove transient problem */ - } - /* Free the buffer if it's not a setup frame. */ - if (lp->skb[entry] != NULL) { - dev_kfree_skb(lp->skb[entry], FREE_WRITE); - lp->skb[entry] = NULL; - } - - /* Update all the pointers */ - lp->tx_old = (++lp->tx_old) % lp->txRingSize; - } - - return 0; -} - -static int -de4x5_ast(struct device *dev) -{ - struct de4x5_private *lp = (struct de4x5_private *)dev->priv; - u_long iobase = dev->base_addr; - s32 gep; - - disable_ast(dev); - - if (lp->chipset == DC21140) { - gep = inl(DE4X5_GEP); - if (((lp->media == _100Mb) && (gep & GEP_SLNK)) || - ((lp->media == _10Mb) && (gep & GEP_LNP)) || - ((lp->media == _10Mb) && !(gep & GEP_SLNK)) || - (lp->media == NC)) { - if (lp->linkProb || ((lp->media == NC) && (!(gep & GEP_LNP)))) { - lp->lostMedia = LOST_MEDIA_THRESHOLD + 1; - lp->linkProb = 0; - kick_tx(dev); - } else { - switch(lp->media) { - case NC: - lp->linkProb = 0; - enable_ast(dev, DE4X5_AUTOSENSE_MS); - break; - - case _10Mb: - lp->linkProb = 1; /* Flag a potential problem */ - enable_ast(dev, 1500); - break; - - case _100Mb: - lp->linkProb = 1; /* Flag a potential problem */ - enable_ast(dev, 4000); - break; - } - } - } else { - lp->linkProb = 0; /* Link OK */ - enable_ast(dev, DE4X5_AUTOSENSE_MS); - } - } - - return 0; -} - -static int -de4x5_close(struct device *dev) -{ - struct de4x5_private *lp = (struct de4x5_private *)dev->priv; - u_long iobase = dev->base_addr; - s32 imr, omr; - - dev->start = 0; - dev->tbusy = 1; - - if (de4x5_debug > 1) { - printk("%s: Shutting down ethercard, status was %8.8x.\n", - dev->name, inl(DE4X5_STS)); - } - - /* - ** We stop the DE4X5 here... mask interrupts and stop TX & RX - */ - DISABLE_IRQs; - - STOP_DE4X5; - - /* - ** Free the associated irq - */ - free_irq(dev->irq); - irq2dev_map[dev->irq] = 0; - - MOD_DEC_USE_COUNT; - - /* Put the adapter to sleep to save power */ - if (lp->chipset == DC21041) { - outl(0, DE4X5_SICR); - outl(CFDA_PSM, PCI_CFDA); - } - - return 0; -} - -static struct enet_statistics * -de4x5_get_stats(struct device *dev) -{ - struct de4x5_private *lp = (struct de4x5_private *)dev->priv; - u_long iobase = dev->base_addr; - - lp->stats.rx_missed_errors = (int) (inl(DE4X5_MFC) & (MFC_OVFL | MFC_CNTR)); - - return &lp->stats; -} - -static void load_packet(struct device *dev, char *buf, u32 flags, struct sk_buff *skb) -{ - struct de4x5_private *lp = (struct de4x5_private *)dev->priv; - - lp->tx_ring[lp->tx_new].buf = virt_to_bus(buf); - lp->tx_ring[lp->tx_new].des1 &= TD_TER; - lp->tx_ring[lp->tx_new].des1 |= flags; - lp->skb[lp->tx_new] = skb; - barrier(); - lp->tx_ring[lp->tx_new].status = T_OWN; - barrier(); - - return; -} -/* -** Set or clear the multicast filter for this adaptor. -** num_addrs == -1 Promiscuous mode, receive all packets - now supported. -** Can also use the ioctls. -** num_addrs == 0 Normal mode, clear multicast list -** num_addrs > 0 Multicast mode, receive normal and MC packets, and do -** best-effort filtering. -** num_addrs == HASH_TABLE_LEN -** Set all multicast bits (pass all multicasts). -*/ -static void -set_multicast_list(struct device *dev) -{ - struct de4x5_private *lp = (struct de4x5_private *)dev->priv; - u_long iobase = dev->base_addr; - - /* First, double check that the adapter is open */ - if (irq2dev_map[dev->irq] != NULL) { - if (dev->flags & IFF_PROMISC) { /* set promiscuous mode */ - u32 omr; - omr = inl(DE4X5_OMR); - omr |= OMR_PR; - outl(omr, DE4X5_OMR); - } else { - SetMulticastFilter(dev); - if (lp->setup_f == HASH_PERF) { - load_packet(dev, lp->setup_frame, TD_IC | HASH_F | TD_SET | - SETUP_FRAME_LEN, NULL); - } else { - load_packet(dev, lp->setup_frame, TD_IC | PERFECT_F | TD_SET | - SETUP_FRAME_LEN, NULL); - } - - lp->tx_new = (++lp->tx_new) % lp->txRingSize; - outl(POLL_DEMAND, DE4X5_TPD); /* Start the TX */ - dev->trans_start = jiffies; - } - } - - return; -} - -/* -** Calculate the hash code and update the logical address filter -** from a list of ethernet multicast addresses. -** Little endian crc one liner from Matt Thomas, DEC. -*/ -static void SetMulticastFilter(struct device *dev) -{ - struct de4x5_private *lp = (struct de4x5_private *)dev->priv; - struct dev_mc_list *dmi=dev->mc_list; - u_long iobase = dev->base_addr; - int i, j, bit, byte; - u16 hashcode; - u32 omr, crc, poly = CRC_POLYNOMIAL_LE; - char *pa; - unsigned char *addrs; - - omr = inl(DE4X5_OMR); - omr &= ~OMR_PR; - pa = build_setup_frame(dev, ALL); /* Build the basic frame */ - - if ((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 14)) { - omr |= OMR_PM; /* Pass all multicasts */ - } else if (lp->setup_f == HASH_PERF) { - /* Now update the MCA table */ - for (i=0;i<dev->mc_count;i++) { /* for each address in the list */ - addrs=dmi->dmi_addr; - dmi=dmi->next; - if ((*addrs & 0x01) == 1) { /* multicast address? */ - crc = 0xffffffff; /* init CRC for each address */ - for (byte=0;byte<ETH_ALEN;byte++) { /* for each address byte */ - /* process each address bit */ - for (bit = *addrs++,j=0;j<8;j++, bit>>=1) { - crc = (crc >> 1) ^ (((crc ^ bit) & 0x01) ? poly : 0); - } - } - hashcode = crc & HASH_BITS; /* hashcode is 9 LSb of CRC */ - - byte = hashcode >> 3; /* bit[3-8] -> byte in filter */ - bit = 1 << (hashcode & 0x07); /* bit[0-2] -> bit in byte */ - - byte <<= 1; /* calc offset into setup frame */ - if (byte & 0x02) { - byte -= 1; - } - lp->setup_frame[byte] |= bit; - } - } - } else { /* Perfect filtering */ - for (j=0; j<dev->mc_count; j++) { - addrs=dmi->dmi_addr; - dmi=dmi->next; - for (i=0; i<ETH_ALEN; i++) { - *(pa + (i&1)) = *addrs++; - if (i & 0x01) pa += 4; - } - } - } - outl(omr, DE4X5_OMR); - - return; -} - -/* -** EISA bus I/O device probe. Probe from slot 1 since slot 0 is usually -** the motherboard. Upto 15 EISA devices are supported. -*/ -static void eisa_probe(struct device *dev, u_long ioaddr) -{ - int i, maxSlots, status; - u_short vendor, device; - s32 cfid; - u_long iobase; - struct bus_type *lp = &bus; - char name[DE4X5_STRLEN]; - - if (!ioaddr && autoprobed) return ; /* Been here before ! */ - if ((ioaddr < 0x1000) && (ioaddr > 0)) return; /* PCI MODULE special */ - - lp->bus = EISA; - - if (ioaddr == 0) { /* Autoprobing */ - iobase = EISA_SLOT_INC; /* Get the first slot address */ - i = 1; - maxSlots = MAX_EISA_SLOTS; - } else { /* Probe a specific location */ - iobase = ioaddr; - i = (ioaddr >> 12); - maxSlots = i + 1; - } - - for (status = -ENODEV; (i<maxSlots) && (dev!=NULL); i++, iobase+=EISA_SLOT_INC) { - if (EISA_signature(name, EISA_ID)) { - cfid = inl(PCI_CFID); - device = (u_short)(cfid >> 16); - vendor = (u_short) cfid; - - lp->bus = EISA; - lp->chipset = device; - if (DevicePresent(EISA_APROM) == 0) { - /* Write the PCI Configuration Registers */ - outl(PCI_COMMAND_IO | PCI_COMMAND_MASTER, PCI_CFCS); - outl(0x00004000, PCI_CFLT); - outl(iobase, PCI_CBIO); - - if (check_region(iobase, DE4X5_EISA_TOTAL_SIZE) == 0) { - if ((dev = alloc_device(dev, iobase)) != NULL) { - if ((status = de4x5_hw_init(dev, iobase)) == 0) { - num_de4x5s++; - } - num_eth++; - } - } else if (autoprobed) { - printk("%s: region already allocated at 0x%04lx.\n", dev->name, iobase); - } - } - } - } - - return; -} - -/* -** PCI bus I/O device probe -** NB: PCI I/O accesses and Bus Mastering are enabled by the PCI BIOS, not -** the driver. Some PCI BIOS's, pre V2.1, need the slot + features to be -** enabled by the user first in the set up utility. Hence we just check for -** enabled features and silently ignore the card if they're not. -** -** STOP PRESS: Some BIOS's __require__ the driver to enable the bus mastering -** bit. Here, check for I/O accesses and then set BM. If you put the card in -** a non BM slot, you're on your own (and complain to the PC vendor that your -** PC doesn't conform to the PCI standard)! -*/ -#define PCI_DEVICE (dev_num << 3) -#define PCI_LAST_DEV 32 - -static void pci_probe(struct device *dev, u_long ioaddr) -{ - u_char irq; - u_char pb, pbus, dev_num, dnum, dev_fn; - u_short vendor, device, index, status; - u_int class = DE4X5_CLASS_CODE; - u_int iobase; - struct bus_type *lp = &bus; - - if (!ioaddr && autoprobed) return ; /* Been here before ! */ - - if (pcibios_present()) { - lp->bus = PCI; - - if (ioaddr < 0x1000) { - pbus = (u_short)(ioaddr >> 8); - dnum = (u_short)(ioaddr & 0xff); - } else { - pbus = 0; - dnum = 0; - } - - for (index=0; - (pcibios_find_class(class, index, &pb, &dev_fn)!= PCIBIOS_DEVICE_NOT_FOUND); - index++) { - dev_num = PCI_SLOT(dev_fn); - - if ((!pbus && !dnum) || ((pbus == pb) && (dnum == dev_num))) { - pcibios_read_config_word(pb, PCI_DEVICE, PCI_VENDOR_ID, &vendor); - pcibios_read_config_word(pb, PCI_DEVICE, PCI_DEVICE_ID, &device); - if (is_DC21040 || is_DC21041 || is_DC21140) { - /* Set the device number information */ - lp->device = dev_num; - lp->bus_num = pb; - - /* Set the chipset information */ - lp->chipset = device; - - /* Get the board I/O address */ - pcibios_read_config_dword(pb, PCI_DEVICE, PCI_BASE_ADDRESS_0, &iobase); - iobase &= CBIO_MASK; - - /* Fetch the IRQ to be used */ - pcibios_read_config_byte(pb, PCI_DEVICE, PCI_INTERRUPT_LINE, &irq); - - /* Check if I/O accesses and Bus Mastering are enabled */ - pcibios_read_config_word(pb, PCI_DEVICE, PCI_COMMAND, &status); - if (status & PCI_COMMAND_IO) { - if (!(status & PCI_COMMAND_MASTER)) { - status |= PCI_COMMAND_MASTER; - pcibios_write_config_word(pb, PCI_DEVICE, PCI_COMMAND, status); - pcibios_read_config_word(pb, PCI_DEVICE, PCI_COMMAND, &status); - } - if (status & PCI_COMMAND_MASTER) { - if ((DevicePresent(DE4X5_APROM) == 0) || is_not_dec) { - if (check_region(iobase, DE4X5_PCI_TOTAL_SIZE) == 0) { - if ((dev = alloc_device(dev, iobase)) != NULL) { - dev->irq = irq; - if ((status = de4x5_hw_init(dev, iobase)) == 0) { - num_de4x5s++; - } - num_eth++; - } - } else if (autoprobed) { - printk("%s: region already allocated at 0x%04x.\n", dev->name, (u_short)iobase); - } - } - } - } - } - } - } - } - - return; -} - -/* -** Allocate the device by pointing to the next available space in the -** device structure. Should one not be available, it is created. -*/ -static struct device *alloc_device(struct device *dev, u_long iobase) -{ - int addAutoProbe = 0; - struct device *tmp = NULL, *ret; - int (*init)(struct device *) = NULL; - - /* - ** Check the device structures for an end of list or unused device - */ - if (!loading_module) { - while (dev->next != NULL) { - if ((dev->base_addr == DE4X5_NDA) || (dev->base_addr == 0)) break; - dev = dev->next; /* walk through eth device list */ - num_eth++; /* increment eth device number */ - } - - /* - ** If an autoprobe is requested for another device, we must re-insert - ** the request later in the list. Remember the current position first. - */ - if ((dev->base_addr == 0) && (num_de4x5s > 0)) { - addAutoProbe++; - tmp = dev->next; /* point to the next device */ - init = dev->init; /* remember the probe function */ - } - - /* - ** If at end of list and can't use current entry, malloc one up. - ** If memory could not be allocated, print an error message. - */ - if ((dev->next == NULL) && - !((dev->base_addr == DE4X5_NDA) || (dev->base_addr == 0))){ - dev->next = (struct device *)kmalloc(sizeof(struct device) + 8, - GFP_KERNEL); - - dev = dev->next; /* point to the new device */ - if (dev == NULL) { - printk("eth%d: Device not initialised, insufficient memory\n", - num_eth); - } else { - /* - ** If the memory was allocated, point to the new memory area - ** and initialize it (name, I/O address, next device (NULL) and - ** initialisation probe routine). - */ - dev->name = (char *)(dev + sizeof(struct device)); - if (num_eth > 9999) { - sprintf(dev->name,"eth????"); /* New device name */ - } else { - sprintf(dev->name,"eth%d", num_eth);/* New device name */ - } - dev->base_addr = iobase; /* assign the io address */ - dev->next = NULL; /* mark the end of list */ - dev->init = &de4x5_probe; /* initialisation routine */ - num_de4x5s++; - } - } - ret = dev; /* return current struct, or NULL */ - - /* - ** Now figure out what to do with the autoprobe that has to be inserted. - ** Firstly, search the (possibly altered) list for an empty space. - */ - if (ret != NULL) { - if (addAutoProbe) { - for (; (tmp->next!=NULL) && (tmp->base_addr!=DE4X5_NDA); tmp=tmp->next); - - /* - ** If no more device structures and can't use the current one, malloc - ** one up. If memory could not be allocated, print an error message. - */ - if ((tmp->next == NULL) && !(tmp->base_addr == DE4X5_NDA)) { - tmp->next = (struct device *)kmalloc(sizeof(struct device) + 8, - GFP_KERNEL); - tmp = tmp->next; /* point to the new device */ - if (tmp == NULL) { - printk("%s: Insufficient memory to extend the device list.\n", - dev->name); - } else { - /* - ** If the memory was allocated, point to the new memory area - ** and initialize it (name, I/O address, next device (NULL) and - ** initialisation probe routine). - */ - tmp->name = (char *)(tmp + sizeof(struct device)); - if (num_eth > 9999) { - sprintf(tmp->name,"eth????"); /* New device name */ - } else { - sprintf(tmp->name,"eth%d", num_eth);/* New device name */ - } - tmp->base_addr = 0; /* re-insert the io address */ - tmp->next = NULL; /* mark the end of list */ - tmp->init = init; /* initialisation routine */ - } - } else { /* structure already exists */ - tmp->base_addr = 0; /* re-insert the io address */ - } - } - } - } else { - ret = dev; - } - - return ret; -} - -/* -** Auto configure the media here rather than setting the port at compile -** time. This routine is called by de4x5_init() when a loss of media is -** detected (excessive collisions, loss of carrier, no carrier or link fail -** [TP]) to check whether the user has been sneaky and changed the port on us. -*/ -static int autoconf_media(struct device *dev) -{ - struct de4x5_private *lp = (struct de4x5_private *)dev->priv; - u_long iobase = dev->base_addr; - - lp->tx_enable = YES; - if (de4x5_debug > 0 ) { - if (lp->chipset != DC21140) { - printk("%s: Searching for media... ",dev->name); - } else { - printk("%s: Searching for mode... ",dev->name); - } - } - - if (lp->chipset == DC21040) { - lp->media = (lp->autosense == AUTO ? TP : lp->autosense); - dc21040_autoconf(dev); - } else if (lp->chipset == DC21041) { - lp->media = (lp->autosense == AUTO ? TP_NW : lp->autosense); - dc21041_autoconf(dev); - } else if (lp->chipset == DC21140) { - disable_ast(dev); - lp->media = (lp->autosense == AUTO ? _10Mb : lp->autosense); - dc21140_autoconf(dev); - } - - if (de4x5_debug > 0 ) { - if (lp->chipset != DC21140) { - printk("media is %s\n", (lp->media == NC ? "unconnected!" : - (lp->media == TP ? "TP." : - (lp->media == ANS ? "TP/Nway." : - (lp->media == BNC ? "BNC." : - (lp->media == AUI ? "AUI." : - "BNC/AUI." - )))))); - } else { - printk("mode is %s\n",(lp->media == NC ? "link down.": - (lp->media == _100Mb ? "100Mb/s." : - (lp->media == _10Mb ? "10Mb/s." : - "\?\?\?" - )))); - } - } - - if (lp->media) { - lp->lostMedia = 0; - inl(DE4X5_MFC); /* Zero the lost frames counter */ - if ((lp->media == TP) || (lp->media == ANS)) { - lp->irq_mask |= IMR_LFM; - } - } - dce_ms_delay(10); - - return (lp->media); -} - -static void dc21040_autoconf(struct device *dev) -{ - struct de4x5_private *lp = (struct de4x5_private *)dev->priv; - u_long iobase = dev->base_addr; - int i, linkBad; - s32 sisr = 0, t_3s = 3000; - - switch (lp->media) { - case TP: - reset_init_sia(dev, 0x8f01, 0xffff, 0x0000); - for (linkBad=1,i=0;(i<t_3s) && linkBad && !(sisr & SISR_NCR);i++) { - if (((sisr = inl(DE4X5_SISR)) & SISR_LKF) == 0) linkBad = 0; - dce_ms_delay(1); - } - if (linkBad && (lp->autosense == AUTO)) { - lp->media = BNC_AUI; - dc21040_autoconf(dev); - } - break; - - case BNC: - case AUI: - case BNC_AUI: - reset_init_sia(dev, 0x8f09, 0x0705, 0x0006); - dce_ms_delay(500); - linkBad = ping_media(dev); - if (linkBad && (lp->autosense == AUTO)) { - lp->media = EXT_SIA; - dc21040_autoconf(dev); - } - break; - - case EXT_SIA: - reset_init_sia(dev, 0x3041, 0x0000, 0x0006); - dce_ms_delay(500); - linkBad = ping_media(dev); - if (linkBad && (lp->autosense == AUTO)) { - lp->media = NC; - dc21040_autoconf(dev); - } - break; - - case NC: -#ifndef __alpha__ - reset_init_sia(dev, 0x8f01, 0xffff, 0x0000); - break; -#else - /* JAE: for Alpha, default to BNC/AUI, *not* TP */ - reset_init_sia(dev, 0x8f09, 0x0705, 0x0006); -#endif /* i386 */ - } - - return; -} - -/* -** Autoconfigure the media when using the DC21041. AUI needs to be tested -** before BNC, because the BNC port will indicate activity if it's not -** terminated correctly. The only way to test for that is to place a loopback -** packet onto the network and watch for errors. -*/ -static void dc21041_autoconf(struct device *dev) -{ - struct de4x5_private *lp = (struct de4x5_private *)dev->priv; - u_long iobase = dev->base_addr; - s32 sts, irqs, irq_mask, omr; - - switch (lp->media) { - case TP_NW: - omr = inl(DE4X5_OMR); /* Set up full duplex for the autonegotiate */ - outl(omr | OMR_FD, DE4X5_OMR); - irqs = STS_LNF | STS_LNP; - irq_mask = IMR_LFM | IMR_LPM; - sts = test_media(dev, irqs, irq_mask, 0xef01, 0xffff, 0x0008, 2400); - if (sts & STS_LNP) { - lp->media = ANS; - } else { - lp->media = AUI; - } - dc21041_autoconf(dev); - break; - - case ANS: - irqs = STS_LNP; - irq_mask = IMR_LPM; - sts = test_ans(dev, irqs, irq_mask, 3000); - if (!(sts & STS_LNP) && (lp->autosense == AUTO)) { - lp->media = TP; - dc21041_autoconf(dev); - } - break; - - case TP: - omr = inl(DE4X5_OMR); /* Set up half duplex for TP */ - outl(omr & ~OMR_FD, DE4X5_OMR); - irqs = STS_LNF | STS_LNP; - irq_mask = IMR_LFM | IMR_LPM; - sts = test_media(dev, irqs, irq_mask, 0xef01, 0xff3f, 0x0008, 2400); - if (!(sts & STS_LNP) && (lp->autosense == AUTO)) { - if (inl(DE4X5_SISR) & SISR_NRA) { /* Non selected port activity */ - lp->media = AUI; - } else { - lp->media = BNC; - } - dc21041_autoconf(dev); - } - break; - - case AUI: - omr = inl(DE4X5_OMR); /* Set up half duplex for AUI */ - outl(omr & ~OMR_FD, DE4X5_OMR); - irqs = 0; - irq_mask = 0; - sts = test_media(dev, irqs, irq_mask, 0xef09, 0xf7fd, 0x000e, 1000); - if (!(inl(DE4X5_SISR) & SISR_SRA) && (lp->autosense == AUTO)) { - lp->media = BNC; - dc21041_autoconf(dev); - } - break; - - case BNC: - omr = inl(DE4X5_OMR); /* Set up half duplex for BNC */ - outl(omr & ~OMR_FD, DE4X5_OMR); - irqs = 0; - irq_mask = 0; - sts = test_media(dev, irqs, irq_mask, 0xef09, 0xf7fd, 0x0006, 1000); - if (!(inl(DE4X5_SISR) & SISR_SRA) && (lp->autosense == AUTO)) { - lp->media = NC; - } else { /* Ensure media connected */ - if (ping_media(dev)) lp->media = NC; - } - break; - - case NC: - omr = inl(DE4X5_OMR); /* Set up full duplex for the autonegotiate */ - outl(omr | OMR_FD, DE4X5_OMR); - reset_init_sia(dev, 0xef01, 0xffff, 0x0008);/* Initialise the SIA */ - break; - } - - return; -} - -/* -** Reduced feature version (temporary I hope) -*/ -static void dc21140_autoconf(struct device *dev) -{ - struct de4x5_private *lp = (struct de4x5_private *)dev->priv; - u_long iobase = dev->base_addr; - s32 omr; - - switch(lp->media) { - case _100Mb: /* Set 100Mb/s, MII Port with PCS Function and Scrambler */ - omr = (inl(DE4X5_OMR) & ~(OMR_PS | OMR_HBD | OMR_TTM | OMR_PCS | OMR_SCR)); - omr |= (de4x5_full_duplex ? OMR_FD : 0); /* Set up Full Duplex */ - outl(omr | OMR_PS | OMR_HBD | OMR_PCS | OMR_SCR, DE4X5_OMR); - outl(GEP_FDXD | GEP_MODE, DE4X5_GEP); - break; - - case _10Mb: /* Set conventional 10Mb/s ENDEC interface */ - omr = (inl(DE4X5_OMR) & ~(OMR_PS | OMR_HBD | OMR_TTM | OMR_PCS | OMR_SCR)); - omr |= (de4x5_full_duplex ? OMR_FD : 0); /* Set up Full Duplex */ - outl(omr | OMR_TTM, DE4X5_OMR); - outl(GEP_FDXD, DE4X5_GEP); - break; - } - - return; -} - -static int -test_media(struct device *dev, s32 irqs, s32 irq_mask, s32 csr13, s32 csr14, s32 csr15, s32 msec) -{ - struct de4x5_private *lp = (struct de4x5_private *)dev->priv; - u_long iobase = dev->base_addr; - s32 sts, time, csr12; - - reset_init_sia(dev, csr13, csr14, csr15); - - /* Set link_fail_inhibit_timer */ - load_ms_timer(dev, msec); - - /* clear all pending interrupts */ - sts = inl(DE4X5_STS); - outl(sts, DE4X5_STS); - - /* clear csr12 NRA and SRA bits */ - csr12 = inl(DE4X5_SISR); - outl(csr12, DE4X5_SISR); - - /* Poll for timeout - timer interrupt doesn't work correctly */ - do { - time = inl(DE4X5_GPT) & GPT_VAL; - sts = inl(DE4X5_STS); - } while ((time != 0) && !(sts & irqs)); - - sts = inl(DE4X5_STS); - - return sts; -} -/* -static int test_sym_link(struct device *dev, u32 msec) -{ - struct de4x5_private *lp = (struct de4x5_private *)dev->priv; - u_long iobase = dev->base_addr; - u32 gep, time; - - / * Set link_fail_inhibit_timer * / - load_ms_timer(dev, msec); - - / * Poll for timeout or SYM_LINK=0 * / - do { - time = inl(DE4X5_GPT) & GPT_VAL; - gep = inl(DE4X5_GEP) & (GEP_SLNK | GEP_LNP); - } while ((time > 0) && (gep & GEP_SLNK)); - - return gep; -} -*/ -/* -** Send a packet onto the media and watch for send errors that indicate the -** media is bad or unconnected. -*/ -static int ping_media(struct device *dev) -{ - struct de4x5_private *lp = (struct de4x5_private *)dev->priv; - u_long iobase = dev->base_addr; - int i, entry, linkBad; - s32 omr, t_3s = 4000; - char frame[64]; - - create_packet(dev, frame, sizeof(frame)); - - entry = lp->tx_new; /* Remember the ring position */ - load_packet(dev, frame, TD_LS | TD_FS | sizeof(frame),NULL); - - omr = inl(DE4X5_OMR); - outl(omr|OMR_ST, DE4X5_OMR); - - lp->tx_new = (++lp->tx_new) % lp->txRingSize; - lp->tx_old = lp->tx_new; - - /* Poll for completion of frame (interrupts are disabled for now)... */ - for (linkBad=1,i=0;(i<t_3s) && linkBad;i++) { - if ((inl(DE4X5_SISR) & SISR_NCR) == 1) break; - if (lp->tx_ring[entry].status >= 0) linkBad=0; - dce_ms_delay(1); - } - outl(omr, DE4X5_OMR); - - return ((linkBad || (lp->tx_ring[entry].status & TD_ES)) ? 1 : 0); -} - -/* -** Check the Auto Negotiation State. Return OK when a link pass interrupt -** is received and the auto-negotiation status is NWAY OK. -*/ -static int test_ans(struct device *dev, s32 irqs, s32 irq_mask, s32 msec) -{ - struct de4x5_private *lp = (struct de4x5_private *)dev->priv; - u_long iobase = dev->base_addr; - s32 sts, ans; - - outl(irq_mask, DE4X5_IMR); - - /* Set timeout limit */ - load_ms_timer(dev, msec); - - /* clear all pending interrupts */ - sts = inl(DE4X5_STS); - outl(sts, DE4X5_STS); - - /* Poll for interrupts */ - do { - ans = inl(DE4X5_SISR) & SISR_ANS; - sts = inl(DE4X5_STS); - } while (!(sts & irqs) && (ans ^ ANS_NWOK) != 0); - - return ((sts & STS_LNP) && ((ans ^ ANS_NWOK) == 0) ? STS_LNP : 0); -} - -/* -** -*/ -static void reset_init_sia(struct device *dev, s32 sicr, s32 strr, s32 sigr) -{ - struct de4x5_private *lp = (struct de4x5_private *)dev->priv; - u_long iobase = dev->base_addr; - - RESET_SIA; - outl(sigr, DE4X5_SIGR); - outl(strr, DE4X5_STRR); - outl(sicr, DE4X5_SICR); - - return; -} - -/* -** Load the timer on the DC21041 and 21140. Max time is 13.42 secs. -*/ -static void load_ms_timer(struct device *dev, u32 msec) -{ - struct de4x5_private *lp = (struct de4x5_private *)dev->priv; - u_long iobase = dev->base_addr; - s32 i = 2048, j; - - if (lp->chipset == DC21140) { - j = inl(DE4X5_OMR); - if ((j & OMR_TTM) && (j & OMR_PS)) { /* 10Mb/s MII */ - i = 8192; - } else if ((~j & OMR_TTM) && (j & OMR_PS)) { /* 100Mb/s MII */ - i = 819; - } - } - - outl((s32)(msec * 10000)/i, DE4X5_GPT); - - return; -} - -/* -** Create an Ethernet packet with an invalid CRC -*/ -static void create_packet(struct device *dev, char *frame, int len) -{ - int i; - char *buf = frame; - - for (i=0; i<ETH_ALEN; i++) { /* Use this source address */ - *buf++ = dev->dev_addr[i]; - } - for (i=0; i<ETH_ALEN; i++) { /* Use this destination address */ - *buf++ = dev->dev_addr[i]; - } - - *buf++ = 0; /* Packet length (2 bytes) */ - *buf++ = 1; - - return; -} - -/* -** Known delay in microseconds -*/ -static void dce_us_delay(u32 usec) -{ - udelay(usec); - - return; -} - -/* -** Known delay in milliseconds, in millisecond steps. -*/ -static void dce_ms_delay(u32 msec) -{ - u_int i; - - for (i=0; i<msec; i++) { - dce_us_delay(1000); - } - - return; -} - - -/* -** Look for a particular board name in the EISA configuration space -*/ -static int EISA_signature(char *name, s32 eisa_id) -{ - u_int i; - const char *signatures[] = DE4X5_SIGNATURE; - char ManCode[DE4X5_STRLEN]; - union { - s32 ID; - char Id[4]; - } Eisa; - int status = 0; - - *name = '\0'; - Eisa.ID = inl(eisa_id); - - ManCode[0]=(((Eisa.Id[0]>>2)&0x1f)+0x40); - ManCode[1]=(((Eisa.Id[1]&0xe0)>>5)+((Eisa.Id[0]&0x03)<<3)+0x40); - ManCode[2]=(((Eisa.Id[2]>>4)&0x0f)+0x30); - ManCode[3]=((Eisa.Id[2]&0x0f)+0x30); - ManCode[4]=(((Eisa.Id[3]>>4)&0x0f)+0x30); - ManCode[5]='\0'; - - for (i=0;(*signatures[i] != '\0') && (*name == '\0');i++) { - if (strstr(ManCode, signatures[i]) != NULL) { - strcpy(name,ManCode); - status = 1; - } - } - - return status; /* return the device name string */ -} - -/* -** Look for a special sequence in the Ethernet station address PROM that -** is common across all DIGITAL network adapter products. -** -** Search the Ethernet address ROM for the signature. Since the ROM address -** counter can start at an arbitrary point, the search must include the entire -** probe sequence length plus the (length_of_the_signature - 1). -** Stop the search IMMEDIATELY after the signature is found so that the -** PROM address counter is correctly positioned at the start of the -** ethernet address for later read out. -*/ - -static int DevicePresent(u_long aprom_addr) -{ - union { - struct { - u32 a; - u32 b; - } llsig; - char Sig[sizeof(u32) << 1]; - } dev; - char data; - int i, j, tmp, status = 0; - short sigLength; - struct bus_type *lp = &bus; - - dev.llsig.a = ETH_PROM_SIG; - dev.llsig.b = ETH_PROM_SIG; - sigLength = sizeof(u32) << 1; - - if (lp->chipset == DC21040) { - for (i=0,j=0;(j<sigLength) && (i<PROBE_LENGTH+sigLength-1);i++) { - if (lp->bus == PCI) { - while ((tmp = inl(aprom_addr)) < 0); - data = (char)tmp; - } else { - data = inb(aprom_addr); - } - if (dev.Sig[j] == data) { /* track signature */ - j++; - } else { /* lost signature; begin search again */ - if (data == dev.Sig[0]) { - j=1; - } else { - j=0; - } - } - } - - if (j!=sigLength) { - status = -ENODEV; /* search failed */ - } - - } else { /* use new srom */ - short *p = (short *)&lp->srom; - for (i=0; i<(sizeof(struct de4x5_srom)>>1); i++) { - *p++ = srom_rd(aprom_addr, i); - } - } - - return status; -} - -static int get_hw_addr(struct device *dev) -{ - u_long iobase = dev->base_addr; - int i, k, tmp, status = 0; - u_short j,chksum; - struct bus_type *lp = &bus; - - for (i=0,k=0,j=0;j<3;j++) { - k <<= 1 ; - if (k > 0xffff) k-=0xffff; - - if (lp->bus == PCI) { - if (lp->chipset == DC21040) { - while ((tmp = inl(DE4X5_APROM)) < 0); - k += (u_char) tmp; - dev->dev_addr[i++] = (u_char) tmp; - while ((tmp = inl(DE4X5_APROM)) < 0); - k += (u_short) (tmp << 8); - dev->dev_addr[i++] = (u_char) tmp; - } else { - dev->dev_addr[i] = (u_char) lp->srom.ieee_addr[i]; i++; - dev->dev_addr[i] = (u_char) lp->srom.ieee_addr[i]; i++; - } - } else { - k += (u_char) (tmp = inb(EISA_APROM)); - dev->dev_addr[i++] = (u_char) tmp; - k += (u_short) ((tmp = inb(EISA_APROM)) << 8); - dev->dev_addr[i++] = (u_char) tmp; - } - - if (k > 0xffff) k-=0xffff; - } - if (k == 0xffff) k=0; - - if (lp->bus == PCI) { - if (lp->chipset == DC21040) { - while ((tmp = inl(DE4X5_APROM)) < 0); - chksum = (u_char) tmp; - while ((tmp = inl(DE4X5_APROM)) < 0); - chksum |= (u_short) (tmp << 8); - if (k != chksum) status = -1; - } - } else { - chksum = (u_char) inb(EISA_APROM); - chksum |= (u_short) (inb(EISA_APROM) << 8); - if (k != chksum) status = -1; - } - - - return status; -} - -/* -** SROM Read -*/ -static short srom_rd(u_long addr, u_char offset) -{ - sendto_srom(SROM_RD | SROM_SR, addr); - - srom_latch(SROM_RD | SROM_SR | DT_CS, addr); - srom_command(SROM_RD | SROM_SR | DT_IN | DT_CS, addr); - srom_address(SROM_RD | SROM_SR | DT_CS, addr, offset); - - return srom_data(SROM_RD | SROM_SR | DT_CS, addr); -} - -static void srom_latch(u_int command, u_long addr) -{ - sendto_srom(command, addr); - sendto_srom(command | DT_CLK, addr); - sendto_srom(command, addr); - - return; -} - -static void srom_command(u_int command, u_long addr) -{ - srom_latch(command, addr); - srom_latch(command, addr); - srom_latch((command & 0x0000ff00) | DT_CS, addr); - - return; -} - -static void srom_address(u_int command, u_long addr, u_char offset) -{ - int i; - char a; - - a = (char)(offset << 2); - for (i=0; i<6; i++, a <<= 1) { - srom_latch(command | ((a < 0) ? DT_IN : 0), addr); - } - dce_us_delay(1); - - i = (getfrom_srom(addr) >> 3) & 0x01; - if (i != 0) { - printk("Bad SROM address phase.....\n"); -/* printk(".");*/ - } - - return; -} - -static short srom_data(u_int command, u_long addr) -{ - int i; - short word = 0; - s32 tmp; - - for (i=0; i<16; i++) { - sendto_srom(command | DT_CLK, addr); - tmp = getfrom_srom(addr); - sendto_srom(command, addr); - - word = (word << 1) | ((tmp >> 3) & 0x01); - } - - sendto_srom(command & 0x0000ff00, addr); - - return word; -} - -/* -static void srom_busy(u_int command, u_long addr) -{ - sendto_srom((command & 0x0000ff00) | DT_CS, addr); - - while (!((getfrom_srom(addr) >> 3) & 0x01)) { - dce_ms_delay(1); - } - - sendto_srom(command & 0x0000ff00, addr); - - return; -} -*/ - -static void sendto_srom(u_int command, u_long addr) -{ - outl(command, addr); - dce_us_delay(1); - - return; -} - -static int getfrom_srom(u_long addr) -{ - s32 tmp; - - tmp = inl(addr); - dce_us_delay(1); - - return tmp; -} - -static char *build_setup_frame(struct device *dev, int mode) -{ - struct de4x5_private *lp = (struct de4x5_private *)dev->priv; - int i; - char *pa = lp->setup_frame; - - /* Initialise the setup frame */ - if (mode == ALL) { - memset(lp->setup_frame, 0, SETUP_FRAME_LEN); - } - - if (lp->setup_f == HASH_PERF) { - for (pa=lp->setup_frame+IMPERF_PA_OFFSET, i=0; i<ETH_ALEN; i++) { - *(pa + i) = dev->dev_addr[i]; /* Host address */ - if (i & 0x01) pa += 2; - } - *(lp->setup_frame + (HASH_TABLE_LEN >> 3) - 3) = 0x80; /* B'cast address */ - } else { - for (i=0; i<ETH_ALEN; i++) { /* Host address */ - *(pa + (i&1)) = dev->dev_addr[i]; - if (i & 0x01) pa += 4; - } - for (i=0; i<ETH_ALEN; i++) { /* Broadcast address */ - *(pa + (i&1)) = (char) 0xff; - if (i & 0x01) pa += 4; - } - } - - return pa; /* Points to the next entry */ -} - -static void enable_ast(struct device *dev, u32 time_out) -{ - struct de4x5_private *lp = (struct de4x5_private *)dev->priv; - u_long iobase = dev->base_addr; - - lp->irq_mask |= IMR_TMM; - outl(lp->irq_mask, DE4X5_IMR); - load_ms_timer(dev, time_out); - - return; -} - -static void disable_ast(struct device *dev) -{ - struct de4x5_private *lp = (struct de4x5_private *)dev->priv; - u_long iobase = dev->base_addr; - - lp->irq_mask &= ~IMR_TMM; - outl(lp->irq_mask, DE4X5_IMR); - load_ms_timer(dev, 0); - - return; -} - -static void kick_tx(struct device *dev) -{ - struct sk_buff *skb; - - if ((skb = alloc_skb(0, GFP_ATOMIC)) != NULL) { - skb->len= FAKE_FRAME_LEN; - skb->arp=1; - skb->dev=dev; - dev_queue_xmit(skb, dev, SOPRI_NORMAL); - } - - return; -} - -/* -** Perform IOCTL call functions here. Some are privileged operations and the -** effective uid is checked in those cases. -*/ -static int de4x5_ioctl(struct device *dev, struct ifreq *rq, int cmd) -{ - struct de4x5_private *lp = (struct de4x5_private *)dev->priv; - struct de4x5_ioctl *ioc = (struct de4x5_ioctl *) &rq->ifr_data; - u_long iobase = dev->base_addr; - int i, j, status = 0; - s32 omr; - union { - u8 addr[(HASH_TABLE_LEN * ETH_ALEN)]; - u16 sval[(HASH_TABLE_LEN * ETH_ALEN) >> 1]; - u32 lval[(HASH_TABLE_LEN * ETH_ALEN) >> 2]; - } tmp; - - switch(ioc->cmd) { - case DE4X5_GET_HWADDR: /* Get the hardware address */ - ioc->len = ETH_ALEN; - status = verify_area(VERIFY_WRITE, (void *)ioc->data, ioc->len); - if (status) - break; - for (i=0; i<ETH_ALEN; i++) { - tmp.addr[i] = dev->dev_addr[i]; - } - memcpy_tofs(ioc->data, tmp.addr, ioc->len); - - break; - case DE4X5_SET_HWADDR: /* Set the hardware address */ - status = verify_area(VERIFY_READ, (void *)ioc->data, ETH_ALEN); - if (status) - break; - status = -EPERM; - if (!suser()) - break; - status = 0; - memcpy_fromfs(tmp.addr, ioc->data, ETH_ALEN); - for (i=0; i<ETH_ALEN; i++) { - dev->dev_addr[i] = tmp.addr[i]; - } - build_setup_frame(dev, PHYS_ADDR_ONLY); - /* Set up the descriptor and give ownership to the card */ - while (set_bit(0, (void *)&dev->tbusy) != 0);/* Wait for lock to free*/ - if (lp->setup_f == HASH_PERF) { - load_packet(dev, lp->setup_frame, TD_IC | HASH_F | TD_SET | - SETUP_FRAME_LEN, NULL); - } else { - load_packet(dev, lp->setup_frame, TD_IC | PERFECT_F | TD_SET | - SETUP_FRAME_LEN, NULL); - } - lp->tx_new = (++lp->tx_new) % lp->txRingSize; - outl(POLL_DEMAND, DE4X5_TPD); /* Start the TX */ - dev->tbusy = 0; /* Unlock the TX ring */ - - break; - case DE4X5_SET_PROM: /* Set Promiscuous Mode */ - if (suser()) { - omr = inl(DE4X5_OMR); - omr |= OMR_PR; - outl(omr, DE4X5_OMR); - } else { - status = -EPERM; - } - - break; - case DE4X5_CLR_PROM: /* Clear Promiscuous Mode */ - if (suser()) { - omr = inl(DE4X5_OMR); - omr &= ~OMR_PR; - outb(omr, DE4X5_OMR); - } else { - status = -EPERM; - } - - break; - case DE4X5_SAY_BOO: /* Say "Boo!" to the kernel log file */ - printk("%s: Boo!\n", dev->name); - - break; - case DE4X5_GET_MCA: /* Get the multicast address table */ - ioc->len = (HASH_TABLE_LEN >> 3); - status = verify_area(VERIFY_WRITE, ioc->data, ioc->len); - if (status) - break; - memcpy_tofs(ioc->data, lp->setup_frame, ioc->len); - - break; - case DE4X5_SET_MCA: /* Set a multicast address */ - if (suser()) { - if (ioc->len != HASH_TABLE_LEN) { /* MCA changes */ - if (!(status = verify_area(VERIFY_READ, (void *)ioc->data, ETH_ALEN * ioc->len))) { - memcpy_fromfs(tmp.addr, ioc->data, ETH_ALEN * ioc->len); - set_multicast_list(dev); - } - } else { - set_multicast_list(dev); - } - } else { - status = -EPERM; - } - - break; - case DE4X5_CLR_MCA: /* Clear all multicast addresses */ - if (suser()) { - set_multicast_list(dev); - } else { - status = -EPERM; - } - - break; - case DE4X5_MCA_EN: /* Enable pass all multicast addressing */ - if (suser()) { - omr = inl(DE4X5_OMR); - omr |= OMR_PM; - outl(omr, DE4X5_OMR); - } else { - status = -EPERM; - } - - break; - case DE4X5_GET_STATS: /* Get the driver statistics */ - ioc->len = sizeof(lp->pktStats); - status = verify_area(VERIFY_WRITE, (void *)ioc->data, ioc->len); - if (status) - break; - - cli(); - memcpy_tofs(ioc->data, &lp->pktStats, ioc->len); - sti(); - - break; - case DE4X5_CLR_STATS: /* Zero out the driver statistics */ - if (suser()) { - cli(); - memset(&lp->pktStats, 0, sizeof(lp->pktStats)); - sti(); - } else { - status = -EPERM; - } - - break; - case DE4X5_GET_OMR: /* Get the OMR Register contents */ - tmp.addr[0] = inl(DE4X5_OMR); - if (!(status = verify_area(VERIFY_WRITE, (void *)ioc->data, 1))) { - memcpy_tofs(ioc->data, tmp.addr, 1); - } - - break; - case DE4X5_SET_OMR: /* Set the OMR Register contents */ - if (suser()) { - if (!(status = verify_area(VERIFY_READ, (void *)ioc->data, 1))) { - memcpy_fromfs(tmp.addr, ioc->data, 1); - outl(tmp.addr[0], DE4X5_OMR); - } - } else { - status = -EPERM; - } - - break; - case DE4X5_GET_REG: /* Get the DE4X5 Registers */ - j = 0; - tmp.lval[0] = inl(DE4X5_STS); j+=4; - tmp.lval[1] = inl(DE4X5_BMR); j+=4; - tmp.lval[2] = inl(DE4X5_IMR); j+=4; - tmp.lval[3] = inl(DE4X5_OMR); j+=4; - tmp.lval[4] = inl(DE4X5_SISR); j+=4; - tmp.lval[5] = inl(DE4X5_SICR); j+=4; - tmp.lval[6] = inl(DE4X5_STRR); j+=4; - tmp.lval[7] = inl(DE4X5_SIGR); j+=4; - ioc->len = j; - if (!(status = verify_area(VERIFY_WRITE, (void *)ioc->data, ioc->len))) { - memcpy_tofs(ioc->data, tmp.addr, ioc->len); - } - break; - -#define DE4X5_DUMP 0x0f /* Dump the DE4X5 Status */ - - case DE4X5_DUMP: - j = 0; - tmp.addr[j++] = dev->irq; - for (i=0; i<ETH_ALEN; i++) { - tmp.addr[j++] = dev->dev_addr[i]; - } - tmp.addr[j++] = lp->rxRingSize; - tmp.lval[j>>2] = (long)lp->rx_ring; j+=4; - tmp.lval[j>>2] = (long)lp->tx_ring; j+=4; - - for (i=0;i<lp->rxRingSize-1;i++){ - if (i < 3) { - tmp.lval[j>>2] = (long)&lp->rx_ring[i].status; j+=4; - } - } - tmp.lval[j>>2] = (long)&lp->rx_ring[i].status; j+=4; - for (i=0;i<lp->txRingSize-1;i++){ - if (i < 3) { - tmp.lval[j>>2] = (long)&lp->tx_ring[i].status; j+=4; - } - } - tmp.lval[j>>2] = (long)&lp->tx_ring[i].status; j+=4; - - for (i=0;i<lp->rxRingSize-1;i++){ - if (i < 3) { - tmp.lval[j>>2] = (s32)lp->rx_ring[i].buf; j+=4; - } - } - tmp.lval[j>>2] = (s32)lp->rx_ring[i].buf; j+=4; - for (i=0;i<lp->txRingSize-1;i++){ - if (i < 3) { - tmp.lval[j>>2] = (s32)lp->tx_ring[i].buf; j+=4; - } - } - tmp.lval[j>>2] = (s32)lp->tx_ring[i].buf; j+=4; - - for (i=0;i<lp->rxRingSize;i++){ - tmp.lval[j>>2] = lp->rx_ring[i].status; j+=4; - } - for (i=0;i<lp->txRingSize;i++){ - tmp.lval[j>>2] = lp->tx_ring[i].status; j+=4; - } - - tmp.lval[j>>2] = inl(DE4X5_STS); j+=4; - tmp.lval[j>>2] = inl(DE4X5_BMR); j+=4; - tmp.lval[j>>2] = inl(DE4X5_IMR); j+=4; - tmp.lval[j>>2] = inl(DE4X5_OMR); j+=4; - tmp.lval[j>>2] = inl(DE4X5_SISR); j+=4; - tmp.lval[j>>2] = inl(DE4X5_SICR); j+=4; - tmp.lval[j>>2] = inl(DE4X5_STRR); j+=4; - tmp.lval[j>>2] = inl(DE4X5_SIGR); j+=4; - - tmp.addr[j++] = lp->txRingSize; - tmp.addr[j++] = dev->tbusy; - - ioc->len = j; - if (!(status = verify_area(VERIFY_WRITE, (void *)ioc->data, ioc->len))) { - memcpy_tofs(ioc->data, tmp.addr, ioc->len); - } - - break; - default: - status = -EOPNOTSUPP; - } - - return status; -} - -#ifdef MODULE -static char devicename[9] = { 0, }; -static struct device thisDE4X5 = { - devicename, /* device name is inserted by linux/drivers/net/net_init.c */ - 0, 0, 0, 0, - 0x2000, 10, /* I/O address, IRQ */ - 0, 0, 0, NULL, de4x5_probe }; - -static int io=0x000b; /* EDIT THESE LINES FOR YOUR CONFIGURATION */ -static int irq=10; /* or use the insmod io= irq= options */ - -int -init_module(void) -{ - thisDE4X5.base_addr=io; - thisDE4X5.irq=irq; - if (register_netdev(&thisDE4X5) != 0) - return -EIO; - return 0; -} - -void -cleanup_module(void) -{ - struct de4x5_private *lp = (struct de4x5_private *) thisDE4X5.priv; - - if (lp) { - kfree_s(bus_to_virt(lp->rx_ring[0].buf), RX_BUFF_SZ * NUM_RX_DESC + ALIGN); - } - kfree_s(thisDE4X5.priv, sizeof(struct de4x5_private) + ALIGN); - thisDE4X5.priv = NULL; - - release_region(thisDE4X5.base_addr, (lp->bus == PCI ? - DE4X5_PCI_TOTAL_SIZE : - DE4X5_EISA_TOTAL_SIZE)); - unregister_netdev(&thisDE4X5); -} -#endif /* MODULE */ - - -/* - * Local variables: - * kernel-compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O2 -m486 -c de4x5.c" - * - * module-compile-command: "gcc -D__KERNEL__ -DMODULE -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O2 -m486 -c de4x5.c" - * End: - */ - - diff --git a/i386/i386at/gpl/linux/net/de4x5.h b/i386/i386at/gpl/linux/net/de4x5.h deleted file mode 100644 index b0ee43ea..00000000 --- a/i386/i386at/gpl/linux/net/de4x5.h +++ /dev/null @@ -1,645 +0,0 @@ -/* - Copyright 1994 Digital Equipment Corporation. - - This software may be used and distributed according to the terms of the - GNU Public License, incorporated herein by reference. - - The author may be reached as davies@wanton.lkg.dec.com or Digital - Equipment Corporation, 550 King Street, Littleton MA 01460. - - ========================================================================= -*/ - -/* -** DC21040 CSR<1..15> Register Address Map -*/ -#define DE4X5_BMR iobase+(0x000 << lp->bus) /* Bus Mode Register */ -#define DE4X5_TPD iobase+(0x008 << lp->bus) /* Transmit Poll Demand Reg */ -#define DE4X5_RPD iobase+(0x010 << lp->bus) /* Receive Poll Demand Reg */ -#define DE4X5_RRBA iobase+(0x018 << lp->bus) /* RX Ring Base Address Reg */ -#define DE4X5_TRBA iobase+(0x020 << lp->bus) /* TX Ring Base Address Reg */ -#define DE4X5_STS iobase+(0x028 << lp->bus) /* Status Register */ -#define DE4X5_OMR iobase+(0x030 << lp->bus) /* Operation Mode Register */ -#define DE4X5_IMR iobase+(0x038 << lp->bus) /* Interrupt Mask Register */ -#define DE4X5_MFC iobase+(0x040 << lp->bus) /* Missed Frame Counter */ -#define DE4X5_APROM iobase+(0x048 << lp->bus) /* Ethernet Address PROM */ -#define DE4X5_BROM iobase+(0x048 << lp->bus) /* Boot ROM Register */ -#define DE4X5_SROM iobase+(0x048 << lp->bus) /* Serial ROM Register */ -#define DE4X5_DDR iobase+(0x050 << lp->bus) /* Data Diagnostic Register */ -#define DE4X5_FDR iobase+(0x058 << lp->bus) /* Full Duplex Register */ -#define DE4X5_GPT iobase+(0x058 << lp->bus) /* General Purpose Timer Reg.*/ -#define DE4X5_GEP iobase+(0x060 << lp->bus) /* General Purpose Register */ -#define DE4X5_SISR iobase+(0x060 << lp->bus) /* SIA Status Register */ -#define DE4X5_SICR iobase+(0x068 << lp->bus) /* SIA Connectivity Register */ -#define DE4X5_STRR iobase+(0x070 << lp->bus) /* SIA TX/RX Register */ -#define DE4X5_SIGR iobase+(0x078 << lp->bus) /* SIA General Register */ - -/* -** EISA Register Address Map -*/ -#define EISA_ID iobase+0x0c80 /* EISA ID Registers */ -#define EISA_ID0 iobase+0x0c80 /* EISA ID Register 0 */ -#define EISA_ID1 iobase+0x0c81 /* EISA ID Register 1 */ -#define EISA_ID2 iobase+0x0c82 /* EISA ID Register 2 */ -#define EISA_ID3 iobase+0x0c83 /* EISA ID Register 3 */ -#define EISA_CR iobase+0x0c84 /* EISA Control Register */ -#define EISA_REG0 iobase+0x0c88 /* EISA Configuration Register 0 */ -#define EISA_REG1 iobase+0x0c89 /* EISA Configuration Register 1 */ -#define EISA_REG2 iobase+0x0c8a /* EISA Configuration Register 2 */ -#define EISA_REG3 iobase+0x0c8f /* EISA Configuration Register 3 */ -#define EISA_APROM iobase+0x0c90 /* Ethernet Address PROM */ - -/* -** PCI/EISA Configuration Registers Address Map -*/ -#define PCI_CFID iobase+0x0008 /* PCI Configuration ID Register */ -#define PCI_CFCS iobase+0x000c /* PCI Command/Status Register */ -#define PCI_CFRV iobase+0x0018 /* PCI Revision Register */ -#define PCI_CFLT iobase+0x001c /* PCI Latency Timer Register */ -#define PCI_CBIO iobase+0x0028 /* PCI Base I/O Register */ -#define PCI_CBMA iobase+0x002c /* PCI Base Memory Address Register */ -#define PCI_CBER iobase+0x0030 /* PCI Expansion ROM Base Address Reg. */ -#define PCI_CFIT iobase+0x003c /* PCI Configuration Interrupt Register */ -#define PCI_CFDA iobase+0x0040 /* PCI Driver Area Register */ - -/* -** EISA Configuration Register 0 bit definitions -*/ -#define ER0_BSW 0x80 /* EISA Bus Slave Width, 1: 32 bits */ -#define ER0_BMW 0x40 /* EISA Bus Master Width, 1: 32 bits */ -#define ER0_EPT 0x20 /* EISA PREEMPT Time, 0: 23 BCLKs */ -#define ER0_ISTS 0x10 /* Interrupt Status (X) */ -#define ER0_LI 0x08 /* Latch Interrupts */ -#define ER0_INTL 0x06 /* INTerrupt Level */ -#define ER0_INTT 0x01 /* INTerrupt Type, 0: Level, 1: Edge */ - -/* -** EISA Configuration Register 1 bit definitions -*/ -#define ER1_IAM 0xe0 /* ISA Address Mode */ -#define ER1_IAE 0x10 /* ISA Addressing Enable */ -#define ER1_UPIN 0x0f /* User Pins */ - -/* -** EISA Configuration Register 2 bit definitions -*/ -#define ER2_BRS 0xc0 /* Boot ROM Size */ -#define ER2_BRA 0x3c /* Boot ROM Address <16:13> */ - -/* -** EISA Configuration Register 3 bit definitions -*/ -#define ER3_BWE 0x40 /* Burst Write Enable */ -#define ER3_BRE 0x04 /* Burst Read Enable */ -#define ER3_LSR 0x02 /* Local Software Reset */ - -/* -** PCI Configuration ID Register (PCI_CFID) -*/ -#define CFID_DID 0xff00 /* Device ID */ -#define CFID_VID 0x00ff /* Vendor ID */ -#define DC21040_DID 0x0002 /* Unique Device ID # */ -#define DC21040_VID 0x1011 /* DC21040 Manufacturer */ -#define DC21041_DID 0x0014 /* Unique Device ID # */ -#define DC21041_VID 0x1011 /* DC21041 Manufacturer */ -#define DC21140_DID 0x0009 /* Unique Device ID # */ -#define DC21140_VID 0x1011 /* DC21140 Manufacturer */ - -/* -** Chipset defines -*/ -#define DC21040 DC21040_DID -#define DC21041 DC21041_DID -#define DC21140 DC21140_DID - -#define is_DC21040 ((vendor == DC21040_VID) && (device == DC21040_DID)) -#define is_DC21041 ((vendor == DC21041_VID) && (device == DC21041_DID)) -#define is_DC21140 ((vendor == DC21140_VID) && (device == DC21140_DID)) - -/* -** PCI Configuration Command/Status Register (PCI_CFCS) -*/ -#define CFCS_DPE 0x80000000 /* Detected Parity Error (S) */ -#define CFCS_SSE 0x40000000 /* Signal System Error (S) */ -#define CFCS_RMA 0x20000000 /* Receive Master Abort (S) */ -#define CFCS_RTA 0x10000000 /* Receive Target Abort (S) */ -#define CFCS_DST 0x06000000 /* DEVSEL Timing (S) */ -#define CFCS_DPR 0x01000000 /* Data Parity Report (S) */ -#define CFCS_FBB 0x00800000 /* Fast Back-To-Back (S) */ -#define CFCS_SLE 0x00000100 /* System Error Enable (C) */ -#define CFCS_PER 0x00000040 /* Parity Error Response (C) */ -#define CFCS_MO 0x00000004 /* Master Operation (C) */ -#define CFCS_MSA 0x00000002 /* Memory Space Access (C) */ -#define CFCS_IOSA 0x00000001 /* I/O Space Access (C) */ - -/* -** PCI Configuration Revision Register (PCI_CFRV) -*/ -#define CFRV_BC 0xff000000 /* Base Class */ -#define CFRV_SC 0x00ff0000 /* Subclass */ -#define CFRV_SN 0x000000f0 /* Step Number */ -#define CFRV_RN 0x0000000f /* Revision Number */ -#define BASE_CLASS 0x02000000 /* Indicates Network Controller */ -#define SUB_CLASS 0x00000000 /* Indicates Ethernet Controller */ -#define STEP_NUMBER 0x00000020 /* Increments for future chips */ -#define REV_NUMBER 0x00000003 /* 0x00, 0x01, 0x02, 0x03: Rev in Step */ -#define CFRV_MASK 0xffff0000 /* Register mask */ - -/* -** PCI Configuration Latency Timer Register (PCI_CFLT) -*/ -#define CFLT_BC 0x0000ff00 /* Latency Timer bits */ - -/* -** PCI Configuration Base I/O Address Register (PCI_CBIO) -*/ -#define CBIO_MASK 0xffffff80 /* Base I/O Address Mask */ -#define CBIO_IOSI 0x00000001 /* I/O Space Indicator (RO, value is 1) */ - -/* -** PCI Configuration Expansion ROM Base Address Register (PCI_CBER) -*/ -#define CBER_MASK 0xfffffc00 /* Expansion ROM Base Address Mask */ -#define CBER_ROME 0x00000001 /* ROM Enable */ - -/* -** PCI Configuration Driver Area Register (PCI_CFDA) -*/ -#define CFDA_PSM 0x80000000 /* Power Saving Mode */ - -/* -** DC21040 Bus Mode Register (DE4X5_BMR) -*/ -#define BMR_DBO 0x00100000 /* Descriptor Byte Ordering (Endian) */ -#define BMR_TAP 0x000e0000 /* Transmit Automatic Polling */ -#define BMR_DAS 0x00010000 /* Diagnostic Address Space */ -#define BMR_CAL 0x0000c000 /* Cache Alignment */ -#define BMR_PBL 0x00003f00 /* Programmable Burst Length */ -#define BMR_BLE 0x00000080 /* Big/Little Endian */ -#define BMR_DSL 0x0000007c /* Descriptor Skip Length */ -#define BMR_BAR 0x00000002 /* Bus ARbitration */ -#define BMR_SWR 0x00000001 /* Software Reset */ - -#define TAP_NOPOLL 0x00000000 /* No automatic polling */ -#define TAP_200US 0x00020000 /* TX automatic polling every 200us */ -#define TAP_800US 0x00040000 /* TX automatic polling every 800us */ -#define TAP_1_6MS 0x00060000 /* TX automatic polling every 1.6ms */ -#define TAP_12_8US 0x00080000 /* TX automatic polling every 12.8us */ -#define TAP_25_6US 0x000a0000 /* TX automatic polling every 25.6us */ -#define TAP_51_2US 0x000c0000 /* TX automatic polling every 51.2us */ -#define TAP_102_4US 0x000e0000 /* TX automatic polling every 102.4us */ - -#define CAL_NOUSE 0x00000000 /* Not used */ -#define CAL_8LONG 0x00004000 /* 8-longword alignment */ -#define CAL_16LONG 0x00008000 /* 16-longword alignment */ -#define CAL_32LONG 0x0000c000 /* 32-longword alignment */ - -#define PBL_0 0x00000000 /* DMA burst length = amount in RX FIFO */ -#define PBL_1 0x00000100 /* 1 longword DMA burst length */ -#define PBL_2 0x00000200 /* 2 longwords DMA burst length */ -#define PBL_4 0x00000400 /* 4 longwords DMA burst length */ -#define PBL_8 0x00000800 /* 8 longwords DMA burst length */ -#define PBL_16 0x00001000 /* 16 longwords DMA burst length */ -#define PBL_32 0x00002000 /* 32 longwords DMA burst length */ - -#define DSL_0 0x00000000 /* 0 longword / descriptor */ -#define DSL_1 0x00000004 /* 1 longword / descriptor */ -#define DSL_2 0x00000008 /* 2 longwords / descriptor */ -#define DSL_4 0x00000010 /* 4 longwords / descriptor */ -#define DSL_8 0x00000020 /* 8 longwords / descriptor */ -#define DSL_16 0x00000040 /* 16 longwords / descriptor */ -#define DSL_32 0x00000080 /* 32 longwords / descriptor */ - -/* -** DC21040 Transmit Poll Demand Register (DE4X5_TPD) -*/ -#define TPD 0x00000001 /* Transmit Poll Demand */ - -/* -** DC21040 Receive Poll Demand Register (DE4X5_RPD) -*/ -#define RPD 0x00000001 /* Receive Poll Demand */ - -/* -** DC21040 Receive Ring Base Address Register (DE4X5_RRBA) -*/ -#define RRBA 0xfffffffc /* RX Descriptor List Start Address */ - -/* -** DC21040 Transmit Ring Base Address Register (DE4X5_TRBA) -*/ -#define TRBA 0xfffffffc /* TX Descriptor List Start Address */ - -/* -** DC21040 Status Register (DE4X5_STS) -*/ -#define STS_BE 0x03800000 /* Bus Error Bits */ -#define STS_TS 0x00700000 /* Transmit Process State */ -#define STS_RS 0x000e0000 /* Receive Process State */ -#define STS_NIS 0x00010000 /* Normal Interrupt Summary */ -#define STS_AIS 0x00008000 /* Abnormal Interrupt Summary */ -#define STS_ER 0x00004000 /* Early Receive */ -#define STS_SE 0x00002000 /* System Error */ -#define STS_LNF 0x00001000 /* Link Fail */ -#define STS_FD 0x00000800 /* Full-Duplex Short Frame Received */ -#define STS_TM 0x00000800 /* Timer Expired (DC21041) */ -#define STS_AT 0x00000400 /* AUI/TP Pin */ -#define STS_RWT 0x00000200 /* Receive Watchdog Time-Out */ -#define STS_RPS 0x00000100 /* Receive Process Stopped */ -#define STS_RU 0x00000080 /* Receive Buffer Unavailable */ -#define STS_RI 0x00000040 /* Receive Interrupt */ -#define STS_UNF 0x00000020 /* Transmit Underflow */ -#define STS_LNP 0x00000010 /* Link Pass */ -#define STS_TJT 0x00000008 /* Transmit Jabber Time-Out */ -#define STS_TU 0x00000004 /* Transmit Buffer Unavailable */ -#define STS_TPS 0x00000002 /* Transmit Process Stopped */ -#define STS_TI 0x00000001 /* Transmit Interrupt */ - -#define EB_PAR 0x00000000 /* Parity Error */ -#define EB_MA 0x00800000 /* Master Abort */ -#define EB_TA 0x01000000 /* Target Abort */ -#define EB_RES0 0x01800000 /* Reserved */ -#define EB_RES1 0x02000000 /* Reserved */ - -#define TS_STOP 0x00000000 /* Stopped */ -#define TS_FTD 0x00100000 /* Fetch Transmit Descriptor */ -#define TS_WEOT 0x00200000 /* Wait for End Of Transmission */ -#define TS_QDAT 0x00300000 /* Queue skb data into TX FIFO */ -#define TS_RES 0x00400000 /* Reserved */ -#define TS_SPKT 0x00500000 /* Setup Packet */ -#define TS_SUSP 0x00600000 /* Suspended */ -#define TS_CLTD 0x00700000 /* Close Transmit Descriptor */ - -#define RS_STOP 0x00000000 /* Stopped */ -#define RS_FRD 0x00020000 /* Fetch Receive Descriptor */ -#define RS_CEOR 0x00040000 /* Check for End of Receive Packet */ -#define RS_WFRP 0x00060000 /* Wait for Receive Packet */ -#define RS_SUSP 0x00080000 /* Suspended */ -#define RS_CLRD 0x000a0000 /* Close Receive Descriptor */ -#define RS_FLUSH 0x000c0000 /* Flush RX FIFO */ -#define RS_QRFS 0x000e0000 /* Queue RX FIFO into RX Skb */ - -#define INT_CANCEL 0x0001ffff /* For zeroing all interrupt sources */ - -/* -** DC21040 Operation Mode Register (DE4X5_OMR) -*/ -#define OMR_SDP 0x02000000 /* SD Polarity - MUST BE ASSERTED */ -#define OMR_SCR 0x01000000 /* Scrambler Mode */ -#define OMR_PCS 0x00800000 /* PCS Function */ -#define OMR_TTM 0x00400000 /* Transmit Threshold Mode */ -#define OMR_SF 0x00200000 /* Store and Forward */ -#define OMR_HBD 0x00080000 /* HeartBeat Disable */ -#define OMR_PS 0x00040000 /* Port Select */ -#define OMR_CA 0x00020000 /* Capture Effect Enable */ -#define OMR_BP 0x00010000 /* Back Pressure */ -#define OMR_TR 0x0000c000 /* Threshold Control Bits */ -#define OMR_ST 0x00002000 /* Start/Stop Transmission Command */ -#define OMR_FC 0x00001000 /* Force Collision Mode */ -#define OMR_OM 0x00000c00 /* Operating Mode */ -#define OMR_FD 0x00000200 /* Full Duplex Mode */ -#define OMR_FKD 0x00000100 /* Flaky Oscillator Disable */ -#define OMR_PM 0x00000080 /* Pass All Multicast */ -#define OMR_PR 0x00000040 /* Promiscuous Mode */ -#define OMR_SB 0x00000020 /* Start/Stop Backoff Counter */ -#define OMR_IF 0x00000010 /* Inverse Filtering */ -#define OMR_PB 0x00000008 /* Pass Bad Frames */ -#define OMR_HO 0x00000004 /* Hash Only Filtering Mode */ -#define OMR_SR 0x00000002 /* Start/Stop Receive */ -#define OMR_HP 0x00000001 /* Hash/Perfect Receive Filtering Mode */ - -#define TR_72 0x00000000 /* Threshold set to 72 bytes */ -#define TR_96 0x00004000 /* Threshold set to 96 bytes */ -#define TR_128 0x00008000 /* Threshold set to 128 bytes */ -#define TR_160 0x0000c000 /* Threshold set to 160 bytes */ - -/* -** DC21040 Interrupt Mask Register (DE4X5_IMR) -*/ -#define IMR_NIM 0x00010000 /* Normal Interrupt Summary Mask */ -#define IMR_AIM 0x00008000 /* Abnormal Interrupt Summary Mask */ -#define IMR_ERM 0x00004000 /* Early Receive Mask */ -#define IMR_SEM 0x00002000 /* System Error Mask */ -#define IMR_LFM 0x00001000 /* Link Fail Mask */ -#define IMR_FDM 0x00000800 /* Full-Duplex (Short Frame) Mask */ -#define IMR_TMM 0x00000800 /* Timer Expired Mask (DC21041) */ -#define IMR_ATM 0x00000400 /* AUI/TP Switch Mask */ -#define IMR_RWM 0x00000200 /* Receive Watchdog Time-Out Mask */ -#define IMR_RSM 0x00000100 /* Receive Stopped Mask */ -#define IMR_RUM 0x00000080 /* Receive Buffer Unavailable Mask */ -#define IMR_RIM 0x00000040 /* Receive Interrupt Mask */ -#define IMR_UNM 0x00000020 /* Underflow Interrupt Mask */ -#define IMR_LPM 0x00000010 /* Link Pass */ -#define IMR_TJM 0x00000008 /* Transmit Time-Out Jabber Mask */ -#define IMR_TUM 0x00000004 /* Transmit Buffer Unavailable Mask */ -#define IMR_TSM 0x00000002 /* Transmission Stopped Mask */ -#define IMR_TIM 0x00000001 /* Transmit Interrupt Mask */ - -/* -** DC21040 Missed Frame Counter (DE4X5_MFC) -*/ -#define MFC_OVFL 0x00010000 /* Counter Overflow Bit */ -#define MFC_CNTR 0x0000ffff /* Counter Bits */ - -/* -** DC21040 Ethernet Address PROM (DE4X5_APROM) -*/ -#define APROM_DN 0x80000000 /* Data Not Valid */ -#define APROM_DT 0x000000ff /* Address Byte */ - -/* -** DC21041 Boot/Ethernet Address ROM (DE4X5_BROM) -*/ -#define BROM_MODE 0x00008000 /* MODE_1: 0, MODE_0: 1 (read only) */ -#define BROM_RD 0x00004000 /* Read from Boot ROM */ -#define BROM_WR 0x00002000 /* Write to Boot ROM */ -#define BROM_BR 0x00001000 /* Select Boot ROM when set */ -#define BROM_SR 0x00000800 /* Select Serial ROM when set */ -#define BROM_REG 0x00000400 /* External Register Select */ -#define BROM_DT 0x000000ff /* Data Byte */ - -/* -** DC21041 Serial/Ethernet Address ROM (DE4X5_SROM) -*/ -#define SROM_MODE 0x00008000 /* MODE_1: 0, MODE_0: 1 (read only) */ -#define SROM_RD 0x00004000 /* Read from Boot ROM */ -#define SROM_WR 0x00002000 /* Write to Boot ROM */ -#define SROM_BR 0x00001000 /* Select Boot ROM when set */ -#define SROM_SR 0x00000800 /* Select Serial ROM when set */ -#define SROM_REG 0x00000400 /* External Register Select */ -#define SROM_DT 0x000000ff /* Data Byte */ - -#define DT_OUT 0x00000008 /* Serial Data Out */ -#define DT_IN 0x00000004 /* Serial Data In */ -#define DT_CLK 0x00000002 /* Serial ROM Clock */ -#define DT_CS 0x00000001 /* Serial ROM Chip Select */ - -/* -** DC21040 Full Duplex Register (DE4X5_FDR) -*/ -#define FDR_FDACV 0x0000ffff /* Full Duplex Auto Configuration Value */ - -/* -** DC21041 General Purpose Timer Register (DE4X5_GPT) -*/ -#define GPT_CON 0x00010000 /* One shot: 0, Continuous: 1 */ -#define GPT_VAL 0x0000ffff /* Timer Value */ - -/* -** DC21140 General Purpose Register (DE4X5_GEP) (hardware dependent bits) -*/ -/* Valid ONLY for DE500 hardware */ -#define GEP_LNP 0x00000080 /* Link Pass (input) */ -#define GEP_SLNK 0x00000040 /* SYM LINK (input) */ -#define GEP_SDET 0x00000020 /* Signal Detect (input) */ -#define GEP_FDXD 0x00000008 /* Full Duplex Disable (output) */ -#define GEP_PHYL 0x00000004 /* PHY Loopback (output) */ -#define GEP_FLED 0x00000002 /* Force Activity LED on (output) */ -#define GEP_MODE 0x00000001 /* 0: 10Mb/s, 1: 100Mb/s */ -#define GEP_INIT 0x0000010f /* Setup inputs (0) and outputs (1) */ - - -/* -** DC21040 SIA Status Register (DE4X5_SISR) -*/ -#define SISR_LPC 0xffff0000 /* Link Partner's Code Word */ -#define SISR_LPN 0x00008000 /* Link Partner Negotiable */ -#define SISR_ANS 0x00007000 /* Auto Negotiation Arbitration State */ -#define SISR_NSN 0x00000800 /* Non Stable NLPs Detected */ -#define SISR_ANR_FDS 0x00000400 /* Auto Negotiate Restart/Full Duplex Sel.*/ -#define SISR_NRA 0x00000200 /* Non Selected Port Receive Activity */ -#define SISR_SRA 0x00000100 /* Selected Port Receive Activity */ -#define SISR_DAO 0x00000080 /* PLL All One */ -#define SISR_DAZ 0x00000040 /* PLL All Zero */ -#define SISR_DSP 0x00000020 /* PLL Self-Test Pass */ -#define SISR_DSD 0x00000010 /* PLL Self-Test Done */ -#define SISR_APS 0x00000008 /* Auto Polarity State */ -#define SISR_LKF 0x00000004 /* Link Fail Status */ -#define SISR_NCR 0x00000002 /* Network Connection Error */ -#define SISR_PAUI 0x00000001 /* AUI_TP Indication */ -#define SIA_RESET 0x00000000 /* SIA Reset */ - -#define ANS_NDIS 0x00000000 /* Nway disable */ -#define ANS_TDIS 0x00001000 /* Transmit Disable */ -#define ANS_ADET 0x00002000 /* Ability Detect */ -#define ANS_ACK 0x00003000 /* Acknowledge */ -#define ANS_CACK 0x00004000 /* Complete Acknowledge */ -#define ANS_NWOK 0x00005000 /* Nway OK - FLP Link Good */ -#define ANS_LCHK 0x00006000 /* Link Check */ - -/* -** DC21040 SIA Connectivity Register (DE4X5_SICR) -*/ -#define SICR_SDM 0xffff0000 /* SIA Diagnostics Mode */ -#define SICR_OE57 0x00008000 /* Output Enable 5 6 7 */ -#define SICR_OE24 0x00004000 /* Output Enable 2 4 */ -#define SICR_OE13 0x00002000 /* Output Enable 1 3 */ -#define SICR_IE 0x00001000 /* Input Enable */ -#define SICR_EXT 0x00000000 /* SIA MUX Select External SIA Mode */ -#define SICR_D_SIA 0x00000400 /* SIA MUX Select Diagnostics - SIA Sigs */ -#define SICR_DPLL 0x00000800 /* SIA MUX Select Diagnostics - DPLL Sigs*/ -#define SICR_APLL 0x00000a00 /* SIA MUX Select Diagnostics - DPLL Sigs*/ -#define SICR_D_RxM 0x00000c00 /* SIA MUX Select Diagnostics - RxM Sigs */ -#define SICR_M_RxM 0x00000d00 /* SIA MUX Select Diagnostics - RxM Sigs */ -#define SICR_LNKT 0x00000e00 /* SIA MUX Select Diagnostics - Link Test*/ -#define SICR_SEL 0x00000f00 /* SIA MUX Select AUI or TP with LEDs */ -#define SICR_ASE 0x00000080 /* APLL Start Enable*/ -#define SICR_SIM 0x00000040 /* Serial Interface Input Multiplexer */ -#define SICR_ENI 0x00000020 /* Encoder Input Multiplexer */ -#define SICR_EDP 0x00000010 /* SIA PLL External Input Enable */ -#define SICR_AUI 0x00000008 /* 10Base-T or AUI */ -#define SICR_CAC 0x00000004 /* CSR Auto Configuration */ -#define SICR_PS 0x00000002 /* Pin AUI/TP Selection */ -#define SICR_SRL 0x00000001 /* SIA Reset */ -#define SICR_RESET 0xffff0000 /* Reset value for SICR */ - -/* -** DC21040 SIA Transmit and Receive Register (DE4X5_STRR) -*/ -#define STRR_TAS 0x00008000 /* 10Base-T/AUI Autosensing Enable */ -#define STRR_SPP 0x00004000 /* Set Polarity Plus */ -#define STRR_APE 0x00002000 /* Auto Polarity Enable */ -#define STRR_LTE 0x00001000 /* Link Test Enable */ -#define STRR_SQE 0x00000800 /* Signal Quality Enable */ -#define STRR_CLD 0x00000400 /* Collision Detect Enable */ -#define STRR_CSQ 0x00000200 /* Collision Squelch Enable */ -#define STRR_RSQ 0x00000100 /* Receive Squelch Enable */ -#define STRR_ANE 0x00000080 /* Auto Negotiate Enable */ -#define STRR_HDE 0x00000040 /* Half Duplex Enable */ -#define STRR_CPEN 0x00000030 /* Compensation Enable */ -#define STRR_LSE 0x00000008 /* Link Pulse Send Enable */ -#define STRR_DREN 0x00000004 /* Driver Enable */ -#define STRR_LBK 0x00000002 /* Loopback Enable */ -#define STRR_ECEN 0x00000001 /* Encoder Enable */ -#define STRR_RESET 0xffffffff /* Reset value for STRR */ - -/* -** DC21040 SIA General Register (DE4X5_SIGR) -*/ -#define SIGR_LV2 0x00008000 /* General Purpose LED2 value */ -#define SIGR_LE2 0x00004000 /* General Purpose LED2 enable */ -#define SIGR_FRL 0x00002000 /* Force Receiver Low */ -#define SIGR_DPST 0x00001000 /* PLL Self Test Start */ -#define SIGR_LSD 0x00000800 /* LED Stretch Disable */ -#define SIGR_FLF 0x00000400 /* Force Link Fail */ -#define SIGR_FUSQ 0x00000200 /* Force Unsquelch */ -#define SIGR_TSCK 0x00000100 /* Test Clock */ -#define SIGR_LV1 0x00000080 /* General Purpose LED1 value */ -#define SIGR_LE1 0x00000040 /* General Purpose LED1 enable */ -#define SIGR_RWR 0x00000020 /* Receive Watchdog Release */ -#define SIGR_RWD 0x00000010 /* Receive Watchdog Disable */ -#define SIGR_ABM 0x00000008 /* BNC: 0, AUI:1 */ -#define SIGR_JCK 0x00000004 /* Jabber Clock */ -#define SIGR_HUJ 0x00000002 /* Host Unjab */ -#define SIGR_JBD 0x00000001 /* Jabber Disable */ -#define SIGR_RESET 0xffff0000 /* Reset value for SIGR */ - -/* -** Receive Descriptor Bit Summary -*/ -#define R_OWN 0x80000000 /* Own Bit */ -#define RD_FL 0x7fff0000 /* Frame Length */ -#define RD_ES 0x00008000 /* Error Summary */ -#define RD_LE 0x00004000 /* Length Error */ -#define RD_DT 0x00003000 /* Data Type */ -#define RD_RF 0x00000800 /* Runt Frame */ -#define RD_MF 0x00000400 /* Multicast Frame */ -#define RD_FS 0x00000200 /* First Descriptor */ -#define RD_LS 0x00000100 /* Last Descriptor */ -#define RD_TL 0x00000080 /* Frame Too Long */ -#define RD_CS 0x00000040 /* Collision Seen */ -#define RD_FT 0x00000020 /* Frame Type */ -#define RD_RJ 0x00000010 /* Receive Watchdog */ -#define RD_DB 0x00000004 /* Dribbling Bit */ -#define RD_CE 0x00000002 /* CRC Error */ -#define RD_OF 0x00000001 /* Overflow */ - -#define RD_RER 0x02000000 /* Receive End Of Ring */ -#define RD_RCH 0x01000000 /* Second Address Chained */ -#define RD_RBS2 0x003ff800 /* Buffer 2 Size */ -#define RD_RBS1 0x000007ff /* Buffer 1 Size */ - -/* -** Transmit Descriptor Bit Summary -*/ -#define T_OWN 0x80000000 /* Own Bit */ -#define TD_ES 0x00008000 /* Error Summary */ -#define TD_TO 0x00004000 /* Transmit Jabber Time-Out */ -#define TD_LO 0x00000800 /* Loss Of Carrier */ -#define TD_NC 0x00000400 /* No Carrier */ -#define TD_LC 0x00000200 /* Late Collision */ -#define TD_EC 0x00000100 /* Excessive Collisions */ -#define TD_HF 0x00000080 /* Heartbeat Fail */ -#define TD_CC 0x00000078 /* Collision Counter */ -#define TD_LF 0x00000004 /* Link Fail */ -#define TD_UF 0x00000002 /* Underflow Error */ -#define TD_DE 0x00000001 /* Deferred */ - -#define TD_IC 0x80000000 /* Interrupt On Completion */ -#define TD_LS 0x40000000 /* Last Segment */ -#define TD_FS 0x20000000 /* First Segment */ -#define TD_FT1 0x10000000 /* Filtering Type */ -#define TD_SET 0x08000000 /* Setup Packet */ -#define TD_AC 0x04000000 /* Add CRC Disable */ -#define TD_TER 0x02000000 /* Transmit End Of Ring */ -#define TD_TCH 0x01000000 /* Second Address Chained */ -#define TD_DPD 0x00800000 /* Disabled Padding */ -#define TD_FT0 0x00400000 /* Filtering Type */ -#define TD_RBS2 0x003ff800 /* Buffer 2 Size */ -#define TD_RBS1 0x000007ff /* Buffer 1 Size */ - -#define PERFECT_F 0x00000000 -#define HASH_F TD_FT0 -#define INVERSE_F TD_FT1 -#define HASH_O_F TD_FT1| TD_F0 - -/* -** Media / mode state machine definitions -*/ -#define NC 0x0000 /* No Connection */ -#define TP 0x0001 /* 10Base-T */ -#define TP_NW 0x0002 /* 10Base-T with Nway */ -#define BNC 0x0004 /* Thinwire */ -#define AUI 0x0008 /* Thickwire */ -#define BNC_AUI 0x0010 /* BNC/AUI on DC21040 indistinguishable */ -#define ANS 0x0020 /* Intermediate AutoNegotiation State */ -#define EXT_SIA 0x0400 /* external SIA (as on DEC MULTIA) */ - -#define _10Mb 0x0040 /* 10Mb/s Ethernet */ -#define _100Mb 0x0080 /* 100Mb/s Ethernet */ -#define SYM_WAIT 0x0100 /* Wait for SYM_LINK */ -#define INIT 0x0200 /* Initial state */ - -#define AUTO 0x4000 /* Auto sense the media or speed */ - -/* -** Miscellaneous -*/ -#define PCI 0 -#define EISA 1 - -#define HASH_TABLE_LEN 512 /* Bits */ -#define HASH_BITS 0x01ff /* 9 LS bits */ - -#define SETUP_FRAME_LEN 192 /* Bytes */ -#define IMPERF_PA_OFFSET 156 /* Bytes */ - -#define POLL_DEMAND 1 - -#define LOST_MEDIA_THRESHOLD 3 - -#define MASK_INTERRUPTS 1 -#define UNMASK_INTERRUPTS 0 - -#define DE4X5_STRLEN 8 - -/* -** Address Filtering Modes -*/ -#define PERFECT 0 /* 16 perfect physical addresses */ -#define HASH_PERF 1 /* 1 perfect, 512 multicast addresses */ -#define PERFECT_REJ 2 /* Reject 16 perfect physical addresses */ -#define ALL_HASH 3 /* Hashes all physical & multicast addrs */ - -#define ALL 0 /* Clear out all the setup frame */ -#define PHYS_ADDR_ONLY 1 /* Update the physical address only */ - -/* -** Booleans -*/ -#define NO 0 -#define FALSE 0 - -#define YES !0 -#define TRUE !0 - -/* -** Include the IOCTL stuff -*/ -#include <linux/sockios.h> - -#define DE4X5IOCTL SIOCDEVPRIVATE - -struct de4x5_ioctl { - unsigned short cmd; /* Command to run */ - unsigned short len; /* Length of the data buffer */ - unsigned char *data; /* Pointer to the data buffer */ -}; - -/* -** Recognised commands for the driver -*/ -#define DE4X5_GET_HWADDR 0x01 /* Get the hardware address */ -#define DE4X5_SET_HWADDR 0x02 /* Get the hardware address */ -#define DE4X5_SET_PROM 0x03 /* Set Promiscuous Mode */ -#define DE4X5_CLR_PROM 0x04 /* Clear Promiscuous Mode */ -#define DE4X5_SAY_BOO 0x05 /* Say "Boo!" to the kernel log file */ -#define DE4X5_GET_MCA 0x06 /* Get a multicast address */ -#define DE4X5_SET_MCA 0x07 /* Set a multicast address */ -#define DE4X5_CLR_MCA 0x08 /* Clear a multicast address */ -#define DE4X5_MCA_EN 0x09 /* Enable a multicast address group */ -#define DE4X5_GET_STATS 0x0a /* Get the driver statistics */ -#define DE4X5_CLR_STATS 0x0b /* Zero out the driver statistics */ -#define DE4X5_GET_OMR 0x0c /* Get the OMR Register contents */ -#define DE4X5_SET_OMR 0x0d /* Set the OMR Register contents */ -#define DE4X5_GET_REG 0x0e /* Get the DE4X5 Registers */ diff --git a/i386/i386at/gpl/linux/net/de600.c b/i386/i386at/gpl/linux/net/de600.c deleted file mode 100644 index 256759df..00000000 --- a/i386/i386at/gpl/linux/net/de600.c +++ /dev/null @@ -1,853 +0,0 @@ -static const char *version = - "de600.c: $Revision: 1.1.1.1 $, Bjorn Ekwall (bj0rn@blox.se)\n"; -/* - * de600.c - * - * Linux driver for the D-Link DE-600 Ethernet pocket adapter. - * - * Portions (C) Copyright 1993, 1994 by Bjorn Ekwall - * The Author may be reached as bj0rn@blox.se - * - * Based on adapter information gathered from DE600.ASM by D-Link Inc., - * as included on disk C in the v.2.11 of PC/TCP from FTP Software. - * For DE600.asm: - * Portions (C) Copyright 1990 D-Link, Inc. - * Copyright, 1988-1992, Russell Nelson, Crynwr Software - * - * Adapted to the sample network driver core for linux, - * written by: Donald Becker <becker@super.org> - * C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715 - * - * compile-command: - * "gcc -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer \ - * -m486 -c de600.c - * - **************************************************************/ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - **************************************************************/ -/* Add another "; SLOW_DOWN_IO" here if your adapter won't work OK: */ -#define DE600_SLOW_DOWN SLOW_DOWN_IO; SLOW_DOWN_IO; SLOW_DOWN_IO - - /* - * If you still have trouble reading/writing to the adapter, - * modify the following "#define": (see <asm/io.h> for more info) -#define REALLY_SLOW_IO - */ -#define SLOW_IO_BY_JUMPING /* Looks "better" than dummy write to port 0x80 :-) */ - -/* - * If you want to enable automatic continuous checking for the DE600, - * keep this #define enabled. - * It doesn't cost much per packet, so I think it is worth it! - * If you disagree, comment away the #define, and live with it... - * - */ -#define CHECK_LOST_DE600 - -/* - * Enable this #define if you want the adapter to do a "ifconfig down" on - * itself when we have detected that something is possibly wrong with it. - * The default behaviour is to retry with "adapter_init()" until success. - * This should be used for debugging purposes only. - * (Depends on the CHECK_LOST_DE600 above) - * - */ -#define SHUTDOWN_WHEN_LOST - -/* - * See comment at "de600_rspace()"! - * This is an *ugly* hack, but for now it achieves its goal of - * faking a TCP flow-control that will not flood the poor DE600. - * - * Tricks TCP to announce a small max window (max 2 fast packets please :-) - * - * Comment away at your own risk! - * - * Update: Use the more general per-device maxwindow parameter instead. - */ -#undef FAKE_SMALL_MAX - -/* use 0 for production, 1 for verification, >2 for debug */ -#ifdef DE600_DEBUG -#define PRINTK(x) if (de600_debug >= 2) printk x -#else -#define DE600_DEBUG 0 -#define PRINTK(x) /**/ -#endif -unsigned int de600_debug = DE600_DEBUG; - -#include <linux/module.h> - -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/types.h> -#include <linux/fcntl.h> -#include <linux/string.h> -#include <linux/interrupt.h> -#include <linux/ioport.h> -#include <asm/io.h> -#include <linux/in.h> -#include <linux/ptrace.h> -#include <asm/system.h> -#include <linux/errno.h> - -#include <linux/inet.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> - -#ifdef FAKE_SMALL_MAX -static unsigned long de600_rspace(struct sock *sk); -#include <net/sock.h> -#endif - -#define netstats enet_statistics -typedef unsigned char byte; - -/************************************************** - * * - * Definition of D-Link Ethernet Pocket adapter * - * * - **************************************************/ -/* - * D-Link Ethernet pocket adapter ports - */ -/* - * OK, so I'm cheating, but there are an awful lot of - * reads and writes in order to get anything in and out - * of the DE-600 with 4 bits at a time in the parallel port, - * so every saved instruction really helps :-) - * - * That is, I don't care what the device struct says - * but hope that Space.c will keep the rest of the drivers happy. - */ -#ifndef DE600_IO -#define DE600_IO 0x378 -#endif - -#define DATA_PORT (DE600_IO) -#define STATUS_PORT (DE600_IO + 1) -#define COMMAND_PORT (DE600_IO + 2) - -#ifndef DE600_IRQ -#define DE600_IRQ 7 -#endif -/* - * It really should look like this, and autoprobing as well... - * -#define DATA_PORT (dev->base_addr + 0) -#define STATUS_PORT (dev->base_addr + 1) -#define COMMAND_PORT (dev->base_addr + 2) -#define DE600_IRQ dev->irq - */ - -/* - * D-Link COMMAND_PORT commands - */ -#define SELECT_NIC 0x04 /* select Network Interface Card */ -#define SELECT_PRN 0x1c /* select Printer */ -#define NML_PRN 0xec /* normal Printer situation */ -#define IRQEN 0x10 /* enable IRQ line */ - -/* - * D-Link STATUS_PORT - */ -#define RX_BUSY 0x80 -#define RX_GOOD 0x40 -#define TX_FAILED16 0x10 -#define TX_BUSY 0x08 - -/* - * D-Link DATA_PORT commands - * command in low 4 bits - * data in high 4 bits - * select current data nibble with HI_NIBBLE bit - */ -#define WRITE_DATA 0x00 /* write memory */ -#define READ_DATA 0x01 /* read memory */ -#define STATUS 0x02 /* read status register */ -#define COMMAND 0x03 /* write command register (see COMMAND below) */ -#define NULL_COMMAND 0x04 /* null command */ -#define RX_LEN 0x05 /* read received packet length */ -#define TX_ADDR 0x06 /* set adapter transmit memory address */ -#define RW_ADDR 0x07 /* set adapter read/write memory address */ -#define HI_NIBBLE 0x08 /* read/write the high nibble of data, - or-ed with rest of command */ - -/* - * command register, accessed through DATA_PORT with low bits = COMMAND - */ -#define RX_ALL 0x01 /* PROMISCUOUS */ -#define RX_BP 0x02 /* default: BROADCAST & PHYSICAL ADDRESS */ -#define RX_MBP 0x03 /* MULTICAST, BROADCAST & PHYSICAL ADDRESS */ - -#define TX_ENABLE 0x04 /* bit 2 */ -#define RX_ENABLE 0x08 /* bit 3 */ - -#define RESET 0x80 /* set bit 7 high */ -#define STOP_RESET 0x00 /* set bit 7 low */ - -/* - * data to command register - * (high 4 bits in write to DATA_PORT) - */ -#define RX_PAGE2_SELECT 0x10 /* bit 4, only 2 pages to select */ -#define RX_BASE_PAGE 0x20 /* bit 5, always set when specifying RX_ADDR */ -#define FLIP_IRQ 0x40 /* bit 6 */ - -/* - * D-Link adapter internal memory: - * - * 0-2K 1:st transmit page (send from pointer up to 2K) - * 2-4K 2:nd transmit page (send from pointer up to 4K) - * - * 4-6K 1:st receive page (data from 4K upwards) - * 6-8K 2:nd receive page (data from 6K upwards) - * - * 8K+ Adapter ROM (contains magic code and last 3 bytes of Ethernet address) - */ -#define MEM_2K 0x0800 /* 2048 */ -#define MEM_4K 0x1000 /* 4096 */ -#define MEM_6K 0x1800 /* 6144 */ -#define NODE_ADDRESS 0x2000 /* 8192 */ - -#define RUNT 60 /* Too small Ethernet packet */ - -/************************************************** - * * - * End of definition * - * * - **************************************************/ - -/* - * Index to functions, as function prototypes. - */ -/* Routines used internally. (See "convenience macros") */ -static byte de600_read_status(struct device *dev); -static byte de600_read_byte(unsigned char type, struct device *dev); - -/* Put in the device structure. */ -static int de600_open(struct device *dev); -static int de600_close(struct device *dev); -static struct netstats *get_stats(struct device *dev); -static int de600_start_xmit(struct sk_buff *skb, struct device *dev); - -/* Dispatch from interrupts. */ -static void de600_interrupt(int irq, struct pt_regs *regs); -static int de600_tx_intr(struct device *dev, int irq_status); -static void de600_rx_intr(struct device *dev); - -/* Initialization */ -static void trigger_interrupt(struct device *dev); -int de600_probe(struct device *dev); -static int adapter_init(struct device *dev); - -/* - * D-Link driver variables: - */ -static volatile int rx_page = 0; - -#define TX_PAGES 2 -static volatile int tx_fifo[TX_PAGES]; -static volatile int tx_fifo_in = 0; -static volatile int tx_fifo_out = 0; -static volatile int free_tx_pages = TX_PAGES; -static int was_down = 0; - -/* - * Convenience macros/functions for D-Link adapter - */ - -#define select_prn() outb_p(SELECT_PRN, COMMAND_PORT); DE600_SLOW_DOWN -#define select_nic() outb_p(SELECT_NIC, COMMAND_PORT); DE600_SLOW_DOWN - -/* Thanks for hints from Mark Burton <markb@ordern.demon.co.uk> */ -#define de600_put_byte(data) ( \ - outb_p(((data) << 4) | WRITE_DATA , DATA_PORT), \ - outb_p(((data) & 0xf0) | WRITE_DATA | HI_NIBBLE, DATA_PORT)) - -/* - * The first two outb_p()'s below could perhaps be deleted if there - * would be more delay in the last two. Not certain about it yet... - */ -#define de600_put_command(cmd) ( \ - outb_p(( rx_page << 4) | COMMAND , DATA_PORT), \ - outb_p(( rx_page & 0xf0) | COMMAND | HI_NIBBLE, DATA_PORT), \ - outb_p(((rx_page | cmd) << 4) | COMMAND , DATA_PORT), \ - outb_p(((rx_page | cmd) & 0xf0) | COMMAND | HI_NIBBLE, DATA_PORT)) - -#define de600_setup_address(addr,type) ( \ - outb_p((((addr) << 4) & 0xf0) | type , DATA_PORT), \ - outb_p(( (addr) & 0xf0) | type | HI_NIBBLE, DATA_PORT), \ - outb_p((((addr) >> 4) & 0xf0) | type , DATA_PORT), \ - outb_p((((addr) >> 8) & 0xf0) | type | HI_NIBBLE, DATA_PORT)) - -#define rx_page_adr() ((rx_page & RX_PAGE2_SELECT)?(MEM_6K):(MEM_4K)) - -/* Flip bit, only 2 pages */ -#define next_rx_page() (rx_page ^= RX_PAGE2_SELECT) - -#define tx_page_adr(a) (((a) + 1) * MEM_2K) - -static inline byte -de600_read_status(struct device *dev) -{ - byte status; - - outb_p(STATUS, DATA_PORT); - status = inb(STATUS_PORT); - outb_p(NULL_COMMAND | HI_NIBBLE, DATA_PORT); - - return status; -} - -static inline byte -de600_read_byte(unsigned char type, struct device *dev) { /* dev used by macros */ - byte lo; - - (void)outb_p((type), DATA_PORT); - lo = ((unsigned char)inb(STATUS_PORT)) >> 4; - (void)outb_p((type) | HI_NIBBLE, DATA_PORT); - return ((unsigned char)inb(STATUS_PORT) & (unsigned char)0xf0) | lo; -} - -/* - * Open/initialize the board. This is called (in the current kernel) - * after booting when 'ifconfig <dev->name> $IP_ADDR' is run (in rc.inet1). - * - * This routine should set everything up anew at each open, even - * registers that "should" only need to be set once at boot, so that - * there is a non-reboot way to recover if something goes wrong. - */ -static int -de600_open(struct device *dev) -{ - if (request_irq(DE600_IRQ, de600_interrupt, 0, "de600")) { - printk ("%s: unable to get IRQ %d\n", dev->name, DE600_IRQ); - return 1; - } - irq2dev_map[DE600_IRQ] = dev; - - MOD_INC_USE_COUNT; - dev->start = 1; - if (adapter_init(dev)) { - return 1; - } - - return 0; -} - -/* - * The inverse routine to de600_open(). - */ -static int -de600_close(struct device *dev) -{ - select_nic(); - rx_page = 0; - de600_put_command(RESET); - de600_put_command(STOP_RESET); - de600_put_command(0); - select_prn(); - - if (dev->start) { - free_irq(DE600_IRQ); - irq2dev_map[DE600_IRQ] = NULL; - dev->start = 0; - MOD_DEC_USE_COUNT; - } - return 0; -} - -static struct netstats * -get_stats(struct device *dev) -{ - return (struct netstats *)(dev->priv); -} - -static inline void -trigger_interrupt(struct device *dev) -{ - de600_put_command(FLIP_IRQ); - select_prn(); - DE600_SLOW_DOWN; - select_nic(); - de600_put_command(0); -} - -/* - * Copy a buffer to the adapter transmit page memory. - * Start sending. - */ -static int -de600_start_xmit(struct sk_buff *skb, struct device *dev) -{ - int transmit_from; - int len; - int tickssofar; - byte *buffer = skb->data; - - /* - * If some higher layer thinks we've missed a - * tx-done interrupt we are passed NULL. - * Caution: dev_tint() handles the cli()/sti() itself. - */ - - if (skb == NULL) { - dev_tint(dev); - return 0; - } - - if (free_tx_pages <= 0) { /* Do timeouts, to avoid hangs. */ - tickssofar = jiffies - dev->trans_start; - - if (tickssofar < 5) - return 1; - - /* else */ - printk("%s: transmit timed out (%d), %s?\n", - dev->name, - tickssofar, - "network cable problem" - ); - /* Restart the adapter. */ - if (adapter_init(dev)) { - return 1; - } - } - - /* Start real output */ - PRINTK(("de600_start_xmit:len=%d, page %d/%d\n", skb->len, tx_fifo_in, free_tx_pages)); - - if ((len = skb->len) < RUNT) - len = RUNT; - - cli(); - select_nic(); - tx_fifo[tx_fifo_in] = transmit_from = tx_page_adr(tx_fifo_in) - len; - tx_fifo_in = (tx_fifo_in + 1) % TX_PAGES; /* Next free tx page */ - -#ifdef CHECK_LOST_DE600 - /* This costs about 40 instructions per packet... */ - de600_setup_address(NODE_ADDRESS, RW_ADDR); - de600_read_byte(READ_DATA, dev); - if (was_down || (de600_read_byte(READ_DATA, dev) != 0xde)) { - if (adapter_init(dev)) { - sti(); - return 1; - } - } -#endif - - de600_setup_address(transmit_from, RW_ADDR); - for ( ; len > 0; --len, ++buffer) - de600_put_byte(*buffer); - - if (free_tx_pages-- == TX_PAGES) { /* No transmission going on */ - dev->trans_start = jiffies; - dev->tbusy = 0; /* allow more packets into adapter */ - /* Send page and generate a faked interrupt */ - de600_setup_address(transmit_from, TX_ADDR); - de600_put_command(TX_ENABLE); - } - else { - dev->tbusy = !free_tx_pages; - select_prn(); - } - - sti(); /* interrupts back on */ - -#ifdef FAKE_SMALL_MAX - /* This will "patch" the socket TCP proto at an early moment */ - if (skb->sk && (skb->sk->protocol == IPPROTO_TCP) && - (skb->sk->prot->rspace != &de600_rspace)) - skb->sk->prot->rspace = de600_rspace; /* Ugh! */ -#endif - - dev_kfree_skb (skb, FREE_WRITE); - - return 0; -} - -/* - * The typical workload of the driver: - * Handle the network interface interrupts. - */ -static void -de600_interrupt(int irq, struct pt_regs * regs) -{ - struct device *dev = irq2dev_map[irq]; - byte irq_status; - int retrig = 0; - int boguscount = 0; - - /* This might just as well be deleted now, no crummy drivers present :-) */ - if ((dev == NULL) || (dev->start == 0) || (DE600_IRQ != irq)) { - printk("%s: bogus interrupt %d\n", dev?dev->name:"DE-600", irq); - return; - } - - dev->interrupt = 1; - select_nic(); - irq_status = de600_read_status(dev); - - do { - PRINTK(("de600_interrupt (%02X)\n", irq_status)); - - if (irq_status & RX_GOOD) - de600_rx_intr(dev); - else if (!(irq_status & RX_BUSY)) - de600_put_command(RX_ENABLE); - - /* Any transmission in progress? */ - if (free_tx_pages < TX_PAGES) - retrig = de600_tx_intr(dev, irq_status); - else - retrig = 0; - - irq_status = de600_read_status(dev); - } while ( (irq_status & RX_GOOD) || ((++boguscount < 100) && retrig) ); - /* - * Yeah, it _looks_ like busy waiting, smells like busy waiting - * and I know it's not PC, but please, it will only occur once - * in a while and then only for a loop or so (< 1ms for sure!) - */ - - /* Enable adapter interrupts */ - dev->interrupt = 0; - select_prn(); - - if (retrig) - trigger_interrupt(dev); - - sti(); - return; -} - -static int -de600_tx_intr(struct device *dev, int irq_status) -{ - /* - * Returns 1 if tx still not done - */ - - mark_bh(NET_BH); - /* Check if current transmission is done yet */ - if (irq_status & TX_BUSY) - return 1; /* tx not done, try again */ - - /* else */ - /* If last transmission OK then bump fifo index */ - if (!(irq_status & TX_FAILED16)) { - tx_fifo_out = (tx_fifo_out + 1) % TX_PAGES; - ++free_tx_pages; - ((struct netstats *)(dev->priv))->tx_packets++; - dev->tbusy = 0; - } - - /* More to send, or resend last packet? */ - if ((free_tx_pages < TX_PAGES) || (irq_status & TX_FAILED16)) { - dev->trans_start = jiffies; - de600_setup_address(tx_fifo[tx_fifo_out], TX_ADDR); - de600_put_command(TX_ENABLE); - return 1; - } - /* else */ - - return 0; -} - -/* - * We have a good packet, get it out of the adapter. - */ -static void -de600_rx_intr(struct device *dev) -{ - struct sk_buff *skb; - int i; - int read_from; - int size; - register unsigned char *buffer; - - cli(); - /* Get size of received packet */ - size = de600_read_byte(RX_LEN, dev); /* low byte */ - size += (de600_read_byte(RX_LEN, dev) << 8); /* high byte */ - size -= 4; /* Ignore trailing 4 CRC-bytes */ - - /* Tell adapter where to store next incoming packet, enable receiver */ - read_from = rx_page_adr(); - next_rx_page(); - de600_put_command(RX_ENABLE); - sti(); - - if ((size < 32) || (size > 1535)) { - printk("%s: Bogus packet size %d.\n", dev->name, size); - if (size > 10000) - adapter_init(dev); - return; - } - - skb = dev_alloc_skb(size+2); - sti(); - if (skb == NULL) { - printk("%s: Couldn't allocate a sk_buff of size %d.\n", - dev->name, size); - return; - } - /* else */ - - skb->dev = dev; - skb_reserve(skb,2); /* Align */ - - /* 'skb->data' points to the start of sk_buff data area. */ - buffer = skb_put(skb,size); - - /* copy the packet into the buffer */ - de600_setup_address(read_from, RW_ADDR); - for (i = size; i > 0; --i, ++buffer) - *buffer = de600_read_byte(READ_DATA, dev); - - ((struct netstats *)(dev->priv))->rx_packets++; /* count all receives */ - - skb->protocol=eth_type_trans(skb,dev); - - netif_rx(skb); - /* - * If any worth-while packets have been received, netif_rx() - * has done a mark_bh(INET_BH) for us and will work on them - * when we get to the bottom-half routine. - */ -} - -int -de600_probe(struct device *dev) -{ - int i; - static struct netstats de600_netstats; - /*dev->priv = kmalloc(sizeof(struct netstats), GFP_KERNEL);*/ - - printk("%s: D-Link DE-600 pocket adapter", dev->name); - /* Alpha testers must have the version number to report bugs. */ - if (de600_debug > 1) - printk(version); - - /* probe for adapter */ - rx_page = 0; - select_nic(); - (void)de600_read_status(dev); - de600_put_command(RESET); - de600_put_command(STOP_RESET); - if (de600_read_status(dev) & 0xf0) { - printk(": not at I/O %#3x.\n", DATA_PORT); - return ENODEV; - } - - /* - * Maybe we found one, - * have to check if it is a D-Link DE-600 adapter... - */ - - /* Get the adapter ethernet address from the ROM */ - de600_setup_address(NODE_ADDRESS, RW_ADDR); - for (i = 0; i < ETH_ALEN; i++) { - dev->dev_addr[i] = de600_read_byte(READ_DATA, dev); - dev->broadcast[i] = 0xff; - } - - /* Check magic code */ - if ((dev->dev_addr[1] == 0xde) && (dev->dev_addr[2] == 0x15)) { - /* OK, install real address */ - dev->dev_addr[0] = 0x00; - dev->dev_addr[1] = 0x80; - dev->dev_addr[2] = 0xc8; - dev->dev_addr[3] &= 0x0f; - dev->dev_addr[3] |= 0x70; - } else { - printk(" not identified in the printer port\n"); - return ENODEV; - } - -#if 0 /* Not yet */ - if (check_region(DE600_IO, 3)) { - printk(", port 0x%x busy\n", DE600_IO); - return EBUSY; - } -#endif - request_region(DE600_IO, 3, "de600"); - - printk(", Ethernet Address: %02X", dev->dev_addr[0]); - for (i = 1; i < ETH_ALEN; i++) - printk(":%02X",dev->dev_addr[i]); - printk("\n"); - - /* Initialize the device structure. */ - /*dev->priv = kmalloc(sizeof(struct netstats), GFP_KERNEL);*/ - dev->priv = &de600_netstats; - - memset(dev->priv, 0, sizeof(struct netstats)); - dev->get_stats = get_stats; - - dev->open = de600_open; - dev->stop = de600_close; - dev->hard_start_xmit = &de600_start_xmit; - - ether_setup(dev); - - dev->flags&=~IFF_MULTICAST; - - select_prn(); - return 0; -} - -static int -adapter_init(struct device *dev) -{ - int i; - long flags; - - save_flags(flags); - cli(); - - select_nic(); - rx_page = 0; /* used by RESET */ - de600_put_command(RESET); - de600_put_command(STOP_RESET); -#ifdef CHECK_LOST_DE600 - /* Check if it is still there... */ - /* Get the some bytes of the adapter ethernet address from the ROM */ - de600_setup_address(NODE_ADDRESS, RW_ADDR); - de600_read_byte(READ_DATA, dev); - if ((de600_read_byte(READ_DATA, dev) != 0xde) || - (de600_read_byte(READ_DATA, dev) != 0x15)) { - /* was: if (de600_read_status(dev) & 0xf0) { */ - printk("Something has happened to the DE-600! Please check it" -#ifdef SHUTDOWN_WHEN_LOST - " and do a new ifconfig" -#endif /* SHUTDOWN_WHEN_LOST */ - "!\n"); -#ifdef SHUTDOWN_WHEN_LOST - /* Goodbye, cruel world... */ - dev->flags &= ~IFF_UP; - de600_close(dev); -#endif /* SHUTDOWN_WHEN_LOST */ - was_down = 1; - dev->tbusy = 1; /* Transmit busy... */ - restore_flags(flags); - return 1; /* failed */ - } -#endif /* CHECK_LOST_DE600 */ - if (was_down) { - printk("Thanks, I feel much better now!\n"); - was_down = 0; - } - - dev->tbusy = 0; /* Transmit busy... */ - dev->interrupt = 0; - tx_fifo_in = 0; - tx_fifo_out = 0; - free_tx_pages = TX_PAGES; - - /* set the ether address. */ - de600_setup_address(NODE_ADDRESS, RW_ADDR); - for (i = 0; i < ETH_ALEN; i++) - de600_put_byte(dev->dev_addr[i]); - - /* where to start saving incoming packets */ - rx_page = RX_BP | RX_BASE_PAGE; - de600_setup_address(MEM_4K, RW_ADDR); - /* Enable receiver */ - de600_put_command(RX_ENABLE); - select_prn(); - restore_flags(flags); - - return 0; /* OK */ -} - -#ifdef FAKE_SMALL_MAX -/* - * The new router code (coming soon 8-) ) will fix this properly. - */ -#define DE600_MIN_WINDOW 1024 -#define DE600_MAX_WINDOW 2048 -#define DE600_TCP_WINDOW_DIFF 1024 -/* - * Copied from "net/inet/sock.c" - * - * Sets a lower max receive window in order to achieve <= 2 - * packets arriving at the adapter in fast succession. - * (No way that a DE-600 can keep up with a net saturated - * with packets homing in on it :-( ) - * - * Since there are only 2 receive buffers in the DE-600 - * and it takes some time to copy from the adapter, - * this is absolutely necessary for any TCP performance whatsoever! - * - * Note that the returned window info will never be smaller than - * DE600_MIN_WINDOW, i.e. 1024 - * This differs from the standard function, that can return an - * arbitrarily small window! - */ -#define min(a,b) ((a)<(b)?(a):(b)) -static unsigned long -de600_rspace(struct sock *sk) -{ - int amt; - - if (sk != NULL) { -/* - * Hack! You might want to play with commenting away the following line, - * if you know what you do! - sk->max_unacked = DE600_MAX_WINDOW - DE600_TCP_WINDOW_DIFF; - */ - - if (sk->rmem_alloc >= sk->rcvbuf-2*DE600_MIN_WINDOW) return(0); - amt = min((sk->rcvbuf-sk->rmem_alloc)/2/*-DE600_MIN_WINDOW*/, DE600_MAX_WINDOW); - if (amt < 0) return(0); - return(amt); - } - return(0); -} -#endif - -#ifdef MODULE -static char nullname[8]; -static struct device de600_dev = { - nullname, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, de600_probe }; - -int -init_module(void) -{ - if (register_netdev(&de600_dev) != 0) - return -EIO; - return 0; -} - -void -cleanup_module(void) -{ - unregister_netdev(&de600_dev); - release_region(DE600_IO, 3); -} -#endif /* MODULE */ -/* - * Local variables: - * kernel-compile-command: "gcc -D__KERNEL__ -Ilinux/include -I../../net/inet -Wall -Wstrict-prototypes -O2 -m486 -c de600.c" - * module-compile-command: "gcc -D__KERNEL__ -DMODULE -Ilinux/include -I../../net/inet -Wall -Wstrict-prototypes -O2 -m486 -c de600.c" - * compile-command: "gcc -D__KERNEL__ -DMODULE -Ilinux/include -I../../net/inet -Wall -Wstrict-prototypes -O2 -m486 -c de600.c" - * End: - */ diff --git a/i386/i386at/gpl/linux/net/de620.c b/i386/i386at/gpl/linux/net/de620.c deleted file mode 100644 index 2b17c390..00000000 --- a/i386/i386at/gpl/linux/net/de620.c +++ /dev/null @@ -1,1045 +0,0 @@ -/* - * de620.c $Revision: 1.1.1.1 $ BETA - * - * - * Linux driver for the D-Link DE-620 Ethernet pocket adapter. - * - * Portions (C) Copyright 1993, 1994 by Bjorn Ekwall <bj0rn@blox.se> - * - * Based on adapter information gathered from DOS packetdriver - * sources from D-Link Inc: (Special thanks to Henry Ngai of D-Link.) - * Portions (C) Copyright D-Link SYSTEM Inc. 1991, 1992 - * Copyright, 1988, Russell Nelson, Crynwr Software - * - * Adapted to the sample network driver core for linux, - * written by: Donald Becker <becker@super.org> - * (Now at <becker@cesdis.gsfc.nasa.gov> - * - * Valuable assistance from: - * J. Joshua Kopper <kopper@rtsg.mot.com> - * Olav Kvittem <Olav.Kvittem@uninett.no> - * Germano Caronni <caronni@nessie.cs.id.ethz.ch> - * Jeremy Fitzhardinge <jeremy@suite.sw.oz.au> - * - *****************************************************************************/ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - *****************************************************************************/ -static const char *version = - "de620.c: $Revision: 1.1.1.1 $, Bjorn Ekwall <bj0rn@blox.se>\n"; - -/*********************************************************************** - * - * "Tuning" section. - * - * Compile-time options: (see below for descriptions) - * -DDE620_IO=0x378 (lpt1) - * -DDE620_IRQ=7 (lpt1) - * -DDE602_DEBUG=... - * -DSHUTDOWN_WHEN_LOST - * -DCOUNT_LOOPS - * -DLOWSPEED - * -DREAD_DELAY - * -DWRITE_DELAY - */ - -/* - * This driver assumes that the printer port is a "normal", - * dumb, uni-directional port! - * If your port is "fancy" in any way, please try to set it to "normal" - * with your BIOS setup. I have no access to machines with bi-directional - * ports, so I can't test such a driver :-( - * (Yes, I _know_ it is possible to use DE620 with bidirectional ports...) - * - * There are some clones of DE620 out there, with different names. - * If the current driver does not recognize a clone, try to change - * the following #define to: - * - * #define DE620_CLONE 1 - */ -#define DE620_CLONE 0 - -/* - * If the adapter has problems with high speeds, enable this #define - * otherwise full printerport speed will be attempted. - * - * You can tune the READ_DELAY/WRITE_DELAY below if you enable LOWSPEED - * -#define LOWSPEED - */ - -#ifndef READ_DELAY -#define READ_DELAY 100 /* adapter internal read delay in 100ns units */ -#endif - -#ifndef WRITE_DELAY -#define WRITE_DELAY 100 /* adapter internal write delay in 100ns units */ -#endif - -/* - * Enable this #define if you want the adapter to do a "ifconfig down" on - * itself when we have detected that something is possibly wrong with it. - * The default behaviour is to retry with "adapter_init()" until success. - * This should be used for debugging purposes only. - * -#define SHUTDOWN_WHEN_LOST - */ - -/* - * Enable debugging by "-DDE620_DEBUG=3" when compiling, - * OR in "./CONFIG" - * OR by enabling the following #define - * - * use 0 for production, 1 for verification, >2 for debug - * -#define DE620_DEBUG 3 - */ - -#ifdef LOWSPEED -/* - * Enable this #define if you want to see debugging output that show how long - * we have to wait before the DE-620 is ready for the next read/write/command. - * -#define COUNT_LOOPS - */ -#endif - -#include <linux/module.h> - -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/types.h> -#include <linux/fcntl.h> -#include <linux/string.h> -#include <linux/interrupt.h> -#include <linux/ioport.h> -#include <asm/io.h> -#include <linux/in.h> -#include <linux/ptrace.h> -#include <asm/system.h> -#include <linux/errno.h> - -#include <linux/inet.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> - -/* Constant definitions for the DE-620 registers, commands and bits */ -#include "de620.h" - -#define netstats enet_statistics -typedef unsigned char byte; - -/******************************************************* - * * - * Definition of D-Link DE-620 Ethernet Pocket adapter * - * See also "de620.h" * - * * - *******************************************************/ -#ifndef DE620_IO /* Compile-time configurable */ -#define DE620_IO 0x378 -#endif - -#ifndef DE620_IRQ /* Compile-time configurable */ -#define DE620_IRQ 7 -#endif - -#define DATA_PORT (dev->base_addr) -#define STATUS_PORT (dev->base_addr + 1) -#define COMMAND_PORT (dev->base_addr + 2) - -#define RUNT 60 /* Too small Ethernet packet */ -#define GIANT 1514 /* largest legal size packet, no fcs */ - -#ifdef DE620_DEBUG /* Compile-time configurable */ -#define PRINTK(x) if (de620_debug >= 2) printk x -#else -#define DE620_DEBUG 0 -#define PRINTK(x) /**/ -#endif - - -/* - * Force media with insmod: - * insmod de620.o bnc=1 - * or - * insmod de620.o utp=1 - * - * Force io and/or irq with insmod: - * insmod de620.o io=0x378 irq=7 - * - * Make a clone skip the Ethernet-address range check: - * insmod de620.o clone=1 - */ -static int bnc = 0; -static int utp = 0; -static int io = DE620_IO; -static int irq = DE620_IRQ; -static int clone = DE620_CLONE; - -static unsigned int de620_debug = DE620_DEBUG; - -/*********************************************** - * * - * Index to functions, as function prototypes. * - * * - ***********************************************/ - -/* - * Routines used internally. (See also "convenience macros.. below") - */ - -/* Put in the device structure. */ -static int de620_open(struct device *); -static int de620_close(struct device *); -static struct netstats *get_stats(struct device *); -static void de620_set_multicast_list(struct device *); -static int de620_start_xmit(struct sk_buff *, struct device *); - -/* Dispatch from interrupts. */ -static void de620_interrupt(int, struct pt_regs *); -static int de620_rx_intr(struct device *); - -/* Initialization */ -static int adapter_init(struct device *); -int de620_probe(struct device *); -static int read_eeprom(struct device *); - - -/* - * D-Link driver variables: - */ -#define SCR_DEF NIBBLEMODE |INTON | SLEEP | AUTOTX -#define TCR_DEF RXPB /* not used: | TXSUCINT | T16INT */ -#define DE620_RX_START_PAGE 12 /* 12 pages (=3k) reserved for tx */ -#define DEF_NIC_CMD IRQEN | ICEN | DS1 - -static volatile byte NIC_Cmd; -static volatile byte next_rx_page; -static byte first_rx_page; -static byte last_rx_page; -static byte EIPRegister; - -static struct nic { - byte NodeID[6]; - byte RAM_Size; - byte Model; - byte Media; - byte SCR; -} nic_data; - -/********************************************************** - * * - * Convenience macros/functions for D-Link DE-620 adapter * - * * - **********************************************************/ -#define de620_tx_buffs(dd) (inb(STATUS_PORT) & (TXBF0 | TXBF1)) -#define de620_flip_ds(dd) NIC_Cmd ^= DS0 | DS1; outb(NIC_Cmd, COMMAND_PORT); - -/* Check for ready-status, and return a nibble (high 4 bits) for data input */ -#ifdef COUNT_LOOPS -static int tot_cnt; -#endif -static inline byte -de620_ready(struct device *dev) -{ - byte value; - register short int cnt = 0; - - while ((((value = inb(STATUS_PORT)) & READY) == 0) && (cnt <= 1000)) - ++cnt; - -#ifdef COUNT_LOOPS - tot_cnt += cnt; -#endif - return value & 0xf0; /* nibble */ -} - -static inline void -de620_send_command(struct device *dev, byte cmd) -{ - de620_ready(dev); - if (cmd == W_DUMMY) - outb(NIC_Cmd, COMMAND_PORT); - - outb(cmd, DATA_PORT); - - outb(NIC_Cmd ^ CS0, COMMAND_PORT); - de620_ready(dev); - outb(NIC_Cmd, COMMAND_PORT); -} - -static inline void -de620_put_byte(struct device *dev, byte value) -{ - /* The de620_ready() makes 7 loops, on the average, on a DX2/66 */ - de620_ready(dev); - outb(value, DATA_PORT); - de620_flip_ds(dev); -} - -static inline byte -de620_read_byte(struct device *dev) -{ - byte value; - - /* The de620_ready() makes 7 loops, on the average, on a DX2/66 */ - value = de620_ready(dev); /* High nibble */ - de620_flip_ds(dev); - value |= de620_ready(dev) >> 4; /* Low nibble */ - return value; -} - -static inline void -de620_write_block(struct device *dev, byte *buffer, int count) -{ -#ifndef LOWSPEED - byte uflip = NIC_Cmd ^ (DS0 | DS1); - byte dflip = NIC_Cmd; -#else /* LOWSPEED */ -#ifdef COUNT_LOOPS - int bytes = count; -#endif /* COUNT_LOOPS */ -#endif /* LOWSPEED */ - -#ifdef LOWSPEED -#ifdef COUNT_LOOPS - tot_cnt = 0; -#endif /* COUNT_LOOPS */ - /* No further optimization useful, the limit is in the adapter. */ - for ( ; count > 0; --count, ++buffer) { - de620_put_byte(dev,*buffer); - } - de620_send_command(dev,W_DUMMY); -#ifdef COUNT_LOOPS - /* trial debug output: loops per byte in de620_ready() */ - printk("WRITE(%d)\n", tot_cnt/((bytes?bytes:1))); -#endif /* COUNT_LOOPS */ -#else /* not LOWSPEED */ - for ( ; count > 0; count -=2) { - outb(*buffer++, DATA_PORT); - outb(uflip, COMMAND_PORT); - outb(*buffer++, DATA_PORT); - outb(dflip, COMMAND_PORT); - } - de620_send_command(dev,W_DUMMY); -#endif /* LOWSPEED */ -} - -static inline void -de620_read_block(struct device *dev, byte *data, int count) -{ -#ifndef LOWSPEED - byte value; - byte uflip = NIC_Cmd ^ (DS0 | DS1); - byte dflip = NIC_Cmd; -#else /* LOWSPEED */ -#ifdef COUNT_LOOPS - int bytes = count; - - tot_cnt = 0; -#endif /* COUNT_LOOPS */ -#endif /* LOWSPEED */ - -#ifdef LOWSPEED - /* No further optimization useful, the limit is in the adapter. */ - while (count-- > 0) { - *data++ = de620_read_byte(dev); - de620_flip_ds(dev); - } -#ifdef COUNT_LOOPS - /* trial debug output: loops per byte in de620_ready() */ - printk("READ(%d)\n", tot_cnt/(2*(bytes?bytes:1))); -#endif /* COUNT_LOOPS */ -#else /* not LOWSPEED */ - while (count-- > 0) { - value = inb(STATUS_PORT) & 0xf0; /* High nibble */ - outb(uflip, COMMAND_PORT); - *data++ = value | inb(STATUS_PORT) >> 4; /* Low nibble */ - outb(dflip , COMMAND_PORT); - } -#endif /* LOWSPEED */ -} - -static inline void -de620_set_delay(struct device *dev) -{ - de620_ready(dev); - outb(W_DFR, DATA_PORT); - outb(NIC_Cmd ^ CS0, COMMAND_PORT); - - de620_ready(dev); -#ifdef LOWSPEED - outb(WRITE_DELAY, DATA_PORT); -#else - outb(0, DATA_PORT); -#endif - de620_flip_ds(dev); - - de620_ready(dev); -#ifdef LOWSPEED - outb(READ_DELAY, DATA_PORT); -#else - outb(0, DATA_PORT); -#endif - de620_flip_ds(dev); -} - -static inline void -de620_set_register(struct device *dev, byte reg, byte value) -{ - de620_ready(dev); - outb(reg, DATA_PORT); - outb(NIC_Cmd ^ CS0, COMMAND_PORT); - - de620_put_byte(dev, value); -} - -static inline byte -de620_get_register(struct device *dev, byte reg) -{ - byte value; - - de620_send_command(dev,reg); - value = de620_read_byte(dev); - de620_send_command(dev,W_DUMMY); - - return value; -} - -/********************************************************************* - * - * Open/initialize the board. - * - * This routine should set everything up anew at each open, even - * registers that "should" only need to be set once at boot, so that - * there is a non-reboot way to recover if something goes wrong. - * - */ -static int -de620_open(struct device *dev) -{ - if (request_irq(dev->irq, de620_interrupt, 0, "de620")) { - printk ("%s: unable to get IRQ %d\n", dev->name, dev->irq); - return 1; - } - irq2dev_map[dev->irq] = dev; - - MOD_INC_USE_COUNT; - if (adapter_init(dev)) { - return 1; - } - dev->start = 1; - return 0; -} - -/************************************************ - * - * The inverse routine to de620_open(). - * - */ -static int -de620_close(struct device *dev) -{ - /* disable recv */ - de620_set_register(dev, W_TCR, RXOFF); - - free_irq(dev->irq); - irq2dev_map[dev->irq] = NULL; - - dev->start = 0; - MOD_DEC_USE_COUNT; - return 0; -} - -/********************************************* - * - * Return current statistics - * - */ -static struct netstats * -get_stats(struct device *dev) -{ - return (struct netstats *)(dev->priv); -} - -/********************************************* - * - * Set or clear the multicast filter for this adaptor. - * (no real multicast implemented for the DE-620, but she can be promiscuous...) - * - */ - -static void de620_set_multicast_list(struct device *dev) -{ - if (dev->mc_count || dev->flags&(IFF_ALLMULTI|IFF_PROMISC)) - { /* Enable promiscuous mode */ - /* - * We must make the kernel realise we had to move - * into promisc mode or we start all out war on - * the cable. - AC - */ - dev->flags|=IFF_PROMISC; - - de620_set_register(dev, W_TCR, (TCR_DEF & ~RXPBM) | RXALL); - } - else - { /* Disable promiscuous mode, use normal mode */ - de620_set_register(dev, W_TCR, TCR_DEF); - } -} - -/******************************************************* - * - * Copy a buffer to the adapter transmit page memory. - * Start sending. - */ -static int -de620_start_xmit(struct sk_buff *skb, struct device *dev) -{ - unsigned long flags; - int len; - int tickssofar; - byte *buffer = skb->data; - byte using_txbuf; - - /* - * If some higher layer thinks we've missed a - * tx-done interrupt we are passed NULL. - * Caution: dev_tint() handles the cli()/sti() itself. - */ - - if (skb == NULL) { - dev_tint(dev); - return 0; - } - - using_txbuf = de620_tx_buffs(dev); /* Peek at the adapter */ - dev->tbusy = (using_txbuf == (TXBF0 | TXBF1)); /* Boolean! */ - - if (dev->tbusy) { /* Do timeouts, to avoid hangs. */ - tickssofar = jiffies - dev->trans_start; - - if (tickssofar < 5) - return 1; - - /* else */ - printk("%s: transmit timed out (%d), %s?\n", - dev->name, - tickssofar, - "network cable problem" - ); - /* Restart the adapter. */ - if (adapter_init(dev)) /* maybe close it */ - return 1; - } - - if ((len = skb->len) < RUNT) - len = RUNT; - if (len & 1) /* send an even number of bytes */ - ++len; - - /* Start real output */ - save_flags(flags); - cli(); - - PRINTK(("de620_start_xmit: len=%d, bufs 0x%02x\n", - (int)skb->len, using_txbuf)); - - /* select a free tx buffer. if there is one... */ - switch (using_txbuf) { - default: /* both are free: use TXBF0 */ - case TXBF1: /* use TXBF0 */ - de620_send_command(dev,W_CR | RW0); - using_txbuf |= TXBF0; - break; - - case TXBF0: /* use TXBF1 */ - de620_send_command(dev,W_CR | RW1); - using_txbuf |= TXBF1; - break; - - case (TXBF0 | TXBF1): /* NONE!!! */ - printk("de620: Ouch! No tx-buffer available!\n"); - restore_flags(flags); - return 1; - break; - } - de620_write_block(dev, buffer, len); - - dev->trans_start = jiffies; - dev->tbusy = (using_txbuf == (TXBF0 | TXBF1)); /* Boolean! */ - - ((struct netstats *)(dev->priv))->tx_packets++; - - restore_flags(flags); /* interrupts maybe back on */ - - dev_kfree_skb (skb, FREE_WRITE); - - return 0; -} - -/***************************************************** - * - * Handle the network interface interrupts. - * - */ -static void -de620_interrupt(int irq_in, struct pt_regs *regs) -{ - struct device *dev = irq2dev_map[irq_in]; - byte irq_status; - int bogus_count = 0; - int again = 0; - - /* This might be deleted now, no crummy drivers present :-) Or..? */ - if ((dev == NULL) || (irq != irq_in)) { - printk("%s: bogus interrupt %d\n", dev?dev->name:"de620", irq_in); - return; - } - - cli(); - dev->interrupt = 1; - - /* Read the status register (_not_ the status port) */ - irq_status = de620_get_register(dev, R_STS); - - PRINTK(("de620_interrupt (%2.2X)\n", irq_status)); - - if (irq_status & RXGOOD) { - do { - again = de620_rx_intr(dev); - PRINTK(("again=%d\n", again)); - } - while (again && (++bogus_count < 100)); - } - - dev->tbusy = (de620_tx_buffs(dev) == (TXBF0 | TXBF1)); /* Boolean! */ - - dev->interrupt = 0; - sti(); - return; -} - -/************************************** - * - * Get a packet from the adapter - * - * Send it "upstairs" - * - */ -static int -de620_rx_intr(struct device *dev) -{ - struct header_buf { - byte status; - byte Rx_NextPage; - unsigned short Rx_ByteCount; - } header_buf; - struct sk_buff *skb; - int size; - byte *buffer; - byte pagelink; - byte curr_page; - - PRINTK(("de620_rx_intr: next_rx_page = %d\n", next_rx_page)); - - /* Tell the adapter that we are going to read data, and from where */ - de620_send_command(dev, W_CR | RRN); - de620_set_register(dev, W_RSA1, next_rx_page); - de620_set_register(dev, W_RSA0, 0); - - /* Deep breath, and away we goooooo */ - de620_read_block(dev, (byte *)&header_buf, sizeof(struct header_buf)); - PRINTK(("page status=0x%02x, nextpage=%d, packetsize=%d\n", - header_buf.status, header_buf.Rx_NextPage, header_buf.Rx_ByteCount)); - - /* Plausible page header? */ - pagelink = header_buf.Rx_NextPage; - if ((pagelink < first_rx_page) || (last_rx_page < pagelink)) { - /* Ouch... Forget it! Skip all and start afresh... */ - printk("%s: Ring overrun? Restoring...\n", dev->name); - /* You win some, you loose some. And sometimes plenty... */ - adapter_init(dev); - ((struct netstats *)(dev->priv))->rx_over_errors++; - return 0; - } - - /* OK, this look good, so far. Let's see if it's consistent... */ - /* Let's compute the start of the next packet, based on where we are */ - pagelink = next_rx_page + - ((header_buf.Rx_ByteCount + (4 - 1 + 0x100)) >> 8); - - /* Are we going to wrap around the page counter? */ - if (pagelink > last_rx_page) - pagelink -= (last_rx_page - first_rx_page + 1); - - /* Is the _computed_ next page number equal to what the adapter says? */ - if (pagelink != header_buf.Rx_NextPage) { - /* Naah, we'll skip this packet. Probably bogus data as well */ - printk("%s: Page link out of sync! Restoring...\n", dev->name); - next_rx_page = header_buf.Rx_NextPage; /* at least a try... */ - de620_send_command(dev, W_DUMMY); - de620_set_register(dev, W_NPRF, next_rx_page); - ((struct netstats *)(dev->priv))->rx_over_errors++; - return 0; - } - next_rx_page = pagelink; - - size = header_buf.Rx_ByteCount - 4; - if ((size < RUNT) || (GIANT < size)) { - printk("%s: Illegal packet size: %d!\n", dev->name, size); - } - else { /* Good packet? */ - skb = dev_alloc_skb(size+2); - if (skb == NULL) { /* Yeah, but no place to put it... */ - printk("%s: Couldn't allocate a sk_buff of size %d.\n", - dev->name, size); - ((struct netstats *)(dev->priv))->rx_dropped++; - } - else { /* Yep! Go get it! */ - skb_reserve(skb,2); /* Align */ - skb->dev = dev; - skb->free = 1; - /* skb->data points to the start of sk_buff data area */ - buffer = skb_put(skb,size); - /* copy the packet into the buffer */ - de620_read_block(dev, buffer, size); - PRINTK(("Read %d bytes\n", size)); - skb->protocol=eth_type_trans(skb,dev); - netif_rx(skb); /* deliver it "upstairs" */ - /* count all receives */ - ((struct netstats *)(dev->priv))->rx_packets++; - } - } - - /* Let's peek ahead to see if we have read the last current packet */ - /* NOTE! We're _not_ checking the 'EMPTY'-flag! This seems better... */ - curr_page = de620_get_register(dev, R_CPR); - de620_set_register(dev, W_NPRF, next_rx_page); - PRINTK(("next_rx_page=%d CPR=%d\n", next_rx_page, curr_page)); - - return (next_rx_page != curr_page); /* That was slightly tricky... */ -} - -/********************************************* - * - * Reset the adapter to a known state - * - */ -static int -adapter_init(struct device *dev) -{ - int i; - static int was_down = 0; - - if ((nic_data.Model == 3) || (nic_data.Model == 0)) { /* CT */ - EIPRegister = NCTL0; - if (nic_data.Media != 1) - EIPRegister |= NIS0; /* not BNC */ - } - else if (nic_data.Model == 2) { /* UTP */ - EIPRegister = NCTL0 | NIS0; - } - - if (utp) - EIPRegister = NCTL0 | NIS0; - if (bnc) - EIPRegister = NCTL0; - - de620_send_command(dev, W_CR | RNOP | CLEAR); - de620_send_command(dev, W_CR | RNOP); - - de620_set_register(dev, W_SCR, SCR_DEF); - /* disable recv to wait init */ - de620_set_register(dev, W_TCR, RXOFF); - - /* Set the node ID in the adapter */ - for (i = 0; i < 6; ++i) { /* W_PARn = 0xaa + n */ - de620_set_register(dev, W_PAR0 + i, dev->dev_addr[i]); - } - - de620_set_register(dev, W_EIP, EIPRegister); - - next_rx_page = first_rx_page = DE620_RX_START_PAGE; - if (nic_data.RAM_Size) - last_rx_page = nic_data.RAM_Size - 1; - else /* 64k RAM */ - last_rx_page = 255; - - de620_set_register(dev, W_SPR, first_rx_page); /* Start Page Register*/ - de620_set_register(dev, W_EPR, last_rx_page); /* End Page Register */ - de620_set_register(dev, W_CPR, first_rx_page);/*Current Page Register*/ - de620_send_command(dev, W_NPR | first_rx_page); /* Next Page Register*/ - de620_send_command(dev, W_DUMMY); - de620_set_delay(dev); - - /* Final sanity check: Anybody out there? */ - /* Let's hope some bits from the statusregister make a good check */ -#define CHECK_MASK ( 0 | TXSUC | T16 | 0 | RXCRC | RXSHORT | 0 | 0 ) -#define CHECK_OK ( 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 ) - /* success: X 0 0 X 0 0 X X */ - /* ignore: EEDI RXGOOD COLS LNKS*/ - - if (((i = de620_get_register(dev, R_STS)) & CHECK_MASK) != CHECK_OK) { - printk("Something has happened to the DE-620! Please check it" -#ifdef SHUTDOWN_WHEN_LOST - " and do a new ifconfig" -#endif - "! (%02x)\n", i); -#ifdef SHUTDOWN_WHEN_LOST - /* Goodbye, cruel world... */ - dev->flags &= ~IFF_UP; - de620_close(dev); -#endif - was_down = 1; - return 1; /* failed */ - } - if (was_down) { - printk("Thanks, I feel much better now!\n"); - was_down = 0; - } - - /* All OK, go ahead... */ - de620_set_register(dev, W_TCR, TCR_DEF); - - return 0; /* all ok */ -} - -/****************************************************************************** - * - * Only start-up code below - * - */ -/**************************************** - * - * Check if there is a DE-620 connected - */ -int -de620_probe(struct device *dev) -{ - static struct netstats de620_netstats; - int i; - byte checkbyte = 0xa5; - - /* - * This is where the base_addr and irq gets set. - * Tunable at compile-time and insmod-time - */ - dev->base_addr = io; - dev->irq = irq; - - if (de620_debug) - printk(version); - - printk("D-Link DE-620 pocket adapter"); - - /* Initially, configure basic nibble mode, so we can read the EEPROM */ - NIC_Cmd = DEF_NIC_CMD; - de620_set_register(dev, W_EIP, EIPRegister); - - /* Anybody out there? */ - de620_set_register(dev, W_CPR, checkbyte); - checkbyte = de620_get_register(dev, R_CPR); - - if ((checkbyte != 0xa5) || (read_eeprom(dev) != 0)) { - printk(" not identified in the printer port\n"); - return ENODEV; - } - -#if 0 /* Not yet */ - if (check_region(dev->base_addr, 3)) { - printk(", port 0x%x busy\n", dev->base_addr); - return EBUSY; - } -#endif - request_region(dev->base_addr, 3, "de620"); - - /* else, got it! */ - printk(", Ethernet Address: %2.2X", - dev->dev_addr[0] = nic_data.NodeID[0]); - for (i = 1; i < ETH_ALEN; i++) { - printk(":%2.2X", dev->dev_addr[i] = nic_data.NodeID[i]); - dev->broadcast[i] = 0xff; - } - - printk(" (%dk RAM,", - (nic_data.RAM_Size) ? (nic_data.RAM_Size >> 2) : 64); - - if (nic_data.Media == 1) - printk(" BNC)\n"); - else - printk(" UTP)\n"); - - /* Initialize the device structure. */ - /*dev->priv = kmalloc(sizeof(struct netstats), GFP_KERNEL);*/ - dev->priv = &de620_netstats; - - memset(dev->priv, 0, sizeof(struct netstats)); - dev->get_stats = get_stats; - dev->open = de620_open; - dev->stop = de620_close; - dev->hard_start_xmit = &de620_start_xmit; - dev->set_multicast_list = &de620_set_multicast_list; - /* base_addr and irq are already set, see above! */ - - ether_setup(dev); - - /* dump eeprom */ - if (de620_debug) { - printk("\nEEPROM contents:\n"); - printk("RAM_Size = 0x%02X\n", nic_data.RAM_Size); - printk("NodeID = %02X:%02X:%02X:%02X:%02X:%02X\n", - nic_data.NodeID[0], nic_data.NodeID[1], - nic_data.NodeID[2], nic_data.NodeID[3], - nic_data.NodeID[4], nic_data.NodeID[5]); - printk("Model = %d\n", nic_data.Model); - printk("Media = %d\n", nic_data.Media); - printk("SCR = 0x%02x\n", nic_data.SCR); - } - - return 0; -} - -/********************************** - * - * Read info from on-board EEPROM - * - * Note: Bitwise serial I/O to/from the EEPROM vi the status _register_! - */ -#define sendit(dev,data) de620_set_register(dev, W_EIP, data | EIPRegister); - -static unsigned short -ReadAWord(struct device *dev, int from) -{ - unsigned short data; - int nbits; - - /* cs [__~~] SET SEND STATE */ - /* di [____] */ - /* sck [_~~_] */ - sendit(dev, 0); sendit(dev, 1); sendit(dev, 5); sendit(dev, 4); - - /* Send the 9-bit address from where we want to read the 16-bit word */ - for (nbits = 9; nbits > 0; --nbits, from <<= 1) { - if (from & 0x0100) { /* bit set? */ - /* cs [~~~~] SEND 1 */ - /* di [~~~~] */ - /* sck [_~~_] */ - sendit(dev, 6); sendit(dev, 7); sendit(dev, 7); sendit(dev, 6); - } - else { - /* cs [~~~~] SEND 0 */ - /* di [____] */ - /* sck [_~~_] */ - sendit(dev, 4); sendit(dev, 5); sendit(dev, 5); sendit(dev, 4); - } - } - - /* Shift in the 16-bit word. The bits appear serially in EEDI (=0x80) */ - for (data = 0, nbits = 16; nbits > 0; --nbits) { - /* cs [~~~~] SEND 0 */ - /* di [____] */ - /* sck [_~~_] */ - sendit(dev, 4); sendit(dev, 5); sendit(dev, 5); sendit(dev, 4); - data = (data << 1) | ((de620_get_register(dev, R_STS) & EEDI) >> 7); - } - /* cs [____] RESET SEND STATE */ - /* di [____] */ - /* sck [_~~_] */ - sendit(dev, 0); sendit(dev, 1); sendit(dev, 1); sendit(dev, 0); - - return data; -} - -static int -read_eeprom(struct device *dev) -{ - unsigned short wrd; - - /* D-Link Ethernet addresses are in the series 00:80:c8:7X:XX:XX:XX */ - wrd = ReadAWord(dev, 0x1aa); /* bytes 0 + 1 of NodeID */ - if (!clone && (wrd != htons(0x0080))) /* Valid D-Link ether sequence? */ - return -1; /* Nope, not a DE-620 */ - nic_data.NodeID[0] = wrd & 0xff; - nic_data.NodeID[1] = wrd >> 8; - - wrd = ReadAWord(dev, 0x1ab); /* bytes 2 + 3 of NodeID */ - if (!clone && ((wrd & 0xff) != 0xc8)) /* Valid D-Link ether sequence? */ - return -1; /* Nope, not a DE-620 */ - nic_data.NodeID[2] = wrd & 0xff; - nic_data.NodeID[3] = wrd >> 8; - - wrd = ReadAWord(dev, 0x1ac); /* bytes 4 + 5 of NodeID */ - nic_data.NodeID[4] = wrd & 0xff; - nic_data.NodeID[5] = wrd >> 8; - - wrd = ReadAWord(dev, 0x1ad); /* RAM size in pages (256 bytes). 0 = 64k */ - nic_data.RAM_Size = (wrd >> 8); - - wrd = ReadAWord(dev, 0x1ae); /* hardware model (CT = 3) */ - nic_data.Model = (wrd & 0xff); - - wrd = ReadAWord(dev, 0x1af); /* media (indicates BNC/UTP) */ - nic_data.Media = (wrd & 0xff); - - wrd = ReadAWord(dev, 0x1a8); /* System Configuration Register */ - nic_data.SCR = (wrd >> 8); - - return 0; /* no errors */ -} - -/****************************************************************************** - * - * Loadable module skeleton - * - */ -#ifdef MODULE -static char nullname[8] = ""; -static struct device de620_dev = { - nullname, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, de620_probe }; - -int -init_module(void) -{ - if (register_netdev(&de620_dev) != 0) - return -EIO; - return 0; -} - -void -cleanup_module(void) -{ - unregister_netdev(&de620_dev); - release_region(de620_dev.base_addr, 3); -} -#endif /* MODULE */ - -/* - * (add '-DMODULE' when compiling as loadable module) - * - * compile-command: - * gcc -D__KERNEL__ -Wall -Wstrict-prototypes -O2 \ - * -fomit-frame-pointer -m486 \ - * -I/usr/src/linux/include -I../../net/inet -c de620.c -*/ -/* - * Local variables: - * kernel-compile-command: "gcc -D__KERNEL__ -Ilinux/include -I../../net/inet -Wall -Wstrict-prototypes -O2 -m486 -c de620.c" - * module-compile-command: "gcc -D__KERNEL__ -DMODULE -Ilinux/include -I../../net/inet -Wall -Wstrict-prototypes -O2 -m486 -c de620.c" - * compile-command: "gcc -D__KERNEL__ -DMODULE -Ilinux/include -I../../net/inet -Wall -Wstrict-prototypes -O2 -m486 -c de620.c" - * End: - */ diff --git a/i386/i386at/gpl/linux/net/de620.h b/i386/i386at/gpl/linux/net/de620.h deleted file mode 100644 index e8d9a88f..00000000 --- a/i386/i386at/gpl/linux/net/de620.h +++ /dev/null @@ -1,117 +0,0 @@ -/********************************************************* - * * - * Definition of D-Link DE-620 Ethernet Pocket adapter * - * * - *********************************************************/ - -/* DE-620's CMD port Command */ -#define CS0 0x08 /* 1->0 command strobe */ -#define ICEN 0x04 /* 0=enable DL3520 host interface */ -#define DS0 0x02 /* 1->0 data strobe 0 */ -#define DS1 0x01 /* 1->0 data strobe 1 */ - -#define WDIR 0x20 /* general 0=read 1=write */ -#define RDIR 0x00 /* (not 100% confirm ) */ -#define PS2WDIR 0x00 /* ps/2 mode 1=read, 0=write */ -#define PS2RDIR 0x20 - -#define IRQEN 0x10 /* 1 = enable printer IRQ line */ -#define SELECTIN 0x08 /* 1 = select printer */ -#define INITP 0x04 /* 0 = initial printer */ -#define AUTOFEED 0x02 /* 1 = printer auto form feed */ -#define STROBE 0x01 /* 0->1 data strobe */ - -#define RESET 0x08 -#define NIS0 0x20 /* 0 = BNC, 1 = UTP */ -#define NCTL0 0x10 - -/* DE-620 DIC Command */ -#define W_DUMMY 0x00 /* DIC reserved command */ -#define W_CR 0x20 /* DIC write command register */ -#define W_NPR 0x40 /* DIC write Next Page Register */ -#define W_TBR 0x60 /* DIC write Tx Byte Count 1 reg */ -#define W_RSA 0x80 /* DIC write Remote Start Addr 1 */ - -/* DE-620's STAT port bits 7-4 */ -#define EMPTY 0x80 /* 1 = receive buffer empty */ -#define INTLEVEL 0x40 /* 1 = interrupt level is high */ -#define TXBF1 0x20 /* 1 = transmit buffer 1 is in use */ -#define TXBF0 0x10 /* 1 = transmit buffer 0 is in use */ -#define READY 0x08 /* 1 = h/w ready to accept cmd/data */ - -/* IDC 1 Command */ -#define W_RSA1 0xa0 /* write remote start address 1 */ -#define W_RSA0 0xa1 /* write remote start address 0 */ -#define W_NPRF 0xa2 /* write next page register NPR15-NPR8 */ -#define W_DFR 0xa3 /* write delay factor register */ -#define W_CPR 0xa4 /* write current page register */ -#define W_SPR 0xa5 /* write start page register */ -#define W_EPR 0xa6 /* write end page register */ -#define W_SCR 0xa7 /* write system configuration register */ -#define W_TCR 0xa8 /* write Transceiver Configuration reg */ -#define W_EIP 0xa9 /* write EEPM Interface port */ -#define W_PAR0 0xaa /* write physical address register 0 */ -#define W_PAR1 0xab /* write physical address register 1 */ -#define W_PAR2 0xac /* write physical address register 2 */ -#define W_PAR3 0xad /* write physical address register 3 */ -#define W_PAR4 0xae /* write physical address register 4 */ -#define W_PAR5 0xaf /* write physical address register 5 */ - -/* IDC 2 Command */ -#define R_STS 0xc0 /* read status register */ -#define R_CPR 0xc1 /* read current page register */ -#define R_BPR 0xc2 /* read boundary page register */ -#define R_TDR 0xc3 /* read time domain reflectometry reg */ - -/* STATUS Register */ -#define EEDI 0x80 /* EEPM DO pin */ -#define TXSUC 0x40 /* tx success */ -#define T16 0x20 /* tx fail 16 times */ -#define TS1 0x40 /* 0=Tx success, 1=T16 */ -#define TS0 0x20 /* 0=Tx success, 1=T16 */ -#define RXGOOD 0x10 /* rx a good packet */ -#define RXCRC 0x08 /* rx a CRC error packet */ -#define RXSHORT 0x04 /* rx a short packet */ -#define COLS 0x02 /* coaxial collision status */ -#define LNKS 0x01 /* UTP link status */ - -/* Command Register */ -#define CLEAR 0x10 /* reset part of hardware */ -#define NOPER 0x08 /* No Operation */ -#define RNOP 0x08 -#define RRA 0x06 /* After RR then auto-advance NPR & BPR(=NPR-1) */ -#define RRN 0x04 /* Normal Remote Read mode */ -#define RW1 0x02 /* Remote Write tx buffer 1 ( page 6 - 11 ) */ -#define RW0 0x00 /* Remote Write tx buffer 0 ( page 0 - 5 ) */ -#define TXEN 0x01 /* 0->1 tx enable */ - -/* System Configuration Register */ -#define TESTON 0x80 /* test host data transfer reliability */ -#define SLEEP 0x40 /* sleep mode */ -#if 0 -#define FASTMODE 0x04 /* fast mode for intel 82360SL fast mode */ -#define BYTEMODE 0x02 /* byte mode */ -#else -#define FASTMODE 0x20 /* fast mode for intel 82360SL fast mode */ -#define BYTEMODE 0x10 /* byte mode */ -#endif -#define NIBBLEMODE 0x00 /* nibble mode */ -#define IRQINV 0x08 /* turn off IRQ line inverter */ -#define IRQNML 0x00 /* turn on IRQ line inverter */ -#define INTON 0x04 -#define AUTOFFSET 0x02 /* auto shift address to TPR+12 */ -#define AUTOTX 0x01 /* auto tx when leave RW mode */ - -/* Transceiver Configuration Register */ -#define JABBER 0x80 /* generate jabber condition */ -#define TXSUCINT 0x40 /* enable tx success interrupt */ -#define T16INT 0x20 /* enable T16 interrupt */ -#define RXERRPKT 0x10 /* accept CRC error or short packet */ -#define EXTERNALB2 0x0C /* external loopback 2 */ -#define EXTERNALB1 0x08 /* external loopback 1 */ -#define INTERNALB 0x04 /* internal loopback */ -#define NMLOPERATE 0x00 /* normal operation */ -#define RXPBM 0x03 /* rx physical, broadcast, multicast */ -#define RXPB 0x02 /* rx physical, broadcast */ -#define RXALL 0x01 /* rx all packet */ -#define RXOFF 0x00 /* rx disable */ diff --git a/i386/i386at/gpl/linux/net/depca.c b/i386/i386at/gpl/linux/net/depca.c deleted file mode 100644 index ae9a8ca3..00000000 --- a/i386/i386at/gpl/linux/net/depca.c +++ /dev/null @@ -1,1901 +0,0 @@ -/* depca.c: A DIGITAL DEPCA & EtherWORKS ethernet driver for linux. - - Written 1994, 1995 by David C. Davies. - - - Copyright 1994 David C. Davies - and - United States Government - (as represented by the Director, National Security Agency). - - Copyright 1995 Digital Equipment Corporation. - - - This software may be used and distributed according to the terms of - the GNU Public License, incorporated herein by reference. - - This driver is written for the Digital Equipment Corporation series - of DEPCA and EtherWORKS ethernet cards: - - DEPCA (the original) - DE100 - DE101 - DE200 Turbo - DE201 Turbo - DE202 Turbo (TP BNC) - DE210 - DE422 (EISA) - - The driver has been tested on DE100, DE200 and DE202 cards in a - relatively busy network. The DE422 has been tested a little. - - This driver will NOT work for the DE203, DE204 and DE205 series of - cards, since they have a new custom ASIC in place of the AMD LANCE - chip. See the 'ewrk3.c' driver in the Linux source tree for running - those cards. - - I have benchmarked the driver with a DE100 at 595kB/s to (542kB/s from) - a DECstation 5000/200. - - The author may be reached at davies@wanton.lkg.dec.com or - davies@maniac.ultranet.com or Digital Equipment Corporation, 550 King - Street, Littleton MA 01460. - - ========================================================================= - - The driver was originally based on the 'lance.c' driver from Donald - Becker which is included with the standard driver distribution for - linux. V0.4 is a complete re-write with only the kernel interface - remaining from the original code. - - 1) Lance.c code in /linux/drivers/net/ - 2) "Ethernet/IEEE 802.3 Family. 1992 World Network Data Book/Handbook", - AMD, 1992 [(800) 222-9323]. - 3) "Am79C90 CMOS Local Area Network Controller for Ethernet (C-LANCE)", - AMD, Pub. #17881, May 1993. - 4) "Am79C960 PCnet-ISA(tm), Single-Chip Ethernet Controller for ISA", - AMD, Pub. #16907, May 1992 - 5) "DEC EtherWORKS LC Ethernet Controller Owners Manual", - Digital Equipment corporation, 1990, Pub. #EK-DE100-OM.003 - 6) "DEC EtherWORKS Turbo Ethernet Controller Owners Manual", - Digital Equipment corporation, 1990, Pub. #EK-DE200-OM.003 - 7) "DEPCA Hardware Reference Manual", Pub. #EK-DEPCA-PR - Digital Equipment Corporation, 1989 - 8) "DEC EtherWORKS Turbo_(TP BNC) Ethernet Controller Owners Manual", - Digital Equipment corporation, 1991, Pub. #EK-DE202-OM.001 - - - Peter Bauer's depca.c (V0.5) was referred to when debugging V0.1 of this - driver. - - The original DEPCA card requires that the ethernet ROM address counter - be enabled to count and has an 8 bit NICSR. The ROM counter enabling is - only done when a 0x08 is read as the first address octet (to minimise - the chances of writing over some other hardware's I/O register). The - NICSR accesses have been changed to byte accesses for all the cards - supported by this driver, since there is only one useful bit in the MSB - (remote boot timeout) and it is not used. Also, there is a maximum of - only 48kB network RAM for this card. My thanks to Torbjorn Lindh for - help debugging all this (and holding my feet to the fire until I got it - right). - - The DE200 series boards have on-board 64kB RAM for use as a shared - memory network buffer. Only the DE100 cards make use of a 2kB buffer - mode which has not been implemented in this driver (only the 32kB and - 64kB modes are supported [16kB/48kB for the original DEPCA]). - - At the most only 2 DEPCA cards can be supported on the ISA bus because - there is only provision for two I/O base addresses on each card (0x300 - and 0x200). The I/O address is detected by searching for a byte sequence - in the Ethernet station address PROM at the expected I/O address for the - Ethernet PROM. The shared memory base address is 'autoprobed' by - looking for the self test PROM and detecting the card name. When a - second DEPCA is detected, information is placed in the base_addr - variable of the next device structure (which is created if necessary), - thus enabling ethif_probe initialization for the device. More than 2 - EISA cards can be supported, but care will be needed assigning the - shared memory to ensure that each slot has the correct IRQ, I/O address - and shared memory address assigned. - - ************************************************************************ - - NOTE: If you are using two ISA DEPCAs, it is important that you assign - the base memory addresses correctly. The driver autoprobes I/O 0x300 - then 0x200. The base memory address for the first device must be less - than that of the second so that the auto probe will correctly assign the - I/O and memory addresses on the same card. I can't think of a way to do - this unambiguously at the moment, since there is nothing on the cards to - tie I/O and memory information together. - - I am unable to test 2 cards together for now, so this code is - unchecked. All reports, good or bad, are welcome. - - ************************************************************************ - - The board IRQ setting must be at an unused IRQ which is auto-probed - using Donald Becker's autoprobe routines. DEPCA and DE100 board IRQs are - {2,3,4,5,7}, whereas the DE200 is at {5,9,10,11,15}. Note that IRQ2 is - really IRQ9 in machines with 16 IRQ lines. - - No 16MB memory limitation should exist with this driver as DMA is not - used and the common memory area is in low memory on the network card (my - current system has 20MB and I've not had problems yet). - - The ability to load this driver as a loadable module has been added. To - utilise this ability, you have to do <8 things: - - 0) have a copy of the loadable modules code installed on your system. - 1) copy depca.c from the /linux/drivers/net directory to your favourite - temporary directory. - 2) if you wish, edit the source code near line 1530 to reflect the I/O - address and IRQ you're using (see also 5). - 3) compile depca.c, but include -DMODULE in the command line to ensure - that the correct bits are compiled (see end of source code). - 4) if you are wanting to add a new card, goto 5. Otherwise, recompile a - kernel with the depca configuration turned off and reboot. - 5) insmod depca.o [irq=7] [io=0x200] [mem=0xd0000] [adapter_name=DE100] - [Alan Cox: Changed the code to allow command line irq/io assignments] - [Dave Davies: Changed the code to allow command line mem/name - assignments] - 6) run the net startup bits for your eth?? interface manually - (usually /etc/rc.inet[12] at boot time). - 7) enjoy! - - Note that autoprobing is not allowed in loadable modules - the system is - already up and running and you're messing with interrupts. - - To unload a module, turn off the associated interface - 'ifconfig eth?? down' then 'rmmod depca'. - - To assign a base memory address for the shared memory when running as a - loadable module, see 5 above. To include the adapter name (if you have - no PROM but know the card name) also see 5 above. Note that this last - option will not work with kernel built-in depca's. - - The shared memory assignment for a loadable module makes sense to avoid - the 'memory autoprobe' picking the wrong shared memory (for the case of - 2 depca's in a PC). - - - TO DO: - ------ - - - Revision History - ---------------- - - Version Date Description - - 0.1 25-jan-94 Initial writing. - 0.2 27-jan-94 Added LANCE TX hardware buffer chaining. - 0.3 1-feb-94 Added multiple DEPCA support. - 0.31 4-feb-94 Added DE202 recognition. - 0.32 19-feb-94 Tidy up. Improve multi-DEPCA support. - 0.33 25-feb-94 Fix DEPCA ethernet ROM counter enable. - Add jabber packet fix from murf@perftech.com - and becker@super.org - 0.34 7-mar-94 Fix DEPCA max network memory RAM & NICSR access. - 0.35 8-mar-94 Added DE201 recognition. Tidied up. - 0.351 30-apr-94 Added EISA support. Added DE422 recognition. - 0.36 16-may-94 DE422 fix released. - 0.37 22-jul-94 Added MODULE support - 0.38 15-aug-94 Added DBR ROM switch in depca_close(). - Multi DEPCA bug fix. - 0.38axp 15-sep-94 Special version for Alpha AXP Linux V1.0. - 0.381 12-dec-94 Added DE101 recognition, fix multicast bug. - 0.382 9-feb-95 Fix recognition bug reported by <bkm@star.rl.ac.uk>. - 0.383 22-feb-95 Fix for conflict with VESA SCSI reported by - <stromain@alf.dec.com> - 0.384 17-mar-95 Fix a ring full bug reported by <bkm@star.rl.ac.uk> - 0.385 3-apr-95 Fix a recognition bug reported by - <ryan.niemi@lastfrontier.com> - 0.386 21-apr-95 Fix the last fix...sorry, must be galloping senility - 0.40 25-May-95 Rewrite for portability & updated. - ALPHA support from <jestabro@amt.tay1.dec.com> - 0.41 26-Jun-95 Added verify_area() calls in depca_ioctl() from - suggestion by <heiko@colossus.escape.de> - 0.42 27-Dec-95 Add 'mem' shared memory assigment for loadable - modules. - Add 'adapter_name' for loadable modules when no PROM. - Both above from a suggestion by - <pchen@woodruffs121.residence.gatech.edu>. - Add new multicasting code. - - ========================================================================= -*/ - -static const char *version = "depca.c:v0.42 95/12/27 davies@wanton.lkg.dec.com\n"; - -#include <linux/module.h> - -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/string.h> -#include <linux/ptrace.h> -#include <linux/errno.h> -#include <linux/ioport.h> -#include <linux/malloc.h> -#include <linux/interrupt.h> -#include <linux/delay.h> -#include <asm/segment.h> -#include <asm/bitops.h> -#include <asm/io.h> -#include <asm/dma.h> - -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> - -#include <linux/time.h> -#include <linux/types.h> -#include <linux/unistd.h> - -#include "depca.h" - -#ifdef DEPCA_DEBUG -static int depca_debug = DEPCA_DEBUG; -#else -static int depca_debug = 1; -#endif - -#define DEPCA_NDA 0xffe0 /* No Device Address */ - -/* -** Ethernet PROM defines -*/ -#define PROBE_LENGTH 32 -#define ETH_PROM_SIG 0xAA5500FFUL - -/* -** Set the number of Tx and Rx buffers. Ensure that the memory requested -** here is <= to the amount of shared memory set up by the board switches. -** The number of descriptors MUST BE A POWER OF 2. -** -** total_memory = NUM_RX_DESC*(8+RX_BUFF_SZ) + NUM_TX_DESC*(8+TX_BUFF_SZ) -*/ -#define NUM_RX_DESC 8 /* Number of RX descriptors */ -#define NUM_TX_DESC 8 /* Number of TX descriptors */ -#define RX_BUFF_SZ 1536 /* Buffer size for each Rx buffer */ -#define TX_BUFF_SZ 1536 /* Buffer size for each Tx buffer */ - -#define CRC_POLYNOMIAL_BE 0x04c11db7UL /* Ethernet CRC, big endian */ -#define CRC_POLYNOMIAL_LE 0xedb88320UL /* Ethernet CRC, little endian */ - -/* -** EISA bus defines -*/ -#define DEPCA_EISA_IO_PORTS 0x0c00 /* I/O port base address, slot 0 */ -#define MAX_EISA_SLOTS 16 -#define EISA_SLOT_INC 0x1000 - -/* -** ISA Bus defines -*/ -#define DEPCA_RAM_BASE_ADDRESSES {0xc0000,0xd0000,0xe0000,0x00000} -#define DEPCA_IO_PORTS {0x300, 0x200, 0} -#define DEPCA_TOTAL_SIZE 0x10 -static short mem_chkd = 0; - -/* -** Name <-> Adapter mapping -*/ -#define DEPCA_SIGNATURE {"DEPCA",\ - "DE100","DE101",\ - "DE200","DE201","DE202",\ - "DE210",\ - "DE422",\ - ""} -static enum {DEPCA, de100, de101, de200, de201, de202, de210, de422, unknown} adapter; - -/* -** Miscellaneous info... -*/ -#define DEPCA_STRLEN 16 -#define MAX_NUM_DEPCAS 2 - -/* -** Memory Alignment. Each descriptor is 4 longwords long. To force a -** particular alignment on the TX descriptor, adjust DESC_SKIP_LEN and -** DESC_ALIGN. ALIGN aligns the start address of the private memory area -** and hence the RX descriptor ring's first entry. -*/ -#define ALIGN4 ((u_long)4 - 1) /* 1 longword align */ -#define ALIGN8 ((u_long)8 - 1) /* 2 longword (quadword) align */ -#define ALIGN ALIGN8 /* Keep the LANCE happy... */ - -/* -** The DEPCA Rx and Tx ring descriptors. -*/ -struct depca_rx_desc { - volatile s32 base; - s16 buf_length; /* This length is negative 2's complement! */ - s16 msg_length; /* This length is "normal". */ -}; - -struct depca_tx_desc { - volatile s32 base; - s16 length; /* This length is negative 2's complement! */ - s16 misc; /* Errors and TDR info */ -}; - -#define LA_MASK 0x0000ffff /* LANCE address mask for mapping network RAM - to LANCE memory address space */ - -/* -** The Lance initialization block, described in databook, in common memory. -*/ -struct depca_init { - u16 mode; /* Mode register */ - u8 phys_addr[ETH_ALEN]; /* Physical ethernet address */ - u8 mcast_table[8]; /* Multicast Hash Table. */ - u32 rx_ring; /* Rx ring base pointer & ring length */ - u32 tx_ring; /* Tx ring base pointer & ring length */ -}; - -#define DEPCA_PKT_STAT_SZ 16 -#define DEPCA_PKT_BIN_SZ 128 /* Should be >=100 unless you - increase DEPCA_PKT_STAT_SZ */ -struct depca_private { - char devname[DEPCA_STRLEN]; /* Device Product String */ - char adapter_name[DEPCA_STRLEN];/* /proc/ioports string */ - char adapter; /* Adapter type */ - struct depca_rx_desc *rx_ring; /* Pointer to start of RX descriptor ring */ - struct depca_tx_desc *tx_ring; /* Pointer to start of TX descriptor ring */ - struct depca_init init_block;/* Shadow Initialization block */ - char *rx_memcpy[NUM_RX_DESC]; /* CPU virt address of sh'd memory buffs */ - char *tx_memcpy[NUM_TX_DESC]; /* CPU virt address of sh'd memory buffs */ - u_long bus_offset; /* (E)ISA bus address offset vs LANCE */ - u_long sh_mem; /* Physical start addr of shared mem area */ - u_long dma_buffs; /* LANCE Rx and Tx buffers start address. */ - int rx_new, tx_new; /* The next free ring entry */ - int rx_old, tx_old; /* The ring entries to be free()ed. */ - struct enet_statistics stats; - struct { /* Private stats counters */ - u32 bins[DEPCA_PKT_STAT_SZ]; - u32 unicast; - u32 multicast; - u32 broadcast; - u32 excessive_collisions; - u32 tx_underruns; - u32 excessive_underruns; - } pktStats; - int txRingMask; /* TX ring mask */ - int rxRingMask; /* RX ring mask */ - s32 rx_rlen; /* log2(rxRingMask+1) for the descriptors */ - s32 tx_rlen; /* log2(txRingMask+1) for the descriptors */ -}; - -/* -** The transmit ring full condition is described by the tx_old and tx_new -** pointers by: -** tx_old = tx_new Empty ring -** tx_old = tx_new+1 Full ring -** tx_old+txRingMask = tx_new Full ring (wrapped condition) -*/ -#define TX_BUFFS_AVAIL ((lp->tx_old<=lp->tx_new)?\ - lp->tx_old+lp->txRingMask-lp->tx_new:\ - lp->tx_old -lp->tx_new-1) - -/* -** Public Functions -*/ -static int depca_open(struct device *dev); -static int depca_start_xmit(struct sk_buff *skb, struct device *dev); -static void depca_interrupt(int irq, struct pt_regs * regs); -static int depca_close(struct device *dev); -static int depca_ioctl(struct device *dev, struct ifreq *rq, int cmd); -static struct enet_statistics *depca_get_stats(struct device *dev); -static void set_multicast_list(struct device *dev); - -/* -** Private functions -*/ -static int depca_hw_init(struct device *dev, u_long ioaddr); -static void depca_init_ring(struct device *dev); -static int depca_rx(struct device *dev); -static int depca_tx(struct device *dev); - -static void LoadCSRs(struct device *dev); -static int InitRestartDepca(struct device *dev); -static void DepcaSignature(char *name, u_long paddr); -static int DevicePresent(u_long ioaddr); -static int get_hw_addr(struct device *dev); -static int EISA_signature(char *name, s32 eisa_id); -static void SetMulticastFilter(struct device *dev); -static void isa_probe(struct device *dev, u_long iobase); -static void eisa_probe(struct device *dev, u_long iobase); -static struct device *alloc_device(struct device *dev, u_long iobase); -static int load_packet(struct device *dev, struct sk_buff *skb); -static void depca_dbg_open(struct device *dev); - -#ifdef MODULE -int init_module(void); -void cleanup_module(void); -static int autoprobed = 1, loading_module = 1; -# else -static u_char de1xx_irq[] = {2,3,4,5,7,0}; -static u_char de2xx_irq[] = {5,9,10,11,15,0}; -static u_char de422_irq[] = {5,9,10,11,0}; -static u_char *depca_irq; -static int autoprobed = 0, loading_module = 0; -#endif /* MODULE */ - -static char name[DEPCA_STRLEN]; -static int num_depcas = 0, num_eth = 0; -static int mem=0; /* For loadable module assignment - use insmod mem=0x????? .... */ -static char *adapter_name = '\0'; /* If no PROM when loadable module - use insmod adapter_name=DE??? ... - */ -/* -** Miscellaneous defines... -*/ -#define STOP_DEPCA \ - outw(CSR0, DEPCA_ADDR);\ - outw(STOP, DEPCA_DATA) - - - -int depca_probe(struct device *dev) -{ - int tmp = num_depcas, status = -ENODEV; - u_long iobase = dev->base_addr; - - if ((iobase == 0) && loading_module){ - printk("Autoprobing is not supported when loading a module based driver.\n"); - status = -EIO; - } else { - isa_probe(dev, iobase); - eisa_probe(dev, iobase); - - if ((tmp == num_depcas) && (iobase != 0) && loading_module) { - printk("%s: depca_probe() cannot find device at 0x%04lx.\n", dev->name, - iobase); - } - - /* - ** Walk the device list to check that at least one device - ** initialised OK - */ - for (; (dev->priv == NULL) && (dev->next != NULL); dev = dev->next); - - if (dev->priv) status = 0; - if (iobase == 0) autoprobed = 1; - } - - return status; -} - -static int -depca_hw_init(struct device *dev, u_long ioaddr) -{ - struct depca_private *lp; - int i, j, offset, netRAM, mem_len, status=0; - s16 nicsr; - u_long mem_start=0, mem_base[] = DEPCA_RAM_BASE_ADDRESSES; - - STOP_DEPCA; - - nicsr = inb(DEPCA_NICSR); - nicsr = ((nicsr & ~SHE & ~RBE & ~IEN) | IM); - outb(nicsr, DEPCA_NICSR); - - if (inw(DEPCA_DATA) == STOP) { - if (mem == 0) { - for (; mem_base[mem_chkd]; mem_chkd++) { - mem_start = mem_base[mem_chkd]; - DepcaSignature(name, mem_start); - if (*name != '\0') break; - } - } else { - mem_start = mem; - if (adapter_name) { - strcpy(name, adapter_name); - } else{ - DepcaSignature(name, mem_start); - } - } - - if ((*name != '\0') && mem_start) { /* found a DEPCA device */ - dev->base_addr = ioaddr; - - if ((ioaddr&0x0fff)==DEPCA_EISA_IO_PORTS) {/* EISA slot address */ - printk("%s: %s at 0x%04lx (EISA slot %d)", - dev->name, name, ioaddr, (int)((ioaddr>>12)&0x0f)); - } else { /* ISA port address */ - printk("%s: %s at 0x%04lx", dev->name, name, ioaddr); - } - - printk(", h/w address "); - status = get_hw_addr(dev); - for (i=0; i<ETH_ALEN - 1; i++) { /* get the ethernet address */ - printk("%2.2x:", dev->dev_addr[i]); - } - printk("%2.2x", dev->dev_addr[i]); - - if (status == 0) { - /* Set up the maximum amount of network RAM(kB) */ - netRAM = ((adapter != DEPCA) ? 64 : 48); - if ((nicsr & _128KB) && (adapter == de422)) netRAM = 128; - offset = 0x0000; - - /* Shared Memory Base Address */ - if (nicsr & BUF) { - offset = 0x8000; /* 32kbyte RAM offset*/ - nicsr &= ~BS; /* DEPCA RAM in top 32k */ - netRAM -= 32; - } - mem_start += offset; /* (E)ISA start address */ - if ((mem_len = (NUM_RX_DESC*(sizeof(struct depca_rx_desc)+RX_BUFF_SZ) + - NUM_TX_DESC*(sizeof(struct depca_tx_desc)+TX_BUFF_SZ) + - sizeof(struct depca_init))) <= - (netRAM<<10)) { - printk(",\n has %dkB RAM at 0x%.5lx", netRAM, mem_start); - - /* Enable the shadow RAM. */ - if (adapter != DEPCA) { - nicsr |= SHE; - outb(nicsr, DEPCA_NICSR); - } - - /* Define the device private memory */ - dev->priv = (void *) kmalloc(sizeof(struct depca_private), GFP_KERNEL); - if (dev->priv == NULL) - return -ENOMEM; - lp = (struct depca_private *)dev->priv; - memset((char *)dev->priv, 0, sizeof(struct depca_private)); - lp->adapter = adapter; - sprintf(lp->adapter_name,"%s (%s)", name, dev->name); - request_region(ioaddr, DEPCA_TOTAL_SIZE, lp->adapter_name); - - /* Initialisation Block */ - lp->sh_mem = mem_start; - mem_start += sizeof(struct depca_init); - - /* Tx & Rx descriptors (aligned to a quadword boundary) */ - mem_start = (mem_start + ALIGN) & ~ALIGN; - lp->rx_ring = (struct depca_rx_desc *)mem_start; - - mem_start += (sizeof(struct depca_rx_desc) * NUM_RX_DESC); - lp->tx_ring = (struct depca_tx_desc *)mem_start; - - mem_start += (sizeof(struct depca_tx_desc) * NUM_TX_DESC); - lp->bus_offset = mem_start & 0x00ff0000; - mem_start &= LA_MASK; /* LANCE re-mapped start address */ - - lp->dma_buffs = mem_start; - - /* Finish initialising the ring information. */ - lp->rxRingMask = NUM_RX_DESC - 1; - lp->txRingMask = NUM_TX_DESC - 1; - - /* Calculate Tx/Rx RLEN size for the descriptors. */ - for (i=0, j = lp->rxRingMask; j>0; i++) { - j >>= 1; - } - lp->rx_rlen = (s32)(i << 29); - for (i=0, j = lp->txRingMask; j>0; i++) { - j >>= 1; - } - lp->tx_rlen = (s32)(i << 29); - - /* Load the initialisation block */ - depca_init_ring(dev); - - /* Initialise the control and status registers */ - LoadCSRs(dev); - - /* Enable DEPCA board interrupts for autoprobing */ - nicsr = ((nicsr & ~IM)|IEN); - outb(nicsr, DEPCA_NICSR); - - /* To auto-IRQ we enable the initialization-done and DMA err, - interrupts. For now we will always get a DMA error. */ - if (dev->irq < 2) { -#ifndef MODULE - unsigned char irqnum; - autoirq_setup(0); - - /* Assign the correct irq list */ - switch (lp->adapter) { - case DEPCA: - case de100: - case de101: - depca_irq = de1xx_irq; - break; - case de200: - case de201: - case de202: - case de210: - depca_irq = de2xx_irq; - break; - case de422: - depca_irq = de422_irq; - break; - } - - /* Trigger an initialization just for the interrupt. */ - outw(INEA | INIT, DEPCA_DATA); - - irqnum = autoirq_report(1); - if (!irqnum) { - printk(" and failed to detect IRQ line.\n"); - status = -ENXIO; - } else { - for (dev->irq=0,i=0; (depca_irq[i]) && (!dev->irq); i++) { - if (irqnum == depca_irq[i]) { - dev->irq = irqnum; - printk(" and uses IRQ%d.\n", dev->irq); - } - } - - if (!dev->irq) { - printk(" but incorrect IRQ line detected.\n"); - status = -ENXIO; - } - } -#endif /* MODULE */ - } else { - printk(" and assigned IRQ%d.\n", dev->irq); - } - if (status) release_region(ioaddr, DEPCA_TOTAL_SIZE); - } else { - printk(",\n requests %dkB RAM: only %dkB is available!\n", - (mem_len>>10), netRAM); - status = -ENXIO; - } - } else { - printk(" which has an Ethernet PROM CRC error.\n"); - status = -ENXIO; - } - } - if (!status) { - if (depca_debug > 0) { - printk(version); - } - - /* The DEPCA-specific entries in the device structure. */ - dev->open = &depca_open; - dev->hard_start_xmit = &depca_start_xmit; - dev->stop = &depca_close; - dev->get_stats = &depca_get_stats; - dev->set_multicast_list = &set_multicast_list; - dev->do_ioctl = &depca_ioctl; - - dev->mem_start = 0; - - /* Fill in the generic field of the device structure. */ - ether_setup(dev); - } else { /* Incorrectly initialised hardware */ - if (dev->priv) { - kfree_s(dev->priv, sizeof(struct depca_private)); - dev->priv = NULL; - } - } - } else { - status = -ENXIO; - } - - return status; -} - - -static int -depca_open(struct device *dev) -{ - struct depca_private *lp = (struct depca_private *)dev->priv; - u_long ioaddr = dev->base_addr; - s16 nicsr; - int status = 0; - - irq2dev_map[dev->irq] = dev; - STOP_DEPCA; - nicsr = inb(DEPCA_NICSR); - - /* Make sure the shadow RAM is enabled */ - if (adapter != DEPCA) { - nicsr |= SHE; - outb(nicsr, DEPCA_NICSR); - } - - /* Re-initialize the DEPCA... */ - depca_init_ring(dev); - LoadCSRs(dev); - - depca_dbg_open(dev); - - if (request_irq(dev->irq, &depca_interrupt, 0, lp->adapter_name)) { - printk("depca_open(): Requested IRQ%d is busy\n",dev->irq); - status = -EAGAIN; - } else { - - /* Enable DEPCA board interrupts and turn off LED */ - nicsr = ((nicsr & ~IM & ~LED)|IEN); - outb(nicsr, DEPCA_NICSR); - outw(CSR0,DEPCA_ADDR); - - dev->tbusy = 0; - dev->interrupt = 0; - dev->start = 1; - - status = InitRestartDepca(dev); - - if (depca_debug > 1){ - printk("CSR0: 0x%4.4x\n",inw(DEPCA_DATA)); - printk("nicsr: 0x%02x\n",inb(DEPCA_NICSR)); - } - } - - MOD_INC_USE_COUNT; - - return status; -} - -/* Initialize the lance Rx and Tx descriptor rings. */ -static void -depca_init_ring(struct device *dev) -{ - struct depca_private *lp = (struct depca_private *)dev->priv; - u_int i; - u_long p; - - /* Lock out other processes whilst setting up the hardware */ - set_bit(0, (void *)&dev->tbusy); - - lp->rx_new = lp->tx_new = 0; - lp->rx_old = lp->tx_old = 0; - - /* Initialize the base addresses and length of each buffer in the ring */ - for (i = 0; i <= lp->rxRingMask; i++) { - writel((p=lp->dma_buffs+i*RX_BUFF_SZ) | R_OWN, &lp->rx_ring[i].base); - writew(-RX_BUFF_SZ, &lp->rx_ring[i].buf_length); - lp->rx_memcpy[i]=(char *)(p+lp->bus_offset); - } - for (i = 0; i <= lp->txRingMask; i++) { - writel((p=lp->dma_buffs+(i+lp->txRingMask+1)*TX_BUFF_SZ) & 0x00ffffff, - &lp->tx_ring[i].base); - lp->tx_memcpy[i]=(char *)(p+lp->bus_offset); - } - - /* Set up the initialization block */ - lp->init_block.rx_ring = ((u32)((u_long)lp->rx_ring)&LA_MASK) | lp->rx_rlen; - lp->init_block.tx_ring = ((u32)((u_long)lp->tx_ring)&LA_MASK) | lp->tx_rlen; - - SetMulticastFilter(dev); - - for (i = 0; i < ETH_ALEN; i++) { - lp->init_block.phys_addr[i] = dev->dev_addr[i]; - } - - lp->init_block.mode = 0x0000; /* Enable the Tx and Rx */ - - return; -} - -/* -** Writes a socket buffer to TX descriptor ring and starts transmission -*/ -static int -depca_start_xmit(struct sk_buff *skb, struct device *dev) -{ - struct depca_private *lp = (struct depca_private *)dev->priv; - u_long ioaddr = dev->base_addr; - int status = 0; - - /* Transmitter timeout, serious problems. */ - if (dev->tbusy) { - int tickssofar = jiffies - dev->trans_start; - if (tickssofar < 1*HZ) { - status = -1; - } else { - printk("%s: transmit timed out, status %04x, resetting.\n", - dev->name, inw(DEPCA_DATA)); - - STOP_DEPCA; - depca_init_ring(dev); - LoadCSRs(dev); - dev->interrupt = UNMASK_INTERRUPTS; - dev->start = 1; - dev->tbusy=0; - dev->trans_start = jiffies; - InitRestartDepca(dev); - } - return status; - } else if (skb == NULL) { - dev_tint(dev); - } else if (skb->len > 0) { - /* Enforce 1 process per h/w access */ - if (set_bit(0, (void*)&dev->tbusy) != 0) { - printk("%s: Transmitter access conflict.\n", dev->name); - status = -1; - } else { - if (TX_BUFFS_AVAIL) { /* Fill in a Tx ring entry */ - status = load_packet(dev, skb); - - if (!status) { - /* Trigger an immediate send demand. */ - outw(CSR0, DEPCA_ADDR); - outw(INEA | TDMD, DEPCA_DATA); - - dev->trans_start = jiffies; - dev_kfree_skb(skb, FREE_WRITE); - } - if (TX_BUFFS_AVAIL) { - dev->tbusy=0; - } - } else { - status = -1; - } - } - } - - return status; -} - -/* -** The DEPCA interrupt handler. -*/ -static void -depca_interrupt(int irq, struct pt_regs * regs) -{ - struct device *dev = (struct device *)(irq2dev_map[irq]); - struct depca_private *lp; - s16 csr0, nicsr; - u_long ioaddr; - - if (dev == NULL) { - printk ("depca_interrupt(): irq %d for unknown device.\n", irq); - } else { - lp = (struct depca_private *)dev->priv; - ioaddr = dev->base_addr; - - if (dev->interrupt) - printk("%s: Re-entering the interrupt handler.\n", dev->name); - - dev->interrupt = MASK_INTERRUPTS; - - /* mask the DEPCA board interrupts and turn on the LED */ - nicsr = inb(DEPCA_NICSR); - nicsr |= (IM|LED); - outb(nicsr, DEPCA_NICSR); - - outw(CSR0, DEPCA_ADDR); - csr0 = inw(DEPCA_DATA); - - /* Acknowledge all of the current interrupt sources ASAP. */ - outw(csr0 & INTE, DEPCA_DATA); - - if (csr0 & RINT) /* Rx interrupt (packet arrived) */ - depca_rx(dev); - - if (csr0 & TINT) /* Tx interrupt (packet sent) */ - depca_tx(dev); - - if ((TX_BUFFS_AVAIL >= 0) && dev->tbusy) { /* any resources available? */ - dev->tbusy = 0; /* clear TX busy flag */ - mark_bh(NET_BH); - } - - /* Unmask the DEPCA board interrupts and turn off the LED */ - nicsr = (nicsr & ~IM & ~LED); - outb(nicsr, DEPCA_NICSR); - - dev->interrupt = UNMASK_INTERRUPTS; - } - - return; -} - -static int -depca_rx(struct device *dev) -{ - struct depca_private *lp = (struct depca_private *)dev->priv; - int i, entry; - s32 status; - - for (entry=lp->rx_new; - !(readl(&lp->rx_ring[entry].base) & R_OWN); - entry=lp->rx_new){ - status = readl(&lp->rx_ring[entry].base) >> 16 ; - if (status & R_STP) { /* Remember start of frame */ - lp->rx_old = entry; - } - if (status & R_ENP) { /* Valid frame status */ - if (status & R_ERR) { /* There was an error. */ - lp->stats.rx_errors++; /* Update the error stats. */ - if (status & R_FRAM) lp->stats.rx_frame_errors++; - if (status & R_OFLO) lp->stats.rx_over_errors++; - if (status & R_CRC) lp->stats.rx_crc_errors++; - if (status & R_BUFF) lp->stats.rx_fifo_errors++; - } else { - short len, pkt_len = readw(&lp->rx_ring[entry].msg_length); - struct sk_buff *skb; - - skb = dev_alloc_skb(pkt_len+2); - if (skb != NULL) { - unsigned char *buf; - skb_reserve(skb,2); /* 16 byte align the IP header */ - buf = skb_put(skb,pkt_len); - skb->dev = dev; - if (entry < lp->rx_old) { /* Wrapped buffer */ - len = (lp->rxRingMask - lp->rx_old + 1) * RX_BUFF_SZ; - memcpy_fromio(buf, lp->rx_memcpy[lp->rx_old], len); - memcpy_fromio(buf + len, lp->rx_memcpy[0], pkt_len-len); - } else { /* Linear buffer */ - memcpy_fromio(buf, lp->rx_memcpy[lp->rx_old], pkt_len); - } - - /* - ** Notify the upper protocol layers that there is another - ** packet to handle - */ - skb->protocol=eth_type_trans(skb,dev); - netif_rx(skb); - - /* - ** Update stats - */ - lp->stats.rx_packets++; - for (i=1; i<DEPCA_PKT_STAT_SZ-1; i++) { - if (pkt_len < (i*DEPCA_PKT_BIN_SZ)) { - lp->pktStats.bins[i]++; - i = DEPCA_PKT_STAT_SZ; - } - } - if (buf[0] & 0x01) { /* Multicast/Broadcast */ - if ((*(s16 *)&buf[0] == -1) && - (*(s16 *)&buf[2] == -1) && - (*(s16 *)&buf[4] == -1)) { - lp->pktStats.broadcast++; - } else { - lp->pktStats.multicast++; - } - } else if ((*(s16 *)&buf[0] == *(s16 *)&dev->dev_addr[0]) && - (*(s16 *)&buf[2] == *(s16 *)&dev->dev_addr[2]) && - (*(s16 *)&buf[4] == *(s16 *)&dev->dev_addr[4])) { - lp->pktStats.unicast++; - } - - lp->pktStats.bins[0]++; /* Duplicates stats.rx_packets */ - if (lp->pktStats.bins[0] == 0) { /* Reset counters */ - memset((char *)&lp->pktStats, 0, sizeof(lp->pktStats)); - } - } else { - printk("%s: Memory squeeze, deferring packet.\n", dev->name); - lp->stats.rx_dropped++; /* Really, deferred. */ - break; - } - } - /* Change buffer ownership for this last frame, back to the adapter */ - for (; lp->rx_old!=entry; lp->rx_old=(++lp->rx_old)&lp->rxRingMask) { - writel(readl(&lp->rx_ring[lp->rx_old].base) | R_OWN, - &lp->rx_ring[lp->rx_old].base); - } - writel(readl(&lp->rx_ring[entry].base) | R_OWN, &lp->rx_ring[entry].base); - } - - /* - ** Update entry information - */ - lp->rx_new = (++lp->rx_new) & lp->rxRingMask; - } - - return 0; -} - -/* -** Buffer sent - check for buffer errors. -*/ -static int -depca_tx(struct device *dev) -{ - struct depca_private *lp = (struct depca_private *)dev->priv; - int entry; - s32 status; - u_long ioaddr = dev->base_addr; - - for (entry = lp->tx_old; entry != lp->tx_new; entry = lp->tx_old) { - status = readl(&lp->tx_ring[entry].base) >> 16 ; - - if (status < 0) { /* Packet not yet sent! */ - break; - } else if (status & T_ERR) { /* An error occured. */ - status = readl(&lp->tx_ring[entry].misc); - lp->stats.tx_errors++; - if (status & TMD3_RTRY) lp->stats.tx_aborted_errors++; - if (status & TMD3_LCAR) lp->stats.tx_carrier_errors++; - if (status & TMD3_LCOL) lp->stats.tx_window_errors++; - if (status & TMD3_UFLO) lp->stats.tx_fifo_errors++; - if (status & (TMD3_BUFF | TMD3_UFLO)) { - /* Trigger an immediate send demand. */ - outw(CSR0, DEPCA_ADDR); - outw(INEA | TDMD, DEPCA_DATA); - } - } else if (status & (T_MORE | T_ONE)) { - lp->stats.collisions++; - } else { - lp->stats.tx_packets++; - } - - /* Update all the pointers */ - lp->tx_old = (++lp->tx_old) & lp->txRingMask; - } - - return 0; -} - -static int -depca_close(struct device *dev) -{ - struct depca_private *lp = (struct depca_private *)dev->priv; - s16 nicsr; - u_long ioaddr = dev->base_addr; - - dev->start = 0; - dev->tbusy = 1; - - outw(CSR0, DEPCA_ADDR); - - if (depca_debug > 1) { - printk("%s: Shutting down ethercard, status was %2.2x.\n", - dev->name, inw(DEPCA_DATA)); - } - - /* - ** We stop the DEPCA here -- it occasionally polls - ** memory if we don't. - */ - outw(STOP, DEPCA_DATA); - - /* - ** Give back the ROM in case the user wants to go to DOS - */ - if (lp->adapter != DEPCA) { - nicsr = inb(DEPCA_NICSR); - nicsr &= ~SHE; - outb(nicsr, DEPCA_NICSR); - } - - /* - ** Free the associated irq - */ - free_irq(dev->irq); - irq2dev_map[dev->irq] = NULL; - - MOD_DEC_USE_COUNT; - - return 0; -} - -static void LoadCSRs(struct device *dev) -{ - struct depca_private *lp = (struct depca_private *)dev->priv; - u_long ioaddr = dev->base_addr; - - outw(CSR1, DEPCA_ADDR); /* initialisation block address LSW */ - outw((u16)(lp->sh_mem & LA_MASK), DEPCA_DATA); - outw(CSR2, DEPCA_ADDR); /* initialisation block address MSW */ - outw((u16)((lp->sh_mem & LA_MASK) >> 16), DEPCA_DATA); - outw(CSR3, DEPCA_ADDR); /* ALE control */ - outw(ACON, DEPCA_DATA); - - outw(CSR0, DEPCA_ADDR); /* Point back to CSR0 */ - - return; -} - -static int InitRestartDepca(struct device *dev) -{ - struct depca_private *lp = (struct depca_private *)dev->priv; - u_long ioaddr = dev->base_addr; - int i, status=0; - - /* Copy the shadow init_block to shared memory */ - memcpy_toio((char *)lp->sh_mem, &lp->init_block, sizeof(struct depca_init)); - - outw(CSR0, DEPCA_ADDR); /* point back to CSR0 */ - outw(INIT, DEPCA_DATA); /* initialize DEPCA */ - - /* wait for lance to complete initialisation */ - for (i=0;(i<100) && !(inw(DEPCA_DATA) & IDON); i++); - - if (i!=100) { - /* clear IDON by writing a "1", enable interrupts and start lance */ - outw(IDON | INEA | STRT, DEPCA_DATA); - if (depca_debug > 2) { - printk("%s: DEPCA open after %d ticks, init block 0x%08lx csr0 %4.4x.\n", - dev->name, i, lp->sh_mem, inw(DEPCA_DATA)); - } - } else { - printk("%s: DEPCA unopen after %d ticks, init block 0x%08lx csr0 %4.4x.\n", - dev->name, i, lp->sh_mem, inw(DEPCA_DATA)); - status = -1; - } - - return status; -} - -static struct enet_statistics * -depca_get_stats(struct device *dev) -{ - struct depca_private *lp = (struct depca_private *)dev->priv; - - /* Null body since there is no framing error counter */ - - return &lp->stats; -} - -/* -** Set or clear the multicast filter for this adaptor. -*/ -static void -set_multicast_list(struct device *dev) -{ - struct depca_private *lp = (struct depca_private *)dev->priv; - u_long ioaddr = dev->base_addr; - - if (irq2dev_map[dev->irq] != NULL) { - while(dev->tbusy); /* Stop ring access */ - set_bit(0, (void*)&dev->tbusy); - while(lp->tx_old != lp->tx_new); /* Wait for the ring to empty */ - - STOP_DEPCA; /* Temporarily stop the depca. */ - depca_init_ring(dev); /* Initialize the descriptor rings */ - - if (dev->flags & IFF_PROMISC) { /* Set promiscuous mode */ - lp->init_block.mode |= PROM; - } else { - SetMulticastFilter(dev); - lp->init_block.mode &= ~PROM; /* Unset promiscuous mode */ - } - - LoadCSRs(dev); /* Reload CSR3 */ - InitRestartDepca(dev); /* Resume normal operation. */ - dev->tbusy = 0; /* Unlock the TX ring */ - } -} - -/* -** Calculate the hash code and update the logical address filter -** from a list of ethernet multicast addresses. -** Big endian crc one liner is mine, all mine, ha ha ha ha! -** LANCE calculates its hash codes big endian. -*/ -static void SetMulticastFilter(struct device *dev) -{ - struct depca_private *lp = (struct depca_private *)dev->priv; - struct dev_mc_list *dmi=dev->mc_list; - char *addrs; - int i, j, bit, byte; - u16 hashcode; - s32 crc, poly = CRC_POLYNOMIAL_BE; - - if (dev->flags & IFF_ALLMULTI) { /* Set all multicast bits */ - for (i=0; i<(HASH_TABLE_LEN>>3); i++) { - lp->init_block.mcast_table[i] = (char)0xff; - } - } else { - for (i=0; i<(HASH_TABLE_LEN>>3); i++){ /* Clear the multicast table */ - lp->init_block.mcast_table[i]=0; - } - /* Add multicast addresses */ - for (i=0;i<dev->mc_count;i++) { /* for each address in the list */ - addrs=dmi->dmi_addr; - dmi=dmi->next; - if ((*addrs & 0x01) == 1) { /* multicast address? */ - crc = 0xffffffff; /* init CRC for each address */ - for (byte=0;byte<ETH_ALEN;byte++) {/* for each address byte */ - /* process each address bit */ - for (bit = *addrs++,j=0;j<8;j++, bit>>=1) { - crc = (crc << 1) ^ ((((crc<0?1:0) ^ bit) & 0x01) ? poly : 0); - } - } - hashcode = (crc & 1); /* hashcode is 6 LSb of CRC ... */ - for (j=0;j<5;j++) { /* ... in reverse order. */ - hashcode = (hashcode << 1) | ((crc>>=1) & 1); - } - - - byte = hashcode >> 3; /* bit[3-5] -> byte in filter */ - bit = 1 << (hashcode & 0x07); /* bit[0-2] -> bit in byte */ - lp->init_block.mcast_table[byte] |= bit; - } - } - } - - return; -} - -/* -** ISA bus I/O device probe -*/ -static void isa_probe(struct device *dev, u_long ioaddr) -{ - int i = num_depcas, maxSlots; - s32 ports[] = DEPCA_IO_PORTS; - - if (!ioaddr && autoprobed) return ; /* Been here before ! */ - if (ioaddr > 0x400) return; /* EISA Address */ - if (i >= MAX_NUM_DEPCAS) return; /* Too many ISA adapters */ - - if (ioaddr == 0) { /* Autoprobing */ - maxSlots = MAX_NUM_DEPCAS; - } else { /* Probe a specific location */ - ports[i] = ioaddr; - maxSlots = i + 1; - } - - for (; (i<maxSlots) && (dev!=NULL) && ports[i]; i++) { - if (DevicePresent(ports[i]) == 0) { - if (check_region(ports[i], DEPCA_TOTAL_SIZE) == 0) { - if ((dev = alloc_device(dev, ports[i])) != NULL) { - if (depca_hw_init(dev, ports[i]) == 0) { - num_depcas++; - } - num_eth++; - } - } else if (autoprobed) { - printk("%s: region already allocated at 0x%04x.\n", dev->name,ports[i]); - } - } - } - - return; -} - -/* -** EISA bus I/O device probe. Probe from slot 1 since slot 0 is usually -** the motherboard. Upto 15 EISA devices are supported. -*/ -static void eisa_probe(struct device *dev, u_long ioaddr) -{ - int i, maxSlots; - u_long iobase; - char name[DEPCA_STRLEN]; - - if (!ioaddr && autoprobed) return ; /* Been here before ! */ - if ((ioaddr < 0x400) && (ioaddr > 0)) return; /* ISA Address */ - - if (ioaddr == 0) { /* Autoprobing */ - iobase = EISA_SLOT_INC; /* Get the first slot address */ - i = 1; - maxSlots = MAX_EISA_SLOTS; - } else { /* Probe a specific location */ - iobase = ioaddr; - i = (ioaddr >> 12); - maxSlots = i + 1; - } - if ((iobase & 0x0fff) == 0) iobase += DEPCA_EISA_IO_PORTS; - - for (; (i<maxSlots) && (dev!=NULL); i++, iobase+=EISA_SLOT_INC) { - if (EISA_signature(name, EISA_ID)) { - if (DevicePresent(iobase) == 0) { - if (check_region(iobase, DEPCA_TOTAL_SIZE) == 0) { - if ((dev = alloc_device(dev, iobase)) != NULL) { - if (depca_hw_init(dev, iobase) == 0) { - num_depcas++; - } - num_eth++; - } - } else if (autoprobed) { - printk("%s: region already allocated at 0x%04lx.\n",dev->name,iobase); - } - } - } - } - - return; -} - -/* -** Allocate the device by pointing to the next available space in the -** device structure. Should one not be available, it is created. -*/ -static struct device *alloc_device(struct device *dev, u_long iobase) -{ - int addAutoProbe = 0; - struct device *tmp = NULL, *ret; - int (*init)(struct device *) = NULL; - - /* - ** Check the device structures for an end of list or unused device - */ - if (!loading_module) { - while (dev->next != NULL) { - if ((dev->base_addr == DEPCA_NDA) || (dev->base_addr == 0)) break; - dev = dev->next; /* walk through eth device list */ - num_eth++; /* increment eth device number */ - } - - /* - ** If an autoprobe is requested for another device, we must re-insert - ** the request later in the list. Remember the current information. - */ - if ((dev->base_addr == 0) && (num_depcas > 0)) { - addAutoProbe++; - tmp = dev->next; /* point to the next device */ - init = dev->init; /* remember the probe function */ - } - - /* - ** If at end of list and can't use current entry, malloc one up. - ** If memory could not be allocated, print an error message. - */ - if ((dev->next == NULL) && - !((dev->base_addr == DEPCA_NDA) || (dev->base_addr == 0))){ - dev->next = (struct device *)kmalloc(sizeof(struct device) + 8, - GFP_KERNEL); - - dev = dev->next; /* point to the new device */ - if (dev == NULL) { - printk("eth%d: Device not initialised, insufficient memory\n", - num_eth); - } else { - /* - ** If the memory was allocated, point to the new memory area - ** and initialize it (name, I/O address, next device (NULL) and - ** initialisation probe routine). - */ - dev->name = (char *)(dev + sizeof(struct device)); - if (num_eth > 9999) { - sprintf(dev->name,"eth????"); /* New device name */ - } else { - sprintf(dev->name,"eth%d", num_eth);/* New device name */ - } - dev->base_addr = iobase; /* assign the io address */ - dev->next = NULL; /* mark the end of list */ - dev->init = &depca_probe; /* initialisation routine */ - num_depcas++; - } - } - ret = dev; /* return current struct, or NULL */ - - /* - ** Now figure out what to do with the autoprobe that has to be inserted. - ** Firstly, search the (possibly altered) list for an empty space. - */ - if (ret != NULL) { - if (addAutoProbe) { - for (;(tmp->next!=NULL) && (tmp->base_addr!=DEPCA_NDA); tmp=tmp->next); - - /* - ** If no more device structures and can't use the current one, malloc - ** one up. If memory could not be allocated, print an error message. - */ - if ((tmp->next == NULL) && !(tmp->base_addr == DEPCA_NDA)) { - tmp->next = (struct device *)kmalloc(sizeof(struct device) + 8, - GFP_KERNEL); - tmp = tmp->next; /* point to the new device */ - if (tmp == NULL) { - printk("%s: Insufficient memory to extend the device list.\n", - dev->name); - } else { - /* - ** If the memory was allocated, point to the new memory area - ** and initialize it (name, I/O address, next device (NULL) and - ** initialisation probe routine). - */ - tmp->name = (char *)(tmp + sizeof(struct device)); - if (num_eth > 9999) { - sprintf(tmp->name,"eth????"); /* New device name */ - } else { - sprintf(tmp->name,"eth%d", num_eth);/* New device name */ - } - tmp->base_addr = 0; /* re-insert the io address */ - tmp->next = NULL; /* mark the end of list */ - tmp->init = init; /* initialisation routine */ - } - } else { /* structure already exists */ - tmp->base_addr = 0; /* re-insert the io address */ - } - } - } - } else { - ret = dev; - } - - return ret; -} - -/* -** Look for a particular board name in the on-board Remote Diagnostics -** and Boot (readb) ROM. This will also give us a clue to the network RAM -** base address. -*/ -static void DepcaSignature(char *name, u_long paddr) -{ - u_int i,j,k; - const char *signatures[] = DEPCA_SIGNATURE; - char tmpstr[16]; - - for (i=0;i<16;i++) { /* copy the first 16 bytes of ROM to */ - tmpstr[i] = readb(paddr+0xc000+i); /* a temporary string */ - } - - strcpy(name,""); - for (i=0;*signatures[i]!='\0' && *name=='\0';i++) { - for (j=0,k=0;j<16 && k<strlen(signatures[i]);j++) { - if (signatures[i][k] == tmpstr[j]) { /* track signature */ - k++; - } else { /* lost signature; begin search again */ - k=0; - } - } - if (k == strlen(signatures[i])) { - strcpy(name,signatures[i]); - } - } - - adapter = i - 1; - - return; -} - -/* -** Look for a special sequence in the Ethernet station address PROM that -** is common across all DEPCA products. Note that the original DEPCA needs -** its ROM address counter to be initialized and enabled. Only enable -** if the first address octet is a 0x08 - this minimises the chances of -** messing around with some other hardware, but it assumes that this DEPCA -** card initialized itself correctly. -** -** Search the Ethernet address ROM for the signature. Since the ROM address -** counter can start at an arbitrary point, the search must include the entire -** probe sequence length plus the (length_of_the_signature - 1). -** Stop the search IMMEDIATELY after the signature is found so that the -** PROM address counter is correctly positioned at the start of the -** ethernet address for later read out. -*/ -static int DevicePresent(u_long ioaddr) -{ - union { - struct { - u32 a; - u32 b; - } llsig; - char Sig[sizeof(u32) << 1]; - } dev; - short sigLength=0; - s8 data; - s16 nicsr; - int i, j, status = 0; - - data = inb(DEPCA_PROM); /* clear counter on DEPCA */ - data = inb(DEPCA_PROM); /* read data */ - - if (data == 0x08) { /* Enable counter on DEPCA */ - nicsr = inb(DEPCA_NICSR); - nicsr |= AAC; - outb(nicsr, DEPCA_NICSR); - } - - dev.llsig.a = ETH_PROM_SIG; - dev.llsig.b = ETH_PROM_SIG; - sigLength = sizeof(u32) << 1; - - for (i=0,j=0;j<sigLength && i<PROBE_LENGTH+sigLength-1;i++) { - data = inb(DEPCA_PROM); - if (dev.Sig[j] == data) { /* track signature */ - j++; - } else { /* lost signature; begin search again */ - if (data == dev.Sig[0]) { /* rare case.... */ - j=1; - } else { - j=0; - } - } - } - - if (j!=sigLength) { - status = -ENODEV; /* search failed */ - } - - return status; -} - -/* -** The DE100 and DE101 PROM accesses were made non-standard for some bizarre -** reason: access the upper half of the PROM with x=0; access the lower half -** with x=1. -*/ -static int get_hw_addr(struct device *dev) -{ - u_long ioaddr = dev->base_addr; - int i, k, tmp, status = 0; - u_short j, x, chksum; - - x = (((adapter == de100) || (adapter == de101)) ? 1 : 0); - - for (i=0,k=0,j=0;j<3;j++) { - k <<= 1 ; - if (k > 0xffff) k-=0xffff; - - k += (u_char) (tmp = inb(DEPCA_PROM + x)); - dev->dev_addr[i++] = (u_char) tmp; - k += (u_short) ((tmp = inb(DEPCA_PROM + x)) << 8); - dev->dev_addr[i++] = (u_char) tmp; - - if (k > 0xffff) k-=0xffff; - } - if (k == 0xffff) k=0; - - chksum = (u_char) inb(DEPCA_PROM + x); - chksum |= (u_short) (inb(DEPCA_PROM + x) << 8); - if (k != chksum) status = -1; - - return status; -} - -/* -** Load a packet into the shared memory -*/ -static int load_packet(struct device *dev, struct sk_buff *skb) -{ - struct depca_private *lp = (struct depca_private *)dev->priv; - int i, entry, end, len, status = 0; - - entry = lp->tx_new; /* Ring around buffer number. */ - end = (entry + (skb->len - 1) / TX_BUFF_SZ) & lp->txRingMask; - if (!(readl(&lp->tx_ring[end].base) & T_OWN)) {/* Enough room? */ - /* - ** Caution: the write order is important here... don't set up the - ** ownership rights until all the other information is in place. - */ - if (end < entry) { /* wrapped buffer */ - len = (lp->txRingMask - entry + 1) * TX_BUFF_SZ; - memcpy_toio(lp->tx_memcpy[entry], skb->data, len); - memcpy_toio(lp->tx_memcpy[0], skb->data + len, skb->len - len); - } else { /* linear buffer */ - memcpy_toio(lp->tx_memcpy[entry], skb->data, skb->len); - } - - /* set up the buffer descriptors */ - len = (skb->len < ETH_ZLEN) ? ETH_ZLEN : skb->len; - for (i = entry; i != end; i = (++i) & lp->txRingMask) { - /* clean out flags */ - writel(readl(&lp->tx_ring[i].base) & ~T_FLAGS, &lp->tx_ring[i].base); - writew(0x0000, &lp->tx_ring[i].misc); /* clears other error flags */ - writew(-TX_BUFF_SZ, &lp->tx_ring[i].length);/* packet length in buffer */ - len -= TX_BUFF_SZ; - } - /* clean out flags */ - writel(readl(&lp->tx_ring[end].base) & ~T_FLAGS, &lp->tx_ring[end].base); - writew(0x0000, &lp->tx_ring[end].misc); /* clears other error flags */ - writew(-len, &lp->tx_ring[end].length); /* packet length in last buff */ - - /* start of packet */ - writel(readl(&lp->tx_ring[entry].base) | T_STP, &lp->tx_ring[entry].base); - /* end of packet */ - writel(readl(&lp->tx_ring[end].base) | T_ENP, &lp->tx_ring[end].base); - - for (i=end; i!=entry; --i) { - /* ownership of packet */ - writel(readl(&lp->tx_ring[i].base) | T_OWN, &lp->tx_ring[i].base); - if (i == 0) i=lp->txRingMask+1; - } - writel(readl(&lp->tx_ring[entry].base) | T_OWN, &lp->tx_ring[entry].base); - - lp->tx_new = (++end) & lp->txRingMask; /* update current pointers */ - } else { - status = -1; - } - - return status; -} - -/* -** Look for a particular board name in the EISA configuration space -*/ -static int EISA_signature(char *name, s32 eisa_id) -{ - u_int i; - const char *signatures[] = DEPCA_SIGNATURE; - char ManCode[DEPCA_STRLEN]; - union { - s32 ID; - char Id[4]; - } Eisa; - int status = 0; - - *name = '\0'; - Eisa.ID = inl(eisa_id); - - ManCode[0]=(((Eisa.Id[0]>>2)&0x1f)+0x40); - ManCode[1]=(((Eisa.Id[1]&0xe0)>>5)+((Eisa.Id[0]&0x03)<<3)+0x40); - ManCode[2]=(((Eisa.Id[2]>>4)&0x0f)+0x30); - ManCode[3]=(( Eisa.Id[2]&0x0f)+0x30); - ManCode[4]=(((Eisa.Id[3]>>4)&0x0f)+0x30); - ManCode[5]='\0'; - - for (i=0;(*signatures[i] != '\0') && (*name == '\0');i++) { - if (strstr(ManCode, signatures[i]) != NULL) { - strcpy(name,ManCode); - status = 1; - } - } - - return status; -} - -static void depca_dbg_open(struct device *dev) -{ - struct depca_private *lp = (struct depca_private *)dev->priv; - u_long ioaddr = dev->base_addr; - struct depca_init *p = (struct depca_init *)lp->sh_mem; - int i; - - if (depca_debug > 1){ - /* Copy the shadow init_block to shared memory */ - memcpy_toio((char *)lp->sh_mem,&lp->init_block,sizeof(struct depca_init)); - - printk("%s: depca open with irq %d\n",dev->name,dev->irq); - printk("Descriptor head addresses:\n"); - printk("\t0x%lx 0x%lx\n",(u_long)lp->rx_ring, (u_long)lp->tx_ring); - printk("Descriptor addresses:\nRX: "); - for (i=0;i<lp->rxRingMask;i++){ - if (i < 3) { - printk("0x%8.8lx ", (long) &lp->rx_ring[i].base); - } - } - printk("...0x%8.8lx\n", (long) &lp->rx_ring[i].base); - printk("TX: "); - for (i=0;i<lp->txRingMask;i++){ - if (i < 3) { - printk("0x%8.8lx ", (long) &lp->tx_ring[i].base); - } - } - printk("...0x%8.8lx\n", (long) &lp->tx_ring[i].base); - printk("\nDescriptor buffers:\nRX: "); - for (i=0;i<lp->rxRingMask;i++){ - if (i < 3) { - printk("0x%8.8x ", (u32) readl(&lp->rx_ring[i].base)); - } - } - printk("...0x%8.8x\n", (u32) readl(&lp->rx_ring[i].base)); - printk("TX: "); - for (i=0;i<lp->txRingMask;i++){ - if (i < 3) { - printk("0x%8.8x ", (u32) readl(&lp->tx_ring[i].base)); - } - } - printk("...0x%8.8x\n", (u32) readl(&lp->tx_ring[i].base)); - printk("Initialisation block at 0x%8.8lx\n",lp->sh_mem); - printk("\tmode: 0x%4.4x\n", (u16) readw(&p->mode)); - printk("\tphysical address: "); - for (i=0;i<ETH_ALEN-1;i++){ - printk("%2.2x:",(u_char)readb(&p->phys_addr[i])); - } - printk("%2.2x\n",(u_char)readb(&p->phys_addr[i])); - printk("\tmulticast hash table: "); - for (i=0;i<(HASH_TABLE_LEN >> 3)-1;i++){ - printk("%2.2x:",(u_char)readb(&p->mcast_table[i])); - } - printk("%2.2x\n",(u_char)readb(&p->mcast_table[i])); - printk("\trx_ring at: 0x%8.8x\n", (u32) readl(&p->rx_ring)); - printk("\ttx_ring at: 0x%8.8x\n", (u32) readl(&p->tx_ring)); - printk("dma_buffs: 0x%8.8lx\n",lp->dma_buffs); - printk("Ring size:\nRX: %d Log2(rxRingMask): 0x%8.8x\n", - (int)lp->rxRingMask + 1, - lp->rx_rlen); - printk("TX: %d Log2(txRingMask): 0x%8.8x\n", - (int)lp->txRingMask + 1, - lp->tx_rlen); - outw(CSR2,DEPCA_ADDR); - printk("CSR2&1: 0x%4.4x",inw(DEPCA_DATA)); - outw(CSR1,DEPCA_ADDR); - printk("%4.4x\n",inw(DEPCA_DATA)); - outw(CSR3,DEPCA_ADDR); - printk("CSR3: 0x%4.4x\n",inw(DEPCA_DATA)); - } - - return; -} - -/* -** Perform IOCTL call functions here. Some are privileged operations and the -** effective uid is checked in those cases. -** All MCA IOCTLs will not work here and are for testing purposes only. -*/ -static int depca_ioctl(struct device *dev, struct ifreq *rq, int cmd) -{ - struct depca_private *lp = (struct depca_private *)dev->priv; - struct depca_ioctl *ioc = (struct depca_ioctl *) &rq->ifr_data; - int i, status = 0; - u_long ioaddr = dev->base_addr; - union { - u8 addr[(HASH_TABLE_LEN * ETH_ALEN)]; - u16 sval[(HASH_TABLE_LEN * ETH_ALEN) >> 1]; - u32 lval[(HASH_TABLE_LEN * ETH_ALEN) >> 2]; - } tmp; - - switch(ioc->cmd) { - case DEPCA_GET_HWADDR: /* Get the hardware address */ - for (i=0; i<ETH_ALEN; i++) { - tmp.addr[i] = dev->dev_addr[i]; - } - ioc->len = ETH_ALEN; - if (!(status = verify_area(VERIFY_WRITE, (void *)ioc->data, ioc->len))) { - memcpy_tofs(ioc->data, tmp.addr, ioc->len); - } - - break; - case DEPCA_SET_HWADDR: /* Set the hardware address */ - if (suser()) { - if (!(status = verify_area(VERIFY_READ, (void *)ioc->data, ETH_ALEN))) { - memcpy_fromfs(tmp.addr,ioc->data,ETH_ALEN); - for (i=0; i<ETH_ALEN; i++) { - dev->dev_addr[i] = tmp.addr[i]; - } - while(dev->tbusy); /* Stop ring access */ - set_bit(0, (void*)&dev->tbusy); - while(lp->tx_old != lp->tx_new);/* Wait for the ring to empty */ - - STOP_DEPCA; /* Temporarily stop the depca. */ - depca_init_ring(dev); /* Initialize the descriptor rings */ - LoadCSRs(dev); /* Reload CSR3 */ - InitRestartDepca(dev); /* Resume normal operation. */ - dev->tbusy = 0; /* Unlock the TX ring */ - } - } else { - status = -EPERM; - } - - break; - case DEPCA_SET_PROM: /* Set Promiscuous Mode */ - if (suser()) { - while(dev->tbusy); /* Stop ring access */ - set_bit(0, (void*)&dev->tbusy); - while(lp->tx_old != lp->tx_new); /* Wait for the ring to empty */ - - STOP_DEPCA; /* Temporarily stop the depca. */ - depca_init_ring(dev); /* Initialize the descriptor rings */ - lp->init_block.mode |= PROM; /* Set promiscuous mode */ - - LoadCSRs(dev); /* Reload CSR3 */ - InitRestartDepca(dev); /* Resume normal operation. */ - dev->tbusy = 0; /* Unlock the TX ring */ - } else { - status = -EPERM; - } - - break; - case DEPCA_CLR_PROM: /* Clear Promiscuous Mode */ - if (suser()) { - while(dev->tbusy); /* Stop ring access */ - set_bit(0, (void*)&dev->tbusy); - while(lp->tx_old != lp->tx_new); /* Wait for the ring to empty */ - - STOP_DEPCA; /* Temporarily stop the depca. */ - depca_init_ring(dev); /* Initialize the descriptor rings */ - lp->init_block.mode &= ~PROM; /* Clear promiscuous mode */ - - LoadCSRs(dev); /* Reload CSR3 */ - InitRestartDepca(dev); /* Resume normal operation. */ - dev->tbusy = 0; /* Unlock the TX ring */ - } else { - status = -EPERM; - } - - break; - case DEPCA_SAY_BOO: /* Say "Boo!" to the kernel log file */ - printk("%s: Boo!\n", dev->name); - - break; - case DEPCA_GET_MCA: /* Get the multicast address table */ - ioc->len = (HASH_TABLE_LEN >> 3); - if (!(status = verify_area(VERIFY_WRITE, ioc->data, ioc->len))) { - memcpy_tofs(ioc->data, lp->init_block.mcast_table, ioc->len); - } - - break; - case DEPCA_SET_MCA: /* Set a multicast address */ - if (suser()) { - if (!(status=verify_area(VERIFY_READ, ioc->data, ETH_ALEN*ioc->len))) { - memcpy_fromfs(tmp.addr, ioc->data, ETH_ALEN * ioc->len); - set_multicast_list(dev); - } - } else { - status = -EPERM; - } - - break; - case DEPCA_CLR_MCA: /* Clear all multicast addresses */ - if (suser()) { - set_multicast_list(dev); - } else { - status = -EPERM; - } - - break; - case DEPCA_MCA_EN: /* Enable pass all multicast addressing */ - if (suser()) { - set_multicast_list(dev); - } else { - status = -EPERM; - } - - break; - case DEPCA_GET_STATS: /* Get the driver statistics */ - cli(); - ioc->len = sizeof(lp->pktStats); - if (!(status=verify_area(VERIFY_WRITE, ioc->data, ioc->len))) { - memcpy_tofs(ioc->data, &lp->pktStats, ioc->len); - } - sti(); - - break; - case DEPCA_CLR_STATS: /* Zero out the driver statistics */ - if (suser()) { - cli(); - memset(&lp->pktStats, 0, sizeof(lp->pktStats)); - sti(); - } else { - status = -EPERM; - } - - break; - case DEPCA_GET_REG: /* Get the DEPCA Registers */ - i=0; - tmp.sval[i++] = inw(DEPCA_NICSR); - outw(CSR0, DEPCA_ADDR); /* status register */ - tmp.sval[i++] = inw(DEPCA_DATA); - memcpy(&tmp.sval[i], &lp->init_block, sizeof(struct depca_init)); - ioc->len = i+sizeof(struct depca_init); - if (!(status=verify_area(VERIFY_WRITE, ioc->data, ioc->len))) { - memcpy_tofs(ioc->data, tmp.addr, ioc->len); - } - - break; - default: - status = -EOPNOTSUPP; - } - - return status; -} - -#ifdef MODULE -static char devicename[9] = { 0, }; -static struct device thisDepca = { - devicename, /* device name is inserted by /linux/drivers/net/net_init.c */ - 0, 0, 0, 0, - 0x200, 7, /* I/O address, IRQ */ - 0, 0, 0, NULL, depca_probe }; - -static int irq=7; /* EDIT THESE LINE FOR YOUR CONFIGURATION */ -static int io=0x200; /* Or use the irq= io= options to insmod */ - -/* See depca_probe() for autoprobe messages when a module */ -int -init_module(void) -{ - thisDepca.irq=irq; - thisDepca.base_addr=io; - - if (register_netdev(&thisDepca) != 0) - return -EIO; - - return 0; -} - -void -cleanup_module(void) -{ - release_region(thisDepca.base_addr, DEPCA_TOTAL_SIZE); - if (thisDepca.priv) { - kfree(thisDepca.priv); - thisDepca.priv = NULL; - } - thisDepca.irq=0; - - unregister_netdev(&thisDepca); -} -#endif /* MODULE */ - - -/* - * Local variables: - * kernel-compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O2 -m486 -c depca.c" - * - * module-compile-command: "gcc -D__KERNEL__ -DMODULE -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O2 -m486 -c depca.c" - * End: - */ diff --git a/i386/i386at/gpl/linux/net/depca.h b/i386/i386at/gpl/linux/net/depca.h deleted file mode 100644 index 012f7399..00000000 --- a/i386/i386at/gpl/linux/net/depca.h +++ /dev/null @@ -1,185 +0,0 @@ -/* - Written 1994 by David C. Davies. - - Copyright 1994 David C. Davies. This software may be used and distributed - according to the terms of the GNU Public License, incorporated herein by - reference. -*/ - -/* -** I/O addresses. Note that the 2k buffer option is not supported in -** this driver. -*/ -#define DEPCA_NICSR ioaddr+0x00 /* Network interface CSR */ -#define DEPCA_RBI ioaddr+0x02 /* RAM buffer index (2k buffer mode) */ -#define DEPCA_DATA ioaddr+0x04 /* LANCE registers' data port */ -#define DEPCA_ADDR ioaddr+0x06 /* LANCE registers' address port */ -#define DEPCA_HBASE ioaddr+0x08 /* EISA high memory base address reg. */ -#define DEPCA_PROM ioaddr+0x0c /* Ethernet address ROM data port */ -#define DEPCA_CNFG ioaddr+0x0c /* EISA Configuration port */ -#define DEPCA_RBSA ioaddr+0x0e /* RAM buffer starting address (2k buff.) */ - -/* -** These are LANCE registers addressable through DEPCA_ADDR -*/ -#define CSR0 0 -#define CSR1 1 -#define CSR2 2 -#define CSR3 3 - -/* -** NETWORK INTERFACE CSR (NI_CSR) bit definitions -*/ - -#define TO 0x0100 /* Time Out for remote boot */ -#define SHE 0x0080 /* SHadow memory Enable */ -#define BS 0x0040 /* Bank Select */ -#define BUF 0x0020 /* BUFfer size (1->32k, 0->64k) */ -#define RBE 0x0010 /* Remote Boot Enable (1->net boot) */ -#define AAC 0x0008 /* Address ROM Address Counter (1->enable) */ -#define _128KB 0x0008 /* 128kB Network RAM (1->enable) */ -#define IM 0x0004 /* Interrupt Mask (1->mask) */ -#define IEN 0x0002 /* Interrupt tristate ENable (1->enable) */ -#define LED 0x0001 /* LED control */ - -/* -** Control and Status Register 0 (CSR0) bit definitions -*/ - -#define ERR 0x8000 /* Error summary */ -#define BABL 0x4000 /* Babble transmitter timeout error */ -#define CERR 0x2000 /* Collision Error */ -#define MISS 0x1000 /* Missed packet */ -#define MERR 0x0800 /* Memory Error */ -#define RINT 0x0400 /* Receiver Interrupt */ -#define TINT 0x0200 /* Transmit Interrupt */ -#define IDON 0x0100 /* Initialization Done */ -#define INTR 0x0080 /* Interrupt Flag */ -#define INEA 0x0040 /* Interrupt Enable */ -#define RXON 0x0020 /* Receiver on */ -#define TXON 0x0010 /* Transmitter on */ -#define TDMD 0x0008 /* Transmit Demand */ -#define STOP 0x0004 /* Stop */ -#define STRT 0x0002 /* Start */ -#define INIT 0x0001 /* Initialize */ -#define INTM 0xff00 /* Interrupt Mask */ -#define INTE 0xfff0 /* Interrupt Enable */ - -/* -** CONTROL AND STATUS REGISTER 3 (CSR3) -*/ - -#define BSWP 0x0004 /* Byte SWaP */ -#define ACON 0x0002 /* ALE control */ -#define BCON 0x0001 /* Byte CONtrol */ - -/* -** Initialization Block Mode Register -*/ - -#define PROM 0x8000 /* Promiscuous Mode */ -#define EMBA 0x0080 /* Enable Modified Back-off Algorithm */ -#define INTL 0x0040 /* Internal Loopback */ -#define DRTY 0x0020 /* Disable Retry */ -#define COLL 0x0010 /* Force Collision */ -#define DTCR 0x0008 /* Disable Transmit CRC */ -#define LOOP 0x0004 /* Loopback */ -#define DTX 0x0002 /* Disable the Transmitter */ -#define DRX 0x0001 /* Disable the Receiver */ - -/* -** Receive Message Descriptor 1 (RMD1) bit definitions. -*/ - -#define R_OWN 0x80000000 /* Owner bit 0 = host, 1 = lance */ -#define R_ERR 0x4000 /* Error Summary */ -#define R_FRAM 0x2000 /* Framing Error */ -#define R_OFLO 0x1000 /* Overflow Error */ -#define R_CRC 0x0800 /* CRC Error */ -#define R_BUFF 0x0400 /* Buffer Error */ -#define R_STP 0x0200 /* Start of Packet */ -#define R_ENP 0x0100 /* End of Packet */ - -/* -** Transmit Message Descriptor 1 (TMD1) bit definitions. -*/ - -#define T_OWN 0x80000000 /* Owner bit 0 = host, 1 = lance */ -#define T_ERR 0x4000 /* Error Summary */ -#define T_ADD_FCS 0x2000 /* More the 1 retry needed to Xmit */ -#define T_MORE 0x1000 /* >1 retry to transmit packet */ -#define T_ONE 0x0800 /* 1 try needed to transmit the packet */ -#define T_DEF 0x0400 /* Deferred */ -#define T_STP 0x02000000 /* Start of Packet */ -#define T_ENP 0x01000000 /* End of Packet */ -#define T_FLAGS 0xff000000 /* TX Flags Field */ - -/* -** Transmit Message Descriptor 3 (TMD3) bit definitions. -*/ - -#define TMD3_BUFF 0x8000 /* BUFFer error */ -#define TMD3_UFLO 0x4000 /* UnderFLOw error */ -#define TMD3_RES 0x2000 /* REServed */ -#define TMD3_LCOL 0x1000 /* Late COLlision */ -#define TMD3_LCAR 0x0800 /* Loss of CARrier */ -#define TMD3_RTRY 0x0400 /* ReTRY error */ - -/* -** EISA configuration Register (CNFG) bit definitions -*/ - -#define TIMEOUT 0x0100 /* 0:2.5 mins, 1: 30 secs */ -#define REMOTE 0x0080 /* Remote Boot Enable -> 1 */ -#define IRQ11 0x0040 /* Enable -> 1 */ -#define IRQ10 0x0020 /* Enable -> 1 */ -#define IRQ9 0x0010 /* Enable -> 1 */ -#define IRQ5 0x0008 /* Enable -> 1 */ -#define BUFF 0x0004 /* 0: 64kB or 128kB, 1: 32kB */ -#define PADR16 0x0002 /* RAM on 64kB boundary */ -#define PADR17 0x0001 /* RAM on 128kB boundary */ - -/* -** Miscellaneous -*/ -#define HASH_TABLE_LEN 64 /* Bits */ -#define HASH_BITS 0x003f /* 6 LS bits */ - -#define MASK_INTERRUPTS 1 -#define UNMASK_INTERRUPTS 0 - -#define EISA_EN 0x0001 /* Enable EISA bus buffers */ -#define EISA_ID iobase+0x0080 /* ID long word for EISA card */ -#define EISA_CTRL iobase+0x0084 /* Control word for EISA card */ - -/* -** Include the IOCTL stuff -*/ -#include <linux/sockios.h> - -#define DEPCAIOCTL SIOCDEVPRIVATE - -struct depca_ioctl { - unsigned short cmd; /* Command to run */ - unsigned short len; /* Length of the data buffer */ - unsigned char *data; /* Pointer to the data buffer */ -}; - -/* -** Recognised commands for the driver -*/ -#define DEPCA_GET_HWADDR 0x01 /* Get the hardware address */ -#define DEPCA_SET_HWADDR 0x02 /* Get the hardware address */ -#define DEPCA_SET_PROM 0x03 /* Set Promiscuous Mode */ -#define DEPCA_CLR_PROM 0x04 /* Clear Promiscuous Mode */ -#define DEPCA_SAY_BOO 0x05 /* Say "Boo!" to the kernel log file */ -#define DEPCA_GET_MCA 0x06 /* Get a multicast address */ -#define DEPCA_SET_MCA 0x07 /* Set a multicast address */ -#define DEPCA_CLR_MCA 0x08 /* Clear a multicast address */ -#define DEPCA_MCA_EN 0x09 /* Enable a multicast address group */ -#define DEPCA_GET_STATS 0x0a /* Get the driver statistics */ -#define DEPCA_CLR_STATS 0x0b /* Zero out the driver statistics */ -#define DEPCA_GET_REG 0x0c /* Get the Register contents */ -#define DEPCA_SET_REG 0x0d /* Set the Register contents */ -#define DEPCA_DUMP 0x0f /* Dump the DEPCA Status */ - diff --git a/i386/i386at/gpl/linux/net/dev.c b/i386/i386at/gpl/linux/net/dev.c deleted file mode 100644 index 69d576ff..00000000 --- a/i386/i386at/gpl/linux/net/dev.c +++ /dev/null @@ -1,1413 +0,0 @@ -/* - * NET3 Protocol independent device support routines. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * Derived from the non IP parts of dev.c 1.0.19 - * Authors: Ross Biro, <bir7@leland.Stanford.Edu> - * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> - * Mark Evans, <evansmp@uhura.aston.ac.uk> - * - * Additional Authors: - * Florian la Roche <rzsfl@rz.uni-sb.de> - * Alan Cox <gw4pts@gw4pts.ampr.org> - * David Hinds <dhinds@allegro.stanford.edu> - * - * Changes: - * Alan Cox : device private ioctl copies fields back. - * Alan Cox : Transmit queue code does relevant stunts to - * keep the queue safe. - * Alan Cox : Fixed double lock. - * Alan Cox : Fixed promisc NULL pointer trap - * ???????? : Support the full private ioctl range - * Alan Cox : Moved ioctl permission check into drivers - * Tim Kordas : SIOCADDMULTI/SIOCDELMULTI - * Alan Cox : 100 backlog just doesn't cut it when - * you start doing multicast video 8) - * Alan Cox : Rewrote net_bh and list manager. - * Alan Cox : Fix ETH_P_ALL echoback lengths. - * Alan Cox : Took out transmit every packet pass - * Saved a few bytes in the ioctl handler - * Alan Cox : Network driver sets packet type before calling netif_rx. Saves - * a function call a packet. - * Alan Cox : Hashed net_bh() - * Richard Kooijman: Timestamp fixes. - * Alan Cox : Wrong field in SIOCGIFDSTADDR - * Alan Cox : Device lock protection. - * Alan Cox : Fixed nasty side effect of device close changes. - * Rudi Cilibrasi : Pass the right thing to set_mac_address() - * Dave Miller : 32bit quantity for the device lock to make it work out - * on a Sparc. - * Bjorn Ekwall : Added KERNELD hack. - * Alan Cox : Cleaned up the backlog initialise. - * Craig Metz : SIOCGIFCONF fix if space for under - * 1 device. - * - */ - -#include <asm/segment.h> -#include <asm/system.h> -#include <asm/bitops.h> -#include <linux/config.h> -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/string.h> -#include <linux/mm.h> -#include <linux/socket.h> -#include <linux/sockios.h> -#include <linux/in.h> -#include <linux/errno.h> -#include <linux/interrupt.h> -#include <linux/if_ether.h> -#include <linux/inet.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/notifier.h> -#include <net/ip.h> -#include <net/route.h> -#include <linux/skbuff.h> -#include <net/sock.h> -#include <net/arp.h> -#include <net/slhc.h> -#include <linux/proc_fs.h> -#include <linux/stat.h> -#ifdef CONFIG_NET_ALIAS -#include <linux/net_alias.h> -#endif -#ifdef CONFIG_KERNELD -#include <linux/kerneld.h> -#endif - -#ifndef MACH -/* - * The list of packet types we will receive (as opposed to discard) - * and the routines to invoke. - */ - -struct packet_type *ptype_base[16]; -struct packet_type *ptype_all = NULL; /* Taps */ - -/* - * Device list lock - */ - -int dev_lockct=0; - -/* - * Our notifier list - */ - -struct notifier_block *netdev_chain=NULL; - -/* - * Device drivers call our routines to queue packets here. We empty the - * queue in the bottom half handler. - */ - -static struct sk_buff_head backlog; - -/* - * We don't overdo the queue or we will thrash memory badly. - */ - -static int backlog_size = 0; - -/* - * Return the lesser of the two values. - */ - -static __inline__ unsigned long min(unsigned long a, unsigned long b) -{ - return (a < b)? a : b; -} - - -/****************************************************************************************** - - Protocol management and registration routines - -*******************************************************************************************/ - -/* - * For efficiency - */ - -static int dev_nit=0; - -/* - * Add a protocol ID to the list. Now that the input handler is - * smarter we can dispense with all the messy stuff that used to be - * here. - */ - -void dev_add_pack(struct packet_type *pt) -{ - int hash; - if(pt->type==htons(ETH_P_ALL)) - { - dev_nit++; - pt->next=ptype_all; - ptype_all=pt; - } - else - { - hash=ntohs(pt->type)&15; - pt->next = ptype_base[hash]; - ptype_base[hash] = pt; - } -} - - -/* - * Remove a protocol ID from the list. - */ - -void dev_remove_pack(struct packet_type *pt) -{ - struct packet_type **pt1; - if(pt->type==htons(ETH_P_ALL)) - { - dev_nit--; - pt1=&ptype_all; - } - else - pt1=&ptype_base[ntohs(pt->type)&15]; - for(; (*pt1)!=NULL; pt1=&((*pt1)->next)) - { - if(pt==(*pt1)) - { - *pt1=pt->next; - return; - } - } - printk("dev_remove_pack: %p not found.\n", pt); -} - -/***************************************************************************************** - - Device Interface Subroutines - -******************************************************************************************/ - -/* - * Find an interface by name. - */ - -struct device *dev_get(const char *name) -{ - struct device *dev; - - for (dev = dev_base; dev != NULL; dev = dev->next) - { - if (strcmp(dev->name, name) == 0) - return(dev); - } - return NULL; -} - -/* - * Find and possibly load an interface. - */ - -#ifdef CONFIG_KERNELD - -extern __inline__ void dev_load(const char *name) -{ - char *sptr; - - if(!dev_get(name)) { -#ifdef CONFIG_NET_ALIAS - for (sptr=name ; *sptr ; sptr++) if(*sptr==':') break; - if (!(*sptr && *(sptr+1))) -#endif - request_module(name); - } -} - -#endif - -/* - * Prepare an interface for use. - */ - -int dev_open(struct device *dev) -{ - int ret = 0; - - /* - * Call device private open method - */ - if (dev->open) - ret = dev->open(dev); - - /* - * If it went open OK then set the flags - */ - - if (ret == 0) - { - dev->flags |= (IFF_UP | IFF_RUNNING); - /* - * Initialise multicasting status - */ - dev_mc_upload(dev); - notifier_call_chain(&netdev_chain, NETDEV_UP, dev); - } - return(ret); -} - - -/* - * Completely shutdown an interface. - */ - -int dev_close(struct device *dev) -{ - int ct=0; - - /* - * Call the device specific close. This cannot fail. - * Only if device is UP - */ - - if ((dev->flags & IFF_UP) && dev->stop) - dev->stop(dev); - - /* - * Device is now down. - */ - - dev->flags&=~(IFF_UP|IFF_RUNNING); - - /* - * Tell people we are going down - */ - notifier_call_chain(&netdev_chain, NETDEV_DOWN, dev); - /* - * Flush the multicast chain - */ - dev_mc_discard(dev); - /* - * Blank the IP addresses - */ - dev->pa_addr = 0; - dev->pa_dstaddr = 0; - dev->pa_brdaddr = 0; - dev->pa_mask = 0; - /* - * Purge any queued packets when we down the link - */ - while(ct<DEV_NUMBUFFS) - { - struct sk_buff *skb; - while((skb=skb_dequeue(&dev->buffs[ct]))!=NULL) - if(skb->free) - kfree_skb(skb,FREE_WRITE); - ct++; - } - return(0); -} - - -/* - * Device change register/unregister. These are not inline or static - * as we export them to the world. - */ - -int register_netdevice_notifier(struct notifier_block *nb) -{ - return notifier_chain_register(&netdev_chain, nb); -} - -int unregister_netdevice_notifier(struct notifier_block *nb) -{ - return notifier_chain_unregister(&netdev_chain,nb); -} - -/* - * Send (or queue for sending) a packet. - * - * IMPORTANT: When this is called to resend frames. The caller MUST - * already have locked the sk_buff. Apart from that we do the - * rest of the magic. - */ - -void dev_queue_xmit(struct sk_buff *skb, struct device *dev, int pri) -{ - unsigned long flags; - struct sk_buff_head *list; - int retransmission = 0; /* used to say if the packet should go */ - /* at the front or the back of the */ - /* queue - front is a retransmit try */ - - if(pri>=0 && !skb_device_locked(skb)) - skb_device_lock(skb); /* Shove a lock on the frame */ -#if CONFIG_SKB_CHECK - IS_SKB(skb); -#endif - skb->dev = dev; - - /* - * Negative priority is used to flag a frame that is being pulled from the - * queue front as a retransmit attempt. It therefore goes back on the queue - * start on a failure. - */ - - if (pri < 0) - { - pri = -pri-1; - retransmission = 1; - } - -#ifdef CONFIG_NET_DEBUG - if (pri >= DEV_NUMBUFFS) - { - printk("bad priority in dev_queue_xmit.\n"); - pri = 1; - } -#endif - - /* - * If the address has not been resolved. Call the device header rebuilder. - * This can cover all protocols and technically not just ARP either. - */ - - if (!skb->arp && dev->rebuild_header(skb->data, dev, skb->raddr, skb)) { - return; - } - - /* - * - * If dev is an alias, switch to its main device. - * "arp" resolution has been made with alias device, so - * arp entries refer to alias, not main. - * - */ - -#ifdef CONFIG_NET_ALIAS - if (net_alias_is(dev)) - skb->dev = dev = net_alias_main_dev(dev); -#endif - list = dev->buffs + pri; - - save_flags(flags); - /* if this isn't a retransmission, use the first packet instead... */ - if (!retransmission) { - if (skb_queue_len(list)) { - /* avoid overrunning the device queue.. */ - if (skb_queue_len(list) > dev->tx_queue_len) { - dev_kfree_skb(skb, FREE_WRITE); - return; - } - cli(); - skb_device_unlock(skb); /* Buffer is on the device queue and can be freed safely */ - __skb_queue_tail(list, skb); - skb = __skb_dequeue(list); - skb_device_lock(skb); /* New buffer needs locking down */ - restore_flags(flags); - } - - /* copy outgoing packets to any sniffer packet handlers */ - if (dev_nit) { - struct packet_type *ptype; - skb->stamp=xtime; - for (ptype = ptype_all; ptype!=NULL; ptype = ptype->next) - { - /* Never send packets back to the socket - * they originated from - MvS (miquels@drinkel.ow.org) - */ - if ((ptype->dev == dev || !ptype->dev) && - ((struct sock *)ptype->data != skb->sk)) - { - struct sk_buff *skb2; - if ((skb2 = skb_clone(skb, GFP_ATOMIC)) == NULL) - break; - skb2->h.raw = skb2->data + dev->hard_header_len; - skb2->mac.raw = skb2->data; - ptype->func(skb2, skb->dev, ptype); - } - } - } - } - start_bh_atomic(); - if (dev->hard_start_xmit(skb, dev) == 0) { - /* - * Packet is now solely the responsibility of the driver - */ - end_bh_atomic(); - return; - } - end_bh_atomic(); - - /* - * Transmission failed, put skb back into a list. Once on the list it's safe and - * no longer device locked (it can be freed safely from the device queue) - */ - cli(); - skb_device_unlock(skb); - __skb_queue_head(list,skb); - restore_flags(flags); -} - -/* - * Receive a packet from a device driver and queue it for the upper - * (protocol) levels. It always succeeds. This is the recommended - * interface to use. - */ - -void netif_rx(struct sk_buff *skb) -{ - static int dropping = 0; - - /* - * Any received buffers are un-owned and should be discarded - * when freed. These will be updated later as the frames get - * owners. - */ - - skb->sk = NULL; - skb->free = 1; - if(skb->stamp.tv_sec==0) - skb->stamp = xtime; - - /* - * Check that we aren't overdoing things. - */ - - if (!backlog_size) - dropping = 0; - else if (backlog_size > 300) - dropping = 1; - - if (dropping) - { - kfree_skb(skb, FREE_READ); - return; - } - - /* - * Add it to the "backlog" queue. - */ -#if CONFIG_SKB_CHECK - IS_SKB(skb); -#endif - skb_queue_tail(&backlog,skb); - backlog_size++; - - /* - * If any packet arrived, mark it for processing after the - * hardware interrupt returns. - */ - -#ifdef CONFIG_NET_RUNONIRQ /* Dont enable yet, needs some driver mods */ - net_bh(); -#else - mark_bh(NET_BH); -#endif - return; -} - -/* - * This routine causes all interfaces to try to send some data. - */ - -void dev_transmit(void) -{ - struct device *dev; - - for (dev = dev_base; dev != NULL; dev = dev->next) - { - if (dev->flags != 0 && !dev->tbusy) { - /* - * Kick the device - */ - dev_tint(dev); - } - } -} - - -/********************************************************************************** - - Receive Queue Processor - -***********************************************************************************/ - -/* - * This is a single non-reentrant routine which takes the received packet - * queue and throws it at the networking layers in the hope that something - * useful will emerge. - */ - -volatile unsigned long in_bh = 0; /* Non-reentrant remember */ - -int in_net_bh() /* Used by timer.c */ -{ - return(in_bh==0?0:1); -} - -/* - * When we are called the queue is ready to grab, the interrupts are - * on and hardware can interrupt and queue to the receive queue a we - * run with no problems. - * This is run as a bottom half after an interrupt handler that does - * mark_bh(NET_BH); - */ - -void net_bh(void *tmp) -{ - struct sk_buff *skb; - struct packet_type *ptype; - struct packet_type *pt_prev; - unsigned short type; - - /* - * Atomically check and mark our BUSY state. - */ - - if (set_bit(1, (void*)&in_bh)) - return; - - /* - * Can we send anything now? We want to clear the - * decks for any more sends that get done as we - * process the input. This also minimises the - * latency on a transmit interrupt bh. - */ - - dev_transmit(); - - /* - * Any data left to process. This may occur because a - * mark_bh() is done after we empty the queue including - * that from the device which does a mark_bh() just after - */ - - cli(); - - /* - * While the queue is not empty - */ - - while((skb=__skb_dequeue(&backlog))!=NULL) - { - /* - * We have a packet. Therefore the queue has shrunk - */ - backlog_size--; - - sti(); - - /* - * Bump the pointer to the next structure. - * - * On entry to the protocol layer. skb->data and - * skb->h.raw point to the MAC and encapsulated data - */ - - skb->h.raw = skb->data; - - /* - * Fetch the packet protocol ID. - */ - - type = skb->protocol; - - /* - * We got a packet ID. Now loop over the "known protocols" - * list. There are two lists. The ptype_all list of taps (normally empty) - * and the main protocol list which is hashed perfectly for normal protocols. - */ - pt_prev = NULL; - for (ptype = ptype_all; ptype!=NULL; ptype=ptype->next) - { - if(pt_prev) - { - struct sk_buff *skb2=skb_clone(skb, GFP_ATOMIC); - if(skb2) - pt_prev->func(skb2,skb->dev, pt_prev); - } - pt_prev=ptype; - } - - for (ptype = ptype_base[ntohs(type)&15]; ptype != NULL; ptype = ptype->next) - { - if (ptype->type == type && (!ptype->dev || ptype->dev==skb->dev)) - { - /* - * We already have a match queued. Deliver - * to it and then remember the new match - */ - if(pt_prev) - { - struct sk_buff *skb2; - - skb2=skb_clone(skb, GFP_ATOMIC); - - /* - * Kick the protocol handler. This should be fast - * and efficient code. - */ - - if(skb2) - pt_prev->func(skb2, skb->dev, pt_prev); - } - /* Remember the current last to do */ - pt_prev=ptype; - } - } /* End of protocol list loop */ - - /* - * Is there a last item to send to ? - */ - - if(pt_prev) - pt_prev->func(skb, skb->dev, pt_prev); - /* - * Has an unknown packet has been received ? - */ - - else - kfree_skb(skb, FREE_WRITE); - - /* - * Again, see if we can transmit anything now. - * [Ought to take this out judging by tests it slows - * us down not speeds us up] - */ -#ifdef XMIT_EVERY - dev_transmit(); -#endif - cli(); - } /* End of queue loop */ - - /* - * We have emptied the queue - */ - - in_bh = 0; - sti(); - - /* - * One last output flush. - */ - -#ifdef XMIT_AFTER - dev_transmit(); -#endif -} - - -/* - * This routine is called when an device driver (i.e. an - * interface) is ready to transmit a packet. - */ - -void dev_tint(struct device *dev) -{ - int i; - unsigned long flags; - struct sk_buff_head * head; - - /* - * aliases do not transmit (for now :) ) - */ - -#ifdef CONFIG_NET_ALIAS - if (net_alias_is(dev)) return; -#endif - head = dev->buffs; - save_flags(flags); - cli(); - - /* - * Work the queues in priority order - */ - for(i = 0;i < DEV_NUMBUFFS; i++,head++) - { - struct sk_buff *skb = skb_peek(head); - - if (skb) { - __skb_unlink(skb, head); - /* - * Stop anyone freeing the buffer while we retransmit it - */ - skb_device_lock(skb); - restore_flags(flags); - /* - * Feed them to the output stage and if it fails - * indicate they re-queue at the front. - */ - dev_queue_xmit(skb,dev,-i - 1); - /* - * If we can take no more then stop here. - */ - if (dev->tbusy) - return; - cli(); - } - } - restore_flags(flags); -} - - -/* - * Perform a SIOCGIFCONF call. This structure will change - * size shortly, and there is nothing I can do about it. - * Thus we will need a 'compatibility mode'. - */ - -static int dev_ifconf(char *arg) -{ - struct ifconf ifc; - struct ifreq ifr; - struct device *dev; - char *pos; - int len; - int err; - - /* - * Fetch the caller's info block. - */ - - err=verify_area(VERIFY_WRITE, arg, sizeof(struct ifconf)); - if(err) - return err; - memcpy_fromfs(&ifc, arg, sizeof(struct ifconf)); - len = ifc.ifc_len; - pos = ifc.ifc_buf; - - /* - * We now walk the device list filling each active device - * into the array. - */ - - err=verify_area(VERIFY_WRITE,pos,len); - if(err) - return err; - - /* - * Loop over the interfaces, and write an info block for each. - */ - - for (dev = dev_base; dev != NULL; dev = dev->next) - { - if(!(dev->flags & IFF_UP)) /* Downed devices don't count */ - continue; - /* - * Have we run out of space here ? - */ - - if (len < sizeof(struct ifreq)) - break; - - memset(&ifr, 0, sizeof(struct ifreq)); - strcpy(ifr.ifr_name, dev->name); - (*(struct sockaddr_in *) &ifr.ifr_addr).sin_family = dev->family; - (*(struct sockaddr_in *) &ifr.ifr_addr).sin_addr.s_addr = dev->pa_addr; - - - /* - * Write this block to the caller's space. - */ - - memcpy_tofs(pos, &ifr, sizeof(struct ifreq)); - pos += sizeof(struct ifreq); - len -= sizeof(struct ifreq); - } - - /* - * All done. Write the updated control block back to the caller. - */ - - ifc.ifc_len = (pos - ifc.ifc_buf); - ifc.ifc_req = (struct ifreq *) ifc.ifc_buf; - memcpy_tofs(arg, &ifc, sizeof(struct ifconf)); - - /* - * Report how much was filled in - */ - - return(pos - arg); -} - - -/* - * This is invoked by the /proc filesystem handler to display a device - * in detail. - */ - -#ifdef CONFIG_PROC_FS -static int sprintf_stats(char *buffer, struct device *dev) -{ - struct enet_statistics *stats = (dev->get_stats ? dev->get_stats(dev): NULL); - int size; - - if (stats) - size = sprintf(buffer, "%6s:%7d %4d %4d %4d %4d %8d %4d %4d %4d %5d %4d\n", - dev->name, - stats->rx_packets, stats->rx_errors, - stats->rx_dropped + stats->rx_missed_errors, - stats->rx_fifo_errors, - stats->rx_length_errors + stats->rx_over_errors - + stats->rx_crc_errors + stats->rx_frame_errors, - stats->tx_packets, stats->tx_errors, stats->tx_dropped, - stats->tx_fifo_errors, stats->collisions, - stats->tx_carrier_errors + stats->tx_aborted_errors - + stats->tx_window_errors + stats->tx_heartbeat_errors); - else - size = sprintf(buffer, "%6s: No statistics available.\n", dev->name); - - return size; -} - -/* - * Called from the PROCfs module. This now uses the new arbitrary sized /proc/net interface - * to create /proc/net/dev - */ - -int dev_get_info(char *buffer, char **start, off_t offset, int length, int dummy) -{ - int len=0; - off_t begin=0; - off_t pos=0; - int size; - - struct device *dev; - - - size = sprintf(buffer, "Inter-| Receive | Transmit\n" - " face |packets errs drop fifo frame|packets errs drop fifo colls carrier\n"); - - pos+=size; - len+=size; - - - for (dev = dev_base; dev != NULL; dev = dev->next) - { - size = sprintf_stats(buffer+len, dev); - len+=size; - pos=begin+len; - - if(pos<offset) - { - len=0; - begin=pos; - } - if(pos>offset+length) - break; - } - - *start=buffer+(offset-begin); /* Start of wanted data */ - len-=(offset-begin); /* Start slop */ - if(len>length) - len=length; /* Ending slop */ - return len; -} -#endif /* CONFIG_PROC_FS */ - - -/* - * This checks bitmasks for the ioctl calls for devices. - */ - -static inline int bad_mask(unsigned long mask, unsigned long addr) -{ - if (addr & (mask = ~mask)) - return 1; - mask = ntohl(mask); - if (mask & (mask+1)) - return 1; - return 0; -} - -/* - * Perform the SIOCxIFxxx calls. - * - * The socket layer has seen an ioctl the address family thinks is - * for the device. At this point we get invoked to make a decision - */ - -static int dev_ifsioc(void *arg, unsigned int getset) -{ - struct ifreq ifr; - struct device *dev; - int ret; - - /* - * Fetch the caller's info block into kernel space - */ - - int err=verify_area(VERIFY_WRITE, arg, sizeof(struct ifreq)); - if(err) - return err; - - memcpy_fromfs(&ifr, arg, sizeof(struct ifreq)); - - /* - * See which interface the caller is talking about. - */ - - /* - * - * net_alias_dev_get(): dev_get() with added alias naming magic. - * only allow alias creation/deletion if (getset==SIOCSIFADDR) - * - */ - -#ifdef CONFIG_KERNELD - dev_load(ifr.ifr_name); -#endif - -#ifdef CONFIG_NET_ALIAS - if ((dev = net_alias_dev_get(ifr.ifr_name, getset == SIOCSIFADDR, &err, NULL, NULL)) == NULL) - return(err); -#else - if ((dev = dev_get(ifr.ifr_name)) == NULL) - return(-ENODEV); -#endif - switch(getset) - { - case SIOCGIFFLAGS: /* Get interface flags */ - ifr.ifr_flags = dev->flags; - goto rarok; - - case SIOCSIFFLAGS: /* Set interface flags */ - { - int old_flags = dev->flags; - - /* - * We are not allowed to potentially close/unload - * a device until we get this lock. - */ - - dev_lock_wait(); - - /* - * Set the flags on our device. - */ - - dev->flags = (ifr.ifr_flags & ( - IFF_BROADCAST | IFF_DEBUG | IFF_LOOPBACK | - IFF_POINTOPOINT | IFF_NOTRAILERS | IFF_RUNNING | - IFF_NOARP | IFF_PROMISC | IFF_ALLMULTI | IFF_SLAVE | IFF_MASTER - | IFF_MULTICAST)) | (dev->flags & IFF_UP); - /* - * Load in the correct multicast list now the flags have changed. - */ - - dev_mc_upload(dev); - - /* - * Have we downed the interface. We handle IFF_UP ourselves - * according to user attempts to set it, rather than blindly - * setting it. - */ - - if ((old_flags^ifr.ifr_flags)&IFF_UP) /* Bit is different ? */ - { - if(old_flags&IFF_UP) /* Gone down */ - ret=dev_close(dev); - else /* Come up */ - { - ret=dev_open(dev); - if(ret<0) - dev->flags&=~IFF_UP; /* Open failed */ - } - } - else - ret=0; - /* - * Load in the correct multicast list now the flags have changed. - */ - - dev_mc_upload(dev); - } - break; - - case SIOCGIFADDR: /* Get interface address (and family) */ - if(ifr.ifr_addr.sa_family==AF_UNSPEC) - { - memcpy(ifr.ifr_hwaddr.sa_data,dev->dev_addr, MAX_ADDR_LEN); - ifr.ifr_hwaddr.sa_family=dev->type; - goto rarok; - } - else - { - (*(struct sockaddr_in *) - &ifr.ifr_addr).sin_addr.s_addr = dev->pa_addr; - (*(struct sockaddr_in *) - &ifr.ifr_addr).sin_family = dev->family; - (*(struct sockaddr_in *) - &ifr.ifr_addr).sin_port = 0; - } - goto rarok; - - case SIOCSIFADDR: /* Set interface address (and family) */ - - /* - * BSDism. SIOCSIFADDR family=AF_UNSPEC sets the - * physical address. We can cope with this now. - */ - - if(ifr.ifr_addr.sa_family==AF_UNSPEC) - { - if(dev->set_mac_address==NULL) - return -EOPNOTSUPP; - ret=dev->set_mac_address(dev,&ifr.ifr_addr); - } - else - { - - /* - * if dev is an alias, must rehash to update - * address change - */ - -#ifdef CONFIG_NET_ALIAS - if (net_alias_is(dev)) - net_alias_dev_rehash(dev ,&ifr.ifr_addr); -#endif - dev->pa_addr = (*(struct sockaddr_in *) - &ifr.ifr_addr).sin_addr.s_addr; - dev->family = ifr.ifr_addr.sa_family; - -#ifdef CONFIG_INET - /* This is naughty. When net-032e comes out It wants moving into the net032 - code not the kernel. Till then it can sit here (SIGH) */ - dev->pa_mask = ip_get_mask(dev->pa_addr); -#endif - dev->pa_brdaddr = dev->pa_addr | ~dev->pa_mask; - ret = 0; - } - break; - - case SIOCGIFBRDADDR: /* Get the broadcast address */ - (*(struct sockaddr_in *) - &ifr.ifr_broadaddr).sin_addr.s_addr = dev->pa_brdaddr; - (*(struct sockaddr_in *) - &ifr.ifr_broadaddr).sin_family = dev->family; - (*(struct sockaddr_in *) - &ifr.ifr_broadaddr).sin_port = 0; - goto rarok; - - case SIOCSIFBRDADDR: /* Set the broadcast address */ - dev->pa_brdaddr = (*(struct sockaddr_in *) - &ifr.ifr_broadaddr).sin_addr.s_addr; - ret = 0; - break; - - case SIOCGIFDSTADDR: /* Get the destination address (for point-to-point links) */ - (*(struct sockaddr_in *) - &ifr.ifr_dstaddr).sin_addr.s_addr = dev->pa_dstaddr; - (*(struct sockaddr_in *) - &ifr.ifr_dstaddr).sin_family = dev->family; - (*(struct sockaddr_in *) - &ifr.ifr_dstaddr).sin_port = 0; - goto rarok; - - case SIOCSIFDSTADDR: /* Set the destination address (for point-to-point links) */ - dev->pa_dstaddr = (*(struct sockaddr_in *) - &ifr.ifr_dstaddr).sin_addr.s_addr; - ret = 0; - break; - - case SIOCGIFNETMASK: /* Get the netmask for the interface */ - (*(struct sockaddr_in *) - &ifr.ifr_netmask).sin_addr.s_addr = dev->pa_mask; - (*(struct sockaddr_in *) - &ifr.ifr_netmask).sin_family = dev->family; - (*(struct sockaddr_in *) - &ifr.ifr_netmask).sin_port = 0; - goto rarok; - - case SIOCSIFNETMASK: /* Set the netmask for the interface */ - { - unsigned long mask = (*(struct sockaddr_in *) - &ifr.ifr_netmask).sin_addr.s_addr; - ret = -EINVAL; - /* - * The mask we set must be legal. - */ - if (bad_mask(mask,0)) - break; - dev->pa_mask = mask; - ret = 0; - } - break; - - case SIOCGIFMETRIC: /* Get the metric on the interface (currently unused) */ - - ifr.ifr_metric = dev->metric; - goto rarok; - - case SIOCSIFMETRIC: /* Set the metric on the interface (currently unused) */ - dev->metric = ifr.ifr_metric; - ret=0; - break; - - case SIOCGIFMTU: /* Get the MTU of a device */ - ifr.ifr_mtu = dev->mtu; - goto rarok; - - case SIOCSIFMTU: /* Set the MTU of a device */ - - /* - * MTU must be positive. - */ - - if(ifr.ifr_mtu<68) - return -EINVAL; - dev->mtu = ifr.ifr_mtu; - ret = 0; - break; - - case SIOCGIFMEM: /* Get the per device memory space. We can add this but currently - do not support it */ - ret = -EINVAL; - break; - - case SIOCSIFMEM: /* Set the per device memory buffer space. Not applicable in our case */ - ret = -EINVAL; - break; - - case SIOCGIFHWADDR: - memcpy(ifr.ifr_hwaddr.sa_data,dev->dev_addr, MAX_ADDR_LEN); - ifr.ifr_hwaddr.sa_family=dev->type; - goto rarok; - - case SIOCSIFHWADDR: - if(dev->set_mac_address==NULL) - return -EOPNOTSUPP; - if(ifr.ifr_hwaddr.sa_family!=dev->type) - return -EINVAL; - ret=dev->set_mac_address(dev,&ifr.ifr_hwaddr); - break; - - case SIOCGIFMAP: - ifr.ifr_map.mem_start=dev->mem_start; - ifr.ifr_map.mem_end=dev->mem_end; - ifr.ifr_map.base_addr=dev->base_addr; - ifr.ifr_map.irq=dev->irq; - ifr.ifr_map.dma=dev->dma; - ifr.ifr_map.port=dev->if_port; - goto rarok; - - case SIOCSIFMAP: - if(dev->set_config==NULL) - return -EOPNOTSUPP; - return dev->set_config(dev,&ifr.ifr_map); - - case SIOCADDMULTI: - if(dev->set_multicast_list==NULL) - return -EINVAL; - if(ifr.ifr_hwaddr.sa_family!=AF_UNSPEC) - return -EINVAL; - dev_mc_add(dev,ifr.ifr_hwaddr.sa_data, dev->addr_len, 1); - return 0; - - case SIOCDELMULTI: - if(dev->set_multicast_list==NULL) - return -EINVAL; - if(ifr.ifr_hwaddr.sa_family!=AF_UNSPEC) - return -EINVAL; - dev_mc_delete(dev,ifr.ifr_hwaddr.sa_data,dev->addr_len, 1); - return 0; - /* - * Unknown or private ioctl - */ - - default: - if((getset >= SIOCDEVPRIVATE) && - (getset <= (SIOCDEVPRIVATE + 15))) { - if(dev->do_ioctl==NULL) - return -EOPNOTSUPP; - ret=dev->do_ioctl(dev, &ifr, getset); - memcpy_tofs(arg,&ifr,sizeof(struct ifreq)); - break; - } - - ret = -EINVAL; - } - return(ret); -/* - * The load of calls that return an ifreq and ok (saves memory). - */ -rarok: - memcpy_tofs(arg, &ifr, sizeof(struct ifreq)); - return 0; -} - - -/* - * This function handles all "interface"-type I/O control requests. The actual - * 'doing' part of this is dev_ifsioc above. - */ - -int dev_ioctl(unsigned int cmd, void *arg) -{ - switch(cmd) - { - case SIOCGIFCONF: - (void) dev_ifconf((char *) arg); - return 0; - - /* - * Ioctl calls that can be done by all. - */ - - case SIOCGIFFLAGS: - case SIOCGIFADDR: - case SIOCGIFDSTADDR: - case SIOCGIFBRDADDR: - case SIOCGIFNETMASK: - case SIOCGIFMETRIC: - case SIOCGIFMTU: - case SIOCGIFMEM: - case SIOCGIFHWADDR: - case SIOCSIFHWADDR: - case SIOCGIFSLAVE: - case SIOCGIFMAP: - return dev_ifsioc(arg, cmd); - - /* - * Ioctl calls requiring the power of a superuser - */ - - case SIOCSIFFLAGS: - case SIOCSIFADDR: - case SIOCSIFDSTADDR: - case SIOCSIFBRDADDR: - case SIOCSIFNETMASK: - case SIOCSIFMETRIC: - case SIOCSIFMTU: - case SIOCSIFMEM: - case SIOCSIFMAP: - case SIOCSIFSLAVE: - case SIOCADDMULTI: - case SIOCDELMULTI: - if (!suser()) - return -EPERM; - return dev_ifsioc(arg, cmd); - - case SIOCSIFLINK: - return -EINVAL; - - /* - * Unknown or private ioctl. - */ - - default: - if((cmd >= SIOCDEVPRIVATE) && - (cmd <= (SIOCDEVPRIVATE + 15))) { - return dev_ifsioc(arg, cmd); - } - return -EINVAL; - } -} -#endif /* ! MACH */ - -/* - * Initialize the DEV module. At boot time this walks the device list and - * unhooks any devices that fail to initialise (normally hardware not - * present) and leaves us with a valid list of present and active devices. - * - */ -extern int lance_init(void); -extern int pi_init(void); -extern int dec21040_init(void); - -int net_dev_init(void) -{ - struct device *dev, **dp; - -#ifndef MACH - /* - * Initialise the packet receive queue. - */ - - skb_queue_head_init(&backlog); -#endif - - /* - * This is VeryUgly(tm). - * - * Some devices want to be initialized eary.. - */ -#if defined(CONFIG_LANCE) - lance_init(); -#endif -#if defined(CONFIG_PI) - pi_init(); -#endif -#if defined(CONFIG_PT) - pt_init(); -#endif -#if defined(CONFIG_DEC_ELCP) - dec21040_init(); -#endif - /* - * SLHC if present needs attaching so other people see it - * even if not opened. - */ -#if (defined(CONFIG_SLIP_COMPRESSED) || defined(CONFIG_PPP)) && defined(CONFIG_SLHC_BUILTIN) - slhc_install(); -#endif - - /* - * Add the devices. - * If the call to dev->init fails, the dev is removed - * from the chain disconnecting the device until the - * next reboot. - */ - - dp = &dev_base; - while ((dev = *dp) != NULL) - { - int i; - for (i = 0; i < DEV_NUMBUFFS; i++) { - skb_queue_head_init(dev->buffs + i); - } - - if (dev->init && dev->init(dev)) - { - /* - * It failed to come up. Unhook it. - */ - *dp = dev->next; - } - else - { - dp = &dev->next; - } - } - -#ifdef CONFIG_PROC_FS - proc_net_register(&(struct proc_dir_entry) { - PROC_NET_DEV, 3, "dev", - S_IFREG | S_IRUGO, 1, 0, 0, - 0, &proc_net_inode_operations, - dev_get_info - }); -#endif - - /* - * Initialise net_alias engine - * - * - register net_alias device notifier - * - register proc entries: /proc/net/alias_types - * /proc/net/aliases - */ - -#ifdef CONFIG_NET_ALIAS - net_alias_init(); -#endif - - bh_base[NET_BH].routine = net_bh; - enable_bh(NET_BH); - return 0; -} diff --git a/i386/i386at/gpl/linux/net/e2100.c b/i386/i386at/gpl/linux/net/e2100.c deleted file mode 100644 index fb0f1de6..00000000 --- a/i386/i386at/gpl/linux/net/e2100.c +++ /dev/null @@ -1,456 +0,0 @@ -/* e2100.c: A Cabletron E2100 series ethernet driver for linux. */ -/* - Written 1993-1994 by Donald Becker. - - Copyright 1994 by Donald Becker. - Copyright 1993 United States Government as represented by the - Director, National Security Agency. This software may be used and - distributed according to the terms of the GNU Public License, - incorporated herein by reference. - - This is a driver for the Cabletron E2100 series ethercards. - - The Author may be reached as becker@cesdis.gsfc.nasa.gov, or - C/O Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771 - - The E2100 series ethercard is a fairly generic shared memory 8390 - implementation. The only unusual aspect is the way the shared memory - registers are set: first you do an inb() in what is normally the - station address region, and the low three bits of next outb() *address* - is used as the write value for that register. Either someone wasn't - too used to dem bit en bites, or they were trying to obfuscate the - programming interface. - - There is an additional complication when setting the window on the packet - buffer. You must first do a read into the packet buffer region with the - low 8 address bits the address setting the page for the start of the packet - buffer window, and then do the above operation. See mem_on() for details. - - One bug on the chip is that even a hard reset won't disable the memory - window, usually resulting in a hung machine if mem_off() isn't called. - If this happens, you must power down the machine for about 30 seconds. -*/ - -static const char *version = - "e2100.c:v1.01 7/21/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n"; - -#include <linux/module.h> - -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/errno.h> -#include <linux/string.h> -#include <linux/ioport.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> - -#include <asm/io.h> -#include <asm/system.h> - -#include "8390.h" - -static int e21_probe_list[] = {0x300, 0x280, 0x380, 0x220, 0}; - -/* Offsets from the base_addr. - Read from the ASIC register, and the low three bits of the next outb() - address is used to set the corresponding register. */ -#define E21_NIC_OFFSET 0 /* Offset to the 8390 NIC. */ -#define E21_ASIC 0x10 -#define E21_MEM_ENABLE 0x10 -#define E21_MEM_ON 0x05 /* Enable memory in 16 bit mode. */ -#define E21_MEM_ON_8 0x07 /* Enable memory in 8 bit mode. */ -#define E21_MEM_BASE 0x11 -#define E21_IRQ_LOW 0x12 /* The low three bits of the IRQ number. */ -#define E21_IRQ_HIGH 0x14 /* The high IRQ bit and media select ... */ -#define E21_MEDIA 0x14 /* (alias). */ -#define E21_ALT_IFPORT 0x02 /* Set to use the other (BNC,AUI) port. */ -#define E21_BIG_MEM 0x04 /* Use a bigger (64K) buffer (we don't) */ -#define E21_SAPROM 0x10 /* Offset to station address data. */ -#define E21_IO_EXTENT 0x20 - -extern inline void mem_on(short port, volatile char *mem_base, - unsigned char start_page ) -{ - /* This is a little weird: set the shared memory window by doing a - read. The low address bits specify the starting page. */ - mem_base[start_page]; - inb(port + E21_MEM_ENABLE); - outb(E21_MEM_ON, port + E21_MEM_ENABLE + E21_MEM_ON); -} - -extern inline void mem_off(short port) -{ - inb(port + E21_MEM_ENABLE); - outb(0x00, port + E21_MEM_ENABLE); -} - -/* In other drivers I put the TX pages first, but the E2100 window circuitry - is designed to have a 4K Tx region last. The windowing circuitry wraps the - window at 0x2fff->0x0000 so that the packets at e.g. 0x2f00 in the RX ring - appear contiguously in the window. */ -#define E21_RX_START_PG 0x00 /* First page of RX buffer */ -#define E21_RX_STOP_PG 0x30 /* Last page +1 of RX ring */ -#define E21_BIG_RX_STOP_PG 0xF0 /* Last page +1 of RX ring */ -#define E21_TX_START_PG E21_RX_STOP_PG /* First page of TX buffer */ - -int e2100_probe(struct device *dev); -int e21_probe1(struct device *dev, int ioaddr); - -static int e21_open(struct device *dev); -static void e21_reset_8390(struct device *dev); -static void e21_block_input(struct device *dev, int count, - struct sk_buff *skb, int ring_offset); -static void e21_block_output(struct device *dev, int count, - const unsigned char *buf, const start_page); -static void e21_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, - int ring_page); - -static int e21_close(struct device *dev); - - -/* Probe for the E2100 series ethercards. These cards have an 8390 at the - base address and the station address at both offset 0x10 and 0x18. I read - the station address from offset 0x18 to avoid the dataport of NE2000 - ethercards, and look for Ctron's unique ID (first three octets of the - station address). - */ - -int e2100_probe(struct device *dev) -{ - int *port; - int base_addr = dev->base_addr; - - if (base_addr > 0x1ff) /* Check a single specified location. */ - return e21_probe1(dev, base_addr); - else if (base_addr != 0) /* Don't probe at all. */ - return ENXIO; - - for (port = e21_probe_list; *port; port++) { - if (check_region(*port, E21_IO_EXTENT)) - continue; - if (e21_probe1(dev, *port) == 0) - return 0; - } - - return ENODEV; -} - -int e21_probe1(struct device *dev, int ioaddr) -{ - int i, status; - unsigned char *station_addr = dev->dev_addr; - static unsigned version_printed = 0; - - /* First check the station address for the Ctron prefix. */ - if (inb(ioaddr + E21_SAPROM + 0) != 0x00 - || inb(ioaddr + E21_SAPROM + 1) != 0x00 - || inb(ioaddr + E21_SAPROM + 2) != 0x1d) - return ENODEV; - - /* Verify by making certain that there is a 8390 at there. */ - outb(E8390_NODMA + E8390_STOP, ioaddr); - SLOW_DOWN_IO; - status = inb(ioaddr); - if (status != 0x21 && status != 0x23) - return ENODEV; - - /* Read the station address PROM. */ - for (i = 0; i < 6; i++) - station_addr[i] = inb(ioaddr + E21_SAPROM + i); - - inb(ioaddr + E21_MEDIA); /* Point to media selection. */ - outb(0, ioaddr + E21_ASIC); /* and disable the secondary interface. */ - - if (ei_debug && version_printed++ == 0) - printk(version); - - /* We should have a "dev" from Space.c or the static module table. */ - if (dev == NULL) { - printk("e2100.c: Passed a NULL device.\n"); - dev = init_etherdev(0, 0); - } - - printk("%s: E21** at %#3x,", dev->name, ioaddr); - for (i = 0; i < 6; i++) - printk(" %02X", station_addr[i]); - - if (dev->irq < 2) { - int irqlist[] = {15,11,10,12,5,9,3,4}, i; - for (i = 0; i < 8; i++) - if (request_irq (irqlist[i], NULL, 0, "bogus") != -EBUSY) { - dev->irq = irqlist[i]; - break; - } - if (i >= 8) { - printk(" unable to get IRQ %d.\n", dev->irq); - return EAGAIN; - } - } else if (dev->irq == 2) /* Fixup luser bogosity: IRQ2 is really IRQ9 */ - dev->irq = 9; - - /* Allocate dev->priv and fill in 8390 specific dev fields. */ - if (ethdev_init(dev)) { - printk (" unable to get memory for dev->priv.\n"); - return -ENOMEM; - } - - /* Grab the region so we can find a different board if IRQ select fails. */ - request_region(ioaddr, E21_IO_EXTENT, "e2100"); - - /* The 8390 is at the base address. */ - dev->base_addr = ioaddr; - - ei_status.name = "E2100"; - ei_status.word16 = 1; - ei_status.tx_start_page = E21_TX_START_PG; - ei_status.rx_start_page = E21_RX_START_PG; - ei_status.stop_page = E21_RX_STOP_PG; - ei_status.saved_irq = dev->irq; - - /* Check the media port used. The port can be passed in on the - low mem_end bits. */ - if (dev->mem_end & 15) - dev->if_port = dev->mem_end & 7; - else { - dev->if_port = 0; - inb(ioaddr + E21_MEDIA); /* Turn automatic media detection on. */ - for(i = 0; i < 6; i++) - if (station_addr[i] != inb(ioaddr + E21_SAPROM + 8 + i)) { - dev->if_port = 1; - break; - } - } - - /* Never map in the E21 shared memory unless you are actively using it. - Also, the shared memory has effective only one setting -- spread all - over the 128K region! */ - if (dev->mem_start == 0) - dev->mem_start = 0xd0000; - -#ifdef notdef - /* These values are unused. The E2100 has a 2K window into the packet - buffer. The window can be set to start on any page boundary. */ - dev->rmem_start = dev->mem_start + TX_PAGES*256; - dev->mem_end = dev->rmem_end = dev->mem_start + 2*1024; -#endif - - printk(", IRQ %d, %s media, memory @ %#lx.\n", dev->irq, - dev->if_port ? "secondary" : "primary", dev->mem_start); - - ei_status.reset_8390 = &e21_reset_8390; - ei_status.block_input = &e21_block_input; - ei_status.block_output = &e21_block_output; - ei_status.get_8390_hdr = &e21_get_8390_hdr; - dev->open = &e21_open; - dev->stop = &e21_close; - NS8390_init(dev, 0); - - return 0; -} - -static int -e21_open(struct device *dev) -{ - short ioaddr = dev->base_addr; - - if (request_irq(dev->irq, ei_interrupt, 0, "e2100")) { - return EBUSY; - } - irq2dev_map[dev->irq] = dev; - - /* Set the interrupt line and memory base on the hardware. */ - inb(ioaddr + E21_IRQ_LOW); - outb(0, ioaddr + E21_ASIC + (dev->irq & 7)); - inb(ioaddr + E21_IRQ_HIGH); /* High IRQ bit, and if_port. */ - outb(0, ioaddr + E21_ASIC + (dev->irq > 7 ? 1:0) - + (dev->if_port ? E21_ALT_IFPORT : 0)); - inb(ioaddr + E21_MEM_BASE); - outb(0, ioaddr + E21_ASIC + ((dev->mem_start >> 17) & 7)); - - ei_open(dev); - MOD_INC_USE_COUNT; - return 0; -} - -static void -e21_reset_8390(struct device *dev) -{ - short ioaddr = dev->base_addr; - - outb(0x01, ioaddr); - if (ei_debug > 1) printk("resetting the E2180x3 t=%ld...", jiffies); - ei_status.txing = 0; - - /* Set up the ASIC registers, just in case something changed them. */ - - if (ei_debug > 1) printk("reset done\n"); - return; -} - -/* Grab the 8390 specific header. We put the 2k window so the header page - appears at the start of the shared memory. */ - -static void -e21_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page) -{ - - short ioaddr = dev->base_addr; - char *shared_mem = (char *)dev->mem_start; - - mem_on(ioaddr, shared_mem, ring_page); - -#ifdef notdef - /* Officially this is what we are doing, but the readl() is faster */ - memcpy_fromio(hdr, shared_mem, sizeof(struct e8390_pkt_hdr)); -#else - ((unsigned int*)hdr)[0] = readl(shared_mem); -#endif - - /* Turn off memory access: we would need to reprogram the window anyway. */ - mem_off(ioaddr); - -} - -/* Block input and output are easy on shared memory ethercards. - The E21xx makes block_input() especially easy by wrapping the top - ring buffer to the bottom automatically. */ -static void -e21_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset) -{ - short ioaddr = dev->base_addr; - char *shared_mem = (char *)dev->mem_start; - - mem_on(ioaddr, shared_mem, (ring_offset>>8)); - - /* Packet is always in one chunk -- we can copy + cksum. */ - eth_io_copy_and_sum(skb, dev->mem_start + (ring_offset & 0xff), count, 0); - - mem_off(ioaddr); -} - -static void -e21_block_output(struct device *dev, int count, const unsigned char *buf, - int start_page) -{ - short ioaddr = dev->base_addr; - volatile char *shared_mem = (char *)dev->mem_start; - - /* Set the shared memory window start by doing a read, with the low address - bits specifying the starting page. */ - readb(shared_mem + start_page); - mem_on(ioaddr, shared_mem, start_page); - - memcpy_toio(shared_mem, buf, count); - mem_off(ioaddr); -} - -static int -e21_close(struct device *dev) -{ - short ioaddr = dev->base_addr; - - if (ei_debug > 1) - printk("%s: Shutting down ethercard.\n", dev->name); - - free_irq(dev->irq); - dev->irq = ei_status.saved_irq; - - /* Shut off the interrupt line and secondary interface. */ - inb(ioaddr + E21_IRQ_LOW); - outb(0, ioaddr + E21_ASIC); - inb(ioaddr + E21_IRQ_HIGH); /* High IRQ bit, and if_port. */ - outb(0, ioaddr + E21_ASIC); - - irq2dev_map[dev->irq] = NULL; - - ei_close(dev); - - /* Double-check that the memory has been turned off, because really - really bad things happen if it isn't. */ - mem_off(ioaddr); - - MOD_DEC_USE_COUNT; - - return 0; -} - -#ifdef HAVE_DEVLIST -struct netdev_entry e21_drv = -{"e21", e21_probe1, E21_IO_EXTENT, e21_probe_list}; -#endif - - -#ifdef MODULE -#define MAX_E21_CARDS 4 /* Max number of E21 cards per module */ -#define NAMELEN 8 /* # of chars for storing dev->name */ -static char namelist[NAMELEN * MAX_E21_CARDS] = { 0, }; -static struct device dev_e21[MAX_E21_CARDS] = { - { - NULL, /* assign a chunk of namelist[] below */ - 0, 0, 0, 0, - 0, 0, - 0, 0, 0, NULL, NULL - }, -}; - -static int io[MAX_E21_CARDS] = { 0, }; -static int irq[MAX_E21_CARDS] = { 0, }; -static int mem[MAX_E21_CARDS] = { 0, }; -static int xcvr[MAX_E21_CARDS] = { 0, }; /* choose int. or ext. xcvr */ - -/* This is set up so that only a single autoprobe takes place per call. -ISA device autoprobes on a running machine are not recommended. */ -int -init_module(void) -{ - int this_dev, found = 0; - - for (this_dev = 0; this_dev < MAX_E21_CARDS; this_dev++) { - struct device *dev = &dev_e21[this_dev]; - dev->name = namelist+(NAMELEN*this_dev); - dev->irq = irq[this_dev]; - dev->base_addr = io[this_dev]; - dev->mem_start = mem[this_dev]; - dev->mem_end = xcvr[this_dev]; /* low 4bits = xcvr sel. */ - dev->init = e2100_probe; - if (io[this_dev] == 0) { - if (this_dev != 0) break; /* only autoprobe 1st one */ - printk(KERN_NOTICE "e2100.c: Presently autoprobing (not recommended) for a single card.\n"); - } - if (register_netdev(dev) != 0) { - printk(KERN_WARNING "e2100.c: No E2100 card found (i/o = 0x%x).\n", io[this_dev]); - if (found != 0) return 0; /* Got at least one. */ - return -ENXIO; - } - found++; - } - - return 0; -} - -void -cleanup_module(void) -{ - int this_dev; - - for (this_dev = 0; this_dev < MAX_E21_CARDS; this_dev++) { - struct device *dev = &dev_e21[this_dev]; - if (dev->priv != NULL) { - /* NB: e21_close() handles free_irq + irq2dev map */ - kfree(dev->priv); - dev->priv = NULL; - release_region(dev->base_addr, E21_IO_EXTENT); - unregister_netdev(dev); - } - } -} -#endif /* MODULE */ - -/* - * Local variables: - * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c e2100.c" - * version-control: t - * tab-width: 4 - * kept-new-versions: 5 - * End: - */ diff --git a/i386/i386at/gpl/linux/net/eepro.c b/i386/i386at/gpl/linux/net/eepro.c deleted file mode 100644 index 2aa2bd14..00000000 --- a/i386/i386at/gpl/linux/net/eepro.c +++ /dev/null @@ -1,1169 +0,0 @@ -/* eepro.c: Intel EtherExpress Pro/10 device driver for Linux. */ -/* - Written 1994, 1995 by Bao C. Ha. - - Copyright (C) 1994, 1995 by Bao C. Ha. - - This software may be used and distributed - according to the terms of the GNU Public License, - incorporated herein by reference. - - The author may be reached at bao@saigon.async.com - or 418 Hastings Place, Martinez, GA 30907. - - Things remaining to do: - Better record keeping of errors. - Eliminate transmit interrupt to reduce overhead. - Implement "concurrent processing". I won't be doing it! - Allow changes to the partition of the transmit and receive - buffers, currently the ratio is 3:1 of receive to transmit - buffer ratio. - - Bugs: - - If you have a problem of not detecting the 82595 during a - reboot (warm reset), disable the FLASH memory should fix it. - This is a compatibility hardware problem. - - Versions: - - 0.07a Fix a stat report which counts every packet as a - heart-beat failure. (BCH, 6/3/95) - - 0.07 Modified to support all other 82595-based lan cards. - The IRQ vector of the EtherExpress Pro will be set - according to the value saved in the EEPROM. For other - cards, I will do autoirq_request() to grab the next - available interrupt vector. (BCH, 3/17/95) - - 0.06a,b Interim released. Minor changes in the comments and - print out format. (BCH, 3/9/95 and 3/14/95) - - 0.06 First stable release that I am comfortable with. (BCH, - 3/2/95) - - 0.05 Complete testing of multicast. (BCH, 2/23/95) - - 0.04 Adding multicast support. (BCH, 2/14/95) - - 0.03 First widely alpha release for public testing. - (BCH, 2/14/95) - -*/ - -static const char *version = - "eepro.c: v0.07a 6/5/95 Bao C. Ha (bao@saigon.async.com)\n"; - -#include <linux/module.h> - -/* - Sources: - - This driver wouldn't have been written without the availability - of the Crynwr's Lan595 driver source code. It helps me to - familiarize with the 82595 chipset while waiting for the Intel - documentation. I also learned how to detect the 82595 using - the packet driver's technique. - - This driver is written by cutting and pasting the skeleton.c driver - provided by Donald Becker. I also borrowed the EEPROM routine from - Donald Becker's 82586 driver. - - Datasheet for the Intel 82595. It provides just enough info that - the casual reader might think that it documents the i82595. - - The User Manual for the 82595. It provides a lot of the missing - information. - -*/ - -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/types.h> -#include <linux/fcntl.h> -#include <linux/interrupt.h> -#include <linux/ptrace.h> -#include <linux/ioport.h> -#include <linux/in.h> -#include <linux/malloc.h> -#include <linux/string.h> -#include <asm/system.h> -#include <asm/bitops.h> -#include <asm/io.h> -#include <asm/dma.h> -#include <linux/errno.h> - -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> - - -/* First, a few definitions that the brave might change. */ -/* A zero-terminated list of I/O addresses to be probed. */ -static unsigned int eepro_portlist[] = - { 0x200, 0x240, 0x280, 0x2C0, 0x300, 0x320, 0x340, 0x360, 0}; - -/* use 0 for production, 1 for verification, >2 for debug */ -#ifndef NET_DEBUG -#define NET_DEBUG 2 -#endif -static unsigned int net_debug = NET_DEBUG; - -/* The number of low I/O ports used by the ethercard. */ -#define EEPRO_IO_EXTENT 16 - -/* Information that need to be kept for each board. */ -struct eepro_local { - struct enet_statistics stats; - unsigned rx_start; - unsigned tx_start; /* start of the transmit chain */ - int tx_last; /* pointer to last packet in the transmit chain */ - unsigned tx_end; /* end of the transmit chain (plus 1) */ - int eepro; /* a flag, TRUE=1 for the EtherExpress Pro/10, - FALSE = 0 for other 82595-based lan cards. */ -}; - -/* The station (ethernet) address prefix, used for IDing the board. */ -#define SA_ADDR0 0x00 -#define SA_ADDR1 0xaa -#define SA_ADDR2 0x00 - -/* Index to functions, as function prototypes. */ - -extern int eepro_probe(struct device *dev); - -static int eepro_probe1(struct device *dev, short ioaddr); -static int eepro_open(struct device *dev); -static int eepro_send_packet(struct sk_buff *skb, struct device *dev); -static void eepro_interrupt(int irq, struct pt_regs *regs); -static void eepro_rx(struct device *dev); -static void eepro_transmit_interrupt(struct device *dev); -static int eepro_close(struct device *dev); -static struct enet_statistics *eepro_get_stats(struct device *dev); -static void set_multicast_list(struct device *dev); - -static int read_eeprom(int ioaddr, int location); -static void hardware_send_packet(struct device *dev, void *buf, short length); -static int eepro_grab_irq(struct device *dev); - -/* - Details of the i82595. - -You will need either the datasheet or the user manual to understand what -is going on here. The 82595 is very different from the 82586, 82593. - -The receive algorithm in eepro_rx() is just an implementation of the -RCV ring structure that the Intel 82595 imposes at the hardware level. -The receive buffer is set at 24K, and the transmit buffer is 8K. I -am assuming that the total buffer memory is 32K, which is true for the -Intel EtherExpress Pro/10. If it is less than that on a generic card, -the driver will be broken. - -The transmit algorithm in the hardware_send_packet() is similar to the -one in the eepro_rx(). The transmit buffer is a ring linked list. -I just queue the next available packet to the end of the list. In my -system, the 82595 is so fast that the list seems to always contain a -single packet. In other systems with faster computers and more congested -network traffics, the ring linked list should improve performance by -allowing up to 8K worth of packets to be queued. - -*/ -#define RAM_SIZE 0x8000 -#define RCV_HEADER 8 -#define RCV_RAM 0x6000 /* 24KB for RCV buffer */ -#define RCV_LOWER_LIMIT 0x00 /* 0x0000 */ -#define RCV_UPPER_LIMIT ((RCV_RAM - 2) >> 8) /* 0x5ffe */ -#define XMT_RAM (RAM_SIZE - RCV_RAM) /* 8KB for XMT buffer */ -#define XMT_LOWER_LIMIT (RCV_RAM >> 8) /* 0x6000 */ -#define XMT_UPPER_LIMIT ((RAM_SIZE - 2) >> 8) /* 0x7ffe */ -#define XMT_HEADER 8 - -#define RCV_DONE 0x0008 -#define RX_OK 0x2000 -#define RX_ERROR 0x0d81 - -#define TX_DONE_BIT 0x0080 -#define CHAIN_BIT 0x8000 -#define XMT_STATUS 0x02 -#define XMT_CHAIN 0x04 -#define XMT_COUNT 0x06 - -#define BANK0_SELECT 0x00 -#define BANK1_SELECT 0x40 -#define BANK2_SELECT 0x80 - -/* Bank 0 registers */ -#define COMMAND_REG 0x00 /* Register 0 */ -#define MC_SETUP 0x03 -#define XMT_CMD 0x04 -#define DIAGNOSE_CMD 0x07 -#define RCV_ENABLE_CMD 0x08 -#define RCV_DISABLE_CMD 0x0a -#define STOP_RCV_CMD 0x0b -#define RESET_CMD 0x0e -#define POWER_DOWN_CMD 0x18 -#define RESUME_XMT_CMD 0x1c -#define SEL_RESET_CMD 0x1e -#define STATUS_REG 0x01 /* Register 1 */ -#define RX_INT 0x02 -#define TX_INT 0x04 -#define EXEC_STATUS 0x30 -#define ID_REG 0x02 /* Register 2 */ -#define R_ROBIN_BITS 0xc0 /* round robin counter */ -#define ID_REG_MASK 0x2c -#define ID_REG_SIG 0x24 -#define AUTO_ENABLE 0x10 -#define INT_MASK_REG 0x03 /* Register 3 */ -#define RX_STOP_MASK 0x01 -#define RX_MASK 0x02 -#define TX_MASK 0x04 -#define EXEC_MASK 0x08 -#define ALL_MASK 0x0f -#define RCV_BAR 0x04 /* The following are word (16-bit) registers */ -#define RCV_STOP 0x06 -#define XMT_BAR 0x0a -#define HOST_ADDRESS_REG 0x0c -#define IO_PORT 0x0e - -/* Bank 1 registers */ -#define REG1 0x01 -#define WORD_WIDTH 0x02 -#define INT_ENABLE 0x80 -#define INT_NO_REG 0x02 -#define RCV_LOWER_LIMIT_REG 0x08 -#define RCV_UPPER_LIMIT_REG 0x09 -#define XMT_LOWER_LIMIT_REG 0x0a -#define XMT_UPPER_LIMIT_REG 0x0b - -/* Bank 2 registers */ -#define XMT_Chain_Int 0x20 /* Interrupt at the end of the transmit chain */ -#define XMT_Chain_ErrStop 0x40 /* Interrupt at the end of the chain even if there are errors */ -#define RCV_Discard_BadFrame 0x80 /* Throw bad frames away, and continue to receive others */ -#define REG2 0x02 -#define PRMSC_Mode 0x01 -#define Multi_IA 0x20 -#define REG3 0x03 -#define TPE_BIT 0x04 -#define BNC_BIT 0x20 - -#define I_ADD_REG0 0x04 -#define I_ADD_REG1 0x05 -#define I_ADD_REG2 0x06 -#define I_ADD_REG3 0x07 -#define I_ADD_REG4 0x08 -#define I_ADD_REG5 0x09 - -#define EEPROM_REG 0x0a -#define EESK 0x01 -#define EECS 0x02 -#define EEDI 0x04 -#define EEDO 0x08 - - -/* Check for a network adaptor of this type, and return '0' iff one exists. - If dev->base_addr == 0, probe all likely locations. - If dev->base_addr == 1, always return failure. - If dev->base_addr == 2, allocate space for the device and return success - (detachable devices only). - */ -#ifdef HAVE_DEVLIST -/* Support for a alternate probe manager, which will eliminate the - boilerplate below. */ -struct netdev_entry netcard_drv = -{"eepro", eepro_probe1, EEPRO_IO_EXTENT, eepro_portlist}; -#else -int -eepro_probe(struct device *dev) -{ - int i; - int base_addr = dev ? dev->base_addr : 0; - - if (base_addr > 0x1ff) /* Check a single specified location. */ - return eepro_probe1(dev, base_addr); - else if (base_addr != 0) /* Don't probe at all. */ - return ENXIO; - - for (i = 0; eepro_portlist[i]; i++) { - int ioaddr = eepro_portlist[i]; - if (check_region(ioaddr, EEPRO_IO_EXTENT)) - continue; - if (eepro_probe1(dev, ioaddr) == 0) - return 0; - } - - return ENODEV; -} -#endif - -/* This is the real probe routine. Linux has a history of friendly device - probes on the ISA bus. A good device probes avoids doing writes, and - verifies that the correct device exists and functions. */ - -int eepro_probe1(struct device *dev, short ioaddr) -{ - unsigned short station_addr[6], id, counter; - int i; - int eepro; /* a flag, TRUE=1 for the EtherExpress Pro/10, - FALSE = 0 for other 82595-based lan cards. */ - const char *ifmap[] = {"AUI", "10Base2", "10BaseT"}; - enum iftype { AUI=0, BNC=1, TPE=2 }; - - /* Now, we are going to check for the signature of the - ID_REG (register 2 of bank 0) */ - - if (((id=inb(ioaddr + ID_REG)) & ID_REG_MASK) == ID_REG_SIG) { - - /* We seem to have the 82595 signature, let's - play with its counter (last 2 bits of - register 2 of bank 0) to be sure. */ - - counter = (id & R_ROBIN_BITS); - if (((id=inb(ioaddr+ID_REG)) & R_ROBIN_BITS) == - (counter + 0x40)) { - - /* Yes, the 82595 has been found */ - - /* Now, get the ethernet hardware address from - the EEPROM */ - - station_addr[0] = read_eeprom(ioaddr, 2); - station_addr[1] = read_eeprom(ioaddr, 3); - station_addr[2] = read_eeprom(ioaddr, 4); - - /* Check the station address for the manufacturer's code */ - - if (station_addr[2] != 0x00aa || (station_addr[1] & 0xff00) != 0x0000) { - eepro = 0; - printk("%s: Intel 82595-based lan card at %#x,", - dev->name, ioaddr); - } - else { - eepro = 1; - printk("%s: Intel EtherExpress Pro/10 at %#x,", - dev->name, ioaddr); - } - - /* Fill in the 'dev' fields. */ - dev->base_addr = ioaddr; - - for (i=0; i < 6; i++) { - dev->dev_addr[i] = ((unsigned char *) station_addr)[5-i]; - printk("%c%02x", i ? ':' : ' ', dev->dev_addr[i]); - } - - outb(BANK2_SELECT, ioaddr); /* be CAREFUL, BANK 2 now */ - id = inb(ioaddr + REG3); - if (id & TPE_BIT) - dev->if_port = TPE; - else dev->if_port = BNC; - - if (dev->irq < 2 && eepro) { - i = read_eeprom(ioaddr, 1); - switch (i & 0x07) { - case 0: dev->irq = 9; break; - case 1: dev->irq = 3; break; - case 2: dev->irq = 5; break; - case 3: dev->irq = 10; break; - case 4: dev->irq = 11; break; - default: /* should never get here !!!!! */ - printk(" illegal interrupt vector stored in EEPROM.\n"); - return ENODEV; - } - } - else if (dev->irq == 2) - dev->irq = 9; - - if (dev->irq > 2) { - printk(", IRQ %d, %s.\n", dev->irq, - ifmap[dev->if_port]); - if (request_irq(dev->irq, &eepro_interrupt, 0, "eepro")) { - printk("%s: unable to get IRQ %d.\n", dev->name, dev->irq); - return -EAGAIN; - } - } - else printk(", %s.\n", ifmap[dev->if_port]); - - if ((dev->mem_start & 0xf) > 0) - net_debug = dev->mem_start & 7; - - if (net_debug > 3) { - i = read_eeprom(ioaddr, 5); - if (i & 0x2000) /* bit 13 of EEPROM word 5 */ - printk("%s: Concurrent Processing is enabled but not used!\n", - dev->name); - } - - if (net_debug) - printk(version); - - /* Grab the region so we can find another board if autoIRQ fails. */ - request_region(ioaddr, EEPRO_IO_EXTENT, "eepro"); - - /* Initialize the device structure */ - dev->priv = kmalloc(sizeof(struct eepro_local), GFP_KERNEL); - if (dev->priv == NULL) - return -ENOMEM; - memset(dev->priv, 0, sizeof(struct eepro_local)); - - dev->open = eepro_open; - dev->stop = eepro_close; - dev->hard_start_xmit = eepro_send_packet; - dev->get_stats = eepro_get_stats; - dev->set_multicast_list = &set_multicast_list; - - /* Fill in the fields of the device structure with - ethernet generic values */ - - ether_setup(dev); - - outb(RESET_CMD, ioaddr); /* RESET the 82595 */ - - return 0; - } - else return ENODEV; - } - else if (net_debug > 3) - printk ("EtherExpress Pro probed failed!\n"); - return ENODEV; -} - -/* Open/initialize the board. This is called (in the current kernel) - sometime after booting when the 'ifconfig' program is run. - - This routine should set everything up anew at each open, even - registers that "should" only need to be set once at boot, so that - there is non-reboot way to recover if something goes wrong. - */ - -static char irqrmap[] = {-1,-1,0,1,-1,2,-1,-1,-1,0,3,4,-1,-1,-1,-1}; -static int eepro_grab_irq(struct device *dev) -{ - int irqlist[] = { 5, 9, 10, 11, 4, 3, 0}; - int *irqp = irqlist, temp_reg, ioaddr = dev->base_addr; - - outb(BANK1_SELECT, ioaddr); /* be CAREFUL, BANK 1 now */ - - /* Enable the interrupt line. */ - temp_reg = inb(ioaddr + REG1); - outb(temp_reg | INT_ENABLE, ioaddr + REG1); - - outb(BANK0_SELECT, ioaddr); /* be CAREFUL, BANK 0 now */ - - /* clear all interrupts */ - outb(ALL_MASK, ioaddr + STATUS_REG); - /* Let EXEC event to interrupt */ - outb(ALL_MASK & ~(EXEC_MASK), ioaddr + INT_MASK_REG); - - do { - outb(BANK1_SELECT, ioaddr); /* be CAREFUL, BANK 1 now */ - - temp_reg = inb(ioaddr + INT_NO_REG); - outb((temp_reg & 0xf8) | irqrmap[*irqp], ioaddr + INT_NO_REG); - - outb(BANK0_SELECT, ioaddr); /* Switch back to Bank 0 */ - - if (request_irq (*irqp, NULL, 0, "bogus") != EBUSY) { - /* Twinkle the interrupt, and check if it's seen */ - autoirq_setup(0); - - outb(DIAGNOSE_CMD, ioaddr); /* RESET the 82595 */ - - if (*irqp == autoirq_report(2) && /* It's a good IRQ line */ - (request_irq(dev->irq = *irqp, &eepro_interrupt, 0, "eepro") == 0)) - break; - - /* clear all interrupts */ - outb(ALL_MASK, ioaddr + STATUS_REG); - } - } while (*++irqp); - - outb(BANK1_SELECT, ioaddr); /* Switch back to Bank 1 */ - - /* Disable the physical interrupt line. */ - temp_reg = inb(ioaddr + REG1); - outb(temp_reg & 0x7f, ioaddr + REG1); - - outb(BANK0_SELECT, ioaddr); /* Switch back to Bank 0 */ - - /* Mask all the interrupts. */ - outb(ALL_MASK, ioaddr + INT_MASK_REG); - - /* clear all interrupts */ - outb(ALL_MASK, ioaddr + STATUS_REG); - - return dev->irq; -} - -static int -eepro_open(struct device *dev) -{ - unsigned short temp_reg; - int i, ioaddr = dev->base_addr; - struct eepro_local *lp = (struct eepro_local *)dev->priv; - - if (net_debug > 3) - printk("eepro: entering eepro_open routine.\n"); - - if (dev->dev_addr[0] == SA_ADDR0 && - dev->dev_addr[1] == SA_ADDR1 && - dev->dev_addr[2] == SA_ADDR2) - lp->eepro = 1; /* Yes, an Intel EtherExpress Pro/10 */ - else lp->eepro = 0; /* No, it is a generic 82585 lan card */ - - /* Get the interrupt vector for the 82595 */ - if (dev->irq < 2 && eepro_grab_irq(dev) == 0) { - printk("%s: unable to get IRQ %d.\n", dev->name, dev->irq); - return -EAGAIN; - } - - if (irq2dev_map[dev->irq] != 0 - || (irq2dev_map[dev->irq] = dev) == 0) - return -EAGAIN; - - /* Initialize the 82595. */ - - outb(BANK2_SELECT, ioaddr); /* be CAREFUL, BANK 2 now */ - temp_reg = inb(ioaddr + EEPROM_REG); - if (temp_reg & 0x10) /* Check the TurnOff Enable bit */ - outb(temp_reg & 0xef, ioaddr + EEPROM_REG); - for (i=0; i < 6; i++) - outb(dev->dev_addr[i] , ioaddr + I_ADD_REG0 + i); - - temp_reg = inb(ioaddr + REG1); /* Setup Transmit Chaining */ - outb(temp_reg | XMT_Chain_Int | XMT_Chain_ErrStop /* and discard bad RCV frames */ - | RCV_Discard_BadFrame, ioaddr + REG1); - - temp_reg = inb(ioaddr + REG2); /* Match broadcast */ - outb(temp_reg | 0x14, ioaddr + REG2); - - temp_reg = inb(ioaddr + REG3); - outb(temp_reg & 0x3f, ioaddr + REG3); /* clear test mode */ - - /* Set the receiving mode */ - outb(BANK1_SELECT, ioaddr); /* be CAREFUL, BANK 1 now */ - - temp_reg = inb(ioaddr + INT_NO_REG); - outb((temp_reg & 0xf8) | irqrmap[dev->irq], ioaddr + INT_NO_REG); - - /* Initialize the RCV and XMT upper and lower limits */ - outb(RCV_LOWER_LIMIT, ioaddr + RCV_LOWER_LIMIT_REG); - outb(RCV_UPPER_LIMIT, ioaddr + RCV_UPPER_LIMIT_REG); - outb(XMT_LOWER_LIMIT, ioaddr + XMT_LOWER_LIMIT_REG); - outb(XMT_UPPER_LIMIT, ioaddr + XMT_UPPER_LIMIT_REG); - - /* Enable the interrupt line. */ - temp_reg = inb(ioaddr + REG1); - outb(temp_reg | INT_ENABLE, ioaddr + REG1); - - outb(BANK0_SELECT, ioaddr); /* Switch back to Bank 0 */ - - /* Let RX and TX events to interrupt */ - outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG); - /* clear all interrupts */ - outb(ALL_MASK, ioaddr + STATUS_REG); - - /* Initialize RCV */ - outw(RCV_LOWER_LIMIT << 8, ioaddr + RCV_BAR); - lp->rx_start = (RCV_LOWER_LIMIT << 8) ; - outw((RCV_UPPER_LIMIT << 8) | 0xfe, ioaddr + RCV_STOP); - - /* Initialize XMT */ - outw(XMT_LOWER_LIMIT << 8, ioaddr + XMT_BAR); - - outb(SEL_RESET_CMD, ioaddr); - /* We are supposed to wait for 2 us after a SEL_RESET */ - SLOW_DOWN_IO; - SLOW_DOWN_IO; - - lp->tx_start = lp->tx_end = XMT_LOWER_LIMIT << 8; /* or = RCV_RAM */ - lp->tx_last = 0; - - dev->tbusy = 0; - dev->interrupt = 0; - dev->start = 1; - - if (net_debug > 3) - printk("eepro: exiting eepro_open routine.\n"); - - outb(RCV_ENABLE_CMD, ioaddr); - - MOD_INC_USE_COUNT; - return 0; -} - -static int -eepro_send_packet(struct sk_buff *skb, struct device *dev) -{ - struct eepro_local *lp = (struct eepro_local *)dev->priv; - int ioaddr = dev->base_addr; - - if (net_debug > 5) - printk("eepro: entering eepro_send_packet routine.\n"); - - if (dev->tbusy) { - /* If we get here, some higher level has decided we are broken. - There should really be a "kick me" function call instead. */ - int tickssofar = jiffies - dev->trans_start; - if (tickssofar < 5) - return 1; - if (net_debug > 1) - printk("%s: transmit timed out, %s?\n", dev->name, - "network cable problem"); - lp->stats.tx_errors++; - /* Try to restart the adaptor. */ - outb(SEL_RESET_CMD, ioaddr); - /* We are supposed to wait for 2 us after a SEL_RESET */ - SLOW_DOWN_IO; - SLOW_DOWN_IO; - - /* Do I also need to flush the transmit buffers here? YES? */ - lp->tx_start = lp->tx_end = RCV_RAM; - lp->tx_last = 0; - - dev->tbusy=0; - dev->trans_start = jiffies; - - outb(RCV_ENABLE_CMD, ioaddr); - - } - - /* If some higher layer thinks we've missed an tx-done interrupt - we are passed NULL. Caution: dev_tint() handles the cli()/sti() - itself. */ - if (skb == NULL) { - dev_tint(dev); - return 0; - } - - /* Block a timer-based transmit from overlapping. */ - if (set_bit(0, (void*)&dev->tbusy) != 0) - printk("%s: Transmitter access conflict.\n", dev->name); - else { - short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; - unsigned char *buf = skb->data; - - hardware_send_packet(dev, buf, length); - dev->trans_start = jiffies; - } - - dev_kfree_skb (skb, FREE_WRITE); - - /* You might need to clean up and record Tx statistics here. */ - /* lp->stats.tx_aborted_errors++; */ - - if (net_debug > 5) - printk("eepro: exiting eepro_send_packet routine.\n"); - - return 0; -} - - -/* The typical workload of the driver: - Handle the network interface interrupts. */ -static void -eepro_interrupt(int irq, struct pt_regs * regs) -{ - struct device *dev = (struct device *)(irq2dev_map[irq]); - int ioaddr, status, boguscount = 0; - - if (net_debug > 5) - printk("eepro: entering eepro_interrupt routine.\n"); - - if (dev == NULL) { - printk ("eepro_interrupt(): irq %d for unknown device.\n", irq); - return; - } - dev->interrupt = 1; - - ioaddr = dev->base_addr; - - do { - status = inb(ioaddr + STATUS_REG); - - if (status & RX_INT) { - if (net_debug > 4) - printk("eepro: packet received interrupt.\n"); - - /* Acknowledge the RX_INT */ - outb(RX_INT, ioaddr + STATUS_REG); - - /* Get the received packets */ - eepro_rx(dev); - } - else if (status & TX_INT) { - if (net_debug > 4) - printk("eepro: packet transmit interrupt.\n"); - - /* Acknowledge the TX_INT */ - outb(TX_INT, ioaddr + STATUS_REG); - - /* Process the status of transmitted packets */ - eepro_transmit_interrupt(dev); - dev->tbusy = 0; - mark_bh(NET_BH); - } - } while ((++boguscount < 10) && (status & 0x06)); - - dev->interrupt = 0; - if (net_debug > 5) - printk("eepro: exiting eepro_interrupt routine.\n"); - - return; -} - -static int -eepro_close(struct device *dev) -{ - struct eepro_local *lp = (struct eepro_local *)dev->priv; - int ioaddr = dev->base_addr; - short temp_reg; - - dev->tbusy = 1; - dev->start = 0; - - outb(BANK1_SELECT, ioaddr); /* Switch back to Bank 1 */ - - /* Disable the physical interrupt line. */ - temp_reg = inb(ioaddr + REG1); - outb(temp_reg & 0x7f, ioaddr + REG1); - - outb(BANK0_SELECT, ioaddr); /* Switch back to Bank 0 */ - - /* Flush the Tx and disable Rx. */ - outb(STOP_RCV_CMD, ioaddr); - lp->tx_start = lp->tx_end = RCV_RAM ; - lp->tx_last = 0; - - /* Mask all the interrupts. */ - outb(ALL_MASK, ioaddr + INT_MASK_REG); - - /* clear all interrupts */ - outb(ALL_MASK, ioaddr + STATUS_REG); - - /* Reset the 82595 */ - outb(RESET_CMD, ioaddr); - - /* release the interrupt */ - free_irq(dev->irq); - - irq2dev_map[dev->irq] = 0; - - /* Update the statistics here. What statistics? */ - - /* We are supposed to wait for 200 us after a RESET */ - SLOW_DOWN_IO; - SLOW_DOWN_IO; /* May not be enough? */ - - MOD_DEC_USE_COUNT; - return 0; -} - -/* Get the current statistics. This may be called with the card open or - closed. */ -static struct enet_statistics * -eepro_get_stats(struct device *dev) -{ - struct eepro_local *lp = (struct eepro_local *)dev->priv; - - return &lp->stats; -} - -/* Set or clear the multicast filter for this adaptor. - */ -static void -set_multicast_list(struct device *dev) -{ - struct eepro_local *lp = (struct eepro_local *)dev->priv; - short ioaddr = dev->base_addr; - unsigned short mode; - struct dev_mc_list *dmi=dev->mc_list; - - if (dev->flags&(IFF_ALLMULTI|IFF_PROMISC) || dev->mc_count > 63) - { - /* - * We must make the kernel realise we had to move - * into promisc mode or we start all out war on - * the cable. If it was a promisc rewquest the - * flag is already set. If not we assert it. - */ - dev->flags|=IFF_PROMISC; - - outb(BANK2_SELECT, ioaddr); /* be CAREFUL, BANK 2 now */ - mode = inb(ioaddr + REG2); - outb(mode | PRMSC_Mode, ioaddr + REG2); - mode = inb(ioaddr + REG3); - outb(mode, ioaddr + REG3); /* writing reg. 3 to complete the update */ - outb(BANK0_SELECT, ioaddr); /* Return to BANK 0 now */ - printk("%s: promiscuous mode enabled.\n", dev->name); - } - else if (dev->mc_count==0 ) - { - outb(BANK2_SELECT, ioaddr); /* be CAREFUL, BANK 2 now */ - mode = inb(ioaddr + REG2); - outb(mode & 0xd6, ioaddr + REG2); /* Turn off Multi-IA and PRMSC_Mode bits */ - mode = inb(ioaddr + REG3); - outb(mode, ioaddr + REG3); /* writing reg. 3 to complete the update */ - outb(BANK0_SELECT, ioaddr); /* Return to BANK 0 now */ - } - else - { - unsigned short status, *eaddrs; - int i, boguscount = 0; - - /* Disable RX and TX interrupts. Neccessary to avoid - corruption of the HOST_ADDRESS_REG by interrupt - service routines. */ - outb(ALL_MASK, ioaddr + INT_MASK_REG); - - outb(BANK2_SELECT, ioaddr); /* be CAREFUL, BANK 2 now */ - mode = inb(ioaddr + REG2); - outb(mode | Multi_IA, ioaddr + REG2); - mode = inb(ioaddr + REG3); - outb(mode, ioaddr + REG3); /* writing reg. 3 to complete the update */ - outb(BANK0_SELECT, ioaddr); /* Return to BANK 0 now */ - outw(lp->tx_end, ioaddr + HOST_ADDRESS_REG); - outw(MC_SETUP, ioaddr + IO_PORT); - outw(0, ioaddr + IO_PORT); - outw(0, ioaddr + IO_PORT); - outw(6*(dev->mc_count + 1), ioaddr + IO_PORT); - for (i = 0; i < dev->mc_count; i++) - { - eaddrs=(unsigned short *)dmi->dmi_addr; - dmi=dmi->next; - outw(*eaddrs++, ioaddr + IO_PORT); - outw(*eaddrs++, ioaddr + IO_PORT); - outw(*eaddrs++, ioaddr + IO_PORT); - } - eaddrs = (unsigned short *) dev->dev_addr; - outw(eaddrs[0], ioaddr + IO_PORT); - outw(eaddrs[1], ioaddr + IO_PORT); - outw(eaddrs[2], ioaddr + IO_PORT); - outw(lp->tx_end, ioaddr + XMT_BAR); - outb(MC_SETUP, ioaddr); - - /* Update the transmit queue */ - i = lp->tx_end + XMT_HEADER + 6*(dev->mc_count + 1); - if (lp->tx_start != lp->tx_end) - { - /* update the next address and the chain bit in the - last packet */ - outw(lp->tx_last + XMT_CHAIN, ioaddr + HOST_ADDRESS_REG); - outw(i, ioaddr + IO_PORT); - outw(lp->tx_last + XMT_COUNT, ioaddr + HOST_ADDRESS_REG); - status = inw(ioaddr + IO_PORT); - outw(status | CHAIN_BIT, ioaddr + IO_PORT); - lp->tx_end = i ; - } - else lp->tx_start = lp->tx_end = i ; - - /* Acknowledge that the MC setup is done */ - do { /* We should be doing this in the eepro_interrupt()! */ - SLOW_DOWN_IO; - SLOW_DOWN_IO; - if (inb(ioaddr + STATUS_REG) & 0x08) - { - i = inb(ioaddr); - outb(0x08, ioaddr + STATUS_REG); - if (i & 0x20) { /* command ABORTed */ - printk("%s: multicast setup failed.\n", - dev->name); - break; - } else if ((i & 0x0f) == 0x03) { /* MC-Done */ - printk("%s: set Rx mode to %d addresses.\n", - dev->name, dev->mc_count); - break; - } - } - } while (++boguscount < 100); - - /* Re-enable RX and TX interrupts */ - outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG); - - } - outb(RCV_ENABLE_CMD, ioaddr); -} - -/* The horrible routine to read a word from the serial EEPROM. */ -/* IMPORTANT - the 82595 will be set to Bank 0 after the eeprom is read */ - -/* The delay between EEPROM clock transitions. */ -#define eeprom_delay() { int _i = 40; while (--_i > 0) { __SLOW_DOWN_IO; }} -#define EE_READ_CMD (6 << 6) - -int -read_eeprom(int ioaddr, int location) -{ - int i; - unsigned short retval = 0; - short ee_addr = ioaddr + EEPROM_REG; - int read_cmd = location | EE_READ_CMD; - short ctrl_val = EECS ; - - outb(BANK2_SELECT, ioaddr); - outb(ctrl_val, ee_addr); - - /* Shift the read command bits out. */ - for (i = 8; i >= 0; i--) { - short outval = (read_cmd & (1 << i)) ? ctrl_val | EEDI - : ctrl_val; - outb(outval, ee_addr); - outb(outval | EESK, ee_addr); /* EEPROM clock tick. */ - eeprom_delay(); - outb(outval, ee_addr); /* Finish EEPROM a clock tick. */ - eeprom_delay(); - } - outb(ctrl_val, ee_addr); - - for (i = 16; i > 0; i--) { - outb(ctrl_val | EESK, ee_addr); eeprom_delay(); - retval = (retval << 1) | ((inb(ee_addr) & EEDO) ? 1 : 0); - outb(ctrl_val, ee_addr); eeprom_delay(); - } - - /* Terminate the EEPROM access. */ - ctrl_val &= ~EECS; - outb(ctrl_val | EESK, ee_addr); - eeprom_delay(); - outb(ctrl_val, ee_addr); - eeprom_delay(); - outb(BANK0_SELECT, ioaddr); - return retval; -} - -static void -hardware_send_packet(struct device *dev, void *buf, short length) -{ - struct eepro_local *lp = (struct eepro_local *)dev->priv; - short ioaddr = dev->base_addr; - unsigned status, tx_available, last, end, boguscount = 10; - - if (net_debug > 5) - printk("eepro: entering hardware_send_packet routine.\n"); - - while (boguscount-- > 0) { - - /* determine how much of the transmit buffer space is available */ - if (lp->tx_end > lp->tx_start) - tx_available = XMT_RAM - (lp->tx_end - lp->tx_start); - else if (lp->tx_end < lp->tx_start) - tx_available = lp->tx_start - lp->tx_end; - else tx_available = XMT_RAM; - - /* Disable RX and TX interrupts. Neccessary to avoid - corruption of the HOST_ADDRESS_REG by interrupt - service routines. */ - outb(ALL_MASK, ioaddr + INT_MASK_REG); - - if (((((length + 1) >> 1) << 1) + 2*XMT_HEADER) - >= tx_available) /* No space available ??? */ - continue; - - last = lp->tx_end; - end = last + (((length + 1) >> 1) << 1) + XMT_HEADER; - - if (end >= RAM_SIZE) { /* the transmit buffer is wrapped around */ - if ((RAM_SIZE - last) <= XMT_HEADER) { - /* Arrrr!!!, must keep the xmt header together, - several days were lost to chase this one down. */ - last = RCV_RAM; - end = last + (((length + 1) >> 1) << 1) + XMT_HEADER; - } - else end = RCV_RAM + (end - RAM_SIZE); - } - - outw(last, ioaddr + HOST_ADDRESS_REG); - outw(XMT_CMD, ioaddr + IO_PORT); - outw(0, ioaddr + IO_PORT); - outw(end, ioaddr + IO_PORT); - outw(length, ioaddr + IO_PORT); - outsw(ioaddr + IO_PORT, buf, (length + 1) >> 1); - - if (lp->tx_start != lp->tx_end) { - /* update the next address and the chain bit in the - last packet */ - if (lp->tx_end != last) { - outw(lp->tx_last + XMT_CHAIN, ioaddr + HOST_ADDRESS_REG); - outw(last, ioaddr + IO_PORT); - } - outw(lp->tx_last + XMT_COUNT, ioaddr + HOST_ADDRESS_REG); - status = inw(ioaddr + IO_PORT); - outw(status | CHAIN_BIT, ioaddr + IO_PORT); - } - - /* A dummy read to flush the DRAM write pipeline */ - status = inw(ioaddr + IO_PORT); - - /* Enable RX and TX interrupts */ - outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG); - - if (lp->tx_start == lp->tx_end) { - outw(last, ioaddr + XMT_BAR); - outb(XMT_CMD, ioaddr); - lp->tx_start = last; /* I don't like to change tx_start here */ - } - else outb(RESUME_XMT_CMD, ioaddr); - - lp->tx_last = last; - lp->tx_end = end; - - if (dev->tbusy) { - dev->tbusy = 0; - mark_bh(NET_BH); - } - - if (net_debug > 5) - printk("eepro: exiting hardware_send_packet routine.\n"); - return; - } - dev->tbusy = 1; - if (net_debug > 5) - printk("eepro: exiting hardware_send_packet routine.\n"); -} - -static void -eepro_rx(struct device *dev) -{ - struct eepro_local *lp = (struct eepro_local *)dev->priv; - short ioaddr = dev->base_addr; - short boguscount = 20; - short rcv_car = lp->rx_start; - unsigned rcv_event, rcv_status, rcv_next_frame, rcv_size; - - if (net_debug > 5) - printk("eepro: entering eepro_rx routine.\n"); - - /* Set the read pointer to the start of the RCV */ - outw(rcv_car, ioaddr + HOST_ADDRESS_REG); - rcv_event = inw(ioaddr + IO_PORT); - - while (rcv_event == RCV_DONE) { - rcv_status = inw(ioaddr + IO_PORT); - rcv_next_frame = inw(ioaddr + IO_PORT); - rcv_size = inw(ioaddr + IO_PORT); - - if ((rcv_status & (RX_OK | RX_ERROR)) == RX_OK) { - /* Malloc up new buffer. */ - struct sk_buff *skb; - - rcv_size &= 0x3fff; - skb = dev_alloc_skb(rcv_size+2); - if (skb == NULL) { - printk("%s: Memory squeeze, dropping packet.\n", dev->name); - lp->stats.rx_dropped++; - break; - } - skb->dev = dev; - skb_reserve(skb,2); - - insw(ioaddr+IO_PORT, skb_put(skb,rcv_size), (rcv_size + 1) >> 1); - - skb->protocol = eth_type_trans(skb,dev); - netif_rx(skb); - lp->stats.rx_packets++; - } - else { /* Not sure will ever reach here, - I set the 595 to discard bad received frames */ - lp->stats.rx_errors++; - if (rcv_status & 0x0100) - lp->stats.rx_over_errors++; - else if (rcv_status & 0x0400) - lp->stats.rx_frame_errors++; - else if (rcv_status & 0x0800) - lp->stats.rx_crc_errors++; - printk("%s: event = %#x, status = %#x, next = %#x, size = %#x\n", - dev->name, rcv_event, rcv_status, rcv_next_frame, rcv_size); - } - if (rcv_status & 0x1000) - lp->stats.rx_length_errors++; - if (--boguscount == 0) - break; - - rcv_car = lp->rx_start + RCV_HEADER + rcv_size; - lp->rx_start = rcv_next_frame; - outw(rcv_next_frame, ioaddr + HOST_ADDRESS_REG); - rcv_event = inw(ioaddr + IO_PORT); - - } - if (rcv_car == 0) - rcv_car = (RCV_UPPER_LIMIT << 8) | 0xff; - outw(rcv_car - 1, ioaddr + RCV_STOP); - - if (net_debug > 5) - printk("eepro: exiting eepro_rx routine.\n"); -} - -static void -eepro_transmit_interrupt(struct device *dev) -{ - struct eepro_local *lp = (struct eepro_local *)dev->priv; - short ioaddr = dev->base_addr; - short boguscount = 10; - short xmt_status; - - while (lp->tx_start != lp->tx_end) { - - outw(lp->tx_start, ioaddr + HOST_ADDRESS_REG); - xmt_status = inw(ioaddr+IO_PORT); - if ((xmt_status & TX_DONE_BIT) == 0) break; - xmt_status = inw(ioaddr+IO_PORT); - lp->tx_start = inw(ioaddr+IO_PORT); - - if (dev->tbusy) { - dev->tbusy = 0; - mark_bh(NET_BH); - } - - if (xmt_status & 0x2000) - lp->stats.tx_packets++; - else { - lp->stats.tx_errors++; - if (xmt_status & 0x0400) - lp->stats.tx_carrier_errors++; - printk("%s: XMT status = %#x\n", - dev->name, xmt_status); - } - if (xmt_status & 0x000f) - lp->stats.collisions += (xmt_status & 0x000f); - if ((xmt_status & 0x0040) == 0x0) - lp->stats.tx_heartbeat_errors++; - - if (--boguscount == 0) - break; - } -} - -#ifdef MODULE -static char devicename[9] = { 0, }; -static struct device dev_eepro = { - devicename, /* device name is inserted by linux/drivers/net/net_init.c */ - 0, 0, 0, 0, - 0, 0, - 0, 0, 0, NULL, eepro_probe }; - -static int io = 0x200; -static int irq = 0; - -int -init_module(void) -{ - if (io == 0) - printk("eepro: You should not use auto-probing with insmod!\n"); - dev_eepro.base_addr = io; - dev_eepro.irq = irq; - - if (register_netdev(&dev_eepro) != 0) - return -EIO; - return 0; -} - -void -cleanup_module(void) -{ - unregister_netdev(&dev_eepro); - kfree_s(dev_eepro.priv,sizeof(struct eepro_local)); - dev_eepro.priv=NULL; - - /* If we don't do this, we can't re-insmod it later. */ - release_region(dev_eepro.base_addr, EEPRO_IO_EXTENT); -} -#endif /* MODULE */ diff --git a/i386/i386at/gpl/linux/net/eexpress.c b/i386/i386at/gpl/linux/net/eexpress.c deleted file mode 100644 index 2f641d68..00000000 --- a/i386/i386at/gpl/linux/net/eexpress.c +++ /dev/null @@ -1,1034 +0,0 @@ -/* eexpress.c: Intel EtherExpress device driver for Linux. */ -/* - Written 1993 by Donald Becker. - Copyright 1993 United States Government as represented by the Director, - National Security Agency. This software may only be used and distributed - according to the terms of the GNU Public License as modified by SRC, - incorporated herein by reference. - - The author may be reached as becker@super.org or - C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715 - - Things remaining to do: - Check that the 586 and ASIC are reset/unreset at the right times. - Check tx and rx buffer setup. - The current Tx is single-buffer-only. - Move the theory of operation and memory map documentation. - Rework the board error reset - The statistics need to be updated correctly. - - Modularized by Pauline Middelink <middelin@polyware.iaf.nl> - Changed to support io= irq= by Alan Cox <Alan.Cox@linux.org> -*/ - -static const char *version = - "eexpress.c:v0.07 1/19/94 Donald Becker (becker@super.org)\n"; - -/* - Sources: - This driver wouldn't have been written with the availability of the - Crynwr driver source code. It provided a known-working implementation - that filled in the gaping holes of the Intel documentation. Three cheers - for Russ Nelson. - - Intel Microcommunications Databook, Vol. 1, 1990. It provides just enough - info that the casual reader might think that it documents the i82586. -*/ - -#include <linux/module.h> - -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/types.h> -#include <linux/fcntl.h> -#include <linux/interrupt.h> -#include <linux/ptrace.h> -#include <linux/ioport.h> -#include <linux/string.h> -#include <linux/in.h> -#include <asm/system.h> -#include <asm/bitops.h> -#include <asm/io.h> -#include <asm/dma.h> -#include <linux/errno.h> - -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> -#include <linux/malloc.h> - -/* use 0 for production, 1 for verification, 2..7 for debug */ -#ifndef NET_DEBUG -#define NET_DEBUG 2 -#endif -static unsigned int net_debug = NET_DEBUG; - -/* - Details of the i82586. - - You'll really need the databook to understand the details of this part, - but the outline is that the i82586 has two separate processing units. - - The Rx unit uses a list of frame descriptors and a list of data buffer - descriptors. We use full-sized (1518 byte) data buffers, so there is - a one-to-one pairing of frame descriptors to buffer descriptors. - - The Tx ("command") unit executes a list of commands that look like: - Status word Written by the 82586 when the command is done. - Command word Command in lower 3 bits, post-command action in upper 3 - Link word The address of the next command. - Parameters (as needed). - - Some definitions related to the Command Word are: - */ -#define CMD_EOL 0x8000 /* The last command of the list, stop. */ -#define CMD_SUSP 0x4000 /* Suspend after doing cmd. */ -#define CMD_INTR 0x2000 /* Interrupt after doing cmd. */ - -enum commands { - CmdNOp = 0, CmdSASetup = 1, CmdConfigure = 2, CmdMulticastList = 3, - CmdTx = 4, CmdTDR = 5, CmdDump = 6, CmdDiagnose = 7}; - -/* Information that need to be kept for each board. */ -struct net_local { - struct enet_statistics stats; - int last_restart; - short rx_head; - short rx_tail; - short tx_head; - short tx_cmd_link; - short tx_reap; -}; - -/* - Details of the EtherExpress Implementation - The EtherExpress takes an unusual approach to host access to packet buffer - memory. The host can use either the Dataport, with independent - autoincrementing read and write pointers, or it can I/O map 32 bytes of the - memory using the "Shadow Memory Pointer" (SMB) as follows: - ioaddr Normal EtherExpress registers - ioaddr+0x4000...0x400f Buffer Memory at SMB...SMB+15 - ioaddr+0x8000...0x800f Buffer Memory at SMB+16...SMB+31 - ioaddr+0xC000...0xC007 "" SMB+16...SMB+23 (hardware flaw?) - ioaddr+0xC008...0xC00f Buffer Memory at 0x0008...0x000f - The last I/O map set is useful if you put the i82586 System Command Block - (the command mailbox) exactly at 0x0008. (There seems to be some - undocumented init structure at 0x0000-7, so I had to use the Crywnr memory - setup verbatim for those four words anyway.) - - A problem with using either one of these mechanisms is that you must run - single-threaded, or the interrupt handler must restore a changed value of - the read, write, or SMB pointers. - - Unlike the Crynwr driver, my driver mostly ignores the I/O mapped "feature" - and relies heavily on the dataport for buffer memory access. To minimize - switching, the read_pointer is dedicated to the Rx interrupt handler, and - the write_pointer is used by the send_packet() routine (it's carefully saved - and restored when it's needed by the interrupt handler). - */ - -/* Offsets from the base I/O address. */ -#define DATAPORT 0 /* Data Transfer Register. */ -#define WRITE_PTR 2 /* Write Address Pointer. */ -#define READ_PTR 4 /* Read Address Pointer. */ -#define SIGNAL_CA 6 /* Frob the 82586 Channel Attention line. */ -#define SET_IRQ 7 /* IRQ Select. */ -#define SHADOW_PTR 8 /* Shadow Memory Bank Pointer. */ -#define MEM_Ctrl 11 -#define MEM_Page_Ctrl 12 -#define Config 13 -#define EEPROM_Ctrl 14 -#define ID_PORT 15 - -#define EEXPRESS_IO_EXTENT 16 - -/* EEPROM_Ctrl bits. */ - -#define EE_SHIFT_CLK 0x01 /* EEPROM shift clock. */ -#define EE_CS 0x02 /* EEPROM chip select. */ -#define EE_DATA_WRITE 0x04 /* EEPROM chip data in. */ -#define EE_DATA_READ 0x08 /* EEPROM chip data out. */ -#define EE_CTRL_BITS (EE_SHIFT_CLK | EE_CS | EE_DATA_WRITE | EE_DATA_READ) -#define ASIC_RESET 0x40 -#define _586_RESET 0x80 - -/* Offsets to elements of the System Control Block structure. */ -#define SCB_STATUS 0xc008 -#define SCB_CMD 0xc00A -#define CUC_START 0x0100 -#define CUC_RESUME 0x0200 -#define CUC_SUSPEND 0x0300 -#define RX_START 0x0010 -#define RX_RESUME 0x0020 -#define RX_SUSPEND 0x0030 -#define SCB_CBL 0xc00C /* Command BLock offset. */ -#define SCB_RFA 0xc00E /* Rx Frame Area offset. */ - -/* - What follows in 'init_words[]' is the "program" that is downloaded to the - 82586 memory. It's mostly tables and command blocks, and starts at the - reset address 0xfffff6. - - Even with the additional "don't care" values, doing it this way takes less - program space than initializing the individual tables, and I feel it's much - cleaner. - - The databook is particularly useless for the first two structures; they are - completely undocumented. I had to use the Crynwr driver as an example. - - The memory setup is as follows: - */ - -#define CONFIG_CMD 0x0018 -#define SET_SA_CMD 0x0024 -#define SA_OFFSET 0x002A -#define IDLELOOP 0x30 -#define TDR_CMD 0x38 -#define TDR_TIME 0x3C -#define DUMP_CMD 0x40 -#define DIAG_CMD 0x48 -#define SET_MC_CMD 0x4E -#define DUMP_DATA 0x56 /* A 170 byte buffer for dump and Set-MC into. */ - -#define TX_BUF_START 0x0100 -#define NUM_TX_BUFS 4 -#define TX_BUF_SIZE 0x0680 /* packet+header+TBD+extra (1518+14+20+16) */ -#define TX_BUF_END 0x2000 - -#define RX_BUF_START 0x2000 -#define RX_BUF_SIZE (0x640) /* packet+header+RBD+extra */ -#define RX_BUF_END 0x4000 - -/* - That's it: only 86 bytes to set up the beast, including every extra - command available. The 170 byte buffer at DUMP_DATA is shared between the - Dump command (called only by the diagnostic program) and the SetMulticastList - command. - - To complete the memory setup you only have to write the station address at - SA_OFFSET and create the Tx & Rx buffer lists. - - The Tx command chain and buffer list is setup as follows: - A Tx command table, with the data buffer pointing to... - A Tx data buffer descriptor. The packet is in a single buffer, rather than - chaining together several smaller buffers. - A NoOp command, which initially points to itself, - And the packet data. - - A transmit is done by filling in the Tx command table and data buffer, - re-writing the NoOp command, and finally changing the offset of the last - command to point to the current Tx command. When the Tx command is finished, - it jumps to the NoOp, when it loops until the next Tx command changes the - "link offset" in the NoOp. This way the 82586 never has to go through the - slow restart sequence. - - The Rx buffer list is set up in the obvious ring structure. We have enough - memory (and low enough interrupt latency) that we can avoid the complicated - Rx buffer linked lists by alway associating a full-size Rx data buffer with - each Rx data frame. - - I current use four transmit buffers starting at TX_BUF_START (0x0100), and - use the rest of memory, from RX_BUF_START to RX_BUF_END, for Rx buffers. - - */ - -static short init_words[] = { - 0x0000, /* Set bus size to 16 bits. */ - 0x0000,0x0000, /* Set control mailbox (SCB) addr. */ - 0,0, /* pad to 0x000000. */ - 0x0001, /* Status word that's cleared when init is done. */ - 0x0008,0,0, /* SCB offset, (skip, skip) */ - - 0,0xf000|RX_START|CUC_START, /* SCB status and cmd. */ - CONFIG_CMD, /* Command list pointer, points to Configure. */ - RX_BUF_START, /* Rx block list. */ - 0,0,0,0, /* Error count: CRC, align, buffer, overrun. */ - - /* 0x0018: Configure command. Change to put MAC data with packet. */ - 0, CmdConfigure, /* Status, command. */ - SET_SA_CMD, /* Next command is Set Station Addr. */ - 0x0804, /* "4" bytes of config data, 8 byte FIFO. */ - 0x2e40, /* Magic values, including MAC data location. */ - 0, /* Unused pad word. */ - - /* 0x0024: Setup station address command. */ - 0, CmdSASetup, - SET_MC_CMD, /* Next command. */ - 0xaa00,0xb000,0x0bad, /* Station address (to be filled in) */ - - /* 0x0030: NOP, looping back to itself. Point to first Tx buffer to Tx. */ - 0, CmdNOp, IDLELOOP, 0 /* pad */, - - /* 0x0038: A unused Time-Domain Reflectometer command. */ - 0, CmdTDR, IDLELOOP, 0, - - /* 0x0040: An unused Dump State command. */ - 0, CmdDump, IDLELOOP, DUMP_DATA, - - /* 0x0048: An unused Diagnose command. */ - 0, CmdDiagnose, IDLELOOP, - - /* 0x004E: An empty set-multicast-list command. */ -#ifdef initial_text_tx - 0, CmdMulticastList, DUMP_DATA, 0, -#else - 0, CmdMulticastList, IDLELOOP, 0, -#endif - - /* 0x0056: A continuous transmit command, only here for testing. */ - 0, CmdTx, DUMP_DATA, DUMP_DATA+8, 0x83ff, -1, DUMP_DATA, 0, -}; - -/* Index to functions, as function prototypes. */ - -extern int express_probe(struct device *dev); /* Called from Space.c */ - -static int eexp_probe1(struct device *dev, short ioaddr); -static int eexp_open(struct device *dev); -static int eexp_send_packet(struct sk_buff *skb, struct device *dev); -static void eexp_interrupt(int irq, struct pt_regs *regs); -static void eexp_rx(struct device *dev); -static int eexp_close(struct device *dev); -static struct enet_statistics *eexp_get_stats(struct device *dev); -static void set_multicast_list(struct device *dev); - -static int read_eeprom(int ioaddr, int location); -static void hardware_send_packet(struct device *dev, void *buf, short length); -static void init_82586_mem(struct device *dev); -static void init_rx_bufs(struct device *dev); - - -/* Check for a network adaptor of this type, and return '0' iff one exists. - If dev->base_addr == 0, probe all likely locations. - If dev->base_addr == 1, always return failure. - If dev->base_addr == 2, (detachable devices only) allocate space for the - device and return success. - */ -int -express_probe(struct device *dev) -{ - /* Don't probe all settable addresses, 0x[23][0-7]0, just common ones. */ - int *port, ports[] = {0x300, 0x270, 0x320, 0x340, 0}; - int base_addr = dev->base_addr; - - if (base_addr > 0x1ff) /* Check a single specified location. */ - return eexp_probe1(dev, base_addr); - else if (base_addr > 0) - return ENXIO; /* Don't probe at all. */ - - for (port = &ports[0]; *port; port++) { - short id_addr = *port + ID_PORT; - unsigned short sum = 0; - int i; -#ifdef notdef - for (i = 16; i > 0; i--) - sum += inb(id_addr); - printk("EtherExpress ID checksum is %04x.\n", sum); -#else - for (i = 4; i > 0; i--) { - short id_val = inb(id_addr); - sum |= (id_val >> 4) << ((id_val & 3) << 2); - } -#endif - if (sum == 0xbaba - && eexp_probe1(dev, *port) == 0) - return 0; - } - - return ENODEV; -} - -int eexp_probe1(struct device *dev, short ioaddr) -{ - unsigned short station_addr[3]; - int i; - - printk("%s: EtherExpress at %#x,", dev->name, ioaddr); - - /* The station address is stored !backwards! in the EEPROM, reverse - after reading. (Hmmm, a little brain-damage there at Intel, eh?) */ - station_addr[0] = read_eeprom(ioaddr, 2); - station_addr[1] = read_eeprom(ioaddr, 3); - station_addr[2] = read_eeprom(ioaddr, 4); - - /* Check the first three octets of the S.A. for the manufacturer's code. */ - if (station_addr[2] != 0x00aa || (station_addr[1] & 0xff00) != 0x0000) { - printk(" rejected (invalid address %04x%04x%04x).\n", - station_addr[2], station_addr[1], station_addr[0]); - return ENODEV; - } - - /* We've committed to using the board, and can start filling in *dev. */ - request_region(ioaddr, EEXPRESS_IO_EXTENT, "eexpress"); - dev->base_addr = ioaddr; - - for (i = 0; i < 6; i++) { - dev->dev_addr[i] = ((unsigned char*)station_addr)[5-i]; - printk(" %02x", dev->dev_addr[i]); - } - - /* There is no reason for the driver to care, but I print out the - interface to minimize bogus bug reports. */ - { - char irqmap[] = {0, 9, 3, 4, 5, 10, 11, 0}; - const char *ifmap[] = {"AUI", "BNC", "10baseT"}; - enum iftype {AUI=0, BNC=1, TP=2}; - unsigned short setupval = read_eeprom(ioaddr, 0); - - dev->irq = irqmap[setupval >> 13]; - dev->if_port = (setupval & 0x1000) == 0 ? AUI : - read_eeprom(ioaddr, 5) & 0x1 ? TP : BNC; - printk(", IRQ %d, Interface %s.\n", dev->irq, ifmap[dev->if_port]); - /* Release the IRQ line so that it can be shared if we don't use the - ethercard. */ - outb(0x00, ioaddr + SET_IRQ); - } - - /* It's now OK to leave the board in reset, pending the open(). */ - outb(ASIC_RESET, ioaddr + EEPROM_Ctrl); - - if ((dev->mem_start & 0xf) > 0) - net_debug = dev->mem_start & 7; - - if (net_debug) - printk(version); - - /* Initialize the device structure. */ - dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL); - if (dev->priv == NULL) - return -ENOMEM; - memset(dev->priv, 0, sizeof(struct net_local)); - - dev->open = eexp_open; - dev->stop = eexp_close; - dev->hard_start_xmit = eexp_send_packet; - dev->get_stats = eexp_get_stats; - dev->set_multicast_list = &set_multicast_list; - - /* Fill in the fields of the device structure with ethernet-generic values. */ - - ether_setup(dev); - - dev->flags&=~IFF_MULTICAST; - - return 0; -} - - -/* Reverse IRQ map: the value to put in the SET_IRQ reg. for IRQ<index>. */ -static char irqrmap[]={0,0,1,2,3,4,0,0,0,1,5,6,0,0,0,0}; - -static int -eexp_open(struct device *dev) -{ - int ioaddr = dev->base_addr; - - if (dev->irq == 0 || irqrmap[dev->irq] == 0) - return -ENXIO; - - if (irq2dev_map[dev->irq] != 0 - /* This is always true, but avoid the false IRQ. */ - || (irq2dev_map[dev->irq] = dev) == 0 - || request_irq(dev->irq, &eexp_interrupt, 0, "EExpress")) { - return -EAGAIN; - } - - /* Initialize the 82586 memory and start it. */ - init_82586_mem(dev); - - /* Enable the interrupt line. */ - outb(irqrmap[dev->irq] | 0x08, ioaddr + SET_IRQ); - - dev->tbusy = 0; - dev->interrupt = 0; - dev->start = 1; - MOD_INC_USE_COUNT; - return 0; -} - -static int -eexp_send_packet(struct sk_buff *skb, struct device *dev) -{ - struct net_local *lp = (struct net_local *)dev->priv; - int ioaddr = dev->base_addr; - - if (dev->tbusy) { - /* If we get here, some higher level has decided we are broken. - There should really be a "kick me" function call instead. */ - int tickssofar = jiffies - dev->trans_start; - if (tickssofar < 5) - return 1; - if (net_debug > 1) - printk("%s: transmit timed out, %s? ", dev->name, - inw(ioaddr+SCB_STATUS) & 0x8000 ? "IRQ conflict" : - "network cable problem"); - lp->stats.tx_errors++; - /* Try to restart the adaptor. */ - if (lp->last_restart == lp->stats.tx_packets) { - if (net_debug > 1) printk("Resetting board.\n"); - /* Completely reset the adaptor. */ - init_82586_mem(dev); - } else { - /* Issue the channel attention signal and hope it "gets better". */ - if (net_debug > 1) printk("Kicking board.\n"); - outw(0xf000|CUC_START|RX_START, ioaddr + SCB_CMD); - outb(0, ioaddr + SIGNAL_CA); - lp->last_restart = lp->stats.tx_packets; - } - dev->tbusy=0; - dev->trans_start = jiffies; - } - - /* If some higher layer thinks we've missed an tx-done interrupt - we are passed NULL. Caution: dev_tint() handles the cli()/sti() - itself. */ - if (skb == NULL) { - dev_tint(dev); - return 0; - } - - /* Block a timer-based transmit from overlapping. */ - if (set_bit(0, (void*)&dev->tbusy) != 0) - printk("%s: Transmitter access conflict.\n", dev->name); - else { - short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; - unsigned char *buf = skb->data; - - /* Disable the 82586's input to the interrupt line. */ - outb(irqrmap[dev->irq], ioaddr + SET_IRQ); - hardware_send_packet(dev, buf, length); - dev->trans_start = jiffies; - /* Enable the 82586 interrupt input. */ - outb(0x08 | irqrmap[dev->irq], ioaddr + SET_IRQ); - } - - dev_kfree_skb (skb, FREE_WRITE); - - /* You might need to clean up and record Tx statistics here. */ - lp->stats.tx_aborted_errors++; - - return 0; -} - -/* The typical workload of the driver: - Handle the network interface interrupts. */ -static void -eexp_interrupt(int irq, struct pt_regs *regs) -{ - struct device *dev = (struct device *)(irq2dev_map[irq]); - struct net_local *lp; - int ioaddr, status, boguscount = 0; - short ack_cmd; - - if (dev == NULL) { - printk ("net_interrupt(): irq %d for unknown device.\n", irq); - return; - } - dev->interrupt = 1; - - ioaddr = dev->base_addr; - lp = (struct net_local *)dev->priv; - - status = inw(ioaddr + SCB_STATUS); - - if (net_debug > 4) { - printk("%s: EExp interrupt, status %4.4x.\n", dev->name, status); - } - - /* Disable the 82586's input to the interrupt line. */ - outb(irqrmap[dev->irq], ioaddr + SET_IRQ); - - /* Reap the Tx packet buffers. */ - while (lp->tx_reap != lp->tx_head) { /* if (status & 0x8000) */ - unsigned short tx_status; - outw(lp->tx_reap, ioaddr + READ_PTR); - tx_status = inw(ioaddr); - if (tx_status == 0) { - if (net_debug > 5) printk("Couldn't reap %#x.\n", lp->tx_reap); - break; - } - if (tx_status & 0x2000) { - lp->stats.tx_packets++; - lp->stats.collisions += tx_status & 0xf; - dev->tbusy = 0; - mark_bh(NET_BH); /* Inform upper layers. */ - } else { - lp->stats.tx_errors++; - if (tx_status & 0x0600) lp->stats.tx_carrier_errors++; - if (tx_status & 0x0100) lp->stats.tx_fifo_errors++; - if (!(tx_status & 0x0040)) lp->stats.tx_heartbeat_errors++; - if (tx_status & 0x0020) lp->stats.tx_aborted_errors++; - } - if (net_debug > 5) - printk("Reaped %x, Tx status %04x.\n" , lp->tx_reap, tx_status); - lp->tx_reap += TX_BUF_SIZE; - if (lp->tx_reap > TX_BUF_END - TX_BUF_SIZE) - lp->tx_reap = TX_BUF_START; - if (++boguscount > 4) - break; - } - - if (status & 0x4000) { /* Packet received. */ - if (net_debug > 5) - printk("Received packet, rx_head %04x.\n", lp->rx_head); - eexp_rx(dev); - } - - /* Acknowledge the interrupt sources. */ - ack_cmd = status & 0xf000; - - if ((status & 0x0700) != 0x0200 && dev->start) { - short saved_write_ptr = inw(ioaddr + WRITE_PTR); - if (net_debug > 1) - printk("%s: Command unit stopped, status %04x, restarting.\n", - dev->name, status); - /* If this ever occurs we must re-write the idle loop, reset - the Tx list, and do a complete restart of the command unit. */ - outw(IDLELOOP, ioaddr + WRITE_PTR); - outw(0, ioaddr); - outw(CmdNOp, ioaddr); - outw(IDLELOOP, ioaddr); - outw(IDLELOOP, SCB_CBL); - lp->tx_cmd_link = IDLELOOP + 4; - lp->tx_head = lp->tx_reap = TX_BUF_START; - /* Restore the saved write pointer. */ - outw(saved_write_ptr, ioaddr + WRITE_PTR); - ack_cmd |= CUC_START; - } - - if ((status & 0x0070) != 0x0040 && dev->start) { - short saved_write_ptr = inw(ioaddr + WRITE_PTR); - /* The Rx unit is not ready, it must be hung. Restart the receiver by - initializing the rx buffers, and issuing an Rx start command. */ - lp->stats.rx_errors++; - if (net_debug > 1) { - int cur_rxbuf = RX_BUF_START; - printk("%s: Rx unit stopped status %04x rx head %04x tail %04x.\n", - dev->name, status, lp->rx_head, lp->rx_tail); - while (cur_rxbuf <= RX_BUF_END - RX_BUF_SIZE) { - int i; - printk(" Rx buf at %04x:", cur_rxbuf); - outw(cur_rxbuf, ioaddr + READ_PTR); - for (i = 0; i < 0x20; i += 2) - printk(" %04x", inw(ioaddr)); - printk(".\n"); - cur_rxbuf += RX_BUF_SIZE; - } - } - init_rx_bufs(dev); - outw(RX_BUF_START, SCB_RFA); - outw(saved_write_ptr, ioaddr + WRITE_PTR); - ack_cmd |= RX_START; - } - - outw(ack_cmd, ioaddr + SCB_CMD); - outb(0, ioaddr + SIGNAL_CA); - - if (net_debug > 5) { - printk("%s: EExp exiting interrupt, status %4.4x.\n", dev->name, - inw(ioaddr + SCB_CMD)); - } - /* Enable the 82586's input to the interrupt line. */ - outb(irqrmap[dev->irq] | 0x08, ioaddr + SET_IRQ); - return; -} - -static int -eexp_close(struct device *dev) -{ - int ioaddr = dev->base_addr; - - dev->tbusy = 1; - dev->start = 0; - - /* Flush the Tx and disable Rx. */ - outw(RX_SUSPEND | CUC_SUSPEND, ioaddr + SCB_CMD); - outb(0, ioaddr + SIGNAL_CA); - - /* Disable the physical interrupt line. */ - outb(0, ioaddr + SET_IRQ); - - free_irq(dev->irq); - - irq2dev_map[dev->irq] = 0; - - /* Update the statistics here. */ - - MOD_DEC_USE_COUNT; - return 0; -} - -/* Get the current statistics. This may be called with the card open or - closed. */ -static struct enet_statistics * -eexp_get_stats(struct device *dev) -{ - struct net_local *lp = (struct net_local *)dev->priv; - - /* ToDo: decide if there are any useful statistics from the SCB. */ - - return &lp->stats; -} - -/* Set or clear the multicast filter for this adaptor. - */ -static void -set_multicast_list(struct device *dev) -{ -/* This doesn't work yet */ -#if 0 - short ioaddr = dev->base_addr; - if (num_addrs < 0) { - /* Not written yet, this requires expanding the init_words config - cmd. */ - } else if (num_addrs > 0) { - /* Fill in the SET_MC_CMD with the number of address bytes, followed - by the list of multicast addresses to be accepted. */ - outw(SET_MC_CMD + 6, ioaddr + WRITE_PTR); - outw(num_addrs * 6, ioaddr); - outsw(ioaddr, addrs, num_addrs*3); /* 3 = addr len in words */ - /* We must trigger a whole 586 reset due to a bug. */ - } else { - /* Not written yet, this requires expanding the init_words config - cmd. */ - outw(99, ioaddr); /* Disable promiscuous mode, use normal mode */ - } -#endif -} - -/* The horrible routine to read a word from the serial EEPROM. */ - -/* The delay between EEPROM clock transitions. */ -#define eeprom_delay() { int _i = 40; while (--_i > 0) { __SLOW_DOWN_IO; }} -#define EE_READ_CMD (6 << 6) - -int -read_eeprom(int ioaddr, int location) -{ - int i; - unsigned short retval = 0; - short ee_addr = ioaddr + EEPROM_Ctrl; - int read_cmd = location | EE_READ_CMD; - short ctrl_val = EE_CS | _586_RESET; - - outb(ctrl_val, ee_addr); - - /* Shift the read command bits out. */ - for (i = 8; i >= 0; i--) { - short outval = (read_cmd & (1 << i)) ? ctrl_val | EE_DATA_WRITE - : ctrl_val; - outb(outval, ee_addr); - outb(outval | EE_SHIFT_CLK, ee_addr); /* EEPROM clock tick. */ - eeprom_delay(); - outb(outval, ee_addr); /* Finish EEPROM a clock tick. */ - eeprom_delay(); - } - outb(ctrl_val, ee_addr); - - for (i = 16; i > 0; i--) { - outb(ctrl_val | EE_SHIFT_CLK, ee_addr); eeprom_delay(); - retval = (retval << 1) | ((inb(ee_addr) & EE_DATA_READ) ? 1 : 0); - outb(ctrl_val, ee_addr); eeprom_delay(); - } - - /* Terminate the EEPROM access. */ - ctrl_val &= ~EE_CS; - outb(ctrl_val | EE_SHIFT_CLK, ee_addr); - eeprom_delay(); - outb(ctrl_val, ee_addr); - eeprom_delay(); - return retval; -} - -static void -init_82586_mem(struct device *dev) -{ - struct net_local *lp = (struct net_local *)dev->priv; - short ioaddr = dev->base_addr; - - /* Enable loopback to protect the wire while starting up. - This is Superstition From Crynwr. */ - outb(inb(ioaddr + Config) | 0x02, ioaddr + Config); - - /* Hold the 586 in reset during the memory initialization. */ - outb(_586_RESET, ioaddr + EEPROM_Ctrl); - - /* Place the write pointer at 0xfff6 (address-aliased to 0xfffff6). */ - outw(0xfff6, ioaddr + WRITE_PTR); - outsw(ioaddr, init_words, sizeof(init_words)>>1); - - /* Fill in the station address. */ - outw(SA_OFFSET, ioaddr + WRITE_PTR); - outsw(ioaddr, dev->dev_addr, 3); - - /* The Tx-block list is written as needed. We just set up the values. */ -#ifdef initial_text_tx - lp->tx_cmd_link = DUMP_DATA + 4; -#else - lp->tx_cmd_link = IDLELOOP + 4; -#endif - lp->tx_head = lp->tx_reap = TX_BUF_START; - - init_rx_bufs(dev); - - /* Start the 586 by releasing the reset line. */ - outb(0x00, ioaddr + EEPROM_Ctrl); - - /* This was time consuming to track down: you need to give two channel - attention signals to reliably start up the i82586. */ - outb(0, ioaddr + SIGNAL_CA); - - { - int boguscnt = 50; - while (inw(ioaddr + SCB_STATUS) == 0) - if (--boguscnt == 0) { - printk("%s: i82586 initialization timed out with status %04x, cmd %04x.\n", - dev->name, inw(ioaddr + SCB_STATUS), inw(ioaddr + SCB_CMD)); - break; - } - /* Issue channel-attn -- the 82586 won't start without it. */ - outb(0, ioaddr + SIGNAL_CA); - } - - /* Disable loopback. */ - outb(inb(ioaddr + Config) & ~0x02, ioaddr + Config); - if (net_debug > 4) - printk("%s: Initialized 82586, status %04x.\n", dev->name, - inw(ioaddr + SCB_STATUS)); - return; -} - -/* Initialize the Rx-block list. */ -static void init_rx_bufs(struct device *dev) -{ - struct net_local *lp = (struct net_local *)dev->priv; - short ioaddr = dev->base_addr; - - int cur_rxbuf = lp->rx_head = RX_BUF_START; - - /* Initialize each Rx frame + data buffer. */ - do { /* While there is room for one more. */ - outw(cur_rxbuf, ioaddr + WRITE_PTR); - outw(0x0000, ioaddr); /* Status */ - outw(0x0000, ioaddr); /* Command */ - outw(cur_rxbuf + RX_BUF_SIZE, ioaddr); /* Link */ - outw(cur_rxbuf + 22, ioaddr); /* Buffer offset */ - outw(0xFeed, ioaddr); /* Pad for dest addr. */ - outw(0xF00d, ioaddr); - outw(0xF001, ioaddr); - outw(0x0505, ioaddr); /* Pad for source addr. */ - outw(0x2424, ioaddr); - outw(0x6565, ioaddr); - outw(0xdeaf, ioaddr); /* Pad for protocol. */ - - outw(0x0000, ioaddr); /* Buffer: Actual count */ - outw(-1, ioaddr); /* Buffer: Next (none). */ - outw(cur_rxbuf + 0x20, ioaddr); /* Buffer: Address low */ - outw(0x0000, ioaddr); - /* Finally, the number of bytes in the buffer. */ - outw(0x8000 + RX_BUF_SIZE-0x20, ioaddr); - - lp->rx_tail = cur_rxbuf; - cur_rxbuf += RX_BUF_SIZE; - } while (cur_rxbuf <= RX_BUF_END - RX_BUF_SIZE); - - /* Terminate the list by setting the EOL bit, and wrap the pointer to make - the list a ring. */ - outw(lp->rx_tail + 2, ioaddr + WRITE_PTR); - outw(0xC000, ioaddr); /* Command, mark as last. */ - outw(lp->rx_head, ioaddr); /* Link */ -} - -static void -hardware_send_packet(struct device *dev, void *buf, short length) -{ - struct net_local *lp = (struct net_local *)dev->priv; - short ioaddr = dev->base_addr; - short tx_block = lp->tx_head; - - /* Set the write pointer to the Tx block, and put out the header. */ - outw(tx_block, ioaddr + WRITE_PTR); - outw(0x0000, ioaddr); /* Tx status */ - outw(CMD_INTR|CmdTx, ioaddr); /* Tx command */ - outw(tx_block+16, ioaddr); /* Next command is a NoOp. */ - outw(tx_block+8, ioaddr); /* Data Buffer offset. */ - - /* Output the data buffer descriptor. */ - outw(length | 0x8000, ioaddr); /* Byte count parameter. */ - outw(-1, ioaddr); /* No next data buffer. */ - outw(tx_block+22, ioaddr); /* Buffer follows the NoOp command. */ - outw(0x0000, ioaddr); /* Buffer address high bits (always zero). */ - - /* Output the Loop-back NoOp command. */ - outw(0x0000, ioaddr); /* Tx status */ - outw(CmdNOp, ioaddr); /* Tx command */ - outw(tx_block+16, ioaddr); /* Next is myself. */ - - /* Output the packet using the write pointer. - Hmmm, it feels a little like a 3c501! */ - outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1); - - /* Set the old command link pointing to this send packet. */ - outw(lp->tx_cmd_link, ioaddr + WRITE_PTR); - outw(tx_block, ioaddr); - lp->tx_cmd_link = tx_block + 20; - - /* Set the next free tx region. */ - lp->tx_head = tx_block + TX_BUF_SIZE; - if (lp->tx_head > TX_BUF_END - TX_BUF_SIZE) - lp->tx_head = TX_BUF_START; - - if (net_debug > 4) { - printk("%s: EExp @%x send length = %d, tx_block %3x, next %3x, " - "reap %4x status %4.4x.\n", dev->name, ioaddr, length, - tx_block, lp->tx_head, lp->tx_reap, inw(ioaddr + SCB_STATUS)); - } - - if (lp->tx_head != lp->tx_reap) - dev->tbusy = 0; -} - -static void -eexp_rx(struct device *dev) -{ - struct net_local *lp = (struct net_local *)dev->priv; - short ioaddr = dev->base_addr; - short saved_write_ptr = inw(ioaddr + WRITE_PTR); - short rx_head = lp->rx_head; - short rx_tail = lp->rx_tail; - short boguscount = 10; - short frame_status; - - /* Set the read pointer to the Rx frame. */ - outw(rx_head, ioaddr + READ_PTR); - while ((frame_status = inw(ioaddr)) < 0) { /* Command complete */ - short rfd_cmd = inw(ioaddr); - short next_rx_frame = inw(ioaddr); - short data_buffer_addr = inw(ioaddr); - short pkt_len; - - /* Set the read pointer the data buffer. */ - outw(data_buffer_addr, ioaddr + READ_PTR); - pkt_len = inw(ioaddr); - - if (rfd_cmd != 0 || data_buffer_addr != rx_head + 22 - || (pkt_len & 0xC000) != 0xC000) { - printk("%s: Rx frame at %#x corrupted, status %04x cmd %04x" - "next %04x data-buf @%04x %04x.\n", dev->name, rx_head, - frame_status, rfd_cmd, next_rx_frame, data_buffer_addr, - pkt_len); - } else if ((frame_status & 0x2000) == 0) { - /* Frame Rxed, but with error. */ - lp->stats.rx_errors++; - if (frame_status & 0x0800) lp->stats.rx_crc_errors++; - if (frame_status & 0x0400) lp->stats.rx_frame_errors++; - if (frame_status & 0x0200) lp->stats.rx_fifo_errors++; - if (frame_status & 0x0100) lp->stats.rx_over_errors++; - if (frame_status & 0x0080) lp->stats.rx_length_errors++; - } else { - /* Malloc up new buffer. */ - struct sk_buff *skb; - - pkt_len &= 0x3fff; - skb = dev_alloc_skb(pkt_len+2); - if (skb == NULL) { - printk("%s: Memory squeeze, dropping packet.\n", dev->name); - lp->stats.rx_dropped++; - break; - } - skb->dev = dev; - skb_reserve(skb,2); - - outw(data_buffer_addr + 10, ioaddr + READ_PTR); - - insw(ioaddr, skb_put(skb,pkt_len), (pkt_len + 1) >> 1); - - skb->protocol=eth_type_trans(skb,dev); - netif_rx(skb); - lp->stats.rx_packets++; - } - - /* Clear the status word and set End-of-List on the rx frame. */ - outw(rx_head, ioaddr + WRITE_PTR); - outw(0x0000, ioaddr); - outw(0xC000, ioaddr); -#ifndef final_version - if (next_rx_frame != rx_head + RX_BUF_SIZE - && next_rx_frame != RX_BUF_START) { - printk("%s: Rx next frame at %#x is %#x instead of %#x.\n", dev->name, - rx_head, next_rx_frame, rx_head + RX_BUF_SIZE); - next_rx_frame = rx_head + RX_BUF_SIZE; - if (next_rx_frame >= RX_BUF_END - RX_BUF_SIZE) - next_rx_frame = RX_BUF_START; - } -#endif - outw(rx_tail+2, ioaddr + WRITE_PTR); - outw(0x0000, ioaddr); /* Clear the end-of-list on the prev. RFD. */ - -#ifndef final_version - outw(rx_tail+4, ioaddr + READ_PTR); - if (inw(ioaddr) != rx_head) { - printk("%s: Rx buf link mismatch, at %04x link %04x instead of %04x.\n", - dev->name, rx_tail, (outw(rx_tail+4, ioaddr + READ_PTR),inw(ioaddr)), - rx_head); - outw(rx_head, ioaddr); - } -#endif - - rx_tail = rx_head; - rx_head = next_rx_frame; - if (--boguscount == 0) - break; - outw(rx_head, ioaddr + READ_PTR); - } - - lp->rx_head = rx_head; - lp->rx_tail = rx_tail; - - /* Restore the original write pointer. */ - outw(saved_write_ptr, ioaddr + WRITE_PTR); -} - -#ifdef MODULE -static char devicename[9] = { 0, }; -static struct device dev_eexpress = { - devicename, /* device name is inserted by linux/drivers/net/net_init.c */ - 0, 0, 0, 0, - 0, 0, - 0, 0, 0, NULL, express_probe }; - - -static int irq=0x300; -static int io=0; - -int -init_module(void) -{ - if (io == 0) - printk("eexpress: You should not use auto-probing with insmod!\n"); - dev_eexpress.base_addr=io; - dev_eexpress.irq=irq; - if (register_netdev(&dev_eexpress) != 0) - return -EIO; - return 0; -} - -void -cleanup_module(void) -{ - unregister_netdev(&dev_eexpress); - kfree_s(dev_eexpress.priv,sizeof(struct net_local)); - dev_eexpress.priv=NULL; - - /* If we don't do this, we can't re-insmod it later. */ - release_region(dev_eexpress.base_addr, EEXPRESS_IO_EXTENT); -} -#endif /* MODULE */ -/* - * Local variables: - * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -I/usr/src/linux/drivers/net -Wall -Wstrict-prototypes -O6 -m486 -c eexpress.c" - * version-control: t - * kept-new-versions: 5 - * tab-width: 4 - * End: - */ diff --git a/i386/i386at/gpl/linux/net/eth16i.c b/i386/i386at/gpl/linux/net/eth16i.c deleted file mode 100644 index b21e4f33..00000000 --- a/i386/i386at/gpl/linux/net/eth16i.c +++ /dev/null @@ -1,1214 +0,0 @@ -/* eth16i.c An ICL EtherTeam 16i and 32 EISA ethernet driver for Linux - - Written 1994-95 by Mika Kuoppala - - Copyright (C) 1994, 1995 by Mika Kuoppala - Based on skeleton.c and at1700.c by Donald Becker - - This software may be used and distributed according to the terms - of the GNU Public Licence, incorporated herein by reference. - - The author may be reached as miku@elt.icl.fi - - This driver supports following cards : - - ICL EtherTeam 16i - - ICL EtherTeam 32 EISA - - Sources: - - skeleton.c a sample network driver core for linux, - written by Donald Becker <becker@CESDIS.gsfc.nasa.gov> - - at1700.c a driver for Allied Telesis AT1700, written - by Donald Becker. - - e16iSRV.asm a Netware 3.X Server Driver for ICL EtherTeam16i - written by Markku Viima - - The Fujitsu MB86965 databook. - - Valuable assistance from: - Markku Viima (ICL) - Ari Valve (ICL) - - Revision history: - - Version Date Description - - 0.01 15.12-94 Initial version (card detection) - 0.02 23.01-95 Interrupt is now hooked correctly - 0.03 01.02-95 Rewrote initialization part - 0.04 07.02-95 Base skeleton done... - Made a few changes to signature checking - to make it a bit reliable. - - fixed bug in tx_buf mapping - - fixed bug in initialization (DLC_EN - wasn't enabled when initialization - was done.) - 0.05 08.02-95 If there were more than one packet to send, - transmit was jammed due to invalid - register write...now fixed - 0.06 19.02-95 Rewrote interrupt handling - 0.07 13.04-95 Wrote EEPROM read routines - Card configuration now set according to - data read from EEPROM - 0.08 23.06-95 Wrote part that tries to probe used interface - port if AUTO is selected - - 0.09 01.09-95 Added module support - - 0.10 04.09-95 Fixed receive packet allocation to work - with kernels > 1.3.x - - 0.20 20.09-95 Added support for EtherTeam32 EISA - - 0.21 17.10-95 Removed the unnecessary extern - init_etherdev() declaration. Some - other cleanups. - Bugs: - In some cases the interface autoprobing code doesn't find - the correct interface type. In this case you can - manually choose the interface type in DOS with E16IC.EXE which is - configuration software for EtherTeam16i and EtherTeam32 cards. - - To do: - - Real multicast support -*/ - -static char *version = - "eth16i.c: v0.21 17-10-95 Mika Kuoppala (miku@elt.icl.fi)\n"; - -#include <linux/module.h> - -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/types.h> -#include <linux/fcntl.h> -#include <linux/interrupt.h> -#include <linux/ptrace.h> -#include <linux/ioport.h> -#include <linux/in.h> -#include <linux/malloc.h> -#include <linux/string.h> -#include <linux/errno.h> - -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> - -#include <asm/system.h> -#include <asm/bitops.h> -#include <asm/io.h> -#include <asm/dma.h> - -/* Few macros */ -#define BIT(a) ( (1 << (a)) ) -#define BITSET(ioaddr, bnum) ((outb(((inb(ioaddr)) | (bnum)), ioaddr))) -#define BITCLR(ioaddr, bnum) ((outb(((inb(ioaddr)) & (~(bnum))), ioaddr))) - -/* This is the I/O address space for Etherteam 16i adapter. */ -#define ETH16I_IO_EXTENT 32 - -/* Ticks before deciding that transmit has timed out */ -#define TIMEOUT_TICKS 30 - -/* Maximum loop count when receiving packets */ -#define MAX_RX_LOOP 40 - -/* Some interrupt masks */ -#define ETH16I_INTR_ON 0x8f82 -#define ETH16I_INTR_OFF 0x0000 - -/* Buffers header status byte meanings */ -#define PKT_GOOD BIT(5) -#define PKT_GOOD_RMT BIT(4) -#define PKT_SHORT BIT(3) -#define PKT_ALIGN_ERR BIT(2) -#define PKT_CRC_ERR BIT(1) -#define PKT_RX_BUF_OVERFLOW BIT(0) - -/* Transmit status register (DLCR0) */ -#define TX_STATUS_REG 0 -#define TX_DONE BIT(7) -#define NET_BUSY BIT(6) -#define TX_PKT_RCD BIT(5) -#define CR_LOST BIT(4) -#define COLLISION BIT(2) -#define COLLISIONS_16 BIT(1) - -/* Receive status register (DLCR1) */ -#define RX_STATUS_REG 1 -#define RX_PKT BIT(7) /* Packet received */ -#define BUS_RD_ERR BIT(6) -#define SHORT_PKT_ERR BIT(3) -#define ALIGN_ERR BIT(2) -#define CRC_ERR BIT(1) -#define RX_BUF_OVERFLOW BIT(0) - -/* Transmit Interrupt Enable Register (DLCR2) */ -#define TX_INTR_REG 2 -#define TX_INTR_DONE BIT(7) -#define TX_INTR_COL BIT(2) -#define TX_INTR_16_COL BIT(1) - -/* Receive Interrupt Enable Register (DLCR3) */ -#define RX_INTR_REG 3 -#define RX_INTR_RECEIVE BIT(7) -#define RX_INTR_SHORT_PKT BIT(3) -#define RX_INTR_CRC_ERR BIT(1) -#define RX_INTR_BUF_OVERFLOW BIT(0) - -/* Transmit Mode Register (DLCR4) */ -#define TRANSMIT_MODE_REG 4 -#define LOOPBACK_CONTROL BIT(1) -#define CONTROL_OUTPUT BIT(2) - -/* Receive Mode Register (DLCR5) */ -#define RECEIVE_MODE_REG 5 -#define RX_BUFFER_EMPTY BIT(6) -#define ACCEPT_BAD_PACKETS BIT(5) -#define RECEIVE_SHORT_ADDR BIT(4) -#define ACCEPT_SHORT_PACKETS BIT(3) -#define REMOTE_RESET BIT(2) - -#define ADDRESS_FILTER_MODE BIT(1) | BIT(0) -#define REJECT_ALL 0 -#define ACCEPT_ALL 3 -#define MODE_1 1 /* NODE ID, BC, MC, 2-24th bit */ -#define MODE_2 2 /* NODE ID, BC, MC, Hash Table */ - -/* Configuration Register 0 (DLCR6) */ -#define CONFIG_REG_0 6 -#define DLC_EN BIT(7) -#define SRAM_CYCLE_TIME_100NS BIT(6) -#define SYSTEM_BUS_WIDTH_8 BIT(5) /* 1 = 8bit, 0 = 16bit */ -#define BUFFER_WIDTH_8 BIT(4) /* 1 = 8bit, 0 = 16bit */ -#define TBS1 BIT(3) -#define TBS0 BIT(2) -#define BS1 BIT(1) /* 00=8kb, 01=16kb */ -#define BS0 BIT(0) /* 10=32kb, 11=64kb */ - -#ifndef ETH16I_TX_BUF_SIZE /* 0 = 2kb, 1 = 4kb */ -#define ETH16I_TX_BUF_SIZE 2 /* 2 = 8kb, 3 = 16kb */ -#endif -#define TX_BUF_1x2048 0 -#define TX_BUF_2x2048 1 -#define TX_BUF_2x4098 2 -#define TX_BUF_2x8192 3 - -/* Configuration Register 1 (DLCR7) */ -#define CONFIG_REG_1 7 -#define POWERUP BIT(5) - -/* Transmit start register */ -#define TRANSMIT_START_REG 10 -#define TRANSMIT_START_RB 2 -#define TX_START BIT(7) /* Rest of register bit indicate*/ - /* number of packets in tx buffer*/ -/* Node ID registers (DLCR8-13) */ -#define NODE_ID_0 8 -#define NODE_ID_RB 0 - -/* Hash Table registers (HT8-15) */ -#define HASH_TABLE_0 8 -#define HASH_TABLE_RB 1 - -/* Buffer memory ports */ -#define BUFFER_MEM_PORT_LB 8 -#define DATAPORT BUFFER_MEM_PORT_LB -#define BUFFER_MEM_PORT_HB 9 - -/* 16 Collision control register (BMPR11) */ -#define COL_16_REG 11 -#define HALT_ON_16 0x00 -#define RETRANS_AND_HALT_ON_16 0x02 - -/* DMA Burst and Transceiver Mode Register (BMPR13) */ -#define TRANSCEIVER_MODE_REG 13 -#define TRANSCEIVER_MODE_RB 2 -#define IO_BASE_UNLOCK BIT(7) -#define LOWER_SQUELCH_TRESH BIT(6) -#define LINK_TEST_DISABLE BIT(5) -#define AUI_SELECT BIT(4) -#define DIS_AUTO_PORT_SEL BIT(3) - -/* Filter Self Receive Register (BMPR14) */ -#define FILTER_SELF_RX_REG 14 -#define SKIP_RECEIVE_PACKET BIT(2) -#define FILTER_SELF_RECEIVE BIT(0) -#define RX_BUF_SKIP_PACKET SKIP_RECEIVE_PACKET | FILTER_SELF_RECEIVE - -/* EEPROM Control Register (BMPR 16) */ -#define EEPROM_CTRL_REG 16 - -/* EEPROM Data Register (BMPR 17) */ -#define EEPROM_DATA_REG 17 - -/* NMC93CSx6 EEPROM Control Bits */ -#define CS_0 0x00 -#define CS_1 0x20 -#define SK_0 0x00 -#define SK_1 0x40 -#define DI_0 0x00 -#define DI_1 0x80 - -/* NMC93CSx6 EEPROM Instructions */ -#define EEPROM_READ 0x80 - -/* NMC93CSx6 EEPROM Addresses */ -#define E_NODEID_0 0x02 -#define E_NODEID_1 0x03 -#define E_NODEID_2 0x04 -#define E_PORT_SELECT 0x14 - #define E_PORT_BNC 0 - #define E_PORT_DIX 1 - #define E_PORT_TP 2 - #define E_PORT_AUTO 3 -#define E_PRODUCT_CFG 0x30 - - -/* Macro to slow down io between EEPROM clock transitions */ -#define eeprom_slow_io() do { int _i = 40; while(--_i > 0) { __SLOW_DOWN_IO; }}while(0) - -/* Jumperless Configuration Register (BMPR19) */ -#define JUMPERLESS_CONFIG 19 - -/* ID ROM registers, writing to them also resets some parts of chip */ -#define ID_ROM_0 24 -#define ID_ROM_7 31 -#define RESET ID_ROM_0 - -/* This is the I/O address list to be probed when seeking the card */ -static unsigned int eth16i_portlist[] = - { 0x260, 0x280, 0x2A0, 0x240, 0x340, 0x320, 0x380, 0x300, 0 }; - -static unsigned int eth32i_portlist[] = - { 0x1000, 0x2000, 0x3000, 0x4000, 0x5000, 0x6000, 0x7000, 0x8000, - 0x9000, 0xA000, 0xB000, 0xC000, 0xD000, 0xE000, 0xF000, 0 }; - -/* This is the Interrupt lookup table for Eth16i card */ -static unsigned int eth16i_irqmap[] = { 9, 10, 5, 15 }; - -/* This is the Interrupt lookup table for Eth32i card */ -static unsigned int eth32i_irqmap[] = { 3, 5, 7, 9, 10, 11, 12, 15 }; -#define EISA_IRQ_REG 0xc89 - -static unsigned int eth16i_tx_buf_map[] = { 2048, 2048, 4096, 8192 }; -unsigned int boot = 1; - -/* Use 0 for production, 1 for verification, >2 for debug */ -#ifndef ETH16I_DEBUG -#define ETH16I_DEBUG 0 -#endif -static unsigned int eth16i_debug = ETH16I_DEBUG; - -/* Information for each board */ -struct eth16i_local { - struct enet_statistics stats; - unsigned int tx_started:1; - unsigned char tx_queue; /* Number of packets in transmit buffer */ - unsigned short tx_queue_len; - unsigned int tx_buf_size; - unsigned long open_time; -}; - -/* Function prototypes */ - -extern int eth16i_probe(struct device *dev); - -static int eth16i_probe1(struct device *dev, short ioaddr); -static int eth16i_check_signature(short ioaddr); -static int eth16i_probe_port(short ioaddr); -static void eth16i_set_port(short ioaddr, int porttype); -static int eth16i_send_probe_packet(short ioaddr, unsigned char *b, int l); -static int eth16i_receive_probe_packet(short ioaddr); -static int eth16i_get_irq(short ioaddr); -static int eth16i_read_eeprom(int ioaddr, int offset); -static int eth16i_read_eeprom_word(int ioaddr); -static void eth16i_eeprom_cmd(int ioaddr, unsigned char command); -static int eth16i_open(struct device *dev); -static int eth16i_close(struct device *dev); -static int eth16i_tx(struct sk_buff *skb, struct device *dev); -static void eth16i_rx(struct device *dev); -static void eth16i_interrupt(int irq, struct pt_regs *regs); -static void eth16i_multicast(struct device *dev, int num_addrs, void *addrs); -static void eth16i_select_regbank(unsigned char regbank, short ioaddr); -static void eth16i_initialize(struct device *dev); -static struct enet_statistics *eth16i_get_stats(struct device *dev); - -static char *cardname = "ICL EtherTeam 16i/32"; - -#ifdef HAVE_DEVLIST -/* Support for alternate probe manager */ -/struct netdev_entry eth16i_drv = - {"eth16i", eth16i_probe1, ETH16I_IO_EXTENT, eth16i_probe_list}; - -#else /* Not HAVE_DEVLIST */ -int eth16i_probe(struct device *dev) -{ - int i; - int ioaddr; - int base_addr = dev ? dev->base_addr : 0; - - if(eth16i_debug > 4) - printk("Probing started for %s\n", cardname); - - if(base_addr > 0x1ff) /* Check only single location */ - return eth16i_probe1(dev, base_addr); - else if(base_addr != 0) /* Don't probe at all */ - return ENXIO; - - /* Seek card from the ISA io address space */ - for(i = 0; (ioaddr = eth16i_portlist[i]) ; i++) { - if(check_region(ioaddr, ETH16I_IO_EXTENT)) - continue; - if(eth16i_probe1(dev, ioaddr) == 0) - return 0; - } - - /* Seek card from the EISA io address space */ - for(i = 0; (ioaddr = eth32i_portlist[i]) ; i++) { - if(check_region(ioaddr, ETH16I_IO_EXTENT)) - continue; - if(eth16i_probe1(dev, ioaddr) == 0) - return 0; - } - - return ENODEV; -} -#endif /* Not HAVE_DEVLIST */ - -static int eth16i_probe1(struct device *dev, short ioaddr) -{ - static unsigned version_printed = 0; - unsigned int irq = 0; - boot = 1; /* To inform initilization that we are in boot probe */ - - /* - The MB86985 chip has on register which holds information in which - io address the chip lies. First read this register and compare - it to our current io address and if match then this could - be our chip. - */ - - if(ioaddr < 0x1000) { - if(eth16i_portlist[(inb(ioaddr + JUMPERLESS_CONFIG) & 0x07)] != ioaddr) - return -ENODEV; - } - - /* Now we will go a bit deeper and try to find the chip's signature */ - - if(eth16i_check_signature(ioaddr) != 0) /* Can we find the signature here */ - return -ENODEV; - - /* - Now it seems that we have found a ethernet chip in this particular - ioaddr. The MB86985 chip has this feature, that when you read a - certain register it will increase it's io base address to next - configurable slot. Now when we have found the chip, first thing is - to make sure that the chip's ioaddr will hold still here. - */ - - eth16i_select_regbank(TRANSCEIVER_MODE_RB, ioaddr); - outb(0x00, ioaddr + TRANSCEIVER_MODE_REG); - - outb(0x00, ioaddr + RESET); /* Will reset some parts of chip */ - BITSET(ioaddr + CONFIG_REG_0, BIT(7)); /* This will disable the data link */ - - if(dev == NULL) - dev = init_etherdev(0, sizeof(struct eth16i_local)); - - if( (eth16i_debug & version_printed++) == 0) - printk(version); - - dev->base_addr = ioaddr; - - irq = eth16i_get_irq(ioaddr); - dev->irq = irq; - - /* Try to obtain interrupt vector */ - if(request_irq(dev->irq, ð16i_interrupt, 0, "eth16i")) { - printk("%s: %s at %#3x, but is unusable due - conflict on IRQ %d.\n", dev->name, cardname, ioaddr, irq); - return EAGAIN; - } - - printk("%s: %s at %#3x, IRQ %d, ", - dev->name, cardname, ioaddr, dev->irq); - - /* Let's grab the region */ - request_region(ioaddr, ETH16I_IO_EXTENT, "eth16i"); - - /* Now we will have to lock the chip's io address */ - eth16i_select_regbank(TRANSCEIVER_MODE_RB, ioaddr); - outb(0x38, ioaddr + TRANSCEIVER_MODE_REG); - - eth16i_initialize(dev); /* Initialize rest of the chip's registers */ - - /* Now let's same some energy by shutting down the chip ;) */ - BITCLR(ioaddr + CONFIG_REG_1, POWERUP); - - /* Initialize the device structure */ - if(dev->priv == NULL) - dev->priv = kmalloc(sizeof(struct eth16i_local), GFP_KERNEL); - memset(dev->priv, 0, sizeof(struct eth16i_local)); - - dev->open = eth16i_open; - dev->stop = eth16i_close; - dev->hard_start_xmit = eth16i_tx; - dev->get_stats = eth16i_get_stats; - dev->set_multicast_list = ð16i_multicast; - - /* Fill in the fields of the device structure with ethernet values. */ - ether_setup(dev); - - boot = 0; - - return 0; -} - - -static void eth16i_initialize(struct device *dev) -{ - short ioaddr = dev->base_addr; - int i, node_w = 0; - unsigned char node_byte = 0; - - /* Setup station address */ - eth16i_select_regbank(NODE_ID_RB, ioaddr); - for(i = 0 ; i < 3 ; i++) { - unsigned short node_val = eth16i_read_eeprom(ioaddr, E_NODEID_0 + i); - ((unsigned short *)dev->dev_addr)[i] = ntohs(node_val); - } - - for(i = 0; i < 6; i++) { - outb( ((unsigned char *)dev->dev_addr)[i], ioaddr + NODE_ID_0 + i); - if(boot) { - printk("%02x", inb(ioaddr + NODE_ID_0 + i)); - if(i != 5) - printk(":"); - } - } - - /* Now we will set multicast addresses to accept none */ - eth16i_select_regbank(HASH_TABLE_RB, ioaddr); - for(i = 0; i < 8; i++) - outb(0x00, ioaddr + HASH_TABLE_0 + i); - - /* - Now let's disable the transmitter and receiver, set the buffer ram - cycle time, bus width and buffer data path width. Also we shall - set transmit buffer size and total buffer size. - */ - - eth16i_select_regbank(2, ioaddr); - - node_byte = 0; - node_w = eth16i_read_eeprom(ioaddr, E_PRODUCT_CFG); - - if( (node_w & 0xFF00) == 0x0800) - node_byte |= BUFFER_WIDTH_8; - - node_byte |= BS1; - - if( (node_w & 0x00FF) == 64) - node_byte |= BS0; - - node_byte |= DLC_EN | SRAM_CYCLE_TIME_100NS | (ETH16I_TX_BUF_SIZE << 2); - - outb(node_byte, ioaddr + CONFIG_REG_0); - - /* We shall halt the transmitting, if 16 collisions are detected */ - outb(RETRANS_AND_HALT_ON_16, ioaddr + COL_16_REG); - - if(boot) /* Now set port type */ - { - char *porttype[] = {"BNC", "DIX", "TP", "AUTO"}; - - ushort ptype = eth16i_read_eeprom(ioaddr, E_PORT_SELECT); - dev->if_port = (ptype & 0x00FF); - - printk(" %s interface.\n", porttype[dev->if_port]); - - if(ptype == E_PORT_AUTO) - ptype = eth16i_probe_port(ioaddr); - - eth16i_set_port(ioaddr, ptype); - } - - /* Set Receive Mode to normal operation */ - outb(MODE_2, ioaddr + RECEIVE_MODE_REG); -} - -static int eth16i_probe_port(short ioaddr) -{ - int i; - int retcode; - unsigned char dummy_packet[64] = { 0 }; - - /* Powerup the chip */ - outb(0xc0 | POWERUP, ioaddr + CONFIG_REG_1); - - BITSET(ioaddr + CONFIG_REG_0, DLC_EN); - - eth16i_select_regbank(NODE_ID_RB, ioaddr); - - for(i = 0; i < 6; i++) { - dummy_packet[i] = inb(ioaddr + NODE_ID_0 + i); - dummy_packet[i+6] = inb(ioaddr + NODE_ID_0 + i); - } - - dummy_packet[12] = 0x00; - dummy_packet[13] = 0x04; - - eth16i_select_regbank(2, ioaddr); - - for(i = 0; i < 3; i++) { - BITSET(ioaddr + CONFIG_REG_0, DLC_EN); - BITCLR(ioaddr + CONFIG_REG_0, DLC_EN); - eth16i_set_port(ioaddr, i); - - if(eth16i_debug > 1) - printk("Set port number %d\n", i); - - retcode = eth16i_send_probe_packet(ioaddr, dummy_packet, 64); - if(retcode == 0) { - retcode = eth16i_receive_probe_packet(ioaddr); - if(retcode != -1) { - if(eth16i_debug > 1) - printk("Eth16i interface port found at %d\n", i); - return i; - } - } - else { - if(eth16i_debug > 1) - printk("TRANSMIT_DONE timeout\n"); - } - } - - if( eth16i_debug > 1) - printk("Using default port\n"); - - return E_PORT_BNC; -} - -static void eth16i_set_port(short ioaddr, int porttype) -{ - unsigned short temp = 0; - - eth16i_select_regbank(TRANSCEIVER_MODE_RB, ioaddr); - outb(LOOPBACK_CONTROL, ioaddr + TRANSMIT_MODE_REG); - - temp |= DIS_AUTO_PORT_SEL; - - switch(porttype) { - - case E_PORT_BNC : - temp |= AUI_SELECT; - break; - - case E_PORT_TP : - break; - - case E_PORT_DIX : - temp |= AUI_SELECT; - BITSET(ioaddr + TRANSMIT_MODE_REG, CONTROL_OUTPUT); - break; - } - outb(temp, ioaddr + TRANSCEIVER_MODE_REG); - - if(eth16i_debug > 1) { - printk("TRANSMIT_MODE_REG = %x\n", inb(ioaddr + TRANSMIT_MODE_REG)); - printk("TRANSCEIVER_MODE_REG = %x\n", inb(ioaddr+TRANSCEIVER_MODE_REG)); - } -} - -static int eth16i_send_probe_packet(short ioaddr, unsigned char *b, int l) -{ - int starttime; - - outb(0xff, ioaddr + TX_STATUS_REG); - - outw(l, ioaddr + DATAPORT); - outsw(ioaddr + DATAPORT, (unsigned short *)b, (l + 1) >> 1); - - starttime = jiffies; - outb(TX_START | 1, ioaddr + TRANSMIT_START_REG); - - while( (inb(ioaddr + TX_STATUS_REG) & 0x80) == 0) { - if( (jiffies - starttime) > TIMEOUT_TICKS) { - break; - } - } - - return(0); -} - -static int eth16i_receive_probe_packet(short ioaddr) -{ - int starttime; - - starttime = jiffies; - - while((inb(ioaddr + TX_STATUS_REG) & 0x20) == 0) { - if( (jiffies - starttime) > TIMEOUT_TICKS) { - - if(eth16i_debug > 1) - printk("Timeout occured waiting transmit packet received\n"); - starttime = jiffies; - while((inb(ioaddr + RX_STATUS_REG) & 0x80) == 0) { - if( (jiffies - starttime) > TIMEOUT_TICKS) { - if(eth16i_debug > 1) - printk("Timeout occured waiting receive packet\n"); - return -1; - } - } - - if(eth16i_debug > 1) - printk("RECEIVE_PACKET\n"); - return(0); /* Found receive packet */ - } - } - - if(eth16i_debug > 1) { - printk("TRANSMIT_PACKET_RECEIVED %x\n", inb(ioaddr + TX_STATUS_REG)); - printk("RX_STATUS_REG = %x\n", inb(ioaddr + RX_STATUS_REG)); - } - - return(0); /* Return success */ -} - -static int eth16i_get_irq(short ioaddr) -{ - unsigned char cbyte; - - if( ioaddr < 0x1000) { - cbyte = inb(ioaddr + JUMPERLESS_CONFIG); - return( eth16i_irqmap[ ((cbyte & 0xC0) >> 6) ] ); - } else { /* Oh..the card is EISA so method getting IRQ different */ - unsigned short index = 0; - cbyte = inb(ioaddr + EISA_IRQ_REG); - while( (cbyte & 0x01) == 0) { - cbyte = cbyte >> 1; - index++; - } - return( eth32i_irqmap[ index ] ); - } -} - -static int eth16i_check_signature(short ioaddr) -{ - int i; - unsigned char creg[4] = { 0 }; - - for(i = 0; i < 4 ; i++) { - - creg[i] = inb(ioaddr + TRANSMIT_MODE_REG + i); - - if(eth16i_debug > 1) - printk("eth16i: read signature byte %x at %x\n", creg[i], - ioaddr + TRANSMIT_MODE_REG + i); - } - - creg[0] &= 0x0F; /* Mask collision cnr */ - creg[2] &= 0x7F; /* Mask DCLEN bit */ - -#ifdef 0 -/* - This was removed because the card was sometimes left to state - from which it couldn't be find anymore. If there is need - to more strict chech still this have to be fixed. -*/ - if( !( (creg[0] == 0x06) && (creg[1] == 0x41)) ) { - if(creg[1] != 0x42) - return -1; - } -#endif - - if( !( (creg[2] == 0x36) && (creg[3] == 0xE0)) ) { - creg[2] &= 0x42; - creg[3] &= 0x03; - - if( !( (creg[2] == 0x42) && (creg[3] == 0x00)) ) - return -1; - } - - if(eth16i_read_eeprom(ioaddr, E_NODEID_0) != 0) - return -1; - if((eth16i_read_eeprom(ioaddr, E_NODEID_1) & 0xFF00) != 0x4B00) - return -1; - - return 0; -} - -static int eth16i_read_eeprom(int ioaddr, int offset) -{ - int data = 0; - - eth16i_eeprom_cmd(ioaddr, EEPROM_READ | offset); - outb(CS_1, ioaddr + EEPROM_CTRL_REG); - data = eth16i_read_eeprom_word(ioaddr); - outb(CS_0 | SK_0, ioaddr + EEPROM_CTRL_REG); - - return(data); -} - -static int eth16i_read_eeprom_word(int ioaddr) -{ - int i; - int data = 0; - - for(i = 16; i > 0; i--) { - outb(CS_1 | SK_0, ioaddr + EEPROM_CTRL_REG); - eeprom_slow_io(); - outb(CS_1 | SK_1, ioaddr + EEPROM_CTRL_REG); - eeprom_slow_io(); - data = (data << 1) | ((inb(ioaddr + EEPROM_DATA_REG) & DI_1) ? 1 : 0); - eeprom_slow_io(); - } - - return(data); -} - -static void eth16i_eeprom_cmd(int ioaddr, unsigned char command) -{ - int i; - - outb(CS_0 | SK_0, ioaddr + EEPROM_CTRL_REG); - outb(DI_0, ioaddr + EEPROM_DATA_REG); - outb(CS_1 | SK_0, ioaddr + EEPROM_CTRL_REG); - outb(DI_1, ioaddr + EEPROM_DATA_REG); - outb(CS_1 | SK_1, ioaddr + EEPROM_CTRL_REG); - - for(i = 7; i >= 0; i--) { - short cmd = ( (command & (1 << i)) ? DI_1 : DI_0 ); - outb(cmd, ioaddr + EEPROM_DATA_REG); - outb(CS_1 | SK_0, ioaddr + EEPROM_CTRL_REG); - eeprom_slow_io(); - outb(CS_1 | SK_1, ioaddr + EEPROM_CTRL_REG); - eeprom_slow_io(); - } -} - -static int eth16i_open(struct device *dev) -{ - struct eth16i_local *lp = (struct eth16i_local *)dev->priv; - int ioaddr = dev->base_addr; - - irq2dev_map[dev->irq] = dev; - - /* Powerup the chip */ - outb(0xc0 | POWERUP, ioaddr + CONFIG_REG_1); - - /* Initialize the chip */ - eth16i_initialize(dev); - - /* Set the transmit buffer size */ - lp->tx_buf_size = eth16i_tx_buf_map[ETH16I_TX_BUF_SIZE & 0x03]; - - if(eth16i_debug > 3) - printk("%s: transmit buffer size %d\n", dev->name, lp->tx_buf_size); - - /* Now enable Transmitter and Receiver sections */ - BITCLR(ioaddr + CONFIG_REG_0, DLC_EN); - - /* Now switch to register bank 2, for run time operation */ - eth16i_select_regbank(2, ioaddr); - - lp->open_time = jiffies; - lp->tx_started = 0; - lp->tx_queue = 0; - lp->tx_queue_len = 0; - - /* Turn on interrupts*/ - outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG); - - dev->tbusy = 0; - dev->interrupt = 0; - dev->start = 1; - -#ifdef MODULE - MOD_INC_USE_COUNT; -#endif - - return 0; -} - -static int eth16i_close(struct device *dev) -{ - struct eth16i_local *lp = (struct eth16i_local *)dev->priv; - int ioaddr = dev->base_addr; - - lp->open_time = 0; - - dev->tbusy = 1; - dev->start = 0; - - /* Disable transmit and receive */ - BITSET(ioaddr + CONFIG_REG_0, DLC_EN); - - /* Reset the chip */ - outb(0xff, ioaddr + RESET); - - /* Save some energy by switching off power */ - BITCLR(ioaddr + CONFIG_REG_1, POWERUP); - -#ifdef MODULE - MOD_DEC_USE_COUNT; -#endif - - return 0; -} - -static int eth16i_tx(struct sk_buff *skb, struct device *dev) -{ - struct eth16i_local *lp = (struct eth16i_local *)dev->priv; - int ioaddr = dev->base_addr; - - if(dev->tbusy) { - /* - If we get here, some higher level has decided that we are broken. - There should really be a "kick me" function call instead. - */ - - int tickssofar = jiffies - dev->trans_start; - if(tickssofar < TIMEOUT_TICKS) /* Let's not rush with our timeout, */ - return 1; /* wait a couple of ticks first */ - - printk("%s: transmit timed out with status %04x, %s ?\n", dev->name, - inw(ioaddr + TX_STATUS_REG), - (inb(ioaddr + TX_STATUS_REG) & TX_DONE) ? - "IRQ conflict" : "network cable problem"); - - /* Let's dump all registers */ - if(eth16i_debug > 0) { - printk("%s: timeout regs: %02x %02x %02x %02x %02x %02x %02x %02x.\n", - dev->name, inb(ioaddr + 0), inb(ioaddr + 1), inb(ioaddr + 2), - inb(ioaddr + 3), inb(ioaddr + 4), inb(ioaddr + 5), - inb(ioaddr + 6), inb(ioaddr + 7)); - - - printk("lp->tx_queue = %d\n", lp->tx_queue); - printk("lp->tx_queue_len = %d\n", lp->tx_queue_len); - printk("lp->tx_started = %d\n", lp->tx_started); - - } - - lp->stats.tx_errors++; - - /* Now let's try to restart the adaptor */ - - BITSET(ioaddr + CONFIG_REG_0, DLC_EN); - outw(0xffff, ioaddr + RESET); - eth16i_initialize(dev); - outw(0xffff, ioaddr + TX_STATUS_REG); - BITCLR(ioaddr + CONFIG_REG_0, DLC_EN); - - lp->tx_started = 0; - lp->tx_queue = 0; - lp->tx_queue_len = 0; - - outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG); - - dev->tbusy = 0; - dev->trans_start = jiffies; - } - - /* - If some higher layer thinks we've missed an tx-done interrupt - we are passed NULL. Caution: dev_tint() handles the cli()/sti() - itself - */ - if(skb == NULL) { - dev_tint(dev); - return 0; - } - - /* Block a timer based transmitter from overlapping. This could better be - done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ - - /* Turn off TX interrupts */ - outw(ETH16I_INTR_OFF, ioaddr + TX_INTR_REG); - - if(set_bit(0, (void *)&dev->tbusy) != 0) - printk("%s: Transmitter access conflict.\n", dev->name); - else { - short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; - unsigned char *buf = skb->data; - - outw(length, ioaddr + DATAPORT); - - if( ioaddr < 0x1000 ) - outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1); - else { - unsigned char frag = length % 4; - - outsl(ioaddr + DATAPORT, buf, length >> 2); - - if( frag != 0 ) { - outsw(ioaddr + DATAPORT, (buf + (length & 0xFFFC)), 1); - if( frag == 3 ) - outsw(ioaddr + DATAPORT, (buf + (length & 0xFFFC) + 2), 1); - } - } - - lp->tx_queue++; - lp->tx_queue_len += length + 2; - - if(lp->tx_started == 0) { - /* If the transmitter is idle..always trigger a transmit */ - outb(TX_START | lp->tx_queue, ioaddr + TRANSMIT_START_REG); - lp->tx_queue = 0; - lp->tx_queue_len = 0; - dev->trans_start = jiffies; - lp->tx_started = 1; - dev->tbusy = 0; - } - else if(lp->tx_queue_len < lp->tx_buf_size - (ETH_FRAME_LEN + 2)) { - /* There is still more room for one more packet in tx buffer */ - dev->tbusy = 0; - } - - outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG); - - /* Turn TX interrupts back on */ - /* outb(TX_INTR_DONE | TX_INTR_16_COL, ioaddr + TX_INTR_REG); */ - } - dev_kfree_skb(skb, FREE_WRITE); - - return 0; -} - -static void eth16i_rx(struct device *dev) -{ - struct eth16i_local *lp = (struct eth16i_local *)dev->priv; - int ioaddr = dev->base_addr; - int boguscount = MAX_RX_LOOP; - - /* Loop until all packets have been read */ - while( (inb(ioaddr + RECEIVE_MODE_REG) & RX_BUFFER_EMPTY) == 0) { - - /* Read status byte from receive buffer */ - ushort status = inw(ioaddr + DATAPORT); - - if(eth16i_debug > 4) - printk("%s: Receiving packet mode %02x status %04x.\n", - dev->name, inb(ioaddr + RECEIVE_MODE_REG), status); - - if( !(status & PKT_GOOD) ) { - /* Hmm..something went wrong. Let's check what error occured */ - lp->stats.rx_errors++; - if( status & PKT_SHORT ) lp->stats.rx_length_errors++; - if( status & PKT_ALIGN_ERR ) lp->stats.rx_frame_errors++; - if( status & PKT_CRC_ERR ) lp->stats.rx_crc_errors++; - if( status & PKT_RX_BUF_OVERFLOW) lp->stats.rx_over_errors++; - } - else { /* Ok so now we should have a good packet */ - struct sk_buff *skb; - - /* Get the size of the packet from receive buffer */ - ushort pkt_len = inw(ioaddr + DATAPORT); - - if(pkt_len > ETH_FRAME_LEN) { - printk("%s: %s claimed a very large packet, size of %d bytes.\n", - dev->name, cardname, pkt_len); - outb(RX_BUF_SKIP_PACKET, ioaddr + FILTER_SELF_RX_REG); - lp->stats.rx_dropped++; - break; - } - - skb = dev_alloc_skb(pkt_len + 3); - if( skb == NULL ) { - printk("%s: Could'n allocate memory for packet (len %d)\n", - dev->name, pkt_len); - outb(RX_BUF_SKIP_PACKET, ioaddr + FILTER_SELF_RX_REG); - lp->stats.rx_dropped++; - break; - } - - skb->dev = dev; - skb_reserve(skb,2); - /* - Now let's get the packet out of buffer. - size is (pkt_len + 1) >> 1, cause we are now reading words - and it have to be even aligned. - */ - - if( ioaddr < 0x1000) - insw(ioaddr + DATAPORT, skb_put(skb, pkt_len), (pkt_len + 1) >> 1); - else { - unsigned char *buf = skb_put(skb, pkt_len); - unsigned char frag = pkt_len % 4; - - insl(ioaddr + DATAPORT, buf, pkt_len >> 2); - - if(frag != 0) { - unsigned short rest[2]; - rest[0] = inw( ioaddr + DATAPORT ); - if(frag == 3) - rest[1] = inw( ioaddr + DATAPORT ); - - memcpy(buf + (pkt_len & 0xfffc), (char *)rest, frag); - } - } - - skb->protocol=eth_type_trans(skb, dev); - netif_rx(skb); - lp->stats.rx_packets++; - - if( eth16i_debug > 5 ) { - int i; - printk("%s: Received packet of length %d.\n", dev->name, pkt_len); - for(i = 0; i < 14; i++) - printk(" %02x", skb->data[i]); - printk(".\n"); - } - - } /* else */ - - if(--boguscount <= 0) - break; - - } /* while */ - -#if 0 - { - int i; - - for(i = 0; i < 20; i++) { - if( (inb(ioaddr+RECEIVE_MODE_REG) & RX_BUFFER_EMPTY) == RX_BUFFER_EMPTY) - break; - inw(ioaddr + DATAPORT); - outb(RX_BUF_SKIP_PACKET, ioaddr + FILTER_SELF_RX_REG); - } - - if(eth16i_debug > 1) - printk("%s: Flushed receive buffer.\n", dev->name); - } -#endif - - return; -} - -static void eth16i_interrupt(int irq, struct pt_regs *regs) -{ - struct device *dev = (struct device *)(irq2dev_map[irq]); - struct eth16i_local *lp; - int ioaddr = 0, - status; - - if(dev == NULL) { - printk("eth16i_interrupt(): irq %d for unknown device. \n", irq); - return; - } - - /* Turn off all interrupts from adapter */ - outw(ETH16I_INTR_OFF, ioaddr + TX_INTR_REG); - - dev->interrupt = 1; - - ioaddr = dev->base_addr; - lp = (struct eth16i_local *)dev->priv; - status = inw(ioaddr + TX_STATUS_REG); /* Get the status */ - outw(status, ioaddr + TX_STATUS_REG); /* Clear status bits */ - - if(eth16i_debug > 3) - printk("%s: Interrupt with status %04x.\n", dev->name, status); - - if( status & 0x00ff ) { /* Let's check the transmit status reg */ - - if(status & TX_DONE) { /* The transmit has been done */ - lp->stats.tx_packets++; - - if(lp->tx_queue) { /* Is there still packets ? */ - /* There was packet(s) so start transmitting and write also - how many packets there is to be sended */ - outb(TX_START | lp->tx_queue, ioaddr + TRANSMIT_START_REG); - lp->tx_queue = 0; - lp->tx_queue_len = 0; - dev->trans_start = jiffies; - dev->tbusy = 0; - mark_bh(NET_BH); - } - else { - lp->tx_started = 0; - dev->tbusy = 0; - mark_bh(NET_BH); - } - } - } - - if( ( status & 0xff00 ) || - ( (inb(ioaddr + RECEIVE_MODE_REG) & RX_BUFFER_EMPTY) == 0) ) { - eth16i_rx(dev); /* We have packet in receive buffer */ - } - - dev->interrupt = 0; - - /* Turn interrupts back on */ - outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG); - - return; -} - -static void eth16i_multicast(struct device *dev, int num_addrs, void *addrs) -{ - short ioaddr = dev->base_addr; - - if(dev->mc_count || dev->flags&(IFF_ALLMULTI|IFF_PROMISC)) - { - dev->flags|=IFF_PROMISC; /* Must do this */ - outb(3, ioaddr + RECEIVE_MODE_REG); - } else { - outb(2, ioaddr + RECEIVE_MODE_REG); - } -} - -static struct enet_statistics *eth16i_get_stats(struct device *dev) -{ - struct eth16i_local *lp = (struct eth16i_local *)dev->priv; - - return &lp->stats; -} - -static void eth16i_select_regbank(unsigned char banknbr, short ioaddr) -{ - unsigned char data; - - data = inb(ioaddr + CONFIG_REG_1); - outb( ((data & 0xF3) | ( (banknbr & 0x03) << 2)), ioaddr + CONFIG_REG_1); -} - -#ifdef MODULE -static char devicename[9] = { 0, }; -static struct device dev_eth16i = { - devicename, - 0, 0, 0, 0, - 0, 0, - 0, 0, 0, NULL, eth16i_probe }; - -int io = 0x2a0; -int irq = 0; - -int init_module(void) -{ - if(io == 0) - printk("eth16i: You should not use auto-probing with insmod!\n"); - - dev_eth16i.base_addr = io; - dev_eth16i.irq = irq; - if( register_netdev( &dev_eth16i ) != 0 ) { - printk("eth16i: register_netdev() returned non-zero.\n"); - return -EIO; - } - - return 0; -} - -void cleanup_module(void) -{ - unregister_netdev( &dev_eth16i ); - free_irq( dev_eth16i.irq ); - irq2dev_map[ dev_eth16i.irq ] = NULL; - release_region( dev_eth16i.base_addr, ETH16I_IO_EXTENT ); -} - -#endif /* MODULE */ - - diff --git a/i386/i386at/gpl/linux/net/ewrk3.c b/i386/i386at/gpl/linux/net/ewrk3.c deleted file mode 100644 index 90e3b932..00000000 --- a/i386/i386at/gpl/linux/net/ewrk3.c +++ /dev/null @@ -1,1933 +0,0 @@ -/* ewrk3.c: A DIGITAL EtherWORKS 3 ethernet driver for Linux. - - Written 1994 by David C. Davies. - - Copyright 1994 Digital Equipment Corporation. - - This software may be used and distributed according to the terms of - the GNU Public License, incorporated herein by reference. - - This driver is written for the Digital Equipment Corporation series - of EtherWORKS ethernet cards: - - DE203 Turbo (BNC) - DE204 Turbo (TP) - DE205 Turbo (TP BNC) - - The driver has been tested on a relatively busy network using the DE205 - card and benchmarked with 'ttcp': it transferred 16M of data at 975kB/s - (7.8Mb/s) to a DECstation 5000/200. - - The author may be reached at davies@wanton.lkg.dec.com or - davies@maniac.ultranet.com or Digital Equipment Corporation, 550 King - Street, Littleton MA 01460. - - ========================================================================= - This driver has been written substantially from scratch, although its - inheritance of style and stack interface from 'depca.c' and in turn from - Donald Becker's 'lance.c' should be obvious. - - The DE203/4/5 boards all use a new proprietary chip in place of the - LANCE chip used in prior cards (DEPCA, DE100, DE200/1/2, DE210, DE422). - Use the depca.c driver in the standard distribution for the LANCE based - cards from DIGITAL; this driver will not work with them. - - The DE203/4/5 cards have 2 main modes: shared memory and I/O only. I/O - only makes all the card accesses through I/O transactions and no high - (shared) memory is used. This mode provides a >48% performance penalty - and is deprecated in this driver, although allowed to provide initial - setup when hardstrapped. - - The shared memory mode comes in 3 flavours: 2kB, 32kB and 64kB. There is - no point in using any mode other than the 2kB mode - their performances - are virtually identical, although the driver has been tested in the 2kB - and 32kB modes. I would suggest you uncomment the line: - - FORCE_2K_MODE; - - to allow the driver to configure the card as a 2kB card at your current - base address, thus leaving more room to clutter your system box with - other memory hungry boards. - - As many ISA and EISA cards can be supported under this driver as you - wish, limited primarily by the available IRQ lines, rather than by the - available I/O addresses (24 ISA, 16 EISA). I have checked different - configurations of multiple depca cards and ewrk3 cards and have not - found a problem yet (provided you have at least depca.c v0.38) ... - - The board IRQ setting must be at an unused IRQ which is auto-probed - using Donald Becker's autoprobe routines. All these cards are at - {5,10,11,15}. - - No 16MB memory limitation should exist with this driver as DMA is not - used and the common memory area is in low memory on the network card (my - current system has 20MB and I've not had problems yet). - - The ability to load this driver as a loadable module has been included - and used extensively during the driver development (to save those long - reboot sequences). To utilise this ability, you have to do 8 things: - - 0) have a copy of the loadable modules code installed on your system. - 1) copy ewrk3.c from the /linux/drivers/net directory to your favourite - temporary directory. - 2) edit the source code near line 1880 to reflect the I/O address and - IRQ you're using. - 3) compile ewrk3.c, but include -DMODULE in the command line to ensure - that the correct bits are compiled (see end of source code). - 4) if you are wanting to add a new card, goto 5. Otherwise, recompile a - kernel with the ewrk3 configuration turned off and reboot. - 5) insmod ewrk3.o - [Alan Cox: Changed this so you can insmod ewrk3.o irq=x io=y] - 6) run the net startup bits for your new eth?? interface manually - (usually /etc/rc.inet[12] at boot time). - 7) enjoy! - - Note that autoprobing is not allowed in loadable modules - the system is - already up and running and you're messing with interrupts. - - To unload a module, turn off the associated interface - 'ifconfig eth?? down' then 'rmmod ewrk3'. - - Promiscuous mode has been turned off in this driver, but all the - multicast address bits have been turned on. This improved the send - performance on a busy network by about 13%. - - Ioctl's have now been provided (primarily because I wanted to grab some - packet size statistics). They are patterned after 'plipconfig.c' from a - suggestion by Alan Cox. Using these ioctls, you can enable promiscuous - mode, add/delete multicast addresses, change the hardware address, get - packet size distribution statistics and muck around with the control and - status register. I'll add others if and when the need arises. - - TO DO: - ------ - - - Revision History - ---------------- - - Version Date Description - - 0.1 26-aug-94 Initial writing. ALPHA code release. - 0.11 31-aug-94 Fixed: 2k mode memory base calc., - LeMAC version calc., - IRQ vector assignments during autoprobe. - 0.12 31-aug-94 Tested working on LeMAC2 (DE20[345]-AC) card. - Fixed up MCA hash table algorithm. - 0.20 4-sep-94 Added IOCTL functionality. - 0.21 14-sep-94 Added I/O mode. - 0.21axp 15-sep-94 Special version for ALPHA AXP Linux V1.0. - 0.22 16-sep-94 Added more IOCTLs & tidied up. - 0.23 21-sep-94 Added transmit cut through. - 0.24 31-oct-94 Added uid checks in some ioctls. - 0.30 1-nov-94 BETA code release. - 0.31 5-dec-94 Added check/allocate region code. - 0.32 16-jan-95 Broadcast packet fix. - 0.33 10-Feb-95 Fix recognition bug reported by <bkm@star.rl.ac.uk>. - 0.40 27-Dec-95 Rationalise MODULE and autoprobe code. - Rewrite for portability & updated. - ALPHA support from <jestabro@amt.tay1.dec.com> - Added verify_area() calls in depca_ioctl() from - suggestion by <heiko@colossus.escape.de>. - Add new multicasting code. - - ========================================================================= -*/ - -static const char *version = "ewrk3.c:v0.40 95/12/27 davies@wanton.lkg.dec.com\n"; - -#include <linux/module.h> - -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/string.h> -#include <linux/ptrace.h> -#include <linux/errno.h> -#include <linux/ioport.h> -#include <linux/malloc.h> -#include <linux/interrupt.h> -#include <linux/delay.h> -#include <asm/bitops.h> -#include <asm/io.h> -#include <asm/dma.h> -#include <asm/segment.h> - -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> - -#include <linux/time.h> -#include <linux/types.h> -#include <linux/unistd.h> - -#include "ewrk3.h" - -#ifdef EWRK3_DEBUG -static int ewrk3_debug = EWRK3_DEBUG; -#else -static int ewrk3_debug = 1; -#endif - -#define EWRK3_NDA 0xffe0 /* No Device Address */ - -#define PROBE_LENGTH 32 -#define ETH_PROM_SIG 0xAA5500FFUL - -#ifndef EWRK3_SIGNATURE -#define EWRK3_SIGNATURE {"DE203","DE204","DE205",""} -#define EWRK3_STRLEN 8 -#endif - -#ifndef EWRK3_RAM_BASE_ADDRESSES -#define EWRK3_RAM_BASE_ADDRESSES {0xc0000,0xd0000,0x00000} -#endif - -/* -** Sets up the I/O area for the autoprobe. -*/ -#define EWRK3_IO_BASE 0x100 /* Start address for probe search */ -#define EWRK3_IOP_INC 0x20 /* I/O address increment */ -#define EWRK3_TOTAL_SIZE 0x20 /* required I/O address length */ - -#ifndef MAX_NUM_EWRK3S -#define MAX_NUM_EWRK3S 21 -#endif - -#ifndef EWRK3_EISA_IO_PORTS -#define EWRK3_EISA_IO_PORTS 0x0c00 /* I/O port base address, slot 0 */ -#endif - -#ifndef MAX_EISA_SLOTS -#define MAX_EISA_SLOTS 16 -#define EISA_SLOT_INC 0x1000 -#endif - -#define CRC_POLYNOMIAL_BE 0x04c11db7UL /* Ethernet CRC, big endian */ -#define CRC_POLYNOMIAL_LE 0xedb88320UL /* Ethernet CRC, little endian */ - -#define QUEUE_PKT_TIMEOUT (100) /* Jiffies */ - -/* -** EtherWORKS 3 shared memory window sizes -*/ -#define IO_ONLY 0x00 -#define SHMEM_2K 0x800 -#define SHMEM_32K 0x8000 -#define SHMEM_64K 0x10000 - -/* -** EtherWORKS 3 IRQ ENABLE/DISABLE -*/ -#define ENABLE_IRQs { \ - icr |= lp->irq_mask;\ - outb(icr, EWRK3_ICR); /* Enable the IRQs */\ -} - -#define DISABLE_IRQs { \ - icr = inb(EWRK3_ICR);\ - icr &= ~lp->irq_mask;\ - outb(icr, EWRK3_ICR); /* Disable the IRQs */\ -} - -/* -** EtherWORKS 3 START/STOP -*/ -#define START_EWRK3 { \ - csr = inb(EWRK3_CSR);\ - csr &= ~(CSR_TXD|CSR_RXD);\ - outb(csr, EWRK3_CSR); /* Enable the TX and/or RX */\ -} - -#define STOP_EWRK3 { \ - csr = (CSR_TXD|CSR_RXD);\ - outb(csr, EWRK3_CSR); /* Disable the TX and/or RX */\ -} - -/* -** The EtherWORKS 3 private structure -*/ -#define EWRK3_PKT_STAT_SZ 16 -#define EWRK3_PKT_BIN_SZ 128 /* Should be >=100 unless you - increase EWRK3_PKT_STAT_SZ */ - -struct ewrk3_private { - char adapter_name[80]; /* Name exported to /proc/ioports */ - u_long shmem_base; /* Shared memory start address */ - u_long shmem_length; /* Shared memory window length */ - struct enet_statistics stats; /* Public stats */ - struct { - u32 bins[EWRK3_PKT_STAT_SZ]; /* Private stats counters */ - u32 unicast; - u32 multicast; - u32 broadcast; - u32 excessive_collisions; - u32 tx_underruns; - u32 excessive_underruns; - } pktStats; - u_char irq_mask; /* Adapter IRQ mask bits */ - u_char mPage; /* Maximum 2kB Page number */ - u_char lemac; /* Chip rev. level */ - u_char hard_strapped; /* Don't allow a full open */ - u_char lock; /* Lock the page register */ - u_char txc; /* Transmit cut through */ - u_char *mctbl; /* Pointer to the multicast table */ -}; - -/* -** Force the EtherWORKS 3 card to be in 2kB MODE -*/ -#define FORCE_2K_MODE { \ - shmem_length = SHMEM_2K;\ - outb(((mem_start - 0x80000) >> 11), EWRK3_MBR);\ -} - -/* -** Public Functions -*/ -static int ewrk3_open(struct device *dev); -static int ewrk3_queue_pkt(struct sk_buff *skb, struct device *dev); -static void ewrk3_interrupt(int irq, struct pt_regs *regs); -static int ewrk3_close(struct device *dev); -static struct enet_statistics *ewrk3_get_stats(struct device *dev); -static void set_multicast_list(struct device *dev); -static int ewrk3_ioctl(struct device *dev, struct ifreq *rq, int cmd); - -/* -** Private functions -*/ -static int ewrk3_hw_init(struct device *dev, u_long iobase); -static void ewrk3_init(struct device *dev); -static int ewrk3_rx(struct device *dev); -static int ewrk3_tx(struct device *dev); - -static void EthwrkSignature(char * name, char *eeprom_image); -static int DevicePresent(u_long iobase); -static void SetMulticastFilter(struct device *dev); -static int EISA_signature(char *name, s32 eisa_id); - -static int Read_EEPROM(u_long iobase, u_char eaddr); -static int Write_EEPROM(short data, u_long iobase, u_char eaddr); -static u_char get_hw_addr (struct device *dev, u_char *eeprom_image, char chipType); - -static void isa_probe(struct device *dev, u_long iobase); -static void eisa_probe(struct device *dev, u_long iobase); -static struct device *alloc_device(struct device *dev, u_long iobase); - - -#ifdef MODULE -int init_module(void); -void cleanup_module(void); -static int autoprobed = 1, loading_module = 1; - -# else -static u_char irq[] = {5,0,10,3,11,9,15,12}; -static int autoprobed = 0, loading_module = 0; - -#endif /* MODULE */ - -static char name[EWRK3_STRLEN + 1]; -static int num_ewrk3s = 0, num_eth = 0; - -/* -** Miscellaneous defines... -*/ -#define INIT_EWRK3 {\ - outb(EEPROM_INIT, EWRK3_IOPR);\ - udelay(1000);\ -} - - - - -int ewrk3_probe(struct device *dev) -{ - int tmp = num_ewrk3s, status = -ENODEV; - u_long iobase = dev->base_addr; - - if ((iobase == 0) && loading_module){ - printk("Autoprobing is not supported when loading a module based driver.\n"); - status = -EIO; - } else { /* First probe for the Ethernet */ - /* Address PROM pattern */ - isa_probe(dev, iobase); - eisa_probe(dev, iobase); - - if ((tmp == num_ewrk3s) && (iobase != 0) && loading_module) { - printk("%s: ewrk3_probe() cannot find device at 0x%04lx.\n", dev->name, - iobase); - } - - /* - ** Walk the device list to check that at least one device - ** initialised OK - */ - for (; (dev->priv == NULL) && (dev->next != NULL); dev = dev->next); - - if (dev->priv) status = 0; - if (iobase == 0) autoprobed = 1; - } - - return status; -} - -static int -ewrk3_hw_init(struct device *dev, u_long iobase) -{ - struct ewrk3_private *lp; - int i, status=0; - u_long mem_start, shmem_length; - u_char cr, cmr, icr, nicsr, lemac, hard_strapped = 0; - u_char eeprom_image[EEPROM_MAX], chksum, eisa_cr = 0; - - /* - ** Stop the EWRK3. Enable the DBR ROM. Disable interrupts and remote boot. - ** This also disables the EISA_ENABLE bit in the EISA Control Register. - */ - if (iobase > 0x400) eisa_cr = inb(EISA_CR); - INIT_EWRK3; - - nicsr = inb(EWRK3_CSR); - - icr = inb(EWRK3_ICR); - icr |= 0xf0; - outb(icr, EWRK3_ICR); /* Disable all the IRQs */ - - if (nicsr == CSR_TXD|CSR_RXD) { - - /* Check that the EEPROM is alive and well and not living on Pluto... */ - for (chksum=0, i=0; i<EEPROM_MAX; i+=2) { - union { - short val; - char c[2]; - } tmp; - - tmp.val = (short)Read_EEPROM(iobase, (i>>1)); - eeprom_image[i] = tmp.c[0]; - eeprom_image[i+1] = tmp.c[1]; - chksum += eeprom_image[i] + eeprom_image[i+1]; - } - - if (chksum != 0) { /* Bad EEPROM Data! */ - printk("%s: Device has a bad on-board EEPROM.\n", dev->name); - status = -ENXIO; - } else { - EthwrkSignature(name, eeprom_image); - if (*name != '\0') { /* found a EWRK3 device */ - dev->base_addr = iobase; - - if (iobase > 0x400) { - outb(eisa_cr, EISA_CR); /* Rewrite the EISA CR */ - } - - lemac = eeprom_image[EEPROM_CHIPVER]; - cmr = inb(EWRK3_CMR); - - if (((lemac == LeMAC) && ((cmr & CMR_NO_EEPROM) != CMR_NO_EEPROM)) || - ((lemac == LeMAC2) && !(cmr & CMR_HS))) { - printk("%s: %s at %#4lx", dev->name, name, iobase); - hard_strapped = 1; - } else if ((iobase&0x0fff)==EWRK3_EISA_IO_PORTS) { - /* EISA slot address */ - printk("%s: %s at %#4lx (EISA slot %ld)", - dev->name, name, iobase, ((iobase>>12)&0x0f)); - } else { /* ISA port address */ - printk("%s: %s at %#4lx", dev->name, name, iobase); - } - - if (!status) { - printk(", h/w address "); - if (lemac!=LeMAC2) DevicePresent(iobase);/* need after EWRK3_INIT */ - status = get_hw_addr(dev, eeprom_image, lemac); - for (i = 0; i < ETH_ALEN - 1; i++) { /* get the ethernet addr. */ - printk("%2.2x:", dev->dev_addr[i]); - } - printk("%2.2x,\n", dev->dev_addr[i]); - - if (status) { - printk(" which has an EEPROM CRC error.\n"); - status = -ENXIO; - } else { - if (lemac == LeMAC2) { /* Special LeMAC2 CMR things */ - cmr &= ~(CMR_RA | CMR_WB | CMR_LINK | CMR_POLARITY | CMR_0WS); - if (eeprom_image[EEPROM_MISC0] & READ_AHEAD) cmr |= CMR_RA; - if (eeprom_image[EEPROM_MISC0] & WRITE_BEHIND) cmr |= CMR_WB; - if (eeprom_image[EEPROM_NETMAN0] & NETMAN_POL) cmr |= CMR_POLARITY; - if (eeprom_image[EEPROM_NETMAN0] & NETMAN_LINK) cmr |= CMR_LINK; - if (eeprom_image[EEPROM_MISC0] & _0WS_ENA) cmr |= CMR_0WS; - } - if (eeprom_image[EEPROM_SETUP] & SETUP_DRAM) cmr |= CMR_DRAM; - outb(cmr, EWRK3_CMR); - - cr = inb(EWRK3_CR); /* Set up the Control Register */ - cr |= eeprom_image[EEPROM_SETUP] & SETUP_APD; - if (cr & SETUP_APD) cr |= eeprom_image[EEPROM_SETUP] & SETUP_PS; - cr |= eeprom_image[EEPROM_MISC0] & FAST_BUS; - cr |= eeprom_image[EEPROM_MISC0] & ENA_16; - outb(cr, EWRK3_CR); - - /* - ** Determine the base address and window length for the EWRK3 - ** RAM from the memory base register. - */ - mem_start = inb(EWRK3_MBR); - shmem_length = 0; - if (mem_start != 0) { - if ((mem_start >= 0x0a) && (mem_start <= 0x0f)) { - mem_start *= SHMEM_64K; - shmem_length = SHMEM_64K; - } else if ((mem_start >= 0x14) && (mem_start <= 0x1f)) { - mem_start *= SHMEM_32K; - shmem_length = SHMEM_32K; - } else if ((mem_start >= 0x40) && (mem_start <= 0xff)) { - mem_start = mem_start * SHMEM_2K + 0x80000; - shmem_length = SHMEM_2K; - } else { - status = -ENXIO; - } - } - - /* - ** See the top of this source code for comments about - ** uncommenting this line. - */ -/* FORCE_2K_MODE;*/ - - if (!status) { - if (hard_strapped) { - printk(" is hard strapped.\n"); - } else if (mem_start) { - printk(" has a %dk RAM window", (int)(shmem_length >> 10)); - printk(" at 0x%.5lx", mem_start); - } else { - printk(" is in I/O only mode"); - } - - /* private area & initialise */ - dev->priv = (void *) kmalloc(sizeof(struct ewrk3_private), - GFP_KERNEL); - if (dev->priv == NULL) { - return -ENOMEM; - } - lp = (struct ewrk3_private *)dev->priv; - memset(dev->priv, 0, sizeof(struct ewrk3_private)); - lp->shmem_base = mem_start; - lp->shmem_length = shmem_length; - lp->lemac = lemac; - lp->hard_strapped = hard_strapped; - - lp->mPage = 64; - if (cmr & CMR_DRAM) lp->mPage <<= 1 ;/* 2 DRAMS on module */ - - sprintf(lp->adapter_name,"%s (%s)", name, dev->name); - request_region(iobase, EWRK3_TOTAL_SIZE, lp->adapter_name); - - lp->irq_mask = ICR_TNEM|ICR_TXDM|ICR_RNEM|ICR_RXDM; - - if (!hard_strapped) { - /* - ** Enable EWRK3 board interrupts for autoprobing - */ - icr |= ICR_IE; /* Enable interrupts */ - outb(icr, EWRK3_ICR); - - /* The DMA channel may be passed in on this parameter. */ - dev->dma = 0; - - /* To auto-IRQ we enable the initialization-done and DMA err, - interrupts. For now we will always get a DMA error. */ - if (dev->irq < 2) { -#ifndef MODULE - u_char irqnum; - - autoirq_setup(0); - - /* - ** Trigger a TNE interrupt. - */ - icr |=ICR_TNEM; - outb(1,EWRK3_TDQ); /* Write to the TX done queue */ - outb(icr, EWRK3_ICR); /* Unmask the TXD interrupt */ - - irqnum = irq[((icr & IRQ_SEL) >> 4)]; - - dev->irq = autoirq_report(1); - if ((dev->irq) && (irqnum == dev->irq)) { - printk(" and uses IRQ%d.\n", dev->irq); - } else { - if (!dev->irq) { - printk(" and failed to detect IRQ line.\n"); - } else if ((irqnum == 1) && (lemac == LeMAC2)) { - printk(" and an illegal IRQ line detected.\n"); - } else { - printk(", but incorrect IRQ line detected.\n"); - } - status = -ENXIO; - } - - DISABLE_IRQs; /* Mask all interrupts */ - -#endif /* MODULE */ - } else { - printk(" and requires IRQ%d.\n", dev->irq); - } - } - if (status) release_region(iobase, EWRK3_TOTAL_SIZE); - } else { - status = -ENXIO; - } - } - } - } else { - status = -ENXIO; - } - } - - if (!status) { - if (ewrk3_debug > 0) { - printk(version); - } - - /* The EWRK3-specific entries in the device structure. */ - dev->open = &ewrk3_open; - dev->hard_start_xmit = &ewrk3_queue_pkt; - dev->stop = &ewrk3_close; - dev->get_stats = &ewrk3_get_stats; - dev->set_multicast_list = &set_multicast_list; - dev->do_ioctl = &ewrk3_ioctl; - - dev->mem_start = 0; - - /* Fill in the generic field of the device structure. */ - ether_setup(dev); - } - } else { - status = -ENXIO; - } - - return status; -} - - -static int -ewrk3_open(struct device *dev) -{ - struct ewrk3_private *lp = (struct ewrk3_private *)dev->priv; - u_long iobase = dev->base_addr; - int i, status = 0; - u_char icr, csr; - - /* - ** Stop the TX and RX... - */ - STOP_EWRK3; - - if (!lp->hard_strapped) { - irq2dev_map[dev->irq] = dev; /* For latched interrupts */ - - if (request_irq(dev->irq, (void *)ewrk3_interrupt, 0, "ewrk3")) { - printk("ewrk3_open(): Requested IRQ%d is busy\n",dev->irq); - status = -EAGAIN; - } else { - - /* - ** Re-initialize the EWRK3... - */ - ewrk3_init(dev); - - if (ewrk3_debug > 1){ - printk("%s: ewrk3 open with irq %d\n",dev->name,dev->irq); - printk(" physical address: "); - for (i=0;i<5;i++){ - printk("%2.2x:",(u_char)dev->dev_addr[i]); - } - printk("%2.2x\n",(u_char)dev->dev_addr[i]); - if (lp->shmem_length == 0) { - printk(" no shared memory, I/O only mode\n"); - } else { - printk(" start of shared memory: 0x%08lx\n",lp->shmem_base); - printk(" window length: 0x%04lx\n",lp->shmem_length); - } - printk(" # of DRAMS: %d\n",((inb(EWRK3_CMR) & 0x02) ? 2 : 1)); - printk(" csr: 0x%02x\n", inb(EWRK3_CSR)); - printk(" cr: 0x%02x\n", inb(EWRK3_CR)); - printk(" icr: 0x%02x\n", inb(EWRK3_ICR)); - printk(" cmr: 0x%02x\n", inb(EWRK3_CMR)); - printk(" fmqc: 0x%02x\n", inb(EWRK3_FMQC)); - } - - dev->tbusy = 0; - dev->start = 1; - dev->interrupt = UNMASK_INTERRUPTS; - - /* - ** Unmask EWRK3 board interrupts - */ - icr = inb(EWRK3_ICR); - ENABLE_IRQs; - - } - } else { - dev->start = 0; - dev->tbusy = 1; - printk("%s: ewrk3 available for hard strapped set up only.\n", dev->name); - printk(" Run the 'ewrk3setup' utility or remove the hard straps.\n"); - } - - MOD_INC_USE_COUNT; - - return status; -} - -/* -** Initialize the EtherWORKS 3 operating conditions -*/ -static void -ewrk3_init(struct device *dev) -{ - struct ewrk3_private *lp = (struct ewrk3_private *)dev->priv; - u_char csr, page; - u_long iobase = dev->base_addr; - - /* - ** Enable any multicasts - */ - set_multicast_list(dev); - - /* - ** Clean out any remaining entries in all the queues here - */ - while (inb(EWRK3_TQ)); - while (inb(EWRK3_TDQ)); - while (inb(EWRK3_RQ)); - while (inb(EWRK3_FMQ)); - - /* - ** Write a clean free memory queue - */ - for (page=1;page<lp->mPage;page++) { /* Write the free page numbers */ - outb(page, EWRK3_FMQ); /* to the Free Memory Queue */ - } - - lp->lock = 0; /* Ensure there are no locks */ - - START_EWRK3; /* Enable the TX and/or RX */ -} - -/* -** Writes a socket buffer to the free page queue -*/ -static int -ewrk3_queue_pkt(struct sk_buff *skb, struct device *dev) -{ - struct ewrk3_private *lp = (struct ewrk3_private *)dev->priv; - u_long iobase = dev->base_addr; - int status = 0; - u_char icr, csr; - - /* Transmitter timeout, serious problems. */ - if (dev->tbusy || lp->lock) { - int tickssofar = jiffies - dev->trans_start; - if (tickssofar < QUEUE_PKT_TIMEOUT) { - status = -1; - } else if (!lp->hard_strapped) { - printk("%s: transmit timed/locked out, status %04x, resetting.\n", - dev->name, inb(EWRK3_CSR)); - - /* - ** Mask all board interrupts - */ - DISABLE_IRQs; - - /* - ** Stop the TX and RX... - */ - STOP_EWRK3; - - ewrk3_init(dev); - - /* - ** Unmask EWRK3 board interrupts - */ - ENABLE_IRQs; - - dev->tbusy=0; - dev->trans_start = jiffies; - } - } else if (skb == NULL) { - dev_tint(dev); - } else if (skb->len > 0) { - - /* - ** Block a timer-based transmit from overlapping. This could better be - ** done with atomic_swap(1, dev->tbusy), but set_bit() works as well. - */ - if (set_bit(0, (void*)&dev->tbusy) != 0) - printk("%s: Transmitter access conflict.\n", dev->name); - - DISABLE_IRQs; /* So that the page # remains correct */ - - /* - ** Get a free page from the FMQ when resources are available - */ - if (inb(EWRK3_FMQC) > 0) { - u_long buf = 0; - u_char page; - - if ((page = inb(EWRK3_FMQ)) < lp->mPage) { - /* - ** Set up shared memory window and pointer into the window - */ - while (set_bit(0, (void *)&lp->lock) != 0); /* Wait for lock to free */ - if (lp->shmem_length == IO_ONLY) { - outb(page, EWRK3_IOPR); - } else if (lp->shmem_length == SHMEM_2K) { - buf = lp->shmem_base; - outb(page, EWRK3_MPR); - } else if (lp->shmem_length == SHMEM_32K) { - buf = ((((short)page << 11) & 0x7800) + lp->shmem_base); - outb((page >> 4), EWRK3_MPR); - } else if (lp->shmem_length == SHMEM_64K) { - buf = ((((short)page << 11) & 0xf800) + lp->shmem_base); - outb((page >> 5), EWRK3_MPR); - } else { - status = -1; - printk("%s: Oops - your private data area is hosed!\n",dev->name); - } - - if (!status) { - - /* - ** Set up the buffer control structures and copy the data from - ** the socket buffer to the shared memory . - */ - - if (lp->shmem_length == IO_ONLY) { - int i; - u_char *p = skb->data; - - outb((char)(TCR_QMODE | TCR_PAD | TCR_IFC), EWRK3_DATA); - outb((char)(skb->len & 0xff), EWRK3_DATA); - outb((char)((skb->len >> 8) & 0xff), EWRK3_DATA); - outb((char)0x04, EWRK3_DATA); - for (i=0; i<skb->len; i++) { - outb(*p++, EWRK3_DATA); - } - outb(page, EWRK3_TQ); /* Start sending pkt */ - } else { - writeb((char)(TCR_QMODE|TCR_PAD|TCR_IFC), (char *)buf);/* ctrl byte*/ - buf+=1; - writeb((char)(skb->len & 0xff), (char *)buf);/* length (16 bit xfer)*/ - buf+=1; - if (lp->txc) { - writeb((char)(((skb->len >> 8) & 0xff) | XCT), (char *)buf); - buf+=1; - writeb(0x04, (char *)buf); /* index byte */ - buf+=1; - writeb(0x00, (char *)(buf + skb->len)); /* Write the XCT flag */ - memcpy_toio(buf, skb->data, PRELOAD);/* Write PRELOAD bytes*/ - outb(page, EWRK3_TQ); /* Start sending pkt */ - memcpy_toio(buf+PRELOAD, skb->data+PRELOAD, skb->len-PRELOAD); - writeb(0xff, (char *)(buf + skb->len)); /* Write the XCT flag */ - } else { - writeb((char)((skb->len >> 8) & 0xff), (char *)buf); - buf+=1; - writeb(0x04, (char *)buf); /* index byte */ - buf+=1; - memcpy_toio((char *)buf, skb->data, skb->len);/* Write data bytes */ - outb(page, EWRK3_TQ); /* Start sending pkt */ - } - } - - dev->trans_start = jiffies; - dev_kfree_skb (skb, FREE_WRITE); - - } else { /* return unused page to the free memory queue */ - outb(page, EWRK3_FMQ); - } - lp->lock = 0; /* unlock the page register */ - } else { - printk("ewrk3_queue_pkt(): Invalid free memory page (%d).\n", - (u_char) page); - } - } else { - printk("ewrk3_queue_pkt(): No free resources...\n"); - printk("ewrk3_queue_pkt(): CSR: %02x ICR: %02x FMQC: %02x\n",inb(EWRK3_CSR),inb(EWRK3_ICR),inb(EWRK3_FMQC)); - } - - /* Check for free resources: clear 'tbusy' if there are some */ - if (inb(EWRK3_FMQC) > 0) { - dev->tbusy = 0; - } - - ENABLE_IRQs; - } - - return status; -} - -/* -** The EWRK3 interrupt handler. -*/ -static void -ewrk3_interrupt(int irq, struct pt_regs * regs) -{ - struct device *dev = (struct device *)(irq2dev_map[irq]); - struct ewrk3_private *lp; - u_long iobase; - u_char icr, cr, csr; - - if (dev == NULL) { - printk ("ewrk3_interrupt(): irq %d for unknown device.\n", irq); - } else { - lp = (struct ewrk3_private *)dev->priv; - iobase = dev->base_addr; - - if (dev->interrupt) - printk("%s: Re-entering the interrupt handler.\n", dev->name); - - dev->interrupt = MASK_INTERRUPTS; - - /* get the interrupt information */ - csr = inb(EWRK3_CSR); - - /* - ** Mask the EWRK3 board interrupts and turn on the LED - */ - DISABLE_IRQs; - - cr = inb(EWRK3_CR); - cr |= CR_LED; - outb(cr, EWRK3_CR); - - if (csr & CSR_RNE) /* Rx interrupt (packet[s] arrived) */ - ewrk3_rx(dev); - - if (csr & CSR_TNE) /* Tx interrupt (packet sent) */ - ewrk3_tx(dev); - - /* - ** Now deal with the TX/RX disable flags. These are set when there - ** are no more resources. If resources free up then enable these - ** interrupts, otherwise mask them - failure to do this will result - ** in the system hanging in an interrupt loop. - */ - if (inb(EWRK3_FMQC)) { /* any resources available? */ - lp->irq_mask |= ICR_TXDM|ICR_RXDM;/* enable the interrupt source */ - csr &= ~(CSR_TXD|CSR_RXD);/* ensure restart of a stalled TX or RX */ - outb(csr, EWRK3_CSR); - dev->tbusy = 0; /* clear TX busy flag */ - mark_bh(NET_BH); - } else { - lp->irq_mask &= ~(ICR_TXDM|ICR_RXDM);/* disable the interrupt source */ - } - - /* Unmask the EWRK3 board interrupts and turn off the LED */ - cr &= ~CR_LED; - outb(cr, EWRK3_CR); - - dev->interrupt = UNMASK_INTERRUPTS; - ENABLE_IRQs; - } - - return; -} - -static int -ewrk3_rx(struct device *dev) -{ - struct ewrk3_private *lp = (struct ewrk3_private *)dev->priv; - u_long iobase = dev->base_addr; - int i, status = 0; - u_char page, tmpPage = 0, tmpLock = 0; - u_long buf = 0; - - while (inb(EWRK3_RQC) && !status) { /* Whilst there's incoming data */ - if ((page = inb(EWRK3_RQ)) < lp->mPage) {/* Get next entry's buffer page */ - /* - ** Preempt any process using the current page register. Check for - ** an existing lock to reduce time taken in I/O transactions. - */ - if ((tmpLock = set_bit(0, (void *)&lp->lock)) == 1) { /* Assert lock */ - if (lp->shmem_length == IO_ONLY) { /* Get existing page */ - tmpPage = inb(EWRK3_IOPR); - } else { - tmpPage = inb(EWRK3_MPR); - } - } - - /* - ** Set up shared memory window and pointer into the window - */ - if (lp->shmem_length == IO_ONLY) { - outb(page, EWRK3_IOPR); - } else if (lp->shmem_length == SHMEM_2K) { - buf = lp->shmem_base; - outb(page, EWRK3_MPR); - } else if (lp->shmem_length == SHMEM_32K) { - buf = ((((short)page << 11) & 0x7800) + lp->shmem_base); - outb((page >> 4), EWRK3_MPR); - } else if (lp->shmem_length == SHMEM_64K) { - buf = ((((short)page << 11) & 0xf800) + lp->shmem_base); - outb((page >> 5), EWRK3_MPR); - } else { - status = -1; - printk("%s: Oops - your private data area is hosed!\n",dev->name); - } - - if (!status) { - char rx_status; - int pkt_len; - - if (lp->shmem_length == IO_ONLY) { - rx_status = inb(EWRK3_DATA); - pkt_len = inb(EWRK3_DATA); - pkt_len |= ((u_short)inb(EWRK3_DATA) << 8); - } else { - rx_status = readb(buf); - buf+=1; - pkt_len = readw(buf); - buf+=3; - } - - if (!(rx_status & R_ROK)) { /* There was an error. */ - lp->stats.rx_errors++; /* Update the error stats. */ - if (rx_status & R_DBE) lp->stats.rx_frame_errors++; - if (rx_status & R_CRC) lp->stats.rx_crc_errors++; - if (rx_status & R_PLL) lp->stats.rx_fifo_errors++; - } else { - struct sk_buff *skb; - - if ((skb = dev_alloc_skb(pkt_len+2)) != NULL) { - unsigned char *p; - skb->dev = dev; - skb_reserve(skb,2); /* Align to 16 bytes */ - p = skb_put(skb,pkt_len); - - if (lp->shmem_length == IO_ONLY) { - *p = inb(EWRK3_DATA); /* dummy read */ - for (i=0; i<pkt_len; i++) { - *p++ = inb(EWRK3_DATA); - } - } else { - memcpy_fromio(p, buf, pkt_len); - } - - /* - ** Notify the upper protocol layers that there is another - ** packet to handle - */ - skb->protocol=eth_type_trans(skb,dev); - netif_rx(skb); - - /* - ** Update stats - */ - lp->stats.rx_packets++; - for (i=1; i<EWRK3_PKT_STAT_SZ-1; i++) { - if (pkt_len < i*EWRK3_PKT_BIN_SZ) { - lp->pktStats.bins[i]++; - i = EWRK3_PKT_STAT_SZ; - } - } - p = skb->data; /* Look at the dest addr */ - if (p[0] & 0x01) { /* Multicast/Broadcast */ - if ((*(s32 *)&p[0] == -1) && (*(s16 *)&p[4] == -1)) { - lp->pktStats.broadcast++; - } else { - lp->pktStats.multicast++; - } - } else if ((*(s32 *)&p[0] == *(s32 *)&dev->dev_addr[0]) && - (*(s16 *)&p[4] == *(s16 *)&dev->dev_addr[4])) { - lp->pktStats.unicast++; - } - - lp->pktStats.bins[0]++; /* Duplicates stats.rx_packets */ - if (lp->pktStats.bins[0] == 0) { /* Reset counters */ - memset(&lp->pktStats, 0, sizeof(lp->pktStats)); - } - } else { - printk("%s: Insufficient memory; nuking packet.\n", dev->name); - lp->stats.rx_dropped++; /* Really, deferred. */ - break; - } - } - } - /* - ** Return the received buffer to the free memory queue - */ - outb(page, EWRK3_FMQ); - - if (tmpLock) { /* If a lock was preempted */ - if (lp->shmem_length == IO_ONLY) { /* Replace old page */ - outb(tmpPage, EWRK3_IOPR); - } else { - outb(tmpPage, EWRK3_MPR); - } - } - lp->lock = 0; /* Unlock the page register */ - } else { - printk("ewrk3_rx(): Illegal page number, page %d\n",page); - printk("ewrk3_rx(): CSR: %02x ICR: %02x FMQC: %02x\n",inb(EWRK3_CSR),inb(EWRK3_ICR),inb(EWRK3_FMQC)); - } - } - return status; -} - -/* -** Buffer sent - check for TX buffer errors. -*/ -static int -ewrk3_tx(struct device *dev) -{ - struct ewrk3_private *lp = (struct ewrk3_private *)dev->priv; - u_long iobase = dev->base_addr; - u_char tx_status; - - while ((tx_status = inb(EWRK3_TDQ)) > 0) { /* Whilst there's old buffers */ - if (tx_status & T_VSTS) { /* The status is valid */ - if (tx_status & T_TXE) { - lp->stats.tx_errors++; - if (tx_status & T_NCL) lp->stats.tx_carrier_errors++; - if (tx_status & T_LCL) lp->stats.tx_window_errors++; - if (tx_status & T_CTU) { - if ((tx_status & T_COLL) ^ T_XUR) { - lp->pktStats.tx_underruns++; - } else { - lp->pktStats.excessive_underruns++; - } - } else if (tx_status & T_COLL) { - if ((tx_status & T_COLL) ^ T_XCOLL) { - lp->stats.collisions++; - } else { - lp->pktStats.excessive_collisions++; - } - } - } else { - lp->stats.tx_packets++; - } - } - } - - return 0; -} - -static int -ewrk3_close(struct device *dev) -{ - struct ewrk3_private *lp = (struct ewrk3_private *)dev->priv; - u_long iobase = dev->base_addr; - u_char icr, csr; - - dev->start = 0; - dev->tbusy = 1; - - if (ewrk3_debug > 1) { - printk("%s: Shutting down ethercard, status was %2.2x.\n", - dev->name, inb(EWRK3_CSR)); - } - - /* - ** We stop the EWRK3 here... mask interrupts and stop TX & RX - */ - DISABLE_IRQs; - - STOP_EWRK3; - - /* - ** Clean out the TX and RX queues here (note that one entry - ** may get added to either the TXD or RX queues if the the TX or RX - ** just starts processing a packet before the STOP_EWRK3 command - ** is received. This will be flushed in the ewrk3_open() call). - */ - while (inb(EWRK3_TQ)); - while (inb(EWRK3_TDQ)); - while (inb(EWRK3_RQ)); - - if (!lp->hard_strapped) { - free_irq(dev->irq); - - irq2dev_map[dev->irq] = 0; - } - - MOD_DEC_USE_COUNT; - - return 0; -} - -static struct enet_statistics * -ewrk3_get_stats(struct device *dev) -{ - struct ewrk3_private *lp = (struct ewrk3_private *)dev->priv; - - /* Null body since there is no framing error counter */ - - return &lp->stats; -} - -/* -** Set or clear the multicast filter for this adaptor. -*/ -static void -set_multicast_list(struct device *dev) -{ - struct ewrk3_private *lp = (struct ewrk3_private *)dev->priv; - u_long iobase = dev->base_addr; - u_char csr; - - if (irq2dev_map[dev->irq] != NULL) { - csr = inb(EWRK3_CSR); - - if (lp->shmem_length == IO_ONLY) { - lp->mctbl = (char *) PAGE0_HTE; - } else { - lp->mctbl = (char *)(lp->shmem_base + PAGE0_HTE); - } - - csr &= ~(CSR_PME | CSR_MCE); - if (dev->flags & IFF_PROMISC) { /* set promiscuous mode */ - csr |= CSR_PME; - outb(csr, EWRK3_CSR); - } else { - SetMulticastFilter(dev); - csr |= CSR_MCE; - outb(csr, EWRK3_CSR); - } - } -} - -/* -** Calculate the hash code and update the logical address filter -** from a list of ethernet multicast addresses. -** Little endian crc one liner from Matt Thomas, DEC. -** -** Note that when clearing the table, the broadcast bit must remain asserted -** to receive broadcast messages. -*/ -static void SetMulticastFilter(struct device *dev) -{ - struct ewrk3_private *lp = (struct ewrk3_private *)dev->priv; - struct dev_mc_list *dmi=dev->mc_list; - u_long iobase = dev->base_addr; - int i; - char *addrs, j, bit, byte; - short *p = (short *) lp->mctbl; - u16 hashcode; - s32 crc, poly = CRC_POLYNOMIAL_LE; - - while (set_bit(0, (void *)&lp->lock) != 0); /* Wait for lock to free */ - - if (lp->shmem_length == IO_ONLY) { - outb(0, EWRK3_IOPR); - outw(EEPROM_OFFSET(lp->mctbl), EWRK3_PIR1); - } else { - outb(0, EWRK3_MPR); - } - - if (dev->flags & IFF_ALLMULTI) { - for (i=0; i<(HASH_TABLE_LEN >> 3); i++) { - if (lp->shmem_length == IO_ONLY) { - outb(0xff, EWRK3_DATA); - } else { /* memset didn't work here */ - writew(0xffff, p); - p++; i++; - } - } - } else { - /* Clear table except for broadcast bit */ - if (lp->shmem_length == IO_ONLY) { - for (i=0; i<(HASH_TABLE_LEN >> 4) - 1; i++) { - outb(0x00, EWRK3_DATA); - } - outb(0x80, EWRK3_DATA); i++; /* insert the broadcast bit */ - for (; i<(HASH_TABLE_LEN >> 3); i++) { - outb(0x00, EWRK3_DATA); - } - } else { - memset_io(lp->mctbl, 0, (HASH_TABLE_LEN >> 3)); - writeb(0x80, (char *)(lp->mctbl + (HASH_TABLE_LEN >> 4) - 1)); - } - - /* Update table */ - for (i=0;i<dev->mc_count;i++) { /* for each address in the list */ - addrs=dmi->dmi_addr; - dmi=dmi->next; - if ((*addrs & 0x01) == 1) { /* multicast address? */ - crc = 0xffffffff; /* init CRC for each address */ - for (byte=0;byte<ETH_ALEN;byte++) { /* for each address byte */ - /* process each address bit */ - for (bit = *addrs++,j=0;j<8;j++, bit>>=1) { - crc = (crc >> 1) ^ (((crc ^ bit) & 0x01) ? poly : 0); - } - } - hashcode = crc & ((1 << 9) - 1); /* hashcode is 9 LSb of CRC */ - - byte = hashcode >> 3; /* bit[3-8] -> byte in filter */ - bit = 1 << (hashcode & 0x07); /* bit[0-2] -> bit in byte */ - - if (lp->shmem_length == IO_ONLY) { - u_char tmp; - - outw((short)((long)lp->mctbl) + byte, EWRK3_PIR1); - tmp = inb(EWRK3_DATA); - tmp |= bit; - outw((short)((long)lp->mctbl) + byte, EWRK3_PIR1); - outb(tmp, EWRK3_DATA); - } else { - writeb(readb(lp->mctbl + byte) | bit, lp->mctbl + byte); - } - } - } - } - - lp->lock = 0; /* Unlock the page register */ - - return; -} - -/* -** ISA bus I/O device probe -*/ -static void isa_probe(struct device *dev, u_long ioaddr) -{ - int i = num_ewrk3s, maxSlots; - u_long iobase; - - if (!ioaddr && autoprobed) return ; /* Been here before ! */ - if (ioaddr >= 0x400) return; /* Not ISA */ - - if (ioaddr == 0) { /* Autoprobing */ - iobase = EWRK3_IO_BASE; /* Get the first slot address */ - maxSlots = 24; - } else { /* Probe a specific location */ - iobase = ioaddr; - maxSlots = i + 1; - } - - for (; (i<maxSlots) && (dev!=NULL);iobase+=EWRK3_IOP_INC, i++) { - if (!check_region(iobase, EWRK3_TOTAL_SIZE)) { - if (DevicePresent(iobase) == 0) { - if ((dev = alloc_device(dev, iobase)) != NULL) { - if (ewrk3_hw_init(dev, iobase) == 0) { - num_ewrk3s++; - } - num_eth++; - } - } - } else if (autoprobed) { - printk("%s: region already allocated at 0x%04lx.\n", dev->name, iobase); - } - } - - return; -} - -/* -** EISA bus I/O device probe. Probe from slot 1 since slot 0 is usually -** the motherboard. -*/ -static void eisa_probe(struct device *dev, u_long ioaddr) -{ - int i, maxSlots; - u_long iobase; - char name[EWRK3_STRLEN]; - - if (!ioaddr && autoprobed) return ; /* Been here before ! */ - if (ioaddr < 0x1000) return; /* Not EISA */ - - if (ioaddr == 0) { /* Autoprobing */ - iobase = EISA_SLOT_INC; /* Get the first slot address */ - i = 1; - maxSlots = MAX_EISA_SLOTS; - } else { /* Probe a specific location */ - iobase = ioaddr; - i = (ioaddr >> 12); - maxSlots = i + 1; - } - - for (i=1; (i<maxSlots) && (dev!=NULL); i++, iobase+=EISA_SLOT_INC) { - if (EISA_signature(name, EISA_ID) == 0) { - if (!check_region(iobase, EWRK3_TOTAL_SIZE)) { - if (DevicePresent(iobase) == 0) { - if ((dev = alloc_device(dev, iobase)) != NULL) { - if (ewrk3_hw_init(dev, iobase) == 0) { - num_ewrk3s++; - } - num_eth++; - } - } - } else if (autoprobed) { - printk("%s: region already allocated at 0x%04lx.\n", dev->name, iobase); - } - } - } - - return; -} - -/* -** Allocate the device by pointing to the next available space in the -** device structure. Should one not be available, it is created. -*/ -static struct device *alloc_device(struct device *dev, u_long iobase) -{ - int addAutoProbe = 0; - struct device *tmp = NULL, *ret; - int (*init)(struct device *) = NULL; - - /* - ** Check the device structures for an end of list or unused device - */ - if (!loading_module) { - while (dev->next != NULL) { - if ((dev->base_addr == EWRK3_NDA) || (dev->base_addr == 0)) break; - dev = dev->next; /* walk through eth device list */ - num_eth++; /* increment eth device number */ - } - - /* - ** If an autoprobe is requested for another device, we must re-insert - ** the request later in the list. Remember the current position first. - */ - if ((dev->base_addr == 0) && (num_ewrk3s > 0)) { - addAutoProbe++; - tmp = dev->next; /* point to the next device */ - init = dev->init; /* remember the probe function */ - } - - /* - ** If at end of list and can't use current entry, malloc one up. - ** If memory could not be allocated, print an error message. - */ - if ((dev->next == NULL) && - !((dev->base_addr == EWRK3_NDA) || (dev->base_addr == 0))){ - dev->next = (struct device *)kmalloc(sizeof(struct device) + 8, - GFP_KERNEL); - - dev = dev->next; /* point to the new device */ - if (dev == NULL) { - printk("eth%d: Device not initialised, insufficient memory\n", - num_eth); - } else { - /* - ** If the memory was allocated, point to the new memory area - ** and initialize it (name, I/O address, next device (NULL) and - ** initialisation probe routine). - */ - dev->name = (char *)(dev + sizeof(struct device)); - if (num_eth > 9999) { - sprintf(dev->name,"eth????"); /* New device name */ - } else { - sprintf(dev->name,"eth%d", num_eth);/* New device name */ - } - dev->base_addr = iobase; /* assign the io address */ - dev->next = NULL; /* mark the end of list */ - dev->init = &ewrk3_probe; /* initialisation routine */ - num_ewrk3s++; - } - } - ret = dev; /* return current struct, or NULL */ - - /* - ** Now figure out what to do with the autoprobe that has to be inserted. - ** Firstly, search the (possibly altered) list for an empty space. - */ - if (ret != NULL) { - if (addAutoProbe) { - for (;(tmp->next!=NULL) && (tmp->base_addr!=EWRK3_NDA); tmp=tmp->next); - - /* - ** If no more device structures and can't use the current one, malloc - ** one up. If memory could not be allocated, print an error message. - */ - if ((tmp->next == NULL) && !(tmp->base_addr == EWRK3_NDA)) { - tmp->next = (struct device *)kmalloc(sizeof(struct device) + 8, - GFP_KERNEL); - tmp = tmp->next; /* point to the new device */ - if (tmp == NULL) { - printk("%s: Insufficient memory to extend the device list.\n", - dev->name); - } else { - /* - ** If the memory was allocated, point to the new memory area - ** and initialize it (name, I/O address, next device (NULL) and - ** initialisation probe routine). - */ - tmp->name = (char *)(tmp + sizeof(struct device)); - if (num_eth > 9999) { - sprintf(tmp->name,"eth????"); /* New device name */ - } else { - sprintf(tmp->name,"eth%d", num_eth);/* New device name */ - } - tmp->base_addr = 0; /* re-insert the io address */ - tmp->next = NULL; /* mark the end of list */ - tmp->init = init; /* initialisation routine */ - } - } else { /* structure already exists */ - tmp->base_addr = 0; /* re-insert the io address */ - } - } - } - } else { - ret = dev; - } - - return ret; -} - -/* -** Read the EWRK3 EEPROM using this routine -*/ -static int Read_EEPROM(u_long iobase, u_char eaddr) -{ - int i; - - outb((eaddr & 0x3f), EWRK3_PIR1); /* set up 6 bits of address info */ - outb(EEPROM_RD, EWRK3_IOPR); /* issue read command */ - for (i=0;i<5000;i++) inb(EWRK3_CSR); /* wait 1msec */ - - return inw(EWRK3_EPROM1); /* 16 bits data return */ -} - -/* -** Write the EWRK3 EEPROM using this routine -*/ -static int Write_EEPROM(short data, u_long iobase, u_char eaddr) -{ - int i; - - outb(EEPROM_WR_EN, EWRK3_IOPR); /* issue write enable command */ - for (i=0;i<5000;i++) inb(EWRK3_CSR); /* wait 1msec */ - outw(data, EWRK3_EPROM1); /* write data to register */ - outb((eaddr & 0x3f), EWRK3_PIR1); /* set up 6 bits of address info */ - outb(EEPROM_WR, EWRK3_IOPR); /* issue write command */ - for (i=0;i<75000;i++) inb(EWRK3_CSR); /* wait 15msec */ - outb(EEPROM_WR_DIS, EWRK3_IOPR); /* issue write disable command */ - for (i=0;i<5000;i++) inb(EWRK3_CSR); /* wait 1msec */ - - return 0; -} - -/* -** Look for a particular board name in the on-board EEPROM. -*/ -static void EthwrkSignature(char *name, char *eeprom_image) -{ - u_long i,j,k; - char *signatures[] = EWRK3_SIGNATURE; - - strcpy(name, ""); - for (i=0;*signatures[i] != '\0' && *name == '\0';i++) { - for (j=EEPROM_PNAME7,k=0;j<=EEPROM_PNAME0 && k<strlen(signatures[i]);j++) { - if (signatures[i][k] == eeprom_image[j]) { /* track signature */ - k++; - } else { /* lost signature; begin search again */ - k=0; - } - } - if (k == strlen(signatures[i])) { - for (k=0; k<EWRK3_STRLEN; k++) { - name[k] = eeprom_image[EEPROM_PNAME7 + k]; - name[EWRK3_STRLEN] = '\0'; - } - } - } - - return; /* return the device name string */ -} - -/* -** Look for a special sequence in the Ethernet station address PROM that -** is common across all EWRK3 products. -** -** Search the Ethernet address ROM for the signature. Since the ROM address -** counter can start at an arbitrary point, the search must include the entire -** probe sequence length plus the (length_of_the_signature - 1). -** Stop the search IMMEDIATELY after the signature is found so that the -** PROM address counter is correctly positioned at the start of the -** ethernet address for later read out. -*/ - -static int DevicePresent(u_long iobase) -{ - union { - struct { - u32 a; - u32 b; - } llsig; - char Sig[sizeof(u32) << 1]; - } dev; - short sigLength; - char data; - int i, j, status = 0; - - dev.llsig.a = ETH_PROM_SIG; - dev.llsig.b = ETH_PROM_SIG; - sigLength = sizeof(u32) << 1; - - for (i=0,j=0;j<sigLength && i<PROBE_LENGTH+sigLength-1;i++) { - data = inb(EWRK3_APROM); - if (dev.Sig[j] == data) { /* track signature */ - j++; - } else { /* lost signature; begin search again */ - if (data == dev.Sig[0]) { - j=1; - } else { - j=0; - } - } - } - - if (j!=sigLength) { - status = -ENODEV; /* search failed */ - } - - return status; -} - -static u_char get_hw_addr(struct device *dev, u_char *eeprom_image, char chipType) -{ - int i, j, k; - u_short chksum; - u_char crc, lfsr, sd, status = 0; - u_long iobase = dev->base_addr; - u16 tmp; - - if (chipType == LeMAC2) { - for (crc=0x6a, j=0; j<ETH_ALEN; j++) { - sd = dev->dev_addr[j] = eeprom_image[EEPROM_PADDR0 + j]; - outb(dev->dev_addr[j], EWRK3_PAR0 + j); - for (k=0; k<8; k++, sd >>= 1) { - lfsr = ((((crc & 0x02) >> 1) ^ (crc & 0x01)) ^ (sd & 0x01)) << 7; - crc = (crc >> 1) + lfsr; - } - } - if (crc != eeprom_image[EEPROM_PA_CRC]) status = -1; - } else { - for (i=0,k=0;i<ETH_ALEN;) { - k <<= 1 ; - if (k > 0xffff) k-=0xffff; - - k += (u_char) (tmp = inb(EWRK3_APROM)); - dev->dev_addr[i] = (u_char) tmp; - outb(dev->dev_addr[i], EWRK3_PAR0 + i); - i++; - k += (u_short) ((tmp = inb(EWRK3_APROM)) << 8); - dev->dev_addr[i] = (u_char) tmp; - outb(dev->dev_addr[i], EWRK3_PAR0 + i); - i++; - - if (k > 0xffff) k-=0xffff; - } - if (k == 0xffff) k=0; - chksum = inb(EWRK3_APROM); - chksum |= (inb(EWRK3_APROM)<<8); - if (k != chksum) status = -1; - } - - return status; -} - -/* -** Look for a particular board name in the EISA configuration space -*/ -static int EISA_signature(char *name, s32 eisa_id) -{ - u_long i; - char *signatures[] = EWRK3_SIGNATURE; - char ManCode[EWRK3_STRLEN]; - union { - s32 ID; - char Id[4]; - } Eisa; - int status = 0; - - *name = '\0'; - for (i=0; i<4; i++) { - Eisa.Id[i] = inb(eisa_id + i); - } - - ManCode[0]=(((Eisa.Id[0]>>2)&0x1f)+0x40); - ManCode[1]=(((Eisa.Id[1]&0xe0)>>5)+((Eisa.Id[0]&0x03)<<3)+0x40); - ManCode[2]=(((Eisa.Id[2]>>4)&0x0f)+0x30); - ManCode[3]=((Eisa.Id[2]&0x0f)+0x30); - ManCode[4]=(((Eisa.Id[3]>>4)&0x0f)+0x30); - ManCode[5]='\0'; - - for (i=0;(*signatures[i] != '\0') && (*name == '\0');i++) { - if (strstr(ManCode, signatures[i]) != NULL) { - strcpy(name,ManCode); - status = 1; - } - } - - return status; /* return the device name string */ -} - -/* -** Perform IOCTL call functions here. Some are privileged operations and the -** effective uid is checked in those cases. -*/ -static int ewrk3_ioctl(struct device *dev, struct ifreq *rq, int cmd) -{ - struct ewrk3_private *lp = (struct ewrk3_private *)dev->priv; - struct ewrk3_ioctl *ioc = (struct ewrk3_ioctl *) &rq->ifr_data; - u_long iobase = dev->base_addr; - int i, j, status = 0; - u_char csr; - union { - u_char addr[HASH_TABLE_LEN * ETH_ALEN]; - u_short val[(HASH_TABLE_LEN * ETH_ALEN) >> 1]; - } tmp; - - switch(ioc->cmd) { - case EWRK3_GET_HWADDR: /* Get the hardware address */ - for (i=0; i<ETH_ALEN; i++) { - tmp.addr[i] = dev->dev_addr[i]; - } - ioc->len = ETH_ALEN; - if (!(status = verify_area(VERIFY_WRITE, (void *)ioc->data, ioc->len))) { - memcpy_tofs(ioc->data, tmp.addr, ioc->len); - } - - break; - case EWRK3_SET_HWADDR: /* Set the hardware address */ - if (suser()) { - if (!(status = verify_area(VERIFY_READ, (void *)ioc->data, ETH_ALEN))) { - csr = inb(EWRK3_CSR); - csr |= (CSR_TXD|CSR_RXD); - outb(csr, EWRK3_CSR); /* Disable the TX and RX */ - - memcpy_fromfs(tmp.addr,ioc->data,ETH_ALEN); - for (i=0; i<ETH_ALEN; i++) { - dev->dev_addr[i] = tmp.addr[i]; - outb(tmp.addr[i], EWRK3_PAR0 + i); - } - - csr &= ~(CSR_TXD|CSR_RXD); /* Enable the TX and RX */ - outb(csr, EWRK3_CSR); - } - } else { - status = -EPERM; - } - - break; - case EWRK3_SET_PROM: /* Set Promiscuous Mode */ - if (suser()) { - csr = inb(EWRK3_CSR); - csr |= CSR_PME; - csr &= ~CSR_MCE; - outb(csr, EWRK3_CSR); - } else { - status = -EPERM; - } - - break; - case EWRK3_CLR_PROM: /* Clear Promiscuous Mode */ - if (suser()) { - csr = inb(EWRK3_CSR); - csr &= ~CSR_PME; - outb(csr, EWRK3_CSR); - } else { - status = -EPERM; - } - - break; - case EWRK3_SAY_BOO: /* Say "Boo!" to the kernel log file */ - printk("%s: Boo!\n", dev->name); - - break; - case EWRK3_GET_MCA: /* Get the multicast address table */ - if (!(status = verify_area(VERIFY_WRITE, ioc->data, ioc->len))) { - while (set_bit(0, (void *)&lp->lock) != 0); /* Wait for lock to free */ - if (lp->shmem_length == IO_ONLY) { - outb(0, EWRK3_IOPR); - outw(PAGE0_HTE, EWRK3_PIR1); - for (i=0; i<(HASH_TABLE_LEN >> 3); i++) { - tmp.addr[i] = inb(EWRK3_DATA); - } - } else { - outb(0, EWRK3_MPR); - memcpy_fromio(tmp.addr, (char *)(lp->shmem_base + PAGE0_HTE), (HASH_TABLE_LEN >> 3)); - } - ioc->len = (HASH_TABLE_LEN >> 3); - memcpy_tofs(ioc->data, tmp.addr, ioc->len); - } - lp->lock = 0; /* Unlock the page register */ - - break; - case EWRK3_SET_MCA: /* Set a multicast address */ - if (suser()) { - if (!(status=verify_area(VERIFY_READ, ioc->data, ETH_ALEN*ioc->len))) { - memcpy_fromfs(tmp.addr, ioc->data, ETH_ALEN * ioc->len); - set_multicast_list(dev); - } - } else { - status = -EPERM; - } - - break; - case EWRK3_CLR_MCA: /* Clear all multicast addresses */ - if (suser()) { - set_multicast_list(dev); - } else { - status = -EPERM; - } - - break; - case EWRK3_MCA_EN: /* Enable multicast addressing */ - if (suser()) { - csr = inb(EWRK3_CSR); - csr |= CSR_MCE; - csr &= ~CSR_PME; - outb(csr, EWRK3_CSR); - } else { - status = -EPERM; - } - - break; - case EWRK3_GET_STATS: /* Get the driver statistics */ - cli(); - ioc->len = sizeof(lp->pktStats); - if (!(status=verify_area(VERIFY_WRITE, ioc->data, ioc->len))) { - memcpy_tofs(ioc->data, &lp->pktStats, ioc->len); - } - sti(); - - break; - case EWRK3_CLR_STATS: /* Zero out the driver statistics */ - if (suser()) { - cli(); - memset(&lp->pktStats, 0, sizeof(lp->pktStats)); - sti(); - } else { - status = -EPERM; - } - - break; - case EWRK3_GET_CSR: /* Get the CSR Register contents */ - tmp.addr[0] = inb(EWRK3_CSR); - ioc->len = 1; - if (!(status=verify_area(VERIFY_WRITE, ioc->data, ioc->len))) { - memcpy_tofs(ioc->data, tmp.addr, ioc->len); - } - - break; - case EWRK3_SET_CSR: /* Set the CSR Register contents */ - if (suser()) { - if (!(status=verify_area(VERIFY_READ, ioc->data, 1))) { - memcpy_fromfs(tmp.addr, ioc->data, 1); - outb(tmp.addr[0], EWRK3_CSR); - } - } else { - status = -EPERM; - } - - break; - case EWRK3_GET_EEPROM: /* Get the EEPROM contents */ - if (suser()) { - for (i=0; i<(EEPROM_MAX>>1); i++) { - tmp.val[i] = (short)Read_EEPROM(iobase, i); - } - i = EEPROM_MAX; - tmp.addr[i++] = inb(EWRK3_CMR); /* Config/Management Reg. */ - for (j=0;j<ETH_ALEN;j++) { - tmp.addr[i++] = inb(EWRK3_PAR0 + j); - } - ioc->len = EEPROM_MAX + 1 + ETH_ALEN; - if (!(status=verify_area(VERIFY_WRITE, ioc->data, ioc->len))) { - memcpy_tofs(ioc->data, tmp.addr, ioc->len); - } - } else { - status = -EPERM; - } - - break; - case EWRK3_SET_EEPROM: /* Set the EEPROM contents */ - if (suser()) { - if (!(status=verify_area(VERIFY_READ, ioc->data, EEPROM_MAX))) { - memcpy_fromfs(tmp.addr, ioc->data, EEPROM_MAX); - for (i=0; i<(EEPROM_MAX>>1); i++) { - Write_EEPROM(tmp.val[i], iobase, i); - } - } - } else { - status = -EPERM; - } - - break; - case EWRK3_GET_CMR: /* Get the CMR Register contents */ - tmp.addr[0] = inb(EWRK3_CMR); - ioc->len = 1; - if (!(status=verify_area(VERIFY_WRITE, ioc->data, ioc->len))) { - memcpy_tofs(ioc->data, tmp.addr, ioc->len); - } - - break; - case EWRK3_SET_TX_CUT_THRU: /* Set TX cut through mode */ - if (suser()) { - lp->txc = 1; - } else { - status = -EPERM; - } - - break; - case EWRK3_CLR_TX_CUT_THRU: /* Clear TX cut through mode */ - if (suser()) { - lp->txc = 0; - } else { - status = -EPERM; - } - - break; - default: - status = -EOPNOTSUPP; - } - - return status; -} - -#ifdef MODULE -static char devicename[9] = { 0, }; -static struct device thisEthwrk = { - devicename, /* device name is inserted by /linux/drivers/net/net_init.c */ - 0, 0, 0, 0, - 0x300, 5, /* I/O address, IRQ */ - 0, 0, 0, NULL, ewrk3_probe }; - -static int io=0x300; /* <--- EDIT THESE LINES FOR YOUR CONFIGURATION */ -static int irq=5; /* or use the insmod io= irq= options */ - -int -init_module(void) -{ - thisEthwrk.base_addr=io; - thisEthwrk.irq=irq; - if (register_netdev(&thisEthwrk) != 0) - return -EIO; - return 0; -} - -void -cleanup_module(void) -{ - release_region(thisEthwrk.base_addr, EWRK3_TOTAL_SIZE); - - if (thisEthwrk.priv) { - kfree(thisEthwrk.priv); - thisEthwrk.priv = NULL; - } - thisEthwrk.irq = 0; - - unregister_netdev(&thisEthwrk); -} -#endif /* MODULE */ - - -/* - * Local variables: - * kernel-compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O2 -m486 -c ewrk3.c" - * - * module-compile-command: "gcc -D__KERNEL__ -DMODULE -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O2 -m486 -c ewrk3.c" - * End: - */ - diff --git a/i386/i386at/gpl/linux/net/ewrk3.h b/i386/i386at/gpl/linux/net/ewrk3.h deleted file mode 100644 index b37abf46..00000000 --- a/i386/i386at/gpl/linux/net/ewrk3.h +++ /dev/null @@ -1,322 +0,0 @@ -/* - Written 1994 by David C. Davies. - - Copyright 1994 Digital Equipment Corporation. - - This software may be used and distributed according to the terms of the - GNU Public License, incorporated herein by reference. - - The author may be reached as davies@wanton.lkg.dec.com or Digital - Equipment Corporation, 550 King Street, Littleton MA 01460. - - ========================================================================= -*/ - -/* -** I/O Address Register Map -*/ -#define EWRK3_CSR iobase+0x00 /* Control and Status Register */ -#define EWRK3_CR iobase+0x01 /* Control Register */ -#define EWRK3_ICR iobase+0x02 /* Interrupt Control Register */ -#define EWRK3_TSR iobase+0x03 /* Transmit Status Register */ -#define EWRK3_RSVD1 iobase+0x04 /* RESERVED */ -#define EWRK3_RSVD2 iobase+0x05 /* RESERVED */ -#define EWRK3_FMQ iobase+0x06 /* Free Memory Queue */ -#define EWRK3_FMQC iobase+0x07 /* Free Memory Queue Counter */ -#define EWRK3_RQ iobase+0x08 /* Receive Queue */ -#define EWRK3_RQC iobase+0x09 /* Receive Queue Counter */ -#define EWRK3_TQ iobase+0x0a /* Transmit Queue */ -#define EWRK3_TQC iobase+0x0b /* Transmit Queue Counter */ -#define EWRK3_TDQ iobase+0x0c /* Transmit Done Queue */ -#define EWRK3_TDQC iobase+0x0d /* Transmit Done Queue Counter */ -#define EWRK3_PIR1 iobase+0x0e /* Page Index Register 1 */ -#define EWRK3_PIR2 iobase+0x0f /* Page Index Register 2 */ -#define EWRK3_DATA iobase+0x10 /* Data Register */ -#define EWRK3_IOPR iobase+0x11 /* I/O Page Register */ -#define EWRK3_IOBR iobase+0x12 /* I/O Base Register */ -#define EWRK3_MPR iobase+0x13 /* Memory Page Register */ -#define EWRK3_MBR iobase+0x14 /* Memory Base Register */ -#define EWRK3_APROM iobase+0x15 /* Address PROM */ -#define EWRK3_EPROM1 iobase+0x16 /* EEPROM Data Register 1 */ -#define EWRK3_EPROM2 iobase+0x17 /* EEPROM Data Register 2 */ -#define EWRK3_PAR0 iobase+0x18 /* Physical Address Register 0 */ -#define EWRK3_PAR1 iobase+0x19 /* Physical Address Register 1 */ -#define EWRK3_PAR2 iobase+0x1a /* Physical Address Register 2 */ -#define EWRK3_PAR3 iobase+0x1b /* Physical Address Register 3 */ -#define EWRK3_PAR4 iobase+0x1c /* Physical Address Register 4 */ -#define EWRK3_PAR5 iobase+0x1d /* Physical Address Register 5 */ -#define EWRK3_CMR iobase+0x1e /* Configuration/Management Register */ - -/* -** Control Page Map -*/ -#define PAGE0_FMQ 0x000 /* Free Memory Queue */ -#define PAGE0_RQ 0x080 /* Receive Queue */ -#define PAGE0_TQ 0x100 /* Transmit Queue */ -#define PAGE0_TDQ 0x180 /* Transmit Done Queue */ -#define PAGE0_HTE 0x200 /* Hash Table Entries */ -#define PAGE0_RSVD 0x240 /* RESERVED */ -#define PAGE0_USRD 0x600 /* User Data */ - -/* -** Control and Status Register bit definitions (EWRK3_CSR) -*/ -#define CSR_RA 0x80 /* Runt Accept */ -#define CSR_PME 0x40 /* Promiscuous Mode Enable */ -#define CSR_MCE 0x20 /* Multicast Enable */ -#define CSR_TNE 0x08 /* TX Done Queue Not Empty */ -#define CSR_RNE 0x04 /* RX Queue Not Empty */ -#define CSR_TXD 0x02 /* TX Disable */ -#define CSR_RXD 0x01 /* RX Disable */ - -/* -** Control Register bit definitions (EWRK3_CR) -*/ -#define CR_APD 0x80 /* Auto Port Disable */ -#define CR_PSEL 0x40 /* Port Select (0->TP port) */ -#define CR_LBCK 0x20 /* LoopBaCK enable */ -#define CR_FDUP 0x10 /* Full DUPlex enable */ -#define CR_FBUS 0x08 /* Fast BUS enable (ISA clk > 8.33MHz) */ -#define CR_EN_16 0x04 /* ENable 16 bit memory accesses */ -#define CR_LED 0x02 /* LED (1-> turn on) */ - -/* -** Interrupt Control Register bit definitions (EWRK3_ICR) -*/ -#define ICR_IE 0x80 /* Interrupt Enable */ -#define ICR_IS 0x60 /* Interrupt Selected */ -#define ICR_TNEM 0x08 /* TNE Mask (0->mask) */ -#define ICR_RNEM 0x04 /* RNE Mask (0->mask) */ -#define ICR_TXDM 0x02 /* TXD Mask (0->mask) */ -#define ICR_RXDM 0x01 /* RXD Mask (0->mask) */ - -/* -** Transmit Status Register bit definitions (EWRK3_TSR) -*/ -#define TSR_NCL 0x80 /* No Carrier Loopback */ -#define TSR_ID 0x40 /* Initially Deferred */ -#define TSR_LCL 0x20 /* Late CoLlision */ -#define TSR_ECL 0x10 /* Excessive CoLlisions */ -#define TSR_RCNTR 0x0f /* Retries CouNTeR */ - -/* -** I/O Page Register bit definitions (EWRK3_IOPR) -*/ -#define EEPROM_INIT 0xc0 /* EEPROM INIT command */ -#define EEPROM_WR_EN 0xc8 /* EEPROM WRITE ENABLE command */ -#define EEPROM_WR 0xd0 /* EEPROM WRITE command */ -#define EEPROM_WR_DIS 0xd8 /* EEPROM WRITE DISABLE command */ -#define EEPROM_RD 0xe0 /* EEPROM READ command */ - -/* -** I/O Base Register bit definitions (EWRK3_IOBR) -*/ -#define EISA_REGS_EN 0x20 /* Enable EISA ID and Control Registers */ -#define EISA_IOB 0x1f /* Compare bits for I/O Base Address */ - -/* -** I/O Congiguration/Management Register bit definitions (EWRK3_CMR) -*/ -#define CMR_RA 0x80 /* Read Ahead */ -#define CMR_WB 0x40 /* Write Behind */ -#define CMR_LINK 0x20 /* 0->TP */ -#define CMR_POLARITY 0x10 /* Informational */ -#define CMR_NO_EEPROM 0x0c /* NO_EEPROM<1:0> pin status */ -#define CMR_HS 0x08 /* Hard Strapped pin status (LeMAC2) */ -#define CMR_PNP 0x04 /* Plug 'n Play */ -#define CMR_DRAM 0x02 /* 0-> 1DRAM, 1-> 2 DRAM on board */ -#define CMR_0WS 0x01 /* Zero Wait State */ - -/* -** MAC Receive Status Register bit definitions -*/ - -#define R_ROK 0x80 /* Receive OK summary */ -#define R_IAM 0x10 /* Individual Address Match */ -#define R_MCM 0x08 /* MultiCast Match */ -#define R_DBE 0x04 /* Dribble Bit Error */ -#define R_CRC 0x02 /* CRC error */ -#define R_PLL 0x01 /* Phase Lock Lost */ - -/* -** MAC Transmit Control Register bit definitions -*/ - -#define TCR_SQEE 0x40 /* SQE Enable - look for heartbeat */ -#define TCR_SED 0x20 /* Stop when Error Detected */ -#define TCR_QMODE 0x10 /* Q_MODE */ -#define TCR_LAB 0x08 /* Less Aggressive Backoff */ -#define TCR_PAD 0x04 /* PAD Runt Packets */ -#define TCR_IFC 0x02 /* Insert Frame Check */ -#define TCR_ISA 0x01 /* Insert Source Address */ - -/* -** MAC Transmit Status Register bit definitions -*/ - -#define T_VSTS 0x80 /* Valid STatuS */ -#define T_CTU 0x40 /* Cut Through Used */ -#define T_SQE 0x20 /* Signal Quality Error */ -#define T_NCL 0x10 /* No Carrier Loopback */ -#define T_LCL 0x08 /* Late Collision */ -#define T_ID 0x04 /* Initially Deferred */ -#define T_COLL 0x03 /* COLLision status */ -#define T_XCOLL 0x03 /* Excessive Collisions */ -#define T_MCOLL 0x02 /* Multiple Collisions */ -#define T_OCOLL 0x01 /* One Collision */ -#define T_NOCOLL 0x00 /* No Collisions */ -#define T_XUR 0x03 /* Excessive Underruns */ -#define T_TXE 0x7f /* TX Errors */ - -/* -** EISA Configuration Register bit definitions -*/ - -#define EISA_ID iobase + 0x0c80 /* EISA ID Registers */ -#define EISA_ID0 iobase + 0x0c80 /* EISA ID Register 0 */ -#define EISA_ID1 iobase + 0x0c81 /* EISA ID Register 1 */ -#define EISA_ID2 iobase + 0x0c82 /* EISA ID Register 2 */ -#define EISA_ID3 iobase + 0x0c83 /* EISA ID Register 3 */ -#define EISA_CR iobase + 0x0c84 /* EISA Control Register */ - -/* -** EEPROM BYTES -*/ -#define EEPROM_MEMB 0x00 -#define EEPROM_IOB 0x01 -#define EEPROM_EISA_ID0 0x02 -#define EEPROM_EISA_ID1 0x03 -#define EEPROM_EISA_ID2 0x04 -#define EEPROM_EISA_ID3 0x05 -#define EEPROM_MISC0 0x06 -#define EEPROM_MISC1 0x07 -#define EEPROM_PNAME7 0x08 -#define EEPROM_PNAME6 0x09 -#define EEPROM_PNAME5 0x0a -#define EEPROM_PNAME4 0x0b -#define EEPROM_PNAME3 0x0c -#define EEPROM_PNAME2 0x0d -#define EEPROM_PNAME1 0x0e -#define EEPROM_PNAME0 0x0f -#define EEPROM_SWFLAGS 0x10 -#define EEPROM_HWCAT 0x11 -#define EEPROM_NETMAN2 0x12 -#define EEPROM_REVLVL 0x13 -#define EEPROM_NETMAN0 0x14 -#define EEPROM_NETMAN1 0x15 -#define EEPROM_CHIPVER 0x16 -#define EEPROM_SETUP 0x17 -#define EEPROM_PADDR0 0x18 -#define EEPROM_PADDR1 0x19 -#define EEPROM_PADDR2 0x1a -#define EEPROM_PADDR3 0x1b -#define EEPROM_PADDR4 0x1c -#define EEPROM_PADDR5 0x1d -#define EEPROM_PA_CRC 0x1e -#define EEPROM_CHKSUM 0x1f - -/* -** EEPROM bytes for checksumming -*/ -#define EEPROM_MAX 32 /* bytes */ - -/* -** EEPROM MISCELLANEOUS FLAGS -*/ -#define RBE_SHADOW 0x0100 /* Remote Boot Enable Shadow */ -#define READ_AHEAD 0x0080 /* Read Ahead feature */ -#define IRQ_SEL2 0x0070 /* IRQ line selection (LeMAC2) */ -#define IRQ_SEL 0x0060 /* IRQ line selection */ -#define FAST_BUS 0x0008 /* ISA Bus speeds > 8.33MHz */ -#define ENA_16 0x0004 /* Enables 16 bit memory transfers */ -#define WRITE_BEHIND 0x0002 /* Write Behind feature */ -#define _0WS_ENA 0x0001 /* Zero Wait State Enable */ - -/* -** EEPROM NETWORK MANAGEMENT FLAGS -*/ -#define NETMAN_POL 0x04 /* Polarity defeat */ -#define NETMAN_LINK 0x02 /* Link defeat */ -#define NETMAN_CCE 0x01 /* Custom Counters Enable */ - -/* -** EEPROM SW FLAGS -*/ -#define SW_SQE 0x10 /* Signal Quality Error */ -#define SW_LAB 0x08 /* Less Aggressive Backoff */ -#define SW_INIT 0x04 /* Initialized */ -#define SW_TIMEOUT 0x02 /* 0:2.5 mins, 1: 30 secs */ -#define SW_REMOTE 0x01 /* Remote Boot Enable -> 1 */ - -/* -** EEPROM SETUP FLAGS -*/ -#define SETUP_APD 0x80 /* AutoPort Disable */ -#define SETUP_PS 0x40 /* Port Select */ -#define SETUP_MP 0x20 /* MultiPort */ -#define SETUP_1TP 0x10 /* 1 port, TP */ -#define SETUP_1COAX 0x00 /* 1 port, Coax */ -#define SETUP_DRAM 0x02 /* Number of DRAMS on board */ - -/* -** EEPROM MANAGEMENT FLAGS -*/ -#define MGMT_CCE 0x01 /* Custom Counters Enable */ - -/* -** EEPROM VERSIONS -*/ -#define LeMAC 0x11 -#define LeMAC2 0x12 - -/* -** Miscellaneous -*/ - -#define EEPROM_WAIT_TIME 1000 /* Number of microseconds */ -#define EISA_EN 0x0001 /* Enable EISA bus buffers */ - -#define HASH_TABLE_LEN 512 /* Bits */ - -#define XCT 0x80 /* Transmit Cut Through */ -#define PRELOAD 16 /* 4 long words */ - -#define MASK_INTERRUPTS 1 -#define UNMASK_INTERRUPTS 0 - -#define EEPROM_OFFSET(a) ((u_short)((u_long)(a))) - -/* -** Include the IOCTL stuff -*/ -#include <linux/sockios.h> - -#define EWRK3IOCTL SIOCDEVPRIVATE - -struct ewrk3_ioctl { - unsigned short cmd; /* Command to run */ - unsigned short len; /* Length of the data buffer */ - unsigned char *data; /* Pointer to the data buffer */ -}; - -/* -** Recognised commands for the driver -*/ -#define EWRK3_GET_HWADDR 0x01 /* Get the hardware address */ -#define EWRK3_SET_HWADDR 0x02 /* Get the hardware address */ -#define EWRK3_SET_PROM 0x03 /* Set Promiscuous Mode */ -#define EWRK3_CLR_PROM 0x04 /* Clear Promiscuous Mode */ -#define EWRK3_SAY_BOO 0x05 /* Say "Boo!" to the kernel log file */ -#define EWRK3_GET_MCA 0x06 /* Get a multicast address */ -#define EWRK3_SET_MCA 0x07 /* Set a multicast address */ -#define EWRK3_CLR_MCA 0x08 /* Clear a multicast address */ -#define EWRK3_MCA_EN 0x09 /* Enable a multicast address group */ -#define EWRK3_GET_STATS 0x0a /* Get the driver statistics */ -#define EWRK3_CLR_STATS 0x0b /* Zero out the driver statistics */ -#define EWRK3_GET_CSR 0x0c /* Get the CSR Register contents */ -#define EWRK3_SET_CSR 0x0d /* Set the CSR Register contents */ -#define EWRK3_GET_EEPROM 0x0e /* Get the EEPROM contents */ -#define EWRK3_SET_EEPROM 0x0f /* Set the EEPROM contents */ -#define EWRK3_GET_CMR 0x10 /* Get the CMR Register contents */ -#define EWRK3_CLR_TX_CUT_THRU 0x11 /* Clear the TX cut through mode */ -#define EWRK3_SET_TX_CUT_THRU 0x12 /* Set the TX cut through mode */ diff --git a/i386/i386at/gpl/linux/net/hp-plus.c b/i386/i386at/gpl/linux/net/hp-plus.c deleted file mode 100644 index aed7ee01..00000000 --- a/i386/i386at/gpl/linux/net/hp-plus.c +++ /dev/null @@ -1,483 +0,0 @@ -/* hp-plus.c: A HP PCLAN/plus ethernet driver for linux. */ -/* - Written 1994 by Donald Becker. - - This driver is for the Hewlett Packard PC LAN (27***) plus ethercards. - These cards are sold under several model numbers, usually 2724*. - - This software may be used and distributed according to the terms - of the GNU Public License, incorporated herein by reference. - - The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O - - Center of Excellence in Space Data and Information Sciences - Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771 - - As is often the case, a great deal of credit is owed to Russ Nelson. - The Crynwr packet driver was my primary source of HP-specific - programming information. -*/ - -static const char *version = -"hp-plus.c:v1.10 9/24/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n"; - -#include <linux/module.h> - -#include <linux/string.h> /* Important -- this inlines word moves. */ -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/errno.h> -#include <linux/ioport.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> - -#include <asm/system.h> -#include <asm/io.h> - - -#include "8390.h" - -/* A zero-terminated list of I/O addresses to be probed. */ -static unsigned int hpplus_portlist[] = -{0x200, 0x240, 0x280, 0x2C0, 0x300, 0x320, 0x340, 0}; - -/* - The HP EtherTwist chip implementation is a fairly routine DP8390 - implementation. It allows both shared memory and programmed-I/O buffer - access, using a custom interface for both. The programmed-I/O mode is - entirely implemented in the HP EtherTwist chip, bypassing the problem - ridden built-in 8390 facilities used on NE2000 designs. The shared - memory mode is likewise special, with an offset register used to make - packets appear at the shared memory base. Both modes use a base and bounds - page register to hide the Rx ring buffer wrap -- a packet that spans the - end of physical buffer memory appears continuous to the driver. (c.f. the - 3c503 and Cabletron E2100) - - A special note: the internal buffer of the board is only 8 bits wide. - This lays several nasty traps for the unaware: - - the 8390 must be programmed for byte-wide operations - - all I/O and memory operations must work on whole words (the access - latches are serially preloaded and have no byte-swapping ability). - - This board is laid out in I/O space much like the earlier HP boards: - the first 16 locations are for the board registers, and the second 16 are - for the 8390. The board is easy to identify, with both a dedicated 16 bit - ID register and a constant 0x530* value in the upper bits of the paging - register. -*/ - -#define HP_ID 0x00 /* ID register, always 0x4850. */ -#define HP_PAGING 0x02 /* Registers visible @ 8-f, see PageName. */ -#define HPP_OPTION 0x04 /* Bitmapped options, see HP_Option. */ -#define HPP_OUT_ADDR 0x08 /* I/O output location in Perf_Page. */ -#define HPP_IN_ADDR 0x0A /* I/O input location in Perf_Page. */ -#define HP_DATAPORT 0x0c /* I/O data transfer in Perf_Page. */ -#define NIC_OFFSET 0x10 /* Offset to the 8390 registers. */ -#define HP_IO_EXTENT 32 - -#define HP_START_PG 0x00 /* First page of TX buffer */ -#define HP_STOP_PG 0x80 /* Last page +1 of RX ring */ - -/* The register set selected in HP_PAGING. */ -enum PageName { - Perf_Page = 0, /* Normal operation. */ - MAC_Page = 1, /* The ethernet address (+checksum). */ - HW_Page = 2, /* EEPROM-loaded hardware parameters. */ - LAN_Page = 4, /* Transceiver selection, testing, etc. */ - ID_Page = 6 }; - -/* The bit definitions for the HPP_OPTION register. */ -enum HP_Option { - NICReset = 1, ChipReset = 2, /* Active low, really UNreset. */ - EnableIRQ = 4, FakeIntr = 8, BootROMEnb = 0x10, IOEnb = 0x20, - MemEnable = 0x40, ZeroWait = 0x80, MemDisable = 0x1000, }; - -int hp_plus_probe(struct device *dev); -int hpp_probe1(struct device *dev, int ioaddr); - -static void hpp_reset_8390(struct device *dev); -static int hpp_open(struct device *dev); -static int hpp_close(struct device *dev); -static void hpp_mem_block_input(struct device *dev, int count, - struct sk_buff *skb, int ring_offset); -static void hpp_mem_block_output(struct device *dev, int count, - const unsigned char *buf, const start_page); -static void hpp_mem_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, - int ring_page); -static void hpp_io_block_input(struct device *dev, int count, - struct sk_buff *skb, int ring_offset); -static void hpp_io_block_output(struct device *dev, int count, - const unsigned char *buf, const start_page); -static void hpp_io_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, - int ring_page); - - -/* Probe a list of addresses for an HP LAN+ adaptor. - This routine is almost boilerplate. */ -#ifdef HAVE_DEVLIST -/* Support for a alternate probe manager, which will eliminate the - boilerplate below. */ -struct netdev_entry hpplus_drv = -{"hpplus", hpp_probe1, HP_IO_EXTENT, hpplus_portlist}; -#else - -int hp_plus_probe(struct device *dev) -{ - int i; - int base_addr = dev ? dev->base_addr : 0; - - if (base_addr > 0x1ff) /* Check a single specified location. */ - return hpp_probe1(dev, base_addr); - else if (base_addr != 0) /* Don't probe at all. */ - return ENXIO; - - for (i = 0; hpplus_portlist[i]; i++) { - int ioaddr = hpplus_portlist[i]; - if (check_region(ioaddr, HP_IO_EXTENT)) - continue; - if (hpp_probe1(dev, ioaddr) == 0) - return 0; - } - - return ENODEV; -} -#endif - -/* Do the interesting part of the probe at a single address. */ -int hpp_probe1(struct device *dev, int ioaddr) -{ - int i; - unsigned char checksum = 0; - const char *name = "HP-PC-LAN+"; - int mem_start; - static unsigned version_printed = 0; - - /* Check for the HP+ signature, 50 48 0x 53. */ - if (inw(ioaddr + HP_ID) != 0x4850 - || (inw(ioaddr + HP_PAGING) & 0xfff0) != 0x5300) - return ENODEV; - - /* We should have a "dev" from Space.c or the static module table. */ - if (dev == NULL) { - printk("hp-plus.c: Passed a NULL device.\n"); - dev = init_etherdev(0, 0); - } - - if (ei_debug && version_printed++ == 0) - printk(version); - - printk("%s: %s at %#3x,", dev->name, name, ioaddr); - - /* Retrieve and checksum the station address. */ - outw(MAC_Page, ioaddr + HP_PAGING); - - for(i = 0; i < ETHER_ADDR_LEN; i++) { - unsigned char inval = inb(ioaddr + 8 + i); - dev->dev_addr[i] = inval; - checksum += inval; - printk(" %2.2x", inval); - } - checksum += inb(ioaddr + 14); - - if (checksum != 0xff) { - printk(" bad checksum %2.2x.\n", checksum); - return ENODEV; - } else { - /* Point at the Software Configuration Flags. */ - outw(ID_Page, ioaddr + HP_PAGING); - printk(" ID %4.4x", inw(ioaddr + 12)); - } - - /* Allocate dev->priv and fill in 8390 specific dev fields. */ - if (ethdev_init(dev)) { - printk ("hp-plus.c: unable to allocate memory for dev->priv.\n"); - return -ENOMEM; - } - - /* Grab the region so we can find another board if something fails. */ - request_region(ioaddr, HP_IO_EXTENT,"hp-plus"); - - /* Read the IRQ line. */ - outw(HW_Page, ioaddr + HP_PAGING); - { - int irq = inb(ioaddr + 13) & 0x0f; - int option = inw(ioaddr + HPP_OPTION); - - dev->irq = irq; - if (option & MemEnable) { - mem_start = inw(ioaddr + 9) << 8; - printk(", IRQ %d, memory address %#x.\n", irq, mem_start); - } else { - mem_start = 0; - printk(", IRQ %d, programmed-I/O mode.\n", irq); - } - } - - /* Set the wrap registers for string I/O reads. */ - outw((HP_START_PG + TX_2X_PAGES) | ((HP_STOP_PG - 1) << 8), ioaddr + 14); - - /* Set the base address to point to the NIC, not the "real" base! */ - dev->base_addr = ioaddr + NIC_OFFSET; - - dev->open = &hpp_open; - dev->stop = &hpp_close; - - ei_status.name = name; - ei_status.word16 = 0; /* Agggghhhhh! Debug time: 2 days! */ - ei_status.tx_start_page = HP_START_PG; - ei_status.rx_start_page = HP_START_PG + TX_2X_PAGES; - ei_status.stop_page = HP_STOP_PG; - - ei_status.reset_8390 = &hpp_reset_8390; - ei_status.block_input = &hpp_io_block_input; - ei_status.block_output = &hpp_io_block_output; - ei_status.get_8390_hdr = &hpp_io_get_8390_hdr; - - /* Check if the memory_enable flag is set in the option register. */ - if (mem_start) { - ei_status.block_input = &hpp_mem_block_input; - ei_status.block_output = &hpp_mem_block_output; - ei_status.get_8390_hdr = &hpp_mem_get_8390_hdr; - dev->mem_start = mem_start; - dev->rmem_start = dev->mem_start + TX_2X_PAGES*256; - dev->mem_end = dev->rmem_end - = dev->mem_start + (HP_STOP_PG - HP_START_PG)*256; - } - - outw(Perf_Page, ioaddr + HP_PAGING); - NS8390_init(dev, 0); - /* Leave the 8390 and HP chip reset. */ - outw(inw(ioaddr + HPP_OPTION) & ~EnableIRQ, ioaddr + HPP_OPTION); - - return 0; -} - -static int -hpp_open(struct device *dev) -{ - int ioaddr = dev->base_addr - NIC_OFFSET; - int option_reg; - - if (request_irq(dev->irq, &ei_interrupt, 0, "hp-plus")) { - return -EAGAIN; - } - - /* Reset the 8390 and HP chip. */ - option_reg = inw(ioaddr + HPP_OPTION); - outw(option_reg & ~(NICReset + ChipReset), ioaddr + HPP_OPTION); - SLOW_DOWN_IO; SLOW_DOWN_IO; - /* Unreset the board and enable interrupts. */ - outw(option_reg | (EnableIRQ + NICReset + ChipReset), ioaddr + HPP_OPTION); - - /* Set the wrap registers for programmed-I/O operation. */ - outw(HW_Page, ioaddr + HP_PAGING); - outw((HP_START_PG + TX_2X_PAGES) | ((HP_STOP_PG - 1) << 8), ioaddr + 14); - - /* Select the operational page. */ - outw(Perf_Page, ioaddr + HP_PAGING); - - ei_open(dev); - MOD_INC_USE_COUNT; - return 0; -} - -static int -hpp_close(struct device *dev) -{ - int ioaddr = dev->base_addr - NIC_OFFSET; - int option_reg = inw(ioaddr + HPP_OPTION); - - free_irq(dev->irq); - irq2dev_map[dev->irq] = NULL; - ei_close(dev); - outw((option_reg & ~EnableIRQ) | MemDisable | NICReset | ChipReset, - ioaddr + HPP_OPTION); - - MOD_DEC_USE_COUNT; - return 0; -} - -static void -hpp_reset_8390(struct device *dev) -{ - int ioaddr = dev->base_addr - NIC_OFFSET; - int option_reg = inw(ioaddr + HPP_OPTION); - - if (ei_debug > 1) printk("resetting the 8390 time=%ld...", jiffies); - - outw(option_reg & ~(NICReset + ChipReset), ioaddr + HPP_OPTION); - /* Pause a few cycles for the hardware reset to take place. */ - SLOW_DOWN_IO; - SLOW_DOWN_IO; - ei_status.txing = 0; - outw(option_reg | (EnableIRQ + NICReset + ChipReset), ioaddr + HPP_OPTION); - - SLOW_DOWN_IO; SLOW_DOWN_IO; - - - if ((inb_p(ioaddr+NIC_OFFSET+EN0_ISR) & ENISR_RESET) == 0) - printk("%s: hp_reset_8390() did not complete.\n", dev->name); - - if (ei_debug > 1) printk("8390 reset done (%ld).", jiffies); - return; -} - -/* The programmed-I/O version of reading the 4 byte 8390 specific header. - Note that transfer with the EtherTwist+ must be on word boundaries. */ - -static void -hpp_io_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page) -{ - int ioaddr = dev->base_addr - NIC_OFFSET; - - outw((ring_page<<8), ioaddr + HPP_IN_ADDR); - insw(ioaddr + HP_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1); -} - -/* Block input and output, similar to the Crynwr packet driver. */ - -static void -hpp_io_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset) -{ - int ioaddr = dev->base_addr - NIC_OFFSET; - char *buf = skb->data; - - outw(ring_offset, ioaddr + HPP_IN_ADDR); - insw(ioaddr + HP_DATAPORT, buf, count>>1); - if (count & 0x01) - buf[count-1] = inw(ioaddr + HP_DATAPORT); -} - -/* The corresponding shared memory versions of the above 2 functions. */ - -static void -hpp_mem_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page) -{ - int ioaddr = dev->base_addr - NIC_OFFSET; - int option_reg = inw(ioaddr + HPP_OPTION); - - outw((ring_page<<8), ioaddr + HPP_IN_ADDR); - outw(option_reg & ~(MemDisable + BootROMEnb), ioaddr + HPP_OPTION); - memcpy_fromio(hdr, dev->mem_start, sizeof(struct e8390_pkt_hdr)); - outw(option_reg, ioaddr + HPP_OPTION); - hdr->count = (hdr->count + 3) & ~3; /* Round up allocation. */ -} - -static void -hpp_mem_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset) -{ - int ioaddr = dev->base_addr - NIC_OFFSET; - int option_reg = inw(ioaddr + HPP_OPTION); - - outw(ring_offset, ioaddr + HPP_IN_ADDR); - - outw(option_reg & ~(MemDisable + BootROMEnb), ioaddr + HPP_OPTION); - - /* Caution: this relies on get_8390_hdr() rounding up count! - Also note that we *can't* use eth_io_copy_and_sum() because - it will not always copy "count" bytes (e.g. padded IP). */ - - memcpy_fromio(skb->data, dev->mem_start, count); - outw(option_reg, ioaddr + HPP_OPTION); -} - -/* A special note: we *must* always transfer >=16 bit words. - It's always safe to round up, so we do. */ -static void -hpp_io_block_output(struct device *dev, int count, - const unsigned char *buf, const start_page) -{ - int ioaddr = dev->base_addr - NIC_OFFSET; - outw(start_page << 8, ioaddr + HPP_OUT_ADDR); - outsl(ioaddr + HP_DATAPORT, buf, (count+3)>>2); - return; -} - -static void -hpp_mem_block_output(struct device *dev, int count, - const unsigned char *buf, const start_page) -{ - int ioaddr = dev->base_addr - NIC_OFFSET; - int option_reg = inw(ioaddr + HPP_OPTION); - - outw(start_page << 8, ioaddr + HPP_OUT_ADDR); - outw(option_reg & ~(MemDisable + BootROMEnb), ioaddr + HPP_OPTION); - memcpy_toio(dev->mem_start, buf, (count + 3) & ~3); - outw(option_reg, ioaddr + HPP_OPTION); - - return; -} - - -#ifdef MODULE -#define MAX_HPP_CARDS 4 /* Max number of HPP cards per module */ -#define NAMELEN 8 /* # of chars for storing dev->name */ -static char namelist[NAMELEN * MAX_HPP_CARDS] = { 0, }; -static struct device dev_hpp[MAX_HPP_CARDS] = { - { - NULL, /* assign a chunk of namelist[] below */ - 0, 0, 0, 0, - 0, 0, - 0, 0, 0, NULL, NULL - }, -}; - -static int io[MAX_HPP_CARDS] = { 0, }; -static int irq[MAX_HPP_CARDS] = { 0, }; - -/* This is set up so that only a single autoprobe takes place per call. -ISA device autoprobes on a running machine are not recommended. */ -int -init_module(void) -{ - int this_dev, found = 0; - - for (this_dev = 0; this_dev < MAX_HPP_CARDS; this_dev++) { - struct device *dev = &dev_hpp[this_dev]; - dev->name = namelist+(NAMELEN*this_dev); - dev->irq = irq[this_dev]; - dev->base_addr = io[this_dev]; - dev->init = hp_plus_probe; - if (io[this_dev] == 0) { - if (this_dev != 0) break; /* only autoprobe 1st one */ - printk(KERN_NOTICE "hp-plus.c: Presently autoprobing (not recommended) for a single card.\n"); - } - if (register_netdev(dev) != 0) { - printk(KERN_WARNING "hp-plus.c: No HP-Plus card found (i/o = 0x%x).\n", io[this_dev]); - if (found != 0) return 0; /* Got at least one. */ - return -ENXIO; - } - found++; - } - - return 0; -} - -void -cleanup_module(void) -{ - int this_dev; - - for (this_dev = 0; this_dev < MAX_HPP_CARDS; this_dev++) { - struct device *dev = &dev_hpp[this_dev]; - if (dev->priv != NULL) { - /* NB: hpp_close() handles free_irq + irq2dev map */ - int ioaddr = dev->base_addr - NIC_OFFSET; - kfree(dev->priv); - dev->priv = NULL; - release_region(ioaddr, HP_IO_EXTENT); - unregister_netdev(dev); - } - } -} -#endif /* MODULE */ - -/* - * Local variables: - * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c hp-plus.c" - * version-control: t - * kept-new-versions: 5 - * tab-width: 4 - * c-indent-level: 4 - * End: - */ diff --git a/i386/i386at/gpl/linux/net/hp.c b/i386/i386at/gpl/linux/net/hp.c deleted file mode 100644 index d0443a7d..00000000 --- a/i386/i386at/gpl/linux/net/hp.c +++ /dev/null @@ -1,451 +0,0 @@ -/* hp.c: A HP LAN ethernet driver for linux. */ -/* - Written 1993-94 by Donald Becker. - - Copyright 1993 United States Government as represented by the - Director, National Security Agency. - - This software may be used and distributed according to the terms - of the GNU Public License, incorporated herein by reference. - - The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O - Center of Excellence in Space Data and Information Sciences - Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771 - - This is a driver for the HP PC-LAN adaptors. - - Sources: - The Crynwr packet driver. -*/ - -static const char *version = - "hp.c:v1.10 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n"; - - -#include <linux/module.h> - -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/errno.h> -#include <linux/ioport.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> - -#include <asm/system.h> -#include <asm/io.h> - -#include "8390.h" - -/* A zero-terminated list of I/O addresses to be probed. */ -static unsigned int hppclan_portlist[] = -{ 0x300, 0x320, 0x340, 0x280, 0x2C0, 0x200, 0x240, 0}; - -#define HP_IO_EXTENT 32 - -#define HP_DATAPORT 0x0c /* "Remote DMA" data port. */ -#define HP_ID 0x07 -#define HP_CONFIGURE 0x08 /* Configuration register. */ -#define HP_RUN 0x01 /* 1 == Run, 0 == reset. */ -#define HP_IRQ 0x0E /* Mask for software-configured IRQ line. */ -#define HP_DATAON 0x10 /* Turn on dataport */ -#define NIC_OFFSET 0x10 /* Offset the 8390 registers. */ - -#define HP_START_PG 0x00 /* First page of TX buffer */ -#define HP_8BSTOP_PG 0x80 /* Last page +1 of RX ring */ -#define HP_16BSTOP_PG 0xFF /* Same, for 16 bit cards. */ - -int hp_probe(struct device *dev); -int hp_probe1(struct device *dev, int ioaddr); - -static int hp_open(struct device *dev); -static int hp_close(struct device *dev); -static void hp_reset_8390(struct device *dev); -static void hp_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, - int ring_page); -static void hp_block_input(struct device *dev, int count, - struct sk_buff *skb , int ring_offset); -static void hp_block_output(struct device *dev, int count, - const unsigned char *buf, const start_page); - -static void hp_init_card(struct device *dev); - -/* The map from IRQ number to HP_CONFIGURE register setting. */ -/* My default is IRQ5 0 1 2 3 4 5 6 7 8 9 10 11 */ -static char irqmap[16] = { 0, 0, 4, 6, 8,10, 0,14, 0, 4, 2,12,0,0,0,0}; - - -/* Probe for an HP LAN adaptor. - Also initialize the card and fill in STATION_ADDR with the station - address. */ -#ifdef HAVE_DEVLIST -struct netdev_entry netcard_drv = -{"hp", hp_probe1, HP_IO_EXTENT, hppclan_portlist}; -#else - -int hp_probe(struct device *dev) -{ - int i; - int base_addr = dev ? dev->base_addr : 0; - - if (base_addr > 0x1ff) /* Check a single specified location. */ - return hp_probe1(dev, base_addr); - else if (base_addr != 0) /* Don't probe at all. */ - return ENXIO; - - for (i = 0; hppclan_portlist[i]; i++) { - int ioaddr = hppclan_portlist[i]; - if (check_region(ioaddr, HP_IO_EXTENT)) - continue; - if (hp_probe1(dev, ioaddr) == 0) - return 0; - } - - return ENODEV; -} -#endif - -int hp_probe1(struct device *dev, int ioaddr) -{ - int i, board_id, wordmode; - const char *name; - static unsigned version_printed = 0; - - /* Check for the HP physical address, 08 00 09 xx xx xx. */ - /* This really isn't good enough: we may pick up HP LANCE boards - also! Avoid the lance 0x5757 signature. */ - if (inb(ioaddr) != 0x08 - || inb(ioaddr+1) != 0x00 - || inb(ioaddr+2) != 0x09 - || inb(ioaddr+14) == 0x57) - return ENODEV; - - /* Set up the parameters based on the board ID. - If you have additional mappings, please mail them to me -djb. */ - if ((board_id = inb(ioaddr + HP_ID)) & 0x80) { - name = "HP27247"; - wordmode = 1; - } else { - name = "HP27250"; - wordmode = 0; - } - - /* We should have a "dev" from Space.c or the static module table. */ - if (dev == NULL) { - printk("hp.c: Passed a NULL device.\n"); - dev = init_etherdev(0, 0); - } - - if (ei_debug && version_printed++ == 0) - printk(version); - - printk("%s: %s (ID %02x) at %#3x,", dev->name, name, board_id, ioaddr); - - for(i = 0; i < ETHER_ADDR_LEN; i++) - printk(" %2.2x", dev->dev_addr[i] = inb(ioaddr + i)); - - /* Snarf the interrupt now. Someday this could be moved to open(). */ - if (dev->irq < 2) { - int irq_16list[] = { 11, 10, 5, 3, 4, 7, 9, 0}; - int irq_8list[] = { 7, 5, 3, 4, 9, 0}; - int *irqp = wordmode ? irq_16list : irq_8list; - do { - int irq = *irqp; - if (request_irq (irq, NULL, 0, "bogus") != -EBUSY) { - autoirq_setup(0); - /* Twinkle the interrupt, and check if it's seen. */ - outb_p(irqmap[irq] | HP_RUN, ioaddr + HP_CONFIGURE); - outb_p( 0x00 | HP_RUN, ioaddr + HP_CONFIGURE); - if (irq == autoirq_report(0) /* It's a good IRQ line! */ - && request_irq (irq, &ei_interrupt, 0, "hp") == 0) { - printk(" selecting IRQ %d.\n", irq); - dev->irq = *irqp; - break; - } - } - } while (*++irqp); - if (*irqp == 0) { - printk(" no free IRQ lines.\n"); - return EBUSY; - } - } else { - if (dev->irq == 2) - dev->irq = 9; - if (request_irq(dev->irq, ei_interrupt, 0, "hp")) { - printk (" unable to get IRQ %d.\n", dev->irq); - return EBUSY; - } - } - - /* Allocate dev->priv and fill in 8390 specific dev fields. */ - if (ethdev_init(dev)) { - printk (" unable to get memory for dev->priv.\n"); - free_irq(dev->irq); - return -ENOMEM; - } - - /* Grab the region so we can find another board if something fails. */ - request_region(ioaddr, HP_IO_EXTENT,"hp"); - - /* Set the base address to point to the NIC, not the "real" base! */ - dev->base_addr = ioaddr + NIC_OFFSET; - dev->open = &hp_open; - dev->stop = &hp_close; - - ei_status.name = name; - ei_status.word16 = wordmode; - ei_status.tx_start_page = HP_START_PG; - ei_status.rx_start_page = HP_START_PG + TX_PAGES; - ei_status.stop_page = wordmode ? HP_16BSTOP_PG : HP_8BSTOP_PG; - - ei_status.reset_8390 = &hp_reset_8390; - ei_status.get_8390_hdr = &hp_get_8390_hdr; - ei_status.block_input = &hp_block_input; - ei_status.block_output = &hp_block_output; - hp_init_card(dev); - - return 0; -} - -static int -hp_open(struct device *dev) -{ - ei_open(dev); - MOD_INC_USE_COUNT; - return 0; -} - -static int -hp_close(struct device *dev) -{ - ei_close(dev); - MOD_DEC_USE_COUNT; - return 0; -} - -static void -hp_reset_8390(struct device *dev) -{ - int hp_base = dev->base_addr - NIC_OFFSET; - int saved_config = inb_p(hp_base + HP_CONFIGURE); - - if (ei_debug > 1) printk("resetting the 8390 time=%ld...", jiffies); - outb_p(0x00, hp_base + HP_CONFIGURE); - ei_status.txing = 0; - /* Pause just a few cycles for the hardware reset to take place. */ - SLOW_DOWN_IO; - SLOW_DOWN_IO; - - outb_p(saved_config, hp_base + HP_CONFIGURE); - SLOW_DOWN_IO; SLOW_DOWN_IO; - - if ((inb_p(hp_base+NIC_OFFSET+EN0_ISR) & ENISR_RESET) == 0) - printk("%s: hp_reset_8390() did not complete.\n", dev->name); - - if (ei_debug > 1) printk("8390 reset done (%ld).", jiffies); - return; -} - -static void -hp_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page) -{ - int nic_base = dev->base_addr; - int saved_config = inb_p(nic_base - NIC_OFFSET + HP_CONFIGURE); - - outb_p(saved_config | HP_DATAON, nic_base - NIC_OFFSET + HP_CONFIGURE); - outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base); - outb_p(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO); - outb_p(0, nic_base + EN0_RCNTHI); - outb_p(0, nic_base + EN0_RSARLO); /* On page boundary */ - outb_p(ring_page, nic_base + EN0_RSARHI); - outb_p(E8390_RREAD+E8390_START, nic_base); - - if (ei_status.word16) - insw(nic_base - NIC_OFFSET + HP_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1); - else - insb(nic_base - NIC_OFFSET + HP_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)); - - outb_p(saved_config & (~HP_DATAON), nic_base - NIC_OFFSET + HP_CONFIGURE); -} - -/* Block input and output, similar to the Crynwr packet driver. If you are - porting to a new ethercard look at the packet driver source for hints. - The HP LAN doesn't use shared memory -- we put the packet - out through the "remote DMA" dataport. */ - -static void -hp_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset) -{ - int nic_base = dev->base_addr; - int saved_config = inb_p(nic_base - NIC_OFFSET + HP_CONFIGURE); - int xfer_count = count; - char *buf = skb->data; - - outb_p(saved_config | HP_DATAON, nic_base - NIC_OFFSET + HP_CONFIGURE); - outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base); - outb_p(count & 0xff, nic_base + EN0_RCNTLO); - outb_p(count >> 8, nic_base + EN0_RCNTHI); - outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO); - outb_p(ring_offset >> 8, nic_base + EN0_RSARHI); - outb_p(E8390_RREAD+E8390_START, nic_base); - if (ei_status.word16) { - insw(nic_base - NIC_OFFSET + HP_DATAPORT,buf,count>>1); - if (count & 0x01) - buf[count-1] = inb(nic_base - NIC_OFFSET + HP_DATAPORT), xfer_count++; - } else { - insb(nic_base - NIC_OFFSET + HP_DATAPORT, buf, count); - } - /* This is for the ALPHA version only, remove for later releases. */ - if (ei_debug > 0) { /* DMA termination address check... */ - int high = inb_p(nic_base + EN0_RSARHI); - int low = inb_p(nic_base + EN0_RSARLO); - int addr = (high << 8) + low; - /* Check only the lower 8 bits so we can ignore ring wrap. */ - if (((ring_offset + xfer_count) & 0xff) != (addr & 0xff)) - printk("%s: RX transfer address mismatch, %#4.4x vs. %#4.4x (actual).\n", - dev->name, ring_offset + xfer_count, addr); - } - outb_p(saved_config & (~HP_DATAON), nic_base - NIC_OFFSET + HP_CONFIGURE); -} - -static void -hp_block_output(struct device *dev, int count, - const unsigned char *buf, const start_page) -{ - int nic_base = dev->base_addr; - int saved_config = inb_p(nic_base - NIC_OFFSET + HP_CONFIGURE); - - outb_p(saved_config | HP_DATAON, nic_base - NIC_OFFSET + HP_CONFIGURE); - /* Round the count up for word writes. Do we need to do this? - What effect will an odd byte count have on the 8390? - I should check someday. */ - if (ei_status.word16 && (count & 0x01)) - count++; - /* We should already be in page 0, but to be safe... */ - outb_p(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base); - -#ifdef NE8390_RW_BUGFIX - /* Handle the read-before-write bug the same way as the - Crynwr packet driver -- the NatSemi method doesn't work. */ - outb_p(0x42, nic_base + EN0_RCNTLO); - outb_p(0, nic_base + EN0_RCNTHI); - outb_p(0xff, nic_base + EN0_RSARLO); - outb_p(0x00, nic_base + EN0_RSARHI); -#define NE_CMD 0x00 - outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD); - /* Make certain that the dummy read has occurred. */ - inb_p(0x61); - inb_p(0x61); -#endif - - outb_p(count & 0xff, nic_base + EN0_RCNTLO); - outb_p(count >> 8, nic_base + EN0_RCNTHI); - outb_p(0x00, nic_base + EN0_RSARLO); - outb_p(start_page, nic_base + EN0_RSARHI); - - outb_p(E8390_RWRITE+E8390_START, nic_base); - if (ei_status.word16) { - /* Use the 'rep' sequence for 16 bit boards. */ - outsw(nic_base - NIC_OFFSET + HP_DATAPORT, buf, count>>1); - } else { - outsb(nic_base - NIC_OFFSET + HP_DATAPORT, buf, count); - } - - /* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here -- it's broken! */ - - /* This is for the ALPHA version only, remove for later releases. */ - if (ei_debug > 0) { /* DMA termination address check... */ - int high = inb_p(nic_base + EN0_RSARHI); - int low = inb_p(nic_base + EN0_RSARLO); - int addr = (high << 8) + low; - if ((start_page << 8) + count != addr) - printk("%s: TX Transfer address mismatch, %#4.4x vs. %#4.4x.\n", - dev->name, (start_page << 8) + count, addr); - } - outb_p(saved_config & (~HP_DATAON), nic_base - NIC_OFFSET + HP_CONFIGURE); - return; -} - -/* This function resets the ethercard if something screws up. */ -static void -hp_init_card(struct device *dev) -{ - int irq = dev->irq; - NS8390_init(dev, 0); - outb_p(irqmap[irq&0x0f] | HP_RUN, - dev->base_addr - NIC_OFFSET + HP_CONFIGURE); - return; -} - -#ifdef MODULE -#define MAX_HP_CARDS 4 /* Max number of HP cards per module */ -#define NAMELEN 8 /* # of chars for storing dev->name */ -static char namelist[NAMELEN * MAX_HP_CARDS] = { 0, }; -static struct device dev_hp[MAX_HP_CARDS] = { - { - NULL, /* assign a chunk of namelist[] below */ - 0, 0, 0, 0, - 0, 0, - 0, 0, 0, NULL, NULL - }, -}; - -static int io[MAX_HP_CARDS] = { 0, }; -static int irq[MAX_HP_CARDS] = { 0, }; - -/* This is set up so that only a single autoprobe takes place per call. -ISA device autoprobes on a running machine are not recommended. */ -int -init_module(void) -{ - int this_dev, found = 0; - - for (this_dev = 0; this_dev < MAX_HP_CARDS; this_dev++) { - struct device *dev = &dev_hp[this_dev]; - dev->name = namelist+(NAMELEN*this_dev); - dev->irq = irq[this_dev]; - dev->base_addr = io[this_dev]; - dev->init = hp_probe; - if (io[this_dev] == 0) { - if (this_dev != 0) break; /* only autoprobe 1st one */ - printk(KERN_NOTICE "hp.c: Presently autoprobing (not recommended) for a single card.\n"); - } - if (register_netdev(dev) != 0) { - printk(KERN_WARNING "hp.c: No HP card found (i/o = 0x%x).\n", io[this_dev]); - if (found != 0) return 0; /* Got at least one. */ - return -ENXIO; - } - found++; - } - - return 0; -} - -void -cleanup_module(void) -{ - int this_dev; - - for (this_dev = 0; this_dev < MAX_HP_CARDS; this_dev++) { - struct device *dev = &dev_hp[this_dev]; - if (dev->priv != NULL) { - int ioaddr = dev->base_addr - NIC_OFFSET; - kfree(dev->priv); - dev->priv = NULL; - free_irq(dev->irq); - irq2dev_map[dev->irq] = NULL; - release_region(ioaddr, HP_IO_EXTENT); - unregister_netdev(dev); - } - } -} -#endif /* MODULE */ - -/* - * Local variables: - * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c hp.c" - * version-control: t - * kept-new-versions: 5 - * tab-width: 4 - * c-indent-level: 4 - * End: - */ diff --git a/i386/i386at/gpl/linux/net/hp100.c b/i386/i386at/gpl/linux/net/hp100.c deleted file mode 100644 index d8186bf1..00000000 --- a/i386/i386at/gpl/linux/net/hp100.c +++ /dev/null @@ -1,1144 +0,0 @@ -/* - * hp100.c: Hewlett Packard HP10/100VG ANY LAN ethernet driver for Linux. - * - * Author: Jaroslav Kysela, <perex@pf.jcu.cz> - * - * Supports only the following Hewlett Packard cards: - * - * HP J2577 10/100 EISA card with REVA Cascade chip - * HP J2573 10/100 ISA card with REVA Cascade chip - * HP 27248B 10 only EISA card with Cascade chip - * HP J2577 10/100 EISA card with Cascade chip - * HP J2573 10/100 ISA card with Cascade chip - * HP J2585 10/100 PCI card - * - * Other ATT2MD01 Chip based boards might be supported in the future - * (there are some minor changes needed). - * - * This driver is based on the 'hpfepkt' crynwr packet driver. - * - * This source/code is public free; you can distribute it and/or modify - * it under terms of the GNU General Public License (published by the - * Free Software Foundation) either version two of this License, or any - * later version. - * ---------------------------------------------------------------------------- - * - * Note: Some routines (interrupt handling, transmit) assumes that - * there is the PERFORMANCE page selected... - * - * ---------------------------------------------------------------------------- - * - * If you are going to use the module version of this driver, you may - * change this values at the "insert time" : - * - * Variable Description - * - * hp100_rx_ratio Range 1-99 - onboard memory used for RX - * packets in %. - * hp100_priority_tx If this variable is nonzero - all outgoing - * packets will be transmitted as priority. - * hp100_port Adapter port (for example 0x380). - * - * ---------------------------------------------------------------------------- - * MY BEST REGARDS GOING TO: - * - * IPEX s.r.o which lend me two HP J2573 cards and - * the HP AdvanceStack 100VG Hub-15 for debugging. - * - * Russel Nellson <nelson@crynwr.com> for help with obtaining sources - * of the 'hpfepkt' packet driver. - * - * Also thanks to Abacus Electric s.r.o which let me to use their - * motherboard for my second computer. - * - * ---------------------------------------------------------------------------- - * - * TO DO: - * ====== - * - ioctl handling - some runtime setup things - * - 100Mb/s Voice Grade AnyLAN network adapter/hub services support - * - 802.5 frames - * - promiscuous mode - * - bridge mode - * - cascaded repeater mode - * - 100Mbit MAC - * - * Revision history: - * ================= - * - * Version Date Description - * - * 0.1 14-May-95 Initial writing. ALPHA code was released. - * Only HP J2573 on 10Mb/s (two machines) tested. - * 0.11 14-Jun-95 Reset interface bug fixed? - * Little bug in hp100_close function fixed. - * 100Mb/s connection debugged. - * 0.12 14-Jul-95 Link down is now handled better. - * 0.20 01-Aug-95 Added PCI support for HP J2585A card. - * Statistics bug fixed. - * 0.21 04-Aug-95 Memory mapped access support for PCI card. - * Added priority transmit support for 100Mb/s - * Voice Grade AnyLAN network. - * - */ - -#include <linux/module.h> - -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/string.h> -#include <linux/errno.h> -#include <linux/ioport.h> -#include <linux/malloc.h> -#include <linux/interrupt.h> -#include <linux/pci.h> -#include <linux/bios32.h> -#include <asm/bitops.h> -#include <asm/io.h> - -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> - -#include <linux/types.h> -#include <linux/config.h> /* for CONFIG_PCI */ - -#include "hp100.h" - -/* - * defines - */ - -#define HP100_BUS_ISA 0 -#define HP100_BUS_EISA 1 -#define HP100_BUS_PCI 2 - -#define HP100_REGION_SIZE 0x20 - -#define HP100_MAX_PACKET_SIZE (1536+4) -#define HP100_MIN_PACKET_SIZE 60 - -#ifndef HP100_DEFAULT_RX_RATIO -/* default - 65% onboard memory on the card are used for RX packets */ -#define HP100_DEFAULT_RX_RATIO 65 -#endif - -#ifndef HP100_DEFAULT_PRIORITY_TX -/* default - don't enable transmit outgoing packets as priority */ -#define HP100_DEFAULT_PRIORITY_TX 0 -#endif - -#ifdef MACH -#define HP100_IO_MAPPED -#endif - -/* - * structures - */ - -struct hp100_eisa_id { - u_int id; - const char *name; - u_char bus; -}; - -struct hp100_private { - struct hp100_eisa_id *id; - u_short soft_model; - u_int memory_size; - u_short rx_ratio; /* 1 - 99 */ - u_short priority_tx; /* != 0 - priority tx */ - short mem_mapped; /* memory mapped access */ - u_char *mem_ptr_virt; /* virtual memory mapped area, maybe NULL */ - u_char *mem_ptr_phys; /* physical memory mapped area */ - short lan_type; /* 10Mb/s, 100Mb/s or -1 (error) */ - int hub_status; /* login to hub was successfull? */ - u_char mac1_mode; - u_char mac2_mode; - struct enet_statistics stats; -}; - -/* - * variables - */ - -static struct hp100_eisa_id hp100_eisa_ids[] = { - - /* 10/100 EISA card with REVA Cascade chip */ - { 0x080F1F022, "HP J2577 rev A", HP100_BUS_EISA }, - - /* 10/100 ISA card with REVA Cascade chip */ - { 0x050F1F022, "HP J2573 rev A", HP100_BUS_ISA }, - - /* 10 only EISA card with Cascade chip */ - { 0x02019F022, "HP 27248B", HP100_BUS_EISA }, - - /* 10/100 EISA card with Cascade chip */ - { 0x04019F022, "HP J2577", HP100_BUS_EISA }, - - /* 10/100 ISA card with Cascade chip */ - { 0x05019F022, "HP J2573", HP100_BUS_ISA }, - - /* 10/100 PCI card */ - /* Note: ID for this card is same as PCI vendor/device numbers. */ - { 0x01030103c, "HP J2585", HP100_BUS_PCI }, -}; - -int hp100_rx_ratio = HP100_DEFAULT_RX_RATIO; -int hp100_priority_tx = HP100_DEFAULT_PRIORITY_TX; - -/* - * prototypes - */ - -static int hp100_probe1( struct device *dev, int ioaddr, int bus ); -static int hp100_open( struct device *dev ); -static int hp100_close( struct device *dev ); -static int hp100_start_xmit( struct sk_buff *skb, struct device *dev ); -static void hp100_rx( struct device *dev ); -static struct enet_statistics *hp100_get_stats( struct device *dev ); -static void hp100_update_stats( struct device *dev ); -static void hp100_clear_stats( int ioaddr ); -static void hp100_set_multicast_list( struct device *dev); -static void hp100_interrupt( int irq, struct pt_regs *regs ); - -static void hp100_start_interface( struct device *dev ); -static void hp100_stop_interface( struct device *dev ); -static void hp100_load_eeprom( struct device *dev ); -static int hp100_sense_lan( struct device *dev ); -static int hp100_login_to_vg_hub( struct device *dev ); -static int hp100_down_vg_link( struct device *dev ); - -/* - * probe functions - */ - -int hp100_probe( struct device *dev ) -{ - int base_addr = dev ? dev -> base_addr : 0; - int ioaddr; -#ifdef CONFIG_PCI - int pci_start_index = 0; -#endif - - if ( base_addr > 0xff ) /* Check a single specified location. */ - { - if ( check_region( base_addr, HP100_REGION_SIZE ) ) return -EINVAL; - if ( base_addr < 0x400 ) - return hp100_probe1( dev, base_addr, HP100_BUS_ISA ); - else - return hp100_probe1( dev, base_addr, HP100_BUS_EISA ); - } - else -#ifdef CONFIG_PCI - if ( base_addr > 0 && base_addr < 8 + 1 ) - pci_start_index = 0x100 | ( base_addr - 1 ); - else -#endif - if ( base_addr != 0 ) return -ENXIO; - - /* at first - scan PCI bus(es) */ - -#ifdef CONFIG_PCI - if ( pcibios_present() ) - { - int pci_index; - -#ifdef HP100_DEBUG_PCI - printk( "hp100: PCI BIOS is present, checking for devices..\n" ); -#endif - for ( pci_index = pci_start_index & 7; pci_index < 8; pci_index++ ) - { - u_char pci_bus, pci_device_fn; - u_short pci_command; - - if ( pcibios_find_device( PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_J2585A, - pci_index, &pci_bus, - &pci_device_fn ) != 0 ) break; - pcibios_read_config_dword( pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_0, &ioaddr ); - - ioaddr &= ~3; /* remove I/O space marker in bit 0. */ - - if ( check_region( ioaddr, HP100_REGION_SIZE ) ) continue; - - pcibios_read_config_word( pci_bus, pci_device_fn, - PCI_COMMAND, &pci_command ); - if ( !( pci_command & PCI_COMMAND_MASTER ) ) - { -#ifdef HP100_DEBUG_PCI - printk( "hp100: PCI Master Bit has not been set. Setting...\n" ); -#endif - pci_command |= PCI_COMMAND_MASTER; - pcibios_write_config_word( pci_bus, pci_device_fn, - PCI_COMMAND, pci_command ); - } -#ifdef HP100_DEBUG_PCI - printk( "hp100: PCI adapter found at 0x%x\n", ioaddr ); -#endif - if ( hp100_probe1( dev, ioaddr, HP100_BUS_PCI ) == 0 ) return 0; - } - } - if ( pci_start_index > 0 ) return -ENODEV; -#endif /* CONFIG_PCI */ - - /* at second - probe all EISA possible port regions (if EISA bus present) */ - - for ( ioaddr = 0x1c38; EISA_bus && ioaddr < 0x10000; ioaddr += 0x400 ) - { - if ( check_region( ioaddr, HP100_REGION_SIZE ) ) continue; - if ( hp100_probe1( dev, ioaddr, HP100_BUS_EISA ) == 0 ) return 0; - } - - /* at third - probe all ISA possible port regions */ - - for ( ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x20 ) - { - if ( check_region( ioaddr, HP100_REGION_SIZE ) ) continue; - if ( hp100_probe1( dev, ioaddr, HP100_BUS_ISA ) == 0 ) return 0; - } - - return -ENODEV; -} - -static int hp100_probe1( struct device *dev, int ioaddr, int bus ) -{ - int i; - u_char uc, uc_1; - u_int eisa_id; - short mem_mapped; - u_char *mem_ptr_phys, *mem_ptr_virt; - struct hp100_private *lp; - struct hp100_eisa_id *eid; - - if ( dev == NULL ) - { -#ifdef HP100_DEBUG - printk( "hp100_probe1: dev == NULL ?\n" ); -#endif - return EIO; - } - - if ( bus != HP100_BUS_PCI ) /* don't check PCI cards again */ - if ( inb( ioaddr + 0 ) != HP100_HW_ID_0 || - inb( ioaddr + 1 ) != HP100_HW_ID_1 || - ( inb( ioaddr + 2 ) & 0xf0 ) != HP100_HW_ID_2_REVA || - inb( ioaddr + 3 ) != HP100_HW_ID_3 ) - return -ENODEV; - - dev -> base_addr = ioaddr; - -#ifdef HP100_DEBUG_PROBE1 - printk( "hp100_probe1: card found at port 0x%x\n", ioaddr ); -#endif - - hp100_page( ID_MAC_ADDR ); - for ( i = uc = eisa_id = 0; i < 4; i++ ) - { - eisa_id >>= 8; - uc_1 = hp100_inb( BOARD_ID + i ); - eisa_id |= uc_1 << 24; - uc += uc_1; - } - uc += hp100_inb( BOARD_ID + 4 ); - -#ifdef HP100_DEBUG_PROBE1 - printk( "hp100_probe1: EISA ID = 0x%08x checksum = 0x%02x\n", eisa_id, uc ); -#endif - - if ( uc != 0xff ) /* bad checksum? */ - { - printk( "hp100_probe: bad EISA ID checksum at base port 0x%x\n", ioaddr ); - return -ENODEV; - } - - for ( i = 0; i < sizeof( hp100_eisa_ids ) / sizeof( struct hp100_eisa_id ); i++ ) - if ( ( hp100_eisa_ids[ i ].id & 0xf0ffffff ) == ( eisa_id & 0xf0ffffff ) ) - break; - if ( i >= sizeof( hp100_eisa_ids ) / sizeof( struct hp100_eisa_id ) ) - { - printk( "hp100_probe1: card at port 0x%x isn't known (id = 0x%x)\n", ioaddr, eisa_id ); - return -ENODEV; - } - eid = &hp100_eisa_ids[ i ]; - if ( ( eid -> id & 0x0f000000 ) < ( eisa_id & 0x0f000000 ) ) - { - printk( "hp100_probe1: newer version of card %s at port 0x%x - unsupported\n", - eid -> name, ioaddr ); - return -ENODEV; - } - - for ( i = uc = 0; i < 7; i++ ) - uc += hp100_inb( LAN_ADDR + i ); - if ( uc != 0xff ) - { - printk( "hp100_probe1: bad lan address checksum (card %s at port 0x%x)\n", - eid -> name, ioaddr ); - return -EIO; - } - -#ifndef HP100_IO_MAPPED - hp100_page( HW_MAP ); - mem_mapped = ( hp100_inw( OPTION_LSW ) & - ( HP100_MEM_EN | HP100_BM_WRITE | HP100_BM_READ ) ) != 0; - mem_ptr_phys = mem_ptr_virt = NULL; - if ( mem_mapped ) - { - mem_ptr_phys = (u_char *)( hp100_inw( MEM_MAP_LSW ) | - ( hp100_inw( MEM_MAP_MSW ) << 16 ) ); - (u_int)mem_ptr_phys &= ~0x1fff; /* 8k aligment */ - if ( bus == HP100_BUS_ISA && ( (u_long)mem_ptr_phys & ~0xfffff ) != 0 ) - { - mem_ptr_phys = NULL; - mem_mapped = 0; - } - if ( mem_mapped && bus == HP100_BUS_PCI ) - { - if ( ( mem_ptr_virt = vremap( (u_long)mem_ptr_phys, 0x2000 ) ) == NULL ) - { - printk( "hp100: vremap for high PCI memory at 0x%lx failed\n", (u_long)mem_ptr_phys ); - mem_ptr_phys = NULL; - mem_mapped = 0; - } - } - } -#else - mem_mapped = 0; - mem_ptr_phys = mem_ptr_virt = NULL; -#endif - - if ( ( dev -> priv = kmalloc( sizeof( struct hp100_private ), GFP_KERNEL ) ) == NULL ) - return -ENOMEM; - memset( dev -> priv, 0, sizeof( struct hp100_private ) ); - - lp = (struct hp100_private *)dev -> priv; - lp -> id = eid; - lp -> mem_mapped = mem_mapped; - lp -> mem_ptr_phys = mem_ptr_phys; - lp -> mem_ptr_virt = mem_ptr_virt; - hp100_page( ID_MAC_ADDR ); - lp -> soft_model = hp100_inb( SOFT_MODEL ); - lp -> mac1_mode = HP100_MAC1MODE3; - lp -> mac2_mode = HP100_MAC2MODE3; - - dev -> base_addr = ioaddr; - hp100_page( HW_MAP ); - dev -> irq = hp100_inb( IRQ_CHANNEL ) & HP100_IRQ_MASK; - if ( dev -> irq == 2 ) dev -> irq = 9; - lp -> memory_size = 0x200 << ( ( hp100_inb( SRAM ) & 0xe0 ) >> 5 ); - lp -> rx_ratio = hp100_rx_ratio; - - dev -> open = hp100_open; - dev -> stop = hp100_close; - dev -> hard_start_xmit = hp100_start_xmit; - dev -> get_stats = hp100_get_stats; - dev -> set_multicast_list = &hp100_set_multicast_list; - - request_region( dev -> base_addr, HP100_REGION_SIZE, eid -> name ); - - hp100_page( ID_MAC_ADDR ); - for ( i = uc = 0; i < 6; i++ ) - dev -> dev_addr[ i ] = hp100_inb( LAN_ADDR + i ); - - hp100_clear_stats( ioaddr ); - - ether_setup( dev ); - - lp -> lan_type = hp100_sense_lan( dev ); - - printk( "%s: %s at 0x%x, IRQ %d, ", - dev -> name, lp -> id -> name, ioaddr, dev -> irq ); - switch ( bus ) { - case HP100_BUS_EISA: printk( "EISA" ); break; - case HP100_BUS_PCI: printk( "PCI" ); break; - default: printk( "ISA" ); break; - } - printk( " bus, %dk SRAM (rx/tx %d%%).\n", - lp -> memory_size >> ( 10 - 4 ), lp -> rx_ratio ); - if ( mem_mapped ) - { - printk( "%s: Memory area at 0x%lx-0x%lx", - dev -> name, (u_long)mem_ptr_phys, (u_long)mem_ptr_phys + 0x1fff ); - if ( mem_ptr_virt ) - printk( " (virtual base 0x%lx)", (u_long)mem_ptr_virt ); - printk( ".\n" ); - } - printk( "%s: ", dev -> name ); - if ( lp -> lan_type != HP100_LAN_ERR ) - printk( "Adapter is attached to " ); - switch ( lp -> lan_type ) { - case HP100_LAN_100: - printk( "100Mb/s Voice Grade AnyLAN network.\n" ); - break; - case HP100_LAN_10: - printk( "10Mb/s network.\n" ); - break; - default: - printk( "Warning! Link down.\n" ); - } - - hp100_stop_interface( dev ); - - return 0; -} - -/* - * open/close functions - */ - -static int hp100_open( struct device *dev ) -{ - int i; - int ioaddr = dev -> base_addr; - struct hp100_private *lp = (struct hp100_private *)dev -> priv; - - if ( request_irq( dev -> irq, hp100_interrupt, SA_INTERRUPT, lp -> id -> name ) ) - { - printk( "%s: unable to get IRQ %d\n", dev -> name, dev -> irq ); - return -EAGAIN; - } - irq2dev_map[ dev -> irq ] = dev; - - MOD_INC_USE_COUNT; - - dev -> tbusy = 0; - dev -> trans_start = jiffies; - dev -> interrupt = 0; - dev -> start = 1; - - lp -> lan_type = hp100_sense_lan( dev ); - lp -> mac1_mode = HP100_MAC1MODE3; - lp -> mac2_mode = HP100_MAC2MODE3; - - hp100_page( MAC_CTRL ); - hp100_orw( HP100_LINK_BEAT_DIS | HP100_RESET_LB, LAN_CFG_10 ); - - hp100_stop_interface( dev ); - hp100_load_eeprom( dev ); - - hp100_outw( HP100_MMAP_DIS | HP100_SET_HB | - HP100_IO_EN | HP100_SET_LB, OPTION_LSW ); - hp100_outw( HP100_DEBUG_EN | HP100_RX_HDR | HP100_EE_EN | HP100_RESET_HB | - HP100_FAKE_INT | HP100_RESET_LB, OPTION_LSW ); - hp100_outw( HP100_ADV_NXT_PKT | HP100_TX_CMD | HP100_RESET_LB | - HP100_PRIORITY_TX | ( hp100_priority_tx ? HP100_SET_HB : HP100_RESET_HB ), - OPTION_MSW ); - - hp100_page( MAC_ADDRESS ); - for ( i = 0; i < 6; i++ ) - hp100_outb( dev -> dev_addr[ i ], MAC_ADDR + i ); - for ( i = 0; i < 8; i++ ) /* setup multicast filter to receive all */ - hp100_outb( 0xff, HASH_BYTE0 + i ); - hp100_page( PERFORMANCE ); - hp100_outw( 0xfefe, IRQ_MASK ); /* mask off all ints */ - hp100_outw( 0xffff, IRQ_STATUS ); /* ack IRQ */ - hp100_outw( (HP100_RX_PACKET | HP100_RX_ERROR | HP100_SET_HB) | - (HP100_TX_ERROR | HP100_SET_LB ), IRQ_MASK ); - /* and enable few */ - hp100_reset_card(); - hp100_page( MMU_CFG ); - hp100_outw( ( lp -> memory_size * lp -> rx_ratio ) / 100, RX_MEM_STOP ); - hp100_outw( lp -> memory_size - 1, TX_MEM_STOP ); - hp100_unreset_card(); - - if ( lp -> lan_type == HP100_LAN_100 ) - lp -> hub_status = hp100_login_to_vg_hub( dev ); - - hp100_start_interface( dev ); - - return 0; -} - -static int hp100_close( struct device *dev ) -{ - int ioaddr = dev -> base_addr; - struct hp100_private *lp = (struct hp100_private *)dev -> priv; - - hp100_page( PERFORMANCE ); - hp100_outw( 0xfefe, IRQ_MASK ); /* mask off all IRQs */ - - hp100_stop_interface( dev ); - - if ( lp -> lan_type == HP100_LAN_100 ) /* relogin */ - hp100_login_to_vg_hub( dev ); - - dev -> tbusy = 1; - dev -> start = 0; - - free_irq( dev -> irq ); - irq2dev_map[ dev -> irq ] = NULL; - MOD_DEC_USE_COUNT; - return 0; -} - -/* - * transmit - */ - -static int hp100_start_xmit( struct sk_buff *skb, struct device *dev ) -{ - int i, ok_flag; - int ioaddr = dev -> base_addr; - u_short val; - struct hp100_private *lp = (struct hp100_private *)dev -> priv; - - if ( lp -> lan_type < 0 ) - { - hp100_stop_interface( dev ); - if ( ( lp -> lan_type = hp100_sense_lan( dev ) ) < 0 ) - { - printk( "%s: no connection found - check wire\n", dev -> name ); - hp100_start_interface( dev ); /* 10Mb/s RX packets maybe handled */ - return -EIO; - } - if ( lp -> lan_type == HP100_LAN_100 ) - lp -> hub_status = hp100_login_to_vg_hub( dev ); - hp100_start_interface( dev ); - } - - if ( ( i = ( hp100_inl( TX_MEM_FREE ) & ~0x7fffffff ) ) < skb -> len + 16 ) - { -#ifdef HP100_DEBUG - printk( "hp100_start_xmit: rx free mem = 0x%x\n", i ); -#endif - if ( jiffies - dev -> trans_start < 2 * HZ ) return -EAGAIN; - if ( lp -> lan_type == HP100_LAN_100 && lp -> hub_status < 0 ) - /* 100Mb/s adapter isn't connected to hub */ - { - printk( "%s: login to 100Mb/s hub retry\n", dev -> name ); - hp100_stop_interface( dev ); - lp -> hub_status = hp100_login_to_vg_hub( dev ); - hp100_start_interface( dev ); - } - else - { - hp100_ints_off(); - i = hp100_sense_lan( dev ); - hp100_page( PERFORMANCE ); - hp100_ints_on(); - if ( i == HP100_LAN_ERR ) - printk( "%s: link down detected\n", dev -> name ); - else - if ( lp -> lan_type != i ) - { - /* it's very heavy - all network setting must be changed!!! */ - printk( "%s: cable change 10Mb/s <-> 100Mb/s detected\n", dev -> name ); - lp -> lan_type = i; - hp100_stop_interface( dev ); - if ( lp -> lan_type == HP100_LAN_100 ) - lp -> hub_status = hp100_login_to_vg_hub( dev ); - hp100_start_interface( dev ); - } - else - { - printk( "%s: interface reset\n", dev -> name ); - hp100_stop_interface( dev ); - hp100_start_interface( dev ); - } - } - dev -> trans_start = jiffies; - return -EAGAIN; - } - - if ( skb == NULL ) - { - dev_tint( dev ); - return 0; - } - - if ( skb -> len <= 0 ) return 0; - - for ( i = 0; i < 6000 && ( hp100_inw( OPTION_MSW ) & HP100_TX_CMD ); i++ ) - { -#ifdef HP100_DEBUG_TX - printk( "hp100_start_xmit: busy\n" ); -#endif - } - - hp100_ints_off(); - val = hp100_inw( IRQ_STATUS ); - hp100_outw( val & HP100_TX_COMPLETE, IRQ_STATUS ); -#ifdef HP100_DEBUG_TX - printk( "hp100_start_xmit: irq_status = 0x%x, len = %d\n", val, (int)skb -> len ); -#endif - ok_flag = skb -> len >= HP100_MIN_PACKET_SIZE; - i = ok_flag ? skb -> len : HP100_MIN_PACKET_SIZE; - hp100_outw( i, DATA32 ); /* length to memory manager */ - hp100_outw( i, FRAGMENT_LEN ); - if ( lp -> mem_mapped ) - { - if ( lp -> mem_ptr_virt ) - { - memcpy( lp -> mem_ptr_virt, skb -> data, skb -> len ); - if ( !ok_flag ) - memset( lp -> mem_ptr_virt, 0, HP100_MIN_PACKET_SIZE - skb -> len ); - } - else - { - memcpy_toio( lp -> mem_ptr_phys, skb -> data, skb -> len ); - if ( !ok_flag ) - memset_io( lp -> mem_ptr_phys, 0, HP100_MIN_PACKET_SIZE - skb -> len ); - } - } - else - { - outsl( ioaddr + HP100_REG_DATA32, skb -> data, ( skb -> len + 3 ) >> 2 ); - if ( !ok_flag ) - for ( i = ( skb -> len + 3 ) & ~3; i < HP100_MIN_PACKET_SIZE; i += 4 ) - hp100_outl( 0, DATA32 ); - } - hp100_outw( HP100_TX_CMD | HP100_SET_LB, OPTION_MSW ); /* send packet */ - lp -> stats.tx_packets++; - dev -> trans_start = jiffies; - hp100_ints_on(); - - dev_kfree_skb( skb, FREE_WRITE ); - -#ifdef HP100_DEBUG_TX - printk( "hp100_start_xmit: end\n" ); -#endif - - return 0; -} - -/* - * receive - called from interrupt handler - */ - -static void hp100_rx( struct device *dev ) -{ - int packets, pkt_len; - int ioaddr = dev -> base_addr; - struct hp100_private *lp = (struct hp100_private *)dev -> priv; - u_int header; - struct sk_buff *skb; - -#if 0 - if ( lp -> lan_type < 0 ) - { - if ( ( lp -> lan_type = hp100_sense_lan( dev ) ) == HP100_LAN_100 ) - lp -> hub_status = hp100_login_to_vg_hub( dev ); - hp100_page( PERFORMANCE ); - } -#endif - - packets = hp100_inb( RX_PKT_CNT ); -#ifdef HP100_DEBUG - if ( packets > 1 ) - printk( "hp100_rx: waiting packets = %d\n", packets ); -#endif - while ( packets-- > 0 ) - { - for ( pkt_len = 0; pkt_len < 6000 && ( hp100_inw( OPTION_MSW ) & HP100_ADV_NXT_PKT ); pkt_len++ ) - { -#ifdef HP100_DEBUG_TX - printk( "hp100_rx: busy, remaining packets = %d\n", packets ); -#endif - } - if ( lp -> mem_mapped ) - { - if ( lp -> mem_ptr_virt ) - header = *(__u32 *)lp -> mem_ptr_virt; - else - header = readl( lp -> mem_ptr_phys ); - } - else - header = hp100_inl( DATA32 ); - pkt_len = header & HP100_PKT_LEN_MASK; -#ifdef HP100_DEBUG_RX - printk( "hp100_rx: new packet - length = %d, errors = 0x%x, dest = 0x%x\n", - header & HP100_PKT_LEN_MASK, ( header >> 16 ) & 0xfff8, ( header >> 16 ) & 7 ); -#endif - /* - * NOTE! This (and the skb_put() below) depends on the skb-functions - * allocating more than asked (notably, aligning the request up to - * the next 16-byte length). - */ - skb = dev_alloc_skb( pkt_len ); - if ( skb == NULL ) - { -#ifdef HP100_DEBUG - printk( "hp100_rx: couldn't allocate a sk_buff of size %d\n", pkt_len ); -#endif - lp -> stats.rx_dropped++; - } - else - { - u_char *ptr; - - skb -> dev = dev; - ptr = (u_char *)skb_put( skb, pkt_len ); - if ( lp -> mem_mapped ) - { - if ( lp -> mem_ptr_virt ) - memcpy( ptr, lp -> mem_ptr_virt, ( pkt_len + 3 ) & ~3 ); - else - memcpy_fromio( ptr, lp -> mem_ptr_phys, ( pkt_len + 3 ) & ~3 ); - } - else - insl( ioaddr + HP100_REG_DATA32, ptr, ( pkt_len + 3 ) >> 2 ); - skb -> protocol = eth_type_trans( skb, dev ); - netif_rx( skb ); - lp -> stats.rx_packets++; -#ifdef HP100_DEBUG_RX - printk( "rx: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", - ptr[ 0 ], ptr[ 1 ], ptr[ 2 ], ptr[ 3 ], ptr[ 4 ], ptr[ 5 ], - ptr[ 6 ], ptr[ 7 ], ptr[ 8 ], ptr[ 9 ], ptr[ 10 ], ptr[ 11 ] ); -#endif - } - hp100_outw( HP100_ADV_NXT_PKT | HP100_SET_LB, OPTION_MSW ); - switch ( header & 0x00070000 ) { - case (HP100_MULTI_ADDR_HASH<<16): - case (HP100_MULTI_ADDR_NO_HASH<<16): - lp -> stats.multicast++; break; - } - } -#ifdef HP100_DEBUG_RX - printk( "hp100_rx: end\n" ); -#endif -} - -/* - * statistics - */ - -static struct enet_statistics *hp100_get_stats( struct device *dev ) -{ - int ioaddr = dev -> base_addr; - - hp100_ints_off(); - hp100_update_stats( dev ); - hp100_ints_on(); - return &((struct hp100_private *)dev -> priv) -> stats; -} - -static void hp100_update_stats( struct device *dev ) -{ - int ioaddr = dev -> base_addr; - u_short val; - struct hp100_private *lp = (struct hp100_private *)dev -> priv; - - hp100_page( MAC_CTRL ); /* get all statistics bytes */ - val = hp100_inw( DROPPED ) & 0x0fff; - lp -> stats.rx_errors += val; - lp -> stats.rx_over_errors += val; - val = hp100_inb( CRC ); - lp -> stats.rx_errors += val; - lp -> stats.rx_crc_errors += val; - val = hp100_inb( ABORT ); - lp -> stats.tx_errors += val; - lp -> stats.tx_aborted_errors += val; - hp100_page( PERFORMANCE ); -} - -static void hp100_clear_stats( int ioaddr ) -{ - cli(); - hp100_page( MAC_CTRL ); /* get all statistics bytes */ - hp100_inw( DROPPED ); - hp100_inb( CRC ); - hp100_inb( ABORT ); - hp100_page( PERFORMANCE ); - sti(); -} - -/* - * multicast setup - */ - -/* - * Set or clear the multicast filter for this adapter. - */ - -static void hp100_set_multicast_list( struct device *dev) -{ - int ioaddr = dev -> base_addr; - struct hp100_private *lp = (struct hp100_private *)dev -> priv; - -#ifdef HP100_DEBUG_MULTI - printk( "hp100_set_multicast_list: num_addrs = %d\n", dev->mc_count); -#endif - cli(); - hp100_ints_off(); - hp100_page( MAC_CTRL ); - hp100_andb( ~(HP100_RX_EN | HP100_TX_EN), MAC_CFG_1 ); /* stop rx/tx */ - - if ( dev->flags&IFF_PROMISC) - { - lp -> mac2_mode = HP100_MAC2MODE6; /* promiscuous mode, all good */ - lp -> mac1_mode = HP100_MAC1MODE6; /* packets on the net */ - } - else - if ( dev->mc_count || dev->flags&IFF_ALLMULTI ) - { - lp -> mac2_mode = HP100_MAC2MODE5; /* multicast mode, packets for me */ - lp -> mac1_mode = HP100_MAC1MODE5; /* broadcasts and all multicasts */ - } - else - { - lp -> mac2_mode = HP100_MAC2MODE3; /* normal mode, packets for me */ - lp -> mac1_mode = HP100_MAC1MODE3; /* and broadcasts */ - } - - hp100_outb( lp -> mac2_mode, MAC_CFG_2 ); - hp100_andb( HP100_MAC1MODEMASK, MAC_CFG_1 ); - hp100_orb( lp -> mac1_mode | - HP100_RX_EN | HP100_RX_IDLE | /* enable rx */ - HP100_TX_EN | HP100_TX_IDLE, MAC_CFG_1 ); /* enable tx */ - hp100_page( PERFORMANCE ); - hp100_ints_on(); - sti(); -} - -/* - * hardware interrupt handling - */ - -static void hp100_interrupt( int irq, struct pt_regs *regs ) -{ - struct device *dev = (struct device *)irq2dev_map[ irq ]; - struct hp100_private *lp; - int ioaddr; - u_short val; - - if ( dev == NULL ) return; - ioaddr = dev -> base_addr; - if ( dev -> interrupt ) - printk( "%s: re-entering the interrupt handler\n", dev -> name ); - hp100_ints_off(); - dev -> interrupt = 1; - hp100_page( PERFORMANCE ); - val = hp100_inw( IRQ_STATUS ); -#ifdef HP100_DEBUG_IRQ - printk( "hp100_interrupt: irq_status = 0x%x\n", val ); -#endif - if ( val & HP100_RX_PACKET ) - { - hp100_rx( dev ); - hp100_outw( HP100_RX_PACKET, IRQ_STATUS ); - } - if ( val & (HP100_TX_SPACE_AVAIL | HP100_TX_COMPLETE) ) - { - hp100_outw( val & (HP100_TX_SPACE_AVAIL | HP100_TX_COMPLETE), IRQ_STATUS ); - } - if ( val & ( HP100_TX_ERROR | HP100_RX_ERROR ) ) - { - lp = (struct hp100_private *)dev -> priv; - hp100_update_stats( dev ); - hp100_outw( val & (HP100_TX_ERROR | HP100_RX_ERROR), IRQ_STATUS ); - } -#ifdef HP100_DEBUG_IRQ - printk( "hp100_interrupt: end\n" ); -#endif - dev -> interrupt = 0; - hp100_ints_on(); -} - -/* - * some misc functions - */ - -static void hp100_start_interface( struct device *dev ) -{ - int ioaddr = dev -> base_addr; - struct hp100_private *lp = (struct hp100_private *)dev -> priv; - - cli(); - hp100_unreset_card(); - hp100_page( MAC_CTRL ); - hp100_outb( lp -> mac2_mode, MAC_CFG_2 ); - hp100_andb( HP100_MAC1MODEMASK, MAC_CFG_1 ); - hp100_orb( lp -> mac1_mode | - HP100_RX_EN | HP100_RX_IDLE | - HP100_TX_EN | HP100_TX_IDLE, MAC_CFG_1 ); - hp100_page( PERFORMANCE ); - hp100_outw( HP100_INT_EN | HP100_SET_LB, OPTION_LSW ); - hp100_outw( HP100_TRI_INT | HP100_RESET_HB, OPTION_LSW ); - if ( lp -> mem_mapped ) - { - /* enable memory mapping */ - hp100_outw( HP100_MMAP_DIS | HP100_RESET_HB, OPTION_LSW ); - } - sti(); -} - -static void hp100_stop_interface( struct device *dev ) -{ - int ioaddr = dev -> base_addr; - u_short val; - - hp100_outw( HP100_INT_EN | HP100_RESET_LB | - HP100_TRI_INT | HP100_MMAP_DIS | HP100_SET_HB, OPTION_LSW ); - val = hp100_inw( OPTION_LSW ); - hp100_page( HW_MAP ); - hp100_andb( HP100_BM_SLAVE, BM ); - hp100_page( MAC_CTRL ); - hp100_andb( ~(HP100_RX_EN | HP100_TX_EN), MAC_CFG_1 ); - if ( !(val & HP100_HW_RST) ) return; - for ( val = 0; val < 6000; val++ ) - if ( ( hp100_inb( MAC_CFG_1 ) & (HP100_TX_IDLE | HP100_RX_IDLE) ) == - (HP100_TX_IDLE | HP100_RX_IDLE) ) - return; - printk( "%s: hp100_stop_interface - timeout\n", dev -> name ); -} - -static void hp100_load_eeprom( struct device *dev ) -{ - int i; - int ioaddr = dev -> base_addr; - - hp100_page( EEPROM_CTRL ); - hp100_andw( ~HP100_EEPROM_LOAD, EEPROM_CTRL ); - hp100_orw( HP100_EEPROM_LOAD, EEPROM_CTRL ); - for ( i = 0; i < 6000; i++ ) - if ( !( hp100_inw( OPTION_MSW ) & HP100_EE_LOAD ) ) return; - printk( "%s: hp100_load_eeprom - timeout\n", dev -> name ); -} - -/* return values: LAN_10, LAN_100 or LAN_ERR (not connected or hub is down)... */ - -static int hp100_sense_lan( struct device *dev ) -{ - int i; - int ioaddr = dev -> base_addr; - u_short val_VG, val_10; - struct hp100_private *lp = (struct hp100_private *)dev -> priv; - - hp100_page( MAC_CTRL ); - hp100_orw( HP100_VG_RESET, LAN_CFG_VG ); - val_10 = hp100_inw( LAN_CFG_10 ); - val_VG = hp100_inw( LAN_CFG_VG ); -#ifdef HP100_DEBUG_SENSE - printk( "hp100_sense_lan: val_VG = 0x%04x, val_10 = 0x%04x\n", val_VG, val_10 ); -#endif - if ( val_10 & HP100_LINK_BEAT_ST ) return HP100_LAN_10; - if ( lp -> id -> id == 0x02019F022 ) /* HP J27248B doesn't have 100Mb/s interface */ - return HP100_LAN_ERR; - for ( i = 0; i < 2500; i++ ) - { - val_VG = hp100_inw( LAN_CFG_VG ); - if ( val_VG & HP100_LINK_CABLE_ST ) return HP100_LAN_100; - } - return HP100_LAN_ERR; -} - -static int hp100_down_vg_link( struct device *dev ) -{ - int ioaddr = dev -> base_addr; - unsigned long time; - int i; - - hp100_page( MAC_CTRL ); - for ( i = 2500; i > 0; i-- ) - if ( hp100_inw( LAN_CFG_VG ) & HP100_LINK_CABLE_ST ) break; - if ( i <= 0 ) /* not signal - not logout */ - return 0; - hp100_andw( ~HP100_LINK_CMD, LAN_CFG_VG ); - time = jiffies + 10; - while ( time > jiffies ) - if ( !( hp100_inw( LAN_CFG_VG ) & ( HP100_LINK_UP_ST | - HP100_LINK_CABLE_ST | - HP100_LINK_GOOD_ST ) ) ) - return 0; -#ifdef HP100_DEBUG - printk( "hp100_down_vg_link: timeout\n" ); -#endif - return -EIO; -} - -static int hp100_login_to_vg_hub( struct device *dev ) -{ - int i; - int ioaddr = dev -> base_addr; - u_short val; - unsigned long time; - - hp100_page( MAC_CTRL ); - hp100_orw( HP100_VG_RESET, LAN_CFG_VG ); - time = jiffies + ( HZ / 2 ); - do { - if ( hp100_inw( LAN_CFG_VG ) & HP100_LINK_CABLE_ST ) break; - } while ( time > jiffies ); - if ( time <= jiffies ) - { -#ifdef HP100_DEBUG - printk( "hp100_login_to_vg_hub: timeout for link\n" ); -#endif - return -EIO; - } - - if ( hp100_down_vg_link( dev ) < 0 ) /* if fail, try reset VG link */ - { - hp100_andw( ~HP100_VG_RESET, LAN_CFG_VG ); - hp100_orw( HP100_VG_RESET, LAN_CFG_VG ); - } - /* bring up link */ - hp100_orw( HP100_LOAD_ADDR | HP100_LINK_CMD, LAN_CFG_VG ); - for ( i = 2500; i > 0; i-- ) - if ( hp100_inw( LAN_CFG_VG ) & HP100_LINK_CABLE_ST ) break; - if ( i <= 0 ) - { -#ifdef HP100_DEBUG - printk( "hp100_login_to_vg_hub: timeout for link (bring up)\n" ); -#endif - goto down_link; - } - - time = jiffies + ( HZ / 2 ); - do { - val = hp100_inw( LAN_CFG_VG ); - if ( ( val & ( HP100_LINK_UP_ST | HP100_LINK_GOOD_ST ) ) == - ( HP100_LINK_UP_ST | HP100_LINK_GOOD_ST ) ) - return 0; /* success */ - } while ( time > jiffies ); - if ( val & HP100_LINK_GOOD_ST ) - printk( "%s: 100Mb cable training failed, check cable.\n", dev -> name ); - else - printk( "%s: 100Mb node not accepted by hub, check frame type or security.\n", dev -> name ); - -down_link: - hp100_down_vg_link( dev ); - hp100_page( MAC_CTRL ); - hp100_andw( ~( HP100_LOAD_ADDR | HP100_PROM_MODE ), LAN_CFG_VG ); - hp100_orw( HP100_LINK_CMD, LAN_CFG_VG ); - return -EIO; -} - -/* - * module section - */ - -#ifdef MODULE - -static int hp100_port = -1; - -static char devicename[9] = { 0, }; -static struct device dev_hp100 = { - devicename, /* device name is inserted by linux/drivers/net/net_init.c */ - 0, 0, 0, 0, - 0, 0, - 0, 0, 0, NULL, hp100_probe -}; - -int init_module( void ) -{ - if (hp100_port == 0 && !EISA_bus) - printk("HP100: You should not use auto-probing with insmod!\n"); - if ( hp100_port > 0 ) - dev_hp100.base_addr = hp100_port; - if ( register_netdev( &dev_hp100 ) != 0 ) - return -EIO; - return 0; -} - -void cleanup_module( void ) -{ - unregister_netdev( &dev_hp100 ); - release_region( dev_hp100.base_addr, HP100_REGION_SIZE ); - if ( ((struct hp100_private *)dev_hp100.priv) -> mem_ptr_virt ) - vfree( ((struct hp100_private *)dev_hp100.priv) -> mem_ptr_virt ); - kfree_s( dev_hp100.priv, sizeof( struct hp100_private ) ); - dev_hp100.priv = NULL; -} - -#endif diff --git a/i386/i386at/gpl/linux/net/hp100.h b/i386/i386at/gpl/linux/net/hp100.h deleted file mode 100644 index 9f14f95a..00000000 --- a/i386/i386at/gpl/linux/net/hp100.h +++ /dev/null @@ -1,374 +0,0 @@ -/* - * hp100.h: Hewlett Packard HP10/100VG ANY LAN ethernet driver for Linux. - * - * Author: Jaroslav Kysela, <perex@pf.jcu.cz> - * - * Header file... - * - * This driver is based on the 'hpfepkt' crynwr packet driver. - * - * This source/code is public free; you can distribute it and/or modify - * it under terms of the GNU General Public License (published by the - * Free Software Foundation) either version two of this License, or any - * later version. - */ - -/**************************************************************************** - * Hardware Constants - ****************************************************************************/ - -/* - * ATT2MD01 Register Page Constants - */ - -#define HP100_PAGE_PERFORMANCE 0x0 /* Page 0 */ -#define HP100_PAGE_MAC_ADDRESS 0x1 /* Page 1 */ -#define HP100_PAGE_HW_MAP 0x2 /* Page 2 */ -#define HP100_PAGE_EEPROM_CTRL 0x3 /* Page 3 */ -#define HP100_PAGE_MAC_CTRL 0x4 /* Page 4 */ -#define HP100_PAGE_MMU_CFG 0x5 /* Page 5 */ -#define HP100_PAGE_ID_MAC_ADDR 0x6 /* Page 6 */ -#define HP100_PAGE_MMU_POINTER 0x7 /* Page 7 */ - -/* - * ATT2MD01 Register Addresses - */ - -/* Present on all pages */ - -#define HP100_REG_HW_ID 0x00 /* R: (16) Unique card ID */ -#define HP100_REG_TRACE 0x00 /* W: (16) Used for debug output */ -#define HP100_REG_PAGING 0x02 /* R: (16),15:4 Card ID */ - /* W: (16),3:0 Switch pages */ -#define HP100_REG_OPTION_LSW 0x04 /* RW: (16) Select card functions */ -#define HP100_REG_OPTION_MSW 0x06 /* RW: (16) Select card functions */ - -/* Page 0 - Performance */ - -#define HP100_REG_IRQ_STATUS 0x08 /* RW: (16) Which ints are pending */ -#define HP100_REG_IRQ_MASK 0x0a /* RW: (16) Select ints to allow */ -#define HP100_REG_FRAGMENT_LEN 0x0c /* RW: (16)12:0 Current fragment len */ -#define HP100_REG_OFFSET 0x0e /* RW: (16)12:0 Offset to start read */ -#define HP100_REG_DATA32 0x10 /* RW: (32) I/O mode data port */ -#define HP100_REG_DATA16 0x12 /* RW: WORDs must be read from here */ -#define HP100_REG_TX_MEM_FREE 0x14 /* RD: (32) Amount of free Tx mem */ -#define HP100_REG_RX_PKT_CNT 0x18 /* RD: (8) Rx count of pkts on card */ -#define HP100_REG_TX_PKT_CNT 0x19 /* RD: (8) Tx count of pkts on card */ - -/* Page 1 - MAC Address/Hash Table */ - -#define HP100_REG_MAC_ADDR 0x08 /* RW: (8) Cards MAC address */ -#define HP100_REG_HASH_BYTE0 0x10 /* RW: (8) Cards multicast filter */ - -/* Page 2 - Hardware Mapping */ - -#define HP100_REG_MEM_MAP_LSW 0x08 /* RW: (16) LSW of cards mem addr */ -#define HP100_REG_MEM_MAP_MSW 0x0a /* RW: (16) MSW of cards mem addr */ -#define HP100_REG_IO_MAP 0x0c /* RW: (8) Cards I/O address */ -#define HP100_REG_IRQ_CHANNEL 0x0d /* RW: (8) IRQ and edge/level int */ -#define HP100_REG_SRAM 0x0e /* RW: (8) How much RAM on card */ -#define HP100_REG_BM 0x0f /* RW: (8) Controls BM functions */ - -/* Page 3 - EEPROM/Boot ROM */ - -#define HP100_REG_EEPROM_CTRL 0x08 /* RW: (16) Used to load EEPROM */ - -/* Page 4 - LAN Configuration */ - -#define HP100_REG_LAN_CFG_10 0x08 /* RW: (16) Set 10M XCVR functions */ -#define HP100_REG_LAN_CFG_VG 0x0a /* RW: (16) Set 100M XCVR functions */ -#define HP100_REG_MAC_CFG_1 0x0c /* RW: (8) Types of pkts to accept */ -#define HP100_REG_MAC_CFG_2 0x0d /* RW: (8) Misc MAC functions */ -/* The follow clear when read: */ -#define HP100_REG_DROPPED 0x10 /* R: (16),11:0 Pkts cant fit in mem*/ -#define HP100_REG_CRC 0x12 /* R: (8) Pkts with CRC */ -#define HP100_REG_ABORT 0x13 /* R: (8) Aborted Tx pkts */ - -/* Page 5 - MMU */ - -#define HP100_REG_RX_MEM_STOP 0x0c /* RW: (16) End of Rx ring addr */ -#define HP100_REG_TX_MEM_STOP 0x0e /* RW: (16) End of Tx ring addr */ - -/* Page 6 - Card ID/Physical LAN Address */ - -#define HP100_REG_BOARD_ID 0x08 /* R: (8) EISA/ISA card ID */ -#define HP100_REG_BOARD_IO_CHCK 0x0c /* R: (8) Added to ID to get FFh */ -#define HP100_REG_SOFT_MODEL 0x0d /* R: (8) Config program defined */ -#define HP100_REG_LAN_ADDR 0x10 /* R: (8) MAC addr of card */ -#define HP100_REG_LAN_ADDR_CHCK 0x16 /* R: (8) Added to addr to get FFh */ - -/* Page 7 - MMU Current Pointers */ - -#define HP100_REG_RX_MEM_BR 0x08 /* R: (16) Current begin of Rx ring */ -#define HP100_REG_RX_MEM_ER 0x0a /* R: (16) Current end of Rx ring */ -#define HP100_REG_TX_MEM_BR 0x0c /* R: (16) Current begin of Tx ring */ -#define HP100_REG_TX_MEM_ER 0x0e /* R: (16) Current end of Rx ring */ -#define HP100_REG_MEM_DEBUG 0x1a /* RW: (16) Used for memory tests */ - -/* - * HardwareIDReg bits/masks - */ - -#define HP100_HW_ID_0 0x50 /* Hardware ID bytes. */ -#define HP100_HW_ID_1 0x48 -#define HP100_HW_ID_2_REVA 0x50 /* Rev. A ID. NOTE: lower nibble not used */ -#define HP100_HW_ID_3 0x53 - -/* - * OptionLSWReg bits/masks - */ - -#define HP100_DEBUG_EN 0x8000 /* 0:Disable, 1:Enable Debug Dump Pointer */ -#define HP100_RX_HDR 0x4000 /* 0:Disable, 1:Enable putting pkt into */ - /* system memory before Rx interrupt */ -#define HP100_MMAP_DIS 0x2000 /* 0:Enable, 1:Disable memory mapping. */ - /* MMAP_DIS must be 0 and MEM_EN must */ - /* be 1 for memory-mapped mode to be */ - /* enabled */ -#define HP100_EE_EN 0x1000 /* 0:Disable,1:Enable EEPROM writing */ -#define HP100_BM_WRITE 0x0800 /* 0:Slave, 1:Bus Master for Tx data */ -#define HP100_BM_READ 0x0400 /* 0:Slave, 1:Bus Master for Rx data */ -#define HP100_TRI_INT 0x0200 /* 0:Dont, 1:Do tri-state the int */ -#define HP100_MEM_EN 0x0040 /* Config program set this to */ - /* 0:Disable, 1:Enable mem map. */ - /* See MMAP_DIS. */ -#define HP100_IO_EN 0x0020 /* 0:Disable, 1:Enable I/O transfers */ -#define HP100_BOOT_EN 0x0010 /* 0:Disable, 1:Enable boot ROM access */ -#define HP100_FAKE_INT 0x0008 /* 0:No int, 1:int */ -#define HP100_INT_EN 0x0004 /* 0:Disable, 1:Enable ints from card */ -#define HP100_HW_RST 0x0002 /* 0:Reset, 1:Out of reset */ - -/* - * OptionMSWReg bits/masks - */ -#define HP100_PRIORITY_TX 0x0080 /* 0:Don't, 1:Do all Tx pkts as priority */ -#define HP100_EE_LOAD 0x0040 /* 1:EEPROM loading, 0 when done */ -#define HP100_ADV_NXT_PKT 0x0004 /* 1:Advance to next pkt in Rx queue, */ - /* h/w will set to 0 when done */ -#define HP100_TX_CMD 0x0002 /* 1:Tell h/w download done, h/w will set */ - /* to 0 when done */ - -/* - * InterruptStatusReg/InterruptMaskReg bits/masks. These bits will 0 when a 1 - * is written to them. - */ -#define HP100_RX_PACKET 0x0400 /* 0:No, 1:Yes pkt has been Rx */ -#define HP100_RX_ERROR 0x0200 /* 0:No, 1:Yes Rx pkt had error */ -#define HP100_TX_SPACE_AVAIL 0x0010 /* 0:<8192, 1:>=8192 Tx free bytes */ -#define HP100_TX_COMPLETE 0x0008 /* 0:No, 1:Yes a Tx has completed */ -#define HP100_TX_ERROR 0x0002 /* 0:No, 1:Yes Tx pkt had error */ - -/* - * TxMemoryFreeCountReg bits/masks. - */ -#define HP100_AUTO_COMPARE 0x8000 /* Says at least 8k is available for Tx. */ - /* NOTE: This mask is for the upper */ - /* word of the register. */ - -/* - * IRQChannelReg bits/masks. - */ -#define HP100_ZERO_WAIT_EN 0x80 /* 0:No, 1:Yes assers NOWS signal */ -#define HP100_LEVEL_IRQ 0x10 /* 0:Edge, 1:Level type interrupts. */ - /* Only valid on EISA cards. */ -#define HP100_IRQ_MASK 0x0F /* Isolate the IRQ bits */ - -/* - * SRAMReg bits/masks. - */ -#define HP100_RAM_SIZE_MASK 0xe0 /* AND to get SRAM size index */ -#define HP100_RAM_SIZE_SHIFT 0x05 /* Shift count to put index in lower bits */ - -/* - * BMReg bits/masks. - */ -#define HP100_BM_SLAVE 0x04 /* 0:Slave, 1:BM mode */ - -/* - * EEPROMControlReg bits/masks. - */ -#define HP100_EEPROM_LOAD 0x0001 /* 0->1 loads the EEPROM into registers. */ - /* When it goes back to 0, load is */ - /* complete. This should take ~600us. */ - -/* - * LANCntrCfg10Reg bits/masks. - */ -#define HP100_SQU_ST 0x0100 /* 0:No, 1:Yes collision signal sent */ - /* after Tx. Only used for AUI. */ -#define HP100_MAC10_SEL 0x00c0 /* Get bits to indicate MAC */ -#define HP100_AUI_SEL 0x0020 /* Status of AUI selection */ -#define HP100_LOW_TH 0x0010 /* 0:No, 1:Yes allow better cabling */ -#define HP100_LINK_BEAT_DIS 0x0008 /* 0:Enable, 1:Disable link beat */ -#define HP100_LINK_BEAT_ST 0x0004 /* 0:No, 1:Yes link beat being Rx */ -#define HP100_R_ROL_ST 0x0002 /* 0:No, 1:Yes Rx twisted pair has been */ - /* reversed */ -#define HP100_AUI_ST 0x0001 /* 0:No, 1:Yes use AUI on TP card */ - -/* MAC Selection, use with MAC10_SEL bits */ -#define HP100_AUTO_SEL_10 0x0 /* Auto select */ -#define HP100_XCVR_LXT901_10 0x1 /* LXT901 10BaseT transceiver */ -#define HP100_XCVR_7213 0x2 /* 7213 transceiver */ -#define HP100_XCVR_82503 0x3 /* 82503 transceiver */ - - -/* - * LANCntrCfgVGReg bits/masks. - */ -#define HP100_FRAME_FORMAT 0x0800 /* 0:802.3, 1:802.5 frames */ -#define HP100_BRIDGE 0x0400 /* 0:No, 1:Yes tell hub it's a bridge */ -#define HP100_PROM_MODE 0x0200 /* 0:No, 1:Yes tell hub card is */ - /* promiscuous */ -#define HP100_REPEATER 0x0100 /* 0:No, 1:Yes tell hub MAC wants to be */ - /* a cascaded repeater */ -#define HP100_MAC100_SEL 0x0080 /* 0:No, 1:Yes use 100 Mbit MAC */ -#define HP100_LINK_UP_ST 0x0040 /* 0:No, 1:Yes endnode logged in */ -#define HP100_LINK_CABLE_ST 0x0020 /* 0:No, 1:Yes cable can hear tones from */ - /* hub */ -#define HP100_LOAD_ADDR 0x0010 /* 0->1 card addr will be sent to hub. */ - /* 100ms later the link status bits are */ - /* valid */ -#define HP100_LINK_CMD 0x0008 /* 0->1 link will attempt to log in. */ - /* 100ms later the link status bits are */ - /* valid */ -#define HP100_LINK_GOOD_ST 0x0002 /* 0:No, 1:Yes cable passed training */ -#define HP100_VG_RESET 0x0001 /* 0:Yes, 1:No reset the 100VG MAC */ - - -/* - * MACConfiguration1Reg bits/masks. - */ -#define HP100_RX_IDLE 0x80 /* 0:Yes, 1:No currently receiving pkts */ -#define HP100_TX_IDLE 0x40 /* 0:Yes, 1:No currently Txing pkts */ -#define HP100_RX_EN 0x20 /* 0:No, 1:Yes allow receiving of pkts */ -#define HP100_TX_EN 0x10 /* 0:No, 1:Yes allow transmiting of pkts */ -#define HP100_ACC_ERRORED 0x08 /* 0:No, 1:Yes allow Rx of errored pkts */ -#define HP100_ACC_MC 0x04 /* 0:No, 1:Yes allow Rx of multicast pkts */ -#define HP100_ACC_BC 0x02 /* 0:No, 1:Yes allow Rx of broadcast pkts */ -#define HP100_ACC_PHY 0x01 /* 0:No, 1:Yes allow Rx of ALL physical pkts */ - -#define HP100_MAC1MODEMASK 0xf0 /* Hide ACC bits */ -#define HP100_MAC1MODE1 0x00 /* Receive nothing, must also disable RX */ -#define HP100_MAC1MODE2 0x00 -#define HP100_MAC1MODE3 HP100_MAC1MODE2 | HP100_ACC_BC -#define HP100_MAC1MODE4 HP100_MAC1MODE3 | HP100_ACC_MC -#define HP100_MAC1MODE5 HP100_MAC1MODE4 /* set mc hash to all ones also */ -#define HP100_MAC1MODE6 HP100_MAC1MODE5 | HP100_ACC_PHY /* Promiscuous */ - -/* Note MODE6 will receive all GOOD packets on the LAN. This really needs - a mode 7 defined to be LAN Analyzer mode, which will receive errored and - runt packets, and keep the CRC bytes. */ - -#define HP100_MAC1MODE7 MAC1MODE6 OR ACC_ERRORED - -/* - * MACConfiguration2Reg bits/masks. - */ -#define HP100_TR_MODE 0x80 /* 0:No, 1:Yes support Token Ring formats */ -#define HP100_TX_SAME 0x40 /* 0:No, 1:Yes Tx same packet continuous */ -#define HP100_LBK_XCVR 0x20 /* 0:No, 1:Yes loopback through MAC & */ - /* transceiver */ -#define HP100_LBK_MAC 0x10 /* 0:No, 1:Yes loopback through MAC */ -#define HP100_CRC_I 0x08 /* 0:No, 1:Yes inhibit CRC on Tx packets */ -#define HP100_KEEP_CRC 0x02 /* 0:No, 1:Yes keep CRC on Rx packets. */ - /* The length will reflect this. */ - -#define HP100_MAC2MODEMASK 0x02 -#define HP100_MAC2MODE1 0x00 -#define HP100_MAC2MODE2 0x00 -#define HP100_MAC2MODE3 0x00 -#define HP100_MAC2MODE4 0x00 -#define HP100_MAC2MODE5 0x00 -#define HP100_MAC2MODE6 0x00 -#define HP100_MAC2MODE7 KEEP_CRC - -/* - * Set/Reset bits - */ -#define HP100_SET_HB 0x0100 /* 0:Set fields to 0 whose mask is 1 */ -#define HP100_SET_LB 0x0001 /* HB sets upper byte, LB sets lower byte */ -#define HP100_RESET_HB 0x0000 /* For readability when resetting bits */ -#define HP100_RESET_LB 0x0000 /* For readability when resetting bits */ - -/* - * Misc. Constants - */ -#define HP100_LAN_100 100 /* lan_type value for VG */ -#define HP100_LAN_10 10 /* lan_type value for 10BaseT */ -#define HP100_LAN_ERR (-1) /* lan_type value for link down */ - -/* - * Receive Header Definition. - */ - -struct hp100_rx_header { - u_short rx_length; /* Pkt length is bits 12:0 */ - u_short rx_status; /* status of the packet */ -}; - -#define HP100_PKT_LEN_MASK 0x1FFF /* AND with RxLength to get length bits */ - -/* Receive Packet Status. Note, the error bits are only valid if ACC_ERRORED - bit in the MAC Configuration Register 1 is set. */ - -#define HP100_RX_PRI 0x8000 /* 0:No, 1:Yes packet is priority */ -#define HP100_SDF_ERR 0x4000 /* 0:No, 1:Yes start of frame error */ -#define HP100_SKEW_ERR 0x2000 /* 0:No, 1:Yes skew out of range */ -#define HP100_BAD_SYMBOL_ERR 0x1000 /* 0:No, 1:Yes invalid symbol received */ -#define HP100_RCV_IPM_ERR 0x0800 /* 0:No, 1:Yes pkt had an invalid packet */ - /* marker */ -#define HP100_SYMBOL_BAL_ERR 0x0400 /* 0:No, 1:Yes symbol balance error */ -#define HP100_VG_ALN_ERR 0x0200 /* 0:No, 1:Yes non-octet received */ -#define HP100_TRUNC_ERR 0x0100 /* 0:No, 1:Yes the packet was truncated */ -#define HP100_RUNT_ERR 0x0040 /* 0:No, 1:Yes pkt length < Min Pkt */ - /* Length Reg. */ -#define HP100_ALN_ERR 0x0010 /* 0:No, 1:Yes align error. */ -#define HP100_CRC_ERR 0x0008 /* 0:No, 1:Yes CRC occurred. */ - -/* The last three bits indicate the type of destination address */ - -#define HP100_MULTI_ADDR_HASH 0x0006 /* 110: Addr multicast, matched hash */ -#define HP100_BROADCAST_ADDR 0x0003 /* x11: Addr broadcast */ -#define HP100_MULTI_ADDR_NO_HASH 0x0002 /* 010: Addr multicast, didn't match hash */ -#define HP100_PHYS_ADDR_MATCH 0x0001 /* x01: Addr was physical and mine */ -#define HP100_PHYS_ADDR_NO_MATCH 0x0000 /* x00: Addr was physical but not mine */ - -/* - * macros - */ - -#define hp100_inb( reg ) \ - inb( ioaddr + HP100_REG_##reg ) -#define hp100_inw( reg ) \ - inw( ioaddr + HP100_REG_##reg ) -#define hp100_inl( reg ) \ - inl( ioaddr + HP100_REG_##reg ) -#define hp100_outb( data, reg ) \ - outb( data, ioaddr + HP100_REG_##reg ) -#define hp100_outw( data, reg ) \ - outw( data, ioaddr + HP100_REG_##reg ) -#define hp100_outl( data, reg ) \ - outl( data, ioaddr + HP100_REG_##reg ) -#define hp100_orb( data, reg ) \ - outb( inb( ioaddr + HP100_REG_##reg ) | (data), ioaddr + HP100_REG_##reg ) -#define hp100_orw( data, reg ) \ - outw( inw( ioaddr + HP100_REG_##reg ) | (data), ioaddr + HP100_REG_##reg ) -#define hp100_andb( data, reg ) \ - outb( inb( ioaddr + HP100_REG_##reg ) & (data), ioaddr + HP100_REG_##reg ) -#define hp100_andw( data, reg ) \ - outw( inw( ioaddr + HP100_REG_##reg ) & (data), ioaddr + HP100_REG_##reg ) - -#define hp100_page( page ) \ - outw( HP100_PAGE_##page, ioaddr + HP100_REG_PAGING ) -#define hp100_ints_off() \ - outw( HP100_INT_EN | HP100_RESET_LB, ioaddr + HP100_REG_OPTION_LSW ) -#define hp100_ints_on() \ - outw( HP100_INT_EN | HP100_SET_LB, ioaddr + HP100_REG_OPTION_LSW ) -#define hp100_mem_map_enable() \ - outw( HP100_MMAP_DIS | HP100_RESET_HB, ioaddr + HP100_REG_OPTION_LSW ) -#define hp100_mem_map_disable() \ - outw( HP100_MMAP_DIS | HP100_SET_HB, ioaddr + HP100_REG_OPTION_LSW ) -#define hp100_reset_card() \ - outw( HP100_HW_RST | HP100_RESET_LB, ioaddr + HP100_REG_OPTION_LSW ) -#define hp100_unreset_card() \ - outw( HP100_HW_RST | HP100_SET_LB, ioaddr + HP100_REG_OPTION_LSW ) diff --git a/i386/i386at/gpl/linux/net/i82586.h b/i386/i386at/gpl/linux/net/i82586.h deleted file mode 100644 index ff229e98..00000000 --- a/i386/i386at/gpl/linux/net/i82586.h +++ /dev/null @@ -1,408 +0,0 @@ -/* - * Intel 82586 IEEE 802.3 Ethernet LAN Coprocessor. - * - * See: - * Intel Microcommunications 1991 - * p1-1 to p1-37 - * Intel order No. 231658 - * ISBN 1-55512-119-5 - * - * Unfortunately, the above chapter mentions neither - * the System Configuration Pointer (SCP) nor the - * Intermediate System Configuration Pointer (ISCP), - * so we probably need to look elsewhere for the - * whole story -- some recommend the "Intel LAN - * Components manual" but I have neither a copy - * nor a full reference. But "elsewhere" may be - * in the same publication... - * The description of a later device, the - * "82596CA High-Performance 32-Bit Local Area Network - * Coprocessor", (ibid. p1-38 to p1-109) does mention - * the SCP and ISCP and also has an i82586 compatibility - * mode. Even more useful is "AP-235 An 82586 Data Link - * Driver" (ibid. p1-337 to p1-417). - */ - -#define I82586_MEMZ (64 * 1024) - -#define I82586_SCP_ADDR (I82586_MEMZ - sizeof(scp_t)) - -#define ADDR_LEN 6 -#define I82586NULL 0xFFFF - -#define toff(t,p,f) (unsigned short)((void *)(&((t *)((void *)0 + (p)))->f) - (void *)0) - -/* - * System Configuration Pointer (SCP). - */ -typedef struct scp_t scp_t; -struct scp_t -{ - unsigned short scp_sysbus; /* 82586 bus width: */ -#define SCP_SY_16BBUS (0x0 << 0) /* 16 bits */ -#define SCP_SY_8BBUS (0x1 << 0) /* 8 bits. */ - unsigned short scp_junk[2]; /* Unused */ - unsigned short scp_iscpl; /* lower 16 bits of ISCP_ADDR */ - unsigned short scp_iscph; /* upper 16 bits of ISCP_ADDR */ -}; - -/* - * Intermediate System Configuration Pointer (ISCP). - */ -typedef struct iscp_t iscp_t; -struct iscp_t -{ - unsigned short iscp_busy; /* set by CPU before first CA, */ - /* cleared by 82586 after read. */ - unsigned short iscp_offset; /* offset of SCB */ - unsigned short iscp_basel; /* base of SCB */ - unsigned short iscp_baseh; /* " */ -}; - -/* - * System Control Block (SCB). - * The 82586 writes its status to scb_status and then - * raises an interrupt to alert the CPU. - * The CPU writes a command to scb_command and - * then issues a Channel Attention (CA) to alert the 82586. - */ -typedef struct scb_t scb_t; -struct scb_t -{ - unsigned short scb_status; /* Status of 82586 */ -#define SCB_ST_INT (0xF << 12) /* Some of: */ -#define SCB_ST_CX (0x1 << 15) /* Cmd completed */ -#define SCB_ST_FR (0x1 << 14) /* Frame received */ -#define SCB_ST_CNA (0x1 << 13) /* Cmd unit not active */ -#define SCB_ST_RNR (0x1 << 12) /* Rcv unit not ready */ -#define SCB_ST_JUNK0 (0x1 << 11) /* 0 */ -#define SCB_ST_CUS (0x7 << 8) /* Cmd unit status */ -#define SCB_ST_CUS_IDLE (0 << 8) /* Idle */ -#define SCB_ST_CUS_SUSP (1 << 8) /* Suspended */ -#define SCB_ST_CUS_ACTV (2 << 8) /* Active */ -#define SCB_ST_JUNK1 (0x1 << 7) /* 0 */ -#define SCB_ST_RUS (0x7 << 4) /* Rcv unit status */ -#define SCB_ST_RUS_IDLE (0 << 4) /* Idle */ -#define SCB_ST_RUS_SUSP (1 << 4) /* Suspended */ -#define SCB_ST_RUS_NRES (2 << 4) /* No resources */ -#define SCB_ST_RUS_RDY (4 << 4) /* Ready */ - unsigned short scb_command; /* Next command */ -#define SCB_CMD_ACK_CX (0x1 << 15) /* Ack cmd completion */ -#define SCB_CMD_ACK_FR (0x1 << 14) /* Ack frame received */ -#define SCB_CMD_ACK_CNA (0x1 << 13) /* Ack CU not active */ -#define SCB_CMD_ACK_RNR (0x1 << 12) /* Ack RU not ready */ -#define SCB_CMD_JUNKX (0x1 << 11) /* Unused */ -#define SCB_CMD_CUC (0x7 << 8) /* Command Unit command */ -#define SCB_CMD_CUC_NOP (0 << 8) /* Nop */ -#define SCB_CMD_CUC_GO (1 << 8) /* Start cbl_offset */ -#define SCB_CMD_CUC_RES (2 << 8) /* Resume execution */ -#define SCB_CMD_CUC_SUS (3 << 8) /* Suspend " */ -#define SCB_CMD_CUC_ABT (4 << 8) /* Abort " */ -#define SCB_CMD_RESET (0x1 << 7) /* Reset chip (hardware) */ -#define SCB_CMD_RUC (0x7 << 4) /* Receive Unit command */ -#define SCB_CMD_RUC_NOP (0 << 4) /* Nop */ -#define SCB_CMD_RUC_GO (1 << 4) /* Start rfa_offset */ -#define SCB_CMD_RUC_RES (2 << 4) /* Resume reception */ -#define SCB_CMD_RUC_SUS (3 << 4) /* Suspend " */ -#define SCB_CMD_RUC_ABT (4 << 4) /* Abort " */ - unsigned short scb_cbl_offset; /* Offset of first command unit */ - /* Action Command */ - unsigned short scb_rfa_offset; /* Offset of first Receive */ - /* Frame Descriptor in the */ - /* Receive Frame Area */ - unsigned short scb_crcerrs; /* Properly aligned frames */ - /* received with a CRC error */ - unsigned short scb_alnerrs; /* Misaligned frames received */ - /* with a CRC error */ - unsigned short scb_rscerrs; /* Frames lost due to no space */ - unsigned short scb_ovrnerrs; /* Frames lost due to slow bus */ -}; - -#define scboff(p,f) toff(scb_t, p, f) - -/* - * The eight Action Commands. - */ -typedef enum acmd_e acmd_e; -enum acmd_e -{ - acmd_nop = 0, /* Do nothing */ - acmd_ia_setup = 1, /* Load an (ethernet) address into the */ - /* 82586 */ - acmd_configure = 2, /* Update the 82586 operating parameters */ - acmd_mc_setup = 3, /* Load a list of (ethernet) multicast */ - /* addresses into the 82586 */ - acmd_transmit = 4, /* Transmit a frame */ - acmd_tdr = 5, /* Perform a Time Domain Reflectometer */ - /* test on the serial link */ - acmd_dump = 6, /* Copy 82586 registers to memory */ - acmd_diagnose = 7, /* Run an internal self test */ -}; - -/* - * Generic Action Command header. - */ -typedef struct ach_t ach_t; -struct ach_t -{ - unsigned short ac_status; /* Command status: */ -#define AC_SFLD_C (0x1 << 15) /* Command completed */ -#define AC_SFLD_B (0x1 << 14) /* Busy executing */ -#define AC_SFLD_OK (0x1 << 13) /* Completed error free */ -#define AC_SFLD_A (0x1 << 12) /* Command aborted */ -#define AC_SFLD_FAIL (0x1 << 11) /* Selftest failed */ -#define AC_SFLD_S10 (0x1 << 10) /* No carrier sense */ - /* during transmission */ -#define AC_SFLD_S9 (0x1 << 9) /* Tx unsuccessful: */ - /* (stopped) lost CTS */ -#define AC_SFLD_S8 (0x1 << 8) /* Tx unsuccessful: */ - /* (stopped) slow DMA */ -#define AC_SFLD_S7 (0x1 << 7) /* Tx deferred: */ - /* other link traffic */ -#define AC_SFLD_S6 (0x1 << 6) /* Heart Beat: collision */ - /* detect after last tx */ -#define AC_SFLD_S5 (0x1 << 5) /* Tx stopped: */ - /* excessive collisions */ -#define AC_SFLD_MAXCOL (0xF << 0) /* Collision count */ - unsigned short ac_command; /* Command specifier: */ -#define AC_CFLD_EL (0x1 << 15) /* End of command list */ -#define AC_CFLD_S (0x1 << 14) /* Suspend on completion */ -#define AC_CFLD_I (0x1 << 13) /* Interrupt on completion */ -#define AC_CFLD_CMD (0x7 << 0) /* acmd_e */ - unsigned short ac_link; /* Next Action Command */ -}; - -#define acoff(p,f) toff(ach_t, p, f) - -/* - * The Nop Action Command. - */ -typedef struct ac_nop_t ac_nop_t; -struct ac_nop_t -{ - ach_t nop_h; -}; - -/* - * The IA-Setup Action Command. - */ -typedef struct ac_ias_t ac_ias_t; -struct ac_ias_t -{ - ach_t ias_h; - unsigned char ias_addr[ADDR_LEN]; /* The (ethernet) address */ -}; - -/* - * The Configure Action Command. - */ -typedef struct ac_cfg_t ac_cfg_t; -struct ac_cfg_t -{ - ach_t cfg_h; - unsigned char cfg_byte_cnt; /* Size foll data: 4-12 */ -#define AC_CFG_BYTE_CNT(v) (((v) & 0xF) << 0) - unsigned char cfg_fifolim; /* FIFO threshold */ -#define AC_CFG_FIFOLIM(v) (((v) & 0xF) << 0) - unsigned char cfg_byte8; -#define AC_CFG_SAV_BF(v) (((v) & 0x1) << 7) /* Save rxd bad frames */ -#define AC_CFG_SRDY(v) (((v) & 0x1) << 6) /* SRDY/ARDY pin means */ - /* external sync. */ - unsigned char cfg_byte9; -#define AC_CFG_ELPBCK(v) (((v) & 0x1) << 7) /* External loopback */ -#define AC_CFG_ILPBCK(v) (((v) & 0x1) << 6) /* Internal loopback */ -#define AC_CFG_PRELEN(v) (((v) & 0x3) << 4) /* Preamble length */ -#define AC_CFG_PLEN_2 0 /* 2 bytes */ -#define AC_CFG_PLEN_4 1 /* 4 bytes */ -#define AC_CFG_PLEN_8 2 /* 8 bytes */ -#define AC_CFG_PLEN_16 3 /* 16 bytes */ -#define AC_CFG_ALOC(v) (((v) & 0x1) << 3) /* Addr/len data is */ - /* explicit in buffers */ -#define AC_CFG_ADDRLEN(v) (((v) & 0x7) << 0) /* Bytes per address */ - unsigned char cfg_byte10; -#define AC_CFG_BOFMET(v) (((v) & 0x1) << 7) /* Use alternate expo. */ - /* backoff method */ -#define AC_CFG_ACR(v) (((v) & 0x7) << 4) /* Accelerated cont. res. */ -#define AC_CFG_LINPRIO(v) (((v) & 0x7) << 0) /* Linear priority */ - unsigned char cfg_ifs; /* Interframe spacing */ - unsigned char cfg_slotl; /* Slot time (low byte) */ - unsigned char cfg_byte13; -#define AC_CFG_RETRYNUM(v) (((v) & 0xF) << 4) /* Max. collision retry */ -#define AC_CFG_SLTTMHI(v) (((v) & 0x7) << 0) /* Slot time (high bits) */ - unsigned char cfg_byte14; -#define AC_CFG_FLGPAD(v) (((v) & 0x1) << 7) /* Pad with HDLC flags */ -#define AC_CFG_BTSTF(v) (((v) & 0x1) << 6) /* Do HDLC bitstuffing */ -#define AC_CFG_CRC16(v) (((v) & 0x1) << 5) /* 16 bit CCITT CRC */ -#define AC_CFG_NCRC(v) (((v) & 0x1) << 4) /* Insert no CRC */ -#define AC_CFG_TNCRS(v) (((v) & 0x1) << 3) /* Tx even if no carrier */ -#define AC_CFG_MANCH(v) (((v) & 0x1) << 2) /* Manchester coding */ -#define AC_CFG_BCDIS(v) (((v) & 0x1) << 1) /* Disable broadcast */ -#define AC_CFG_PRM(v) (((v) & 0x1) << 0) /* Promiscuous mode */ - unsigned char cfg_byte15; -#define AC_CFG_ICDS(v) (((v) & 0x1) << 7) /* Internal collision */ - /* detect source */ -#define AC_CFG_CDTF(v) (((v) & 0x7) << 4) /* Collision detect */ - /* filter in bit times */ -#define AC_CFG_ICSS(v) (((v) & 0x1) << 3) /* Internal carrier */ - /* sense source */ -#define AC_CFG_CSTF(v) (((v) & 0x7) << 0) /* Carrier sense */ - /* filter in bit times */ - unsigned short cfg_min_frm_len; -#define AC_CFG_MNFRM(v) (((v) & 0xFF) << 0) /* Min. bytes/frame (<= 255) */ -}; - -/* - * The MC-Setup Action Command. - */ -typedef struct ac_mcs_t ac_mcs_t; -struct ac_mcs_t -{ - ach_t mcs_h; - unsigned short mcs_cnt; /* No. of bytes of MC addresses */ - unsigned short mcs_data[3]; /* The first MC address .. */ -}; - -/* - * The Transmit Action Command. - */ -typedef struct ac_tx_t ac_tx_t; -struct ac_tx_t -{ - ach_t tx_h; - unsigned short tx_tbd_offset; /* Address of list of buffers. */ -#if 0 -Linux packets are passed down with the destination MAC address -and length/type field already prepended to the data, -so we do not need to insert it. Consistent with this -we must also set the AC_CFG_ALOC(..) flag during the -ac_cfg_t action command. - unsigned char tx_addr[ADDR_LEN]; /* The frame dest. address */ - unsigned short tx_length; /* The frame length */ -#endif /* 0 */ -}; - -/* - * The Time Domain Reflectometer Action Command. - */ -typedef struct ac_tdr_t ac_tdr_t; -struct ac_tdr_t -{ - ach_t tdr_h; - unsigned short tdr_result; /* Result. */ -#define AC_TDR_LNK_OK (0x1 << 15) /* No link problem */ -#define AC_TDR_XCVR_PRB (0x1 << 14) /* Txcvr cable problem */ -#define AC_TDR_ET_OPN (0x1 << 13) /* Open on the link */ -#define AC_TDR_ET_SRT (0x1 << 12) /* Short on the link */ -#define AC_TDR_TIME (0x7FF << 0) /* Distance to problem */ - /* site in transmit */ - /* clock cycles */ -}; - -/* - * The Dump Action Command. - */ -typedef struct ac_dmp_t ac_dmp_t; -struct ac_dmp_t -{ - ach_t dmp_h; - unsigned short dmp_offset; /* Result. */ -}; - -/* - * Size of the result of the dump command. - */ -#define DUMPBYTES 170 - -/* - * The Diagnose Action Command. - */ -typedef struct ac_dgn_t ac_dgn_t; -struct ac_dgn_t -{ - ach_t dgn_h; -}; - -/* - * Transmit Buffer Descriptor (TBD). - */ -typedef struct tbd_t tbd_t; -struct tbd_t -{ - unsigned short tbd_status; /* Written by the CPU */ -#define TBD_STATUS_EOF (0x1 << 15) /* This TBD is the */ - /* last for this frame */ -#define TBD_STATUS_ACNT (0x3FFF << 0) /* Actual count of data */ - /* bytes in this buffer */ - unsigned short tbd_next_bd_offset; /* Next in list */ - unsigned short tbd_bufl; /* Buffer address (low) */ - unsigned short tbd_bufh; /* " " (high) */ -}; - -/* - * Receive Buffer Descriptor (RBD). - */ -typedef struct rbd_t rbd_t; -struct rbd_t -{ - unsigned short rbd_status; /* Written by the 82586 */ -#define RBD_STATUS_EOF (0x1 << 15) /* This RBD is the */ - /* last for this frame */ -#define RBD_STATUS_F (0x1 << 14) /* ACNT field is valid */ -#define RBD_STATUS_ACNT (0x3FFF << 0) /* Actual no. of data */ - /* bytes in this buffer */ - unsigned short rbd_next_rbd_offset; /* Next rbd in list */ - unsigned short rbd_bufl; /* Data pointer (low) */ - unsigned short rbd_bufh; /* " " (high) */ - unsigned short rbd_el_size; /* EL+Data buf. size */ -#define RBD_EL (0x1 << 15) /* This BD is the */ - /* last in the list */ -#define RBD_SIZE (0x3FFF << 0) /* No. of bytes the */ - /* buffer can hold */ -}; - -#define rbdoff(p,f) toff(rbd_t, p, f) - -/* - * Frame Descriptor (FD). - */ -typedef struct fd_t fd_t; -struct fd_t -{ - unsigned short fd_status; /* Written by the 82586 */ -#define FD_STATUS_C (0x1 << 15) /* Completed storing frame */ -#define FD_STATUS_B (0x1 << 14) /* FD was consumed by RU */ -#define FD_STATUS_OK (0x1 << 13) /* Frame rxd successfully */ -#define FD_STATUS_S11 (0x1 << 11) /* CRC error */ -#define FD_STATUS_S10 (0x1 << 10) /* Alignment error */ -#define FD_STATUS_S9 (0x1 << 9) /* Ran out of resources */ -#define FD_STATUS_S8 (0x1 << 8) /* Rx DMA overrun */ -#define FD_STATUS_S7 (0x1 << 7) /* Frame too short */ -#define FD_STATUS_S6 (0x1 << 6) /* No EOF flag */ - unsigned short fd_command; /* Command */ -#define FD_COMMAND_EL (0x1 << 15) /* Last FD in list */ -#define FD_COMMAND_S (0x1 << 14) /* Suspend RU after rx */ - unsigned short fd_link_offset; /* Next FD */ - unsigned short fd_rbd_offset; /* First RBD (data) */ - /* Prepared by CPU, */ - /* updated by 82586 */ -#if 0 -I think the rest is unused since we -have set AC_CFG_ALOC(..). However, just -in case, we leave the space. -#endif /* 0 */ - unsigned char fd_dest[ADDR_LEN]; /* Destination address */ - /* Written by 82586 */ - unsigned char fd_src[ADDR_LEN]; /* Source address */ - /* Written by 82586 */ - unsigned short fd_length; /* Frame length or type */ - /* Written by 82586 */ -}; - -#define fdoff(p,f) toff(fd_t, p, f) - -/* - * This software may only be used and distributed - * according to the terms of the GNU Public License. - * - * For more details, see wavelan.c. - */ diff --git a/i386/i386at/gpl/linux/net/iow.h b/i386/i386at/gpl/linux/net/iow.h deleted file mode 100644 index 6e15688f..00000000 --- a/i386/i386at/gpl/linux/net/iow.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _ASM_IOW_H -#define _ASM_IOW_H - -/* no longer used */ - -#endif diff --git a/i386/i386at/gpl/linux/net/lance.c b/i386/i386at/gpl/linux/net/lance.c deleted file mode 100644 index 4a388f77..00000000 --- a/i386/i386at/gpl/linux/net/lance.c +++ /dev/null @@ -1,1129 +0,0 @@ -/* lance.c: An AMD LANCE ethernet driver for linux. */ -/* - Written 1993,1994,1995 by Donald Becker. - - Copyright 1993 United States Government as represented by the - Director, National Security Agency. - This software may be used and distributed according to the terms - of the GNU Public License, incorporated herein by reference. - - This driver is for the Allied Telesis AT1500 and HP J2405A, and should work - with most other LANCE-based bus-master (NE2100 clone) ethercards. - - The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O - Center of Excellence in Space Data and Information Sciences - Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771 -*/ - -static const char *version = "lance.c:v1.08 4/10/95 dplatt@3do.com\n"; - -#include <linux/config.h> -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/string.h> -#include <linux/ptrace.h> -#include <linux/errno.h> -#include <linux/ioport.h> -#include <linux/malloc.h> -#include <linux/interrupt.h> -#include <linux/pci.h> -#include <linux/bios32.h> -#include <asm/bitops.h> -#include <asm/io.h> -#include <asm/dma.h> - -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> - -static unsigned int lance_portlist[] = {0x300, 0x320, 0x340, 0x360, 0}; -void lance_probe1(int ioaddr); - -#ifdef HAVE_DEVLIST -struct netdev_entry lance_drv = -{"lance", lance_probe1, LANCE_TOTAL_SIZE, lance_portlist}; -#endif - -#ifdef LANCE_DEBUG -int lance_debug = LANCE_DEBUG; -#else -int lance_debug = 1; -#endif - -/* - Theory of Operation - -I. Board Compatibility - -This device driver is designed for the AMD 79C960, the "PCnet-ISA -single-chip ethernet controller for ISA". This chip is used in a wide -variety of boards from vendors such as Allied Telesis, HP, Kingston, -and Boca. This driver is also intended to work with older AMD 7990 -designs, such as the NE1500 and NE2100, and newer 79C961. For convenience, -I use the name LANCE to refer to all of the AMD chips, even though it properly -refers only to the original 7990. - -II. Board-specific settings - -The driver is designed to work the boards that use the faster -bus-master mode, rather than in shared memory mode. (Only older designs -have on-board buffer memory needed to support the slower shared memory mode.) - -Most ISA boards have jumpered settings for the I/O base, IRQ line, and DMA -channel. This driver probes the likely base addresses: -{0x300, 0x320, 0x340, 0x360}. -After the board is found it generates a DMA-timeout interrupt and uses -autoIRQ to find the IRQ line. The DMA channel can be set with the low bits -of the otherwise-unused dev->mem_start value (aka PARAM1). If unset it is -probed for by enabling each free DMA channel in turn and checking if -initialization succeeds. - -The HP-J2405A board is an exception: with this board it's easy to read the -EEPROM-set values for the base, IRQ, and DMA. (Of course you must already -_know_ the base address -- that field is for writing the EEPROM.) - -III. Driver operation - -IIIa. Ring buffers -The LANCE uses ring buffers of Tx and Rx descriptors. Each entry describes -the base and length of the data buffer, along with status bits. The length -of these buffers is set by LANCE_LOG_{RX,TX}_BUFFERS, which is log_2() of -the buffer length (rather than being directly the buffer length) for -implementation ease. The current values are 2 (Tx) and 4 (Rx), which leads to -ring sizes of 4 (Tx) and 16 (Rx). Increasing the number of ring entries -needlessly uses extra space and reduces the chance that an upper layer will -be able to reorder queued Tx packets based on priority. Decreasing the number -of entries makes it more difficult to achieve back-to-back packet transmission -and increases the chance that Rx ring will overflow. (Consider the worst case -of receiving back-to-back minimum-sized packets.) - -The LANCE has the capability to "chain" both Rx and Tx buffers, but this driver -statically allocates full-sized (slightly oversized -- PKT_BUF_SZ) buffers to -avoid the administrative overhead. For the Rx side this avoids dynamically -allocating full-sized buffers "just in case", at the expense of a -memory-to-memory data copy for each packet received. For most systems this -is a good tradeoff: the Rx buffer will always be in low memory, the copy -is inexpensive, and it primes the cache for later packet processing. For Tx -the buffers are only used when needed as low-memory bounce buffers. - -IIIB. 16M memory limitations. -For the ISA bus master mode all structures used directly by the LANCE, -the initialization block, Rx and Tx rings, and data buffers, must be -accessible from the ISA bus, i.e. in the lower 16M of real memory. -This is a problem for current Linux kernels on >16M machines. The network -devices are initialized after memory initialization, and the kernel doles out -memory from the top of memory downward. The current solution is to have a -special network initialization routine that's called before memory -initialization; this will eventually be generalized for all network devices. -As mentioned before, low-memory "bounce-buffers" are used when needed. - -IIIC. Synchronization -The driver runs as two independent, single-threaded flows of control. One -is the send-packet routine, which enforces single-threaded use by the -dev->tbusy flag. The other thread is the interrupt handler, which is single -threaded by the hardware and other software. - -The send packet thread has partial control over the Tx ring and 'dev->tbusy' -flag. It sets the tbusy flag whenever it's queuing a Tx packet. If the next -queue slot is empty, it clears the tbusy flag when finished otherwise it sets -the 'lp->tx_full' flag. - -The interrupt handler has exclusive control over the Rx ring and records stats -from the Tx ring. (The Tx-done interrupt can't be selectively turned off, so -we can't avoid the interrupt overhead by having the Tx routine reap the Tx -stats.) After reaping the stats, it marks the queue entry as empty by setting -the 'base' to zero. Iff the 'lp->tx_full' flag is set, it clears both the -tx_full and tbusy flags. - -*/ - -/* Set the number of Tx and Rx buffers, using Log_2(# buffers). - Reasonable default values are 4 Tx buffers, and 16 Rx buffers. - That translates to 2 (4 == 2^^2) and 4 (16 == 2^^4). */ -#ifndef LANCE_LOG_TX_BUFFERS -#define LANCE_LOG_TX_BUFFERS 4 -#define LANCE_LOG_RX_BUFFERS 4 -#endif - -#define TX_RING_SIZE (1 << (LANCE_LOG_TX_BUFFERS)) -#define TX_RING_MOD_MASK (TX_RING_SIZE - 1) -#define TX_RING_LEN_BITS ((LANCE_LOG_TX_BUFFERS) << 29) - -#define RX_RING_SIZE (1 << (LANCE_LOG_RX_BUFFERS)) -#define RX_RING_MOD_MASK (RX_RING_SIZE - 1) -#define RX_RING_LEN_BITS ((LANCE_LOG_RX_BUFFERS) << 29) - -#define PKT_BUF_SZ 1544 - -/* Offsets from base I/O address. */ -#define LANCE_DATA 0x10 -#define LANCE_ADDR 0x12 -#define LANCE_RESET 0x14 -#define LANCE_BUS_IF 0x16 -#define LANCE_TOTAL_SIZE 0x18 - -/* The LANCE Rx and Tx ring descriptors. */ -struct lance_rx_head { - int base; - short buf_length; /* This length is 2s complement (negative)! */ - short msg_length; /* This length is "normal". */ -}; - -struct lance_tx_head { - int base; - short length; /* Length is 2s complement (negative)! */ - short misc; -}; - -/* The LANCE initialization block, described in databook. */ -struct lance_init_block { - unsigned short mode; /* Pre-set mode (reg. 15) */ - unsigned char phys_addr[6]; /* Physical ethernet address */ - unsigned filter[2]; /* Multicast filter (unused). */ - /* Receive and transmit ring base, along with extra bits. */ - unsigned rx_ring; /* Tx and Rx ring base pointers */ - unsigned tx_ring; -}; - -struct lance_private { - /* The Tx and Rx ring entries must be aligned on 8-byte boundaries. - This is always true for kmalloc'ed memory */ - struct lance_rx_head rx_ring[RX_RING_SIZE]; - struct lance_tx_head tx_ring[TX_RING_SIZE]; - struct lance_init_block init_block; - const char *name; - /* The saved address of a sent-in-place packet/buffer, for skfree(). */ - struct sk_buff* tx_skbuff[TX_RING_SIZE]; - long rx_buffs; /* Address of Rx and Tx buffers. */ - /* Tx low-memory "bounce buffer" address. */ - char (*tx_bounce_buffs)[PKT_BUF_SZ]; - int cur_rx, cur_tx; /* The next free ring entry */ - int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */ - int dma; - struct enet_statistics stats; - unsigned char chip_version; /* See lance_chip_type. */ - char tx_full; - char lock; -}; - -#define LANCE_MUST_PAD 0x00000001 -#define LANCE_ENABLE_AUTOSELECT 0x00000002 -#define LANCE_MUST_REINIT_RING 0x00000004 -#define LANCE_MUST_UNRESET 0x00000008 -#define LANCE_HAS_MISSED_FRAME 0x00000010 - -/* A mapping from the chip ID number to the part number and features. - These are from the datasheets -- in real life the '970 version - reportedly has the same ID as the '965. */ -static struct lance_chip_type { - int id_number; - const char *name; - int flags; -} chip_table[] = { - {0x0000, "LANCE 7990", /* Ancient lance chip. */ - LANCE_MUST_PAD + LANCE_MUST_UNRESET}, - {0x0003, "PCnet/ISA 79C960", /* 79C960 PCnet/ISA. */ - LANCE_ENABLE_AUTOSELECT + LANCE_MUST_REINIT_RING + - LANCE_HAS_MISSED_FRAME}, - {0x2260, "PCnet/ISA+ 79C961", /* 79C961 PCnet/ISA+, Plug-n-Play. */ - LANCE_ENABLE_AUTOSELECT + LANCE_MUST_REINIT_RING + - LANCE_HAS_MISSED_FRAME}, - {0x2420, "PCnet/PCI 79C970", /* 79C970 or 79C974 PCnet-SCSI, PCI. */ - LANCE_ENABLE_AUTOSELECT + LANCE_MUST_REINIT_RING + - LANCE_HAS_MISSED_FRAME}, - /* Bug: the PCnet/PCI actually uses the PCnet/VLB ID number, so just call - it the PCnet32. */ - {0x2430, "PCnet32", /* 79C965 PCnet for VL bus. */ - LANCE_ENABLE_AUTOSELECT + LANCE_MUST_REINIT_RING + - LANCE_HAS_MISSED_FRAME}, - {0x0, "PCnet (unknown)", - LANCE_ENABLE_AUTOSELECT + LANCE_MUST_REINIT_RING + - LANCE_HAS_MISSED_FRAME}, -}; - -enum {OLD_LANCE = 0, PCNET_ISA=1, PCNET_ISAP=2, PCNET_PCI=3, PCNET_VLB=4, LANCE_UNKNOWN=5}; - -/* Non-zero only if the current card is a PCI with BIOS-set IRQ. */ -static unsigned char pci_irq_line = 0; - -/* Non-zero if lance_probe1() needs to allocate low-memory bounce buffers. - Assume yes until we know the memory size. */ -static unsigned char lance_need_isa_bounce_buffers = 1; - -static int lance_open(struct device *dev); -static void lance_init_ring(struct device *dev); -static int lance_start_xmit(struct sk_buff *skb, struct device *dev); -static int lance_rx(struct device *dev); -static void lance_interrupt(int irq, struct pt_regs *regs); -static int lance_close(struct device *dev); -static struct enet_statistics *lance_get_stats(struct device *dev); -static void set_multicast_list(struct device *dev); - - - -/* This lance probe is unlike the other board probes in 1.0.*. The LANCE may - have to allocate a contiguous low-memory region for bounce buffers. - This requirement is satisfied by having the lance initialization occur - before the memory management system is started, and thus well before the - other probes. */ - -int lance_init(void) -{ - int *port; - - if (high_memory <= 16*1024*1024) - lance_need_isa_bounce_buffers = 0; - -#if defined(CONFIG_PCI) - if (pcibios_present()) { - int pci_index; - printk("lance.c: PCI bios is present, checking for devices...\n"); - for (pci_index = 0; pci_index < 8; pci_index++) { - unsigned char pci_bus, pci_device_fn; - unsigned int pci_ioaddr; - unsigned short pci_command; - - if (pcibios_find_device (PCI_VENDOR_ID_AMD, - PCI_DEVICE_ID_AMD_LANCE, pci_index, - &pci_bus, &pci_device_fn) != 0) - break; - pcibios_read_config_byte(pci_bus, pci_device_fn, - PCI_INTERRUPT_LINE, &pci_irq_line); - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_0, &pci_ioaddr); - /* Remove I/O space marker in bit 0. */ - pci_ioaddr &= ~3; - /* PCI Spec 2.1 states that it is either the driver or PCI card's - * responsibility to set the PCI Master Enable Bit if needed. - * (From Mark Stockton <marks@schooner.sys.hou.compaq.com>) - */ - pcibios_read_config_word(pci_bus, pci_device_fn, - PCI_COMMAND, &pci_command); - if ( ! (pci_command & PCI_COMMAND_MASTER)) { - printk("PCI Master Bit has not been set. Setting...\n"); - pci_command |= PCI_COMMAND_MASTER; - pcibios_write_config_word(pci_bus, pci_device_fn, - PCI_COMMAND, pci_command); - } - printk("Found PCnet/PCI at %#x, irq %d.\n", - pci_ioaddr, pci_irq_line); - lance_probe1(pci_ioaddr); - pci_irq_line = 0; - } - } -#endif /* defined(CONFIG_PCI) */ - - for (port = lance_portlist; *port; port++) { - int ioaddr = *port; - - if ( check_region(ioaddr, LANCE_TOTAL_SIZE) == 0) { - /* Detect "normal" 0x57 0x57 and the NI6510EB 0x52 0x44 - signatures w/ minimal I/O reads */ - char offset15, offset14 = inb(ioaddr + 14); - - if ((offset14 == 0x52 || offset14 == 0x57) && - ((offset15 = inb(ioaddr + 15)) == 0x57 || offset15 == 0x44)) - lance_probe1(ioaddr); - } - } - - return 0; -} - -void lance_probe1(int ioaddr) -{ - struct device *dev; - struct lance_private *lp; - short dma_channels; /* Mark spuriously-busy DMA channels */ - int i, reset_val, lance_version; - const char *chipname; - /* Flags for specific chips or boards. */ - unsigned char hpJ2405A = 0; /* HP ISA adaptor */ - int hp_builtin = 0; /* HP on-board ethernet. */ - static int did_version = 0; /* Already printed version info. */ - - /* First we look for special cases. - Check for HP's on-board ethernet by looking for 'HP' in the BIOS. - There are two HP versions, check the BIOS for the configuration port. - This method provided by L. Julliard, Laurent_Julliard@grenoble.hp.com. - */ - if ( *((unsigned short *) 0x000f0102) == 0x5048) { - static const short ioaddr_table[] = { 0x300, 0x320, 0x340, 0x360}; - int hp_port = ( *((unsigned char *) 0x000f00f1) & 1) ? 0x499 : 0x99; - /* We can have boards other than the built-in! Verify this is on-board. */ - if ((inb(hp_port) & 0xc0) == 0x80 - && ioaddr_table[inb(hp_port) & 3] == ioaddr) - hp_builtin = hp_port; - } - /* We also recognize the HP Vectra on-board here, but check below. */ - hpJ2405A = (inb(ioaddr) == 0x08 && inb(ioaddr+1) == 0x00 - && inb(ioaddr+2) == 0x09); - - /* Reset the LANCE. */ - reset_val = inw(ioaddr+LANCE_RESET); /* Reset the LANCE */ - - /* The Un-Reset needed is only needed for the real NE2100, and will - confuse the HP board. */ - if (!hpJ2405A) - outw(reset_val, ioaddr+LANCE_RESET); - - outw(0x0000, ioaddr+LANCE_ADDR); /* Switch to window 0 */ - if (inw(ioaddr+LANCE_DATA) != 0x0004) - return; - - /* Get the version of the chip. */ - outw(88, ioaddr+LANCE_ADDR); - if (inw(ioaddr+LANCE_ADDR) != 88) { - lance_version = 0; - } else { /* Good, it's a newer chip. */ - int chip_version = inw(ioaddr+LANCE_DATA); - outw(89, ioaddr+LANCE_ADDR); - chip_version |= inw(ioaddr+LANCE_DATA) << 16; - if (lance_debug > 2) - printk(" LANCE chip version is %#x.\n", chip_version); - if ((chip_version & 0xfff) != 0x003) - return; - chip_version = (chip_version >> 12) & 0xffff; - for (lance_version = 1; chip_table[lance_version].id_number; lance_version++) { - if (chip_table[lance_version].id_number == chip_version) - break; - } - } - - dev = init_etherdev(0, 0); - chipname = chip_table[lance_version].name; - printk("%s: %s at %#3x,", dev->name, chipname, ioaddr); - - /* There is a 16 byte station address PROM at the base address. - The first six bytes are the station address. */ - for (i = 0; i < 6; i++) - printk(" %2.2x", dev->dev_addr[i] = inb(ioaddr + i)); - - dev->base_addr = ioaddr; - request_region(ioaddr, LANCE_TOTAL_SIZE, chip_table[lance_version].name); - - /* Make certain the data structures used by the LANCE are aligned and DMAble. */ - lp = (struct lance_private *) kmalloc(sizeof(*lp), GFP_DMA | GFP_KERNEL); - memset(lp, 0, sizeof(*lp)); - dev->priv = lp; - lp->name = chipname; - lp->rx_buffs = (unsigned long) kmalloc(PKT_BUF_SZ*RX_RING_SIZE, GFP_DMA | GFP_KERNEL); - lp->tx_bounce_buffs = NULL; - if (lance_need_isa_bounce_buffers) - lp->tx_bounce_buffs = kmalloc(PKT_BUF_SZ*TX_RING_SIZE, GFP_DMA | GFP_KERNEL); - - lp->chip_version = lance_version; - - lp->init_block.mode = 0x0003; /* Disable Rx and Tx. */ - for (i = 0; i < 6; i++) - lp->init_block.phys_addr[i] = dev->dev_addr[i]; - lp->init_block.filter[0] = 0x00000000; - lp->init_block.filter[1] = 0x00000000; - lp->init_block.rx_ring = (int)lp->rx_ring | RX_RING_LEN_BITS; - lp->init_block.tx_ring = (int)lp->tx_ring | TX_RING_LEN_BITS; - - outw(0x0001, ioaddr+LANCE_ADDR); - inw(ioaddr+LANCE_ADDR); - outw((short) (int) &lp->init_block, ioaddr+LANCE_DATA); - outw(0x0002, ioaddr+LANCE_ADDR); - inw(ioaddr+LANCE_ADDR); - outw(((int)&lp->init_block) >> 16, ioaddr+LANCE_DATA); - outw(0x0000, ioaddr+LANCE_ADDR); - inw(ioaddr+LANCE_ADDR); - - if (pci_irq_line) { - dev->dma = 4; /* Native bus-master, no DMA channel needed. */ - dev->irq = pci_irq_line; - } else if (hp_builtin) { - static const char dma_tbl[4] = {3, 5, 6, 0}; - static const char irq_tbl[4] = {3, 4, 5, 9}; - unsigned char port_val = inb(hp_builtin); - dev->dma = dma_tbl[(port_val >> 4) & 3]; - dev->irq = irq_tbl[(port_val >> 2) & 3]; - printk(" HP Vectra IRQ %d DMA %d.\n", dev->irq, dev->dma); - } else if (hpJ2405A) { - static const char dma_tbl[4] = {3, 5, 6, 7}; - static const char irq_tbl[8] = {3, 4, 5, 9, 10, 11, 12, 15}; - short reset_val = inw(ioaddr+LANCE_RESET); - dev->dma = dma_tbl[(reset_val >> 2) & 3]; - dev->irq = irq_tbl[(reset_val >> 4) & 7]; - printk(" HP J2405A IRQ %d DMA %d.\n", dev->irq, dev->dma); - } else if (lance_version == PCNET_ISAP) { /* The plug-n-play version. */ - short bus_info; - outw(8, ioaddr+LANCE_ADDR); - bus_info = inw(ioaddr+LANCE_BUS_IF); - dev->dma = bus_info & 0x07; - dev->irq = (bus_info >> 4) & 0x0F; - } else { - /* The DMA channel may be passed in PARAM1. */ - if (dev->mem_start & 0x07) - dev->dma = dev->mem_start & 0x07; - } - - if (dev->dma == 0) { - /* Read the DMA channel status register, so that we can avoid - stuck DMA channels in the DMA detection below. */ - dma_channels = ((inb(DMA1_STAT_REG) >> 4) & 0x0f) | - (inb(DMA2_STAT_REG) & 0xf0); - } - if (dev->irq >= 2) - printk(" assigned IRQ %d", dev->irq); - else { - /* To auto-IRQ we enable the initialization-done and DMA error - interrupts. For ISA boards we get a DMA error, but VLB and PCI - boards will work. */ - autoirq_setup(0); - - /* Trigger an initialization just for the interrupt. */ - outw(0x0041, ioaddr+LANCE_DATA); - - dev->irq = autoirq_report(1); - if (dev->irq) - printk(", probed IRQ %d", dev->irq); - else { - printk(", failed to detect IRQ line.\n"); - return; - } - - /* Check for the initialization done bit, 0x0100, which means - that we don't need a DMA channel. */ - if (inw(ioaddr+LANCE_DATA) & 0x0100) - dev->dma = 4; - } - - if (dev->dma == 4) { - printk(", no DMA needed.\n"); - } else if (dev->dma) { - if (request_dma(dev->dma, chipname)) { - printk("DMA %d allocation failed.\n", dev->dma); - return; - } else - printk(", assigned DMA %d.\n", dev->dma); - } else { /* OK, we have to auto-DMA. */ - for (i = 0; i < 4; i++) { - static const char dmas[] = { 5, 6, 7, 3 }; - int dma = dmas[i]; - int boguscnt; - - /* Don't enable a permanently busy DMA channel, or the machine - will hang. */ - if (test_bit(dma, &dma_channels)) - continue; - outw(0x7f04, ioaddr+LANCE_DATA); /* Clear the memory error bits. */ - if (request_dma(dma, chipname)) - continue; - set_dma_mode(dma, DMA_MODE_CASCADE); - enable_dma(dma); - - /* Trigger an initialization. */ - outw(0x0001, ioaddr+LANCE_DATA); - for (boguscnt = 100; boguscnt > 0; --boguscnt) - if (inw(ioaddr+LANCE_DATA) & 0x0900) - break; - if (inw(ioaddr+LANCE_DATA) & 0x0100) { - dev->dma = dma; - printk(", DMA %d.\n", dev->dma); - break; - } else { - disable_dma(dma); - free_dma(dma); - } - } - if (i == 4) { /* Failure: bail. */ - printk("DMA detection failed.\n"); - return; - } - } - - if (chip_table[lp->chip_version].flags & LANCE_ENABLE_AUTOSELECT) { - /* Turn on auto-select of media (10baseT or BNC) so that the user - can watch the LEDs even if the board isn't opened. */ - outw(0x0002, ioaddr+LANCE_ADDR); - outw(0x0002, ioaddr+LANCE_BUS_IF); - } - - if (lance_debug > 0 && did_version++ == 0) - printk(version); - - /* The LANCE-specific entries in the device structure. */ - dev->open = &lance_open; - dev->hard_start_xmit = &lance_start_xmit; - dev->stop = &lance_close; - dev->get_stats = &lance_get_stats; - dev->set_multicast_list = &set_multicast_list; - - return; -} - - -static int -lance_open(struct device *dev) -{ - struct lance_private *lp = (struct lance_private *)dev->priv; - int ioaddr = dev->base_addr; - int i; - - if (dev->irq == 0 || - request_irq(dev->irq, &lance_interrupt, 0, lp->name)) { - return -EAGAIN; - } - - /* We used to allocate DMA here, but that was silly. - DMA lines can't be shared! We now permanently allocate them. */ - - irq2dev_map[dev->irq] = dev; - - /* Reset the LANCE */ - inw(ioaddr+LANCE_RESET); - - /* The DMA controller is used as a no-operation slave, "cascade mode". */ - if (dev->dma != 4) { - enable_dma(dev->dma); - set_dma_mode(dev->dma, DMA_MODE_CASCADE); - } - - /* Un-Reset the LANCE, needed only for the NE2100. */ - if (chip_table[lp->chip_version].flags & LANCE_MUST_UNRESET) - outw(0, ioaddr+LANCE_RESET); - - if (chip_table[lp->chip_version].flags & LANCE_ENABLE_AUTOSELECT) { - /* This is 79C960-specific: Turn on auto-select of media (AUI, BNC). */ - outw(0x0002, ioaddr+LANCE_ADDR); - outw(0x0002, ioaddr+LANCE_BUS_IF); - } - - if (lance_debug > 1) - printk("%s: lance_open() irq %d dma %d tx/rx rings %#x/%#x init %#x.\n", - dev->name, dev->irq, dev->dma, (int) lp->tx_ring, (int) lp->rx_ring, - (int) &lp->init_block); - - lance_init_ring(dev); - /* Re-initialize the LANCE, and start it when done. */ - outw(0x0001, ioaddr+LANCE_ADDR); - outw((short) (int) &lp->init_block, ioaddr+LANCE_DATA); - outw(0x0002, ioaddr+LANCE_ADDR); - outw(((int)&lp->init_block) >> 16, ioaddr+LANCE_DATA); - - outw(0x0004, ioaddr+LANCE_ADDR); - outw(0x0915, ioaddr+LANCE_DATA); - - outw(0x0000, ioaddr+LANCE_ADDR); - outw(0x0001, ioaddr+LANCE_DATA); - - dev->tbusy = 0; - dev->interrupt = 0; - dev->start = 1; - i = 0; - while (i++ < 100) - if (inw(ioaddr+LANCE_DATA) & 0x0100) - break; - /* - * We used to clear the InitDone bit, 0x0100, here but Mark Stockton - * reports that doing so triggers a bug in the '974. - */ - outw(0x0042, ioaddr+LANCE_DATA); - - if (lance_debug > 2) - printk("%s: LANCE open after %d ticks, init block %#x csr0 %4.4x.\n", - dev->name, i, (int) &lp->init_block, inw(ioaddr+LANCE_DATA)); - - return 0; /* Always succeed */ -} - -/* The LANCE has been halted for one reason or another (busmaster memory - arbitration error, Tx FIFO underflow, driver stopped it to reconfigure, - etc.). Modern LANCE variants always reload their ring-buffer - configuration when restarted, so we must reinitialize our ring - context before restarting. As part of this reinitialization, - find all packets still on the Tx ring and pretend that they had been - sent (in effect, drop the packets on the floor) - the higher-level - protocols will time out and retransmit. It'd be better to shuffle - these skbs to a temp list and then actually re-Tx them after - restarting the chip, but I'm too lazy to do so right now. dplatt@3do.com -*/ - -static void -lance_purge_tx_ring(struct device *dev) -{ - struct lance_private *lp = (struct lance_private *)dev->priv; - int i; - - for (i = 0; i < TX_RING_SIZE; i++) { - if (lp->tx_skbuff[i]) { - dev_kfree_skb(lp->tx_skbuff[i],FREE_WRITE); - lp->tx_skbuff[i] = NULL; - } - } -} - - -/* Initialize the LANCE Rx and Tx rings. */ -static void -lance_init_ring(struct device *dev) -{ - struct lance_private *lp = (struct lance_private *)dev->priv; - int i; - - lp->lock = 0, lp->tx_full = 0; - lp->cur_rx = lp->cur_tx = 0; - lp->dirty_rx = lp->dirty_tx = 0; - - for (i = 0; i < RX_RING_SIZE; i++) { - lp->rx_ring[i].base = (lp->rx_buffs + i*PKT_BUF_SZ) | 0x80000000; - lp->rx_ring[i].buf_length = -PKT_BUF_SZ; - } - /* The Tx buffer address is filled in as needed, but we do need to clear - the upper ownership bit. */ - for (i = 0; i < TX_RING_SIZE; i++) { - lp->tx_ring[i].base = 0; - } - - lp->init_block.mode = 0x0000; - for (i = 0; i < 6; i++) - lp->init_block.phys_addr[i] = dev->dev_addr[i]; - lp->init_block.filter[0] = 0x00000000; - lp->init_block.filter[1] = 0x00000000; - lp->init_block.rx_ring = (int)lp->rx_ring | RX_RING_LEN_BITS; - lp->init_block.tx_ring = (int)lp->tx_ring | TX_RING_LEN_BITS; -} - -static void -lance_restart(struct device *dev, unsigned int csr0_bits, int must_reinit) -{ - struct lance_private *lp = (struct lance_private *)dev->priv; - - if (must_reinit || - (chip_table[lp->chip_version].flags & LANCE_MUST_REINIT_RING)) { - lance_purge_tx_ring(dev); - lance_init_ring(dev); - } - outw(0x0000, dev->base_addr + LANCE_ADDR); - outw(csr0_bits, dev->base_addr + LANCE_DATA); -} - -static int -lance_start_xmit(struct sk_buff *skb, struct device *dev) -{ - struct lance_private *lp = (struct lance_private *)dev->priv; - int ioaddr = dev->base_addr; - int entry; - unsigned long flags; - - /* Transmitter timeout, serious problems. */ - if (dev->tbusy) { - int tickssofar = jiffies - dev->trans_start; - if (tickssofar < 20) - return 1; - outw(0, ioaddr+LANCE_ADDR); - printk("%s: transmit timed out, status %4.4x, resetting.\n", - dev->name, inw(ioaddr+LANCE_DATA)); - outw(0x0004, ioaddr+LANCE_DATA); - lp->stats.tx_errors++; -#ifndef final_version - { - int i; - printk(" Ring data dump: dirty_tx %d cur_tx %d%s cur_rx %d.", - lp->dirty_tx, lp->cur_tx, lp->tx_full ? " (full)" : "", - lp->cur_rx); - for (i = 0 ; i < RX_RING_SIZE; i++) - printk("%s %08x %04x %04x", i & 0x3 ? "" : "\n ", - lp->rx_ring[i].base, -lp->rx_ring[i].buf_length, - lp->rx_ring[i].msg_length); - for (i = 0 ; i < TX_RING_SIZE; i++) - printk("%s %08x %04x %04x", i & 0x3 ? "" : "\n ", - lp->tx_ring[i].base, -lp->tx_ring[i].length, - lp->tx_ring[i].misc); - printk("\n"); - } -#endif - lance_restart(dev, 0x0043, 1); - - dev->tbusy=0; - dev->trans_start = jiffies; - - return 0; - } - - if (skb == NULL) { - dev_tint(dev); - return 0; - } - - if (skb->len <= 0) - return 0; - - if (lance_debug > 3) { - outw(0x0000, ioaddr+LANCE_ADDR); - printk("%s: lance_start_xmit() called, csr0 %4.4x.\n", dev->name, - inw(ioaddr+LANCE_DATA)); - outw(0x0000, ioaddr+LANCE_DATA); - } - - /* Block a timer-based transmit from overlapping. This could better be - done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ - if (set_bit(0, (void*)&dev->tbusy) != 0) { - printk("%s: Transmitter access conflict.\n", dev->name); - return 1; - } - - if (set_bit(0, (void*)&lp->lock) != 0) { - if (lance_debug > 0) - printk("%s: tx queue lock!.\n", dev->name); - /* don't clear dev->tbusy flag. */ - return 1; - } - - /* Fill in a Tx ring entry */ - - /* Mask to ring buffer boundary. */ - entry = lp->cur_tx & TX_RING_MOD_MASK; - - /* Caution: the write order is important here, set the base address - with the "ownership" bits last. */ - - /* The old LANCE chips doesn't automatically pad buffers to min. size. */ - if (chip_table[lp->chip_version].flags & LANCE_MUST_PAD) { - lp->tx_ring[entry].length = - -(ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN); - } else - lp->tx_ring[entry].length = -skb->len; - - lp->tx_ring[entry].misc = 0x0000; - - /* If any part of this buffer is >16M we must copy it to a low-memory - buffer. */ - if ((int)(skb->data) + skb->len > 0x01000000) { - if (lance_debug > 5) - printk("%s: bouncing a high-memory packet (%#x).\n", - dev->name, (int)(skb->data)); - memcpy(&lp->tx_bounce_buffs[entry], skb->data, skb->len); - lp->tx_ring[entry].base = - (int)(lp->tx_bounce_buffs + entry) | 0x83000000; - dev_kfree_skb (skb, FREE_WRITE); - } else { - lp->tx_skbuff[entry] = skb; - lp->tx_ring[entry].base = (int)(skb->data) | 0x83000000; - } - lp->cur_tx++; - - /* Trigger an immediate send poll. */ - outw(0x0000, ioaddr+LANCE_ADDR); - outw(0x0048, ioaddr+LANCE_DATA); - - dev->trans_start = jiffies; - - save_flags(flags); - cli(); - lp->lock = 0; - if (lp->tx_ring[(entry+1) & TX_RING_MOD_MASK].base == 0) - dev->tbusy=0; - else - lp->tx_full = 1; - restore_flags(flags); - - return 0; -} - -/* The LANCE interrupt handler. */ -static void -lance_interrupt(int irq, struct pt_regs * regs) -{ - struct device *dev = (struct device *)(irq2dev_map[irq]); - struct lance_private *lp; - int csr0, ioaddr, boguscnt=10; - int must_restart; - - if (dev == NULL) { - printk ("lance_interrupt(): irq %d for unknown device.\n", irq); - return; - } - - ioaddr = dev->base_addr; - lp = (struct lance_private *)dev->priv; - if (dev->interrupt) - printk("%s: Re-entering the interrupt handler.\n", dev->name); - - dev->interrupt = 1; - - outw(0x00, dev->base_addr + LANCE_ADDR); - while ((csr0 = inw(dev->base_addr + LANCE_DATA)) & 0x8600 - && --boguscnt >= 0) { - /* Acknowledge all of the current interrupt sources ASAP. */ - outw(csr0 & ~0x004f, dev->base_addr + LANCE_DATA); - - must_restart = 0; - - if (lance_debug > 5) - printk("%s: interrupt csr0=%#2.2x new csr=%#2.2x.\n", - dev->name, csr0, inw(dev->base_addr + LANCE_DATA)); - - if (csr0 & 0x0400) /* Rx interrupt */ - lance_rx(dev); - - if (csr0 & 0x0200) { /* Tx-done interrupt */ - int dirty_tx = lp->dirty_tx; - - while (dirty_tx < lp->cur_tx) { - int entry = dirty_tx & TX_RING_MOD_MASK; - int status = lp->tx_ring[entry].base; - - if (status < 0) - break; /* It still hasn't been Txed */ - - lp->tx_ring[entry].base = 0; - - if (status & 0x40000000) { - /* There was an major error, log it. */ - int err_status = lp->tx_ring[entry].misc; - lp->stats.tx_errors++; - if (err_status & 0x0400) lp->stats.tx_aborted_errors++; - if (err_status & 0x0800) lp->stats.tx_carrier_errors++; - if (err_status & 0x1000) lp->stats.tx_window_errors++; - if (err_status & 0x4000) { - /* Ackk! On FIFO errors the Tx unit is turned off! */ - lp->stats.tx_fifo_errors++; - /* Remove this verbosity later! */ - printk("%s: Tx FIFO error! Status %4.4x.\n", - dev->name, csr0); - /* Restart the chip. */ - must_restart = 1; - } - } else { - if (status & 0x18000000) - lp->stats.collisions++; - lp->stats.tx_packets++; - } - - /* We must free the original skb if it's not a data-only copy - in the bounce buffer. */ - if (lp->tx_skbuff[entry]) { - dev_kfree_skb(lp->tx_skbuff[entry],FREE_WRITE); - lp->tx_skbuff[entry] = 0; - } - dirty_tx++; - } - -#ifndef final_version - if (lp->cur_tx - dirty_tx >= TX_RING_SIZE) { - printk("out-of-sync dirty pointer, %d vs. %d, full=%d.\n", - dirty_tx, lp->cur_tx, lp->tx_full); - dirty_tx += TX_RING_SIZE; - } -#endif - - if (lp->tx_full && dev->tbusy - && dirty_tx > lp->cur_tx - TX_RING_SIZE + 2) { - /* The ring is no longer full, clear tbusy. */ - lp->tx_full = 0; - dev->tbusy = 0; - mark_bh(NET_BH); - } - - lp->dirty_tx = dirty_tx; - } - - /* Log misc errors. */ - if (csr0 & 0x4000) lp->stats.tx_errors++; /* Tx babble. */ - if (csr0 & 0x1000) lp->stats.rx_errors++; /* Missed a Rx frame. */ - if (csr0 & 0x0800) { - printk("%s: Bus master arbitration failure, status %4.4x.\n", - dev->name, csr0); - /* Restart the chip. */ - must_restart = 1; - } - - if (must_restart) { - /* stop the chip to clear the error condition, then restart */ - outw(0x0000, dev->base_addr + LANCE_ADDR); - outw(0x0004, dev->base_addr + LANCE_DATA); - lance_restart(dev, 0x0002, 0); - } - } - - /* Clear any other interrupt, and set interrupt enable. */ - outw(0x0000, dev->base_addr + LANCE_ADDR); - outw(0x7940, dev->base_addr + LANCE_DATA); - - if (lance_debug > 4) - printk("%s: exiting interrupt, csr%d=%#4.4x.\n", - dev->name, inw(ioaddr + LANCE_ADDR), - inw(dev->base_addr + LANCE_DATA)); - - dev->interrupt = 0; - return; -} - -static int -lance_rx(struct device *dev) -{ - struct lance_private *lp = (struct lance_private *)dev->priv; - int entry = lp->cur_rx & RX_RING_MOD_MASK; - int i; - - /* If we own the next entry, it's a new packet. Send it up. */ - while (lp->rx_ring[entry].base >= 0) { - int status = lp->rx_ring[entry].base >> 24; - - if (status != 0x03) { /* There was an error. */ - /* There is a tricky error noted by John Murphy, - <murf@perftech.com> to Russ Nelson: Even with full-sized - buffers it's possible for a jabber packet to use two - buffers, with only the last correctly noting the error. */ - if (status & 0x01) /* Only count a general error at the */ - lp->stats.rx_errors++; /* end of a packet.*/ - if (status & 0x20) lp->stats.rx_frame_errors++; - if (status & 0x10) lp->stats.rx_over_errors++; - if (status & 0x08) lp->stats.rx_crc_errors++; - if (status & 0x04) lp->stats.rx_fifo_errors++; - lp->rx_ring[entry].base &= 0x03ffffff; - } - else - { - /* Malloc up new buffer, compatible with net-2e. */ - short pkt_len = (lp->rx_ring[entry].msg_length & 0xfff)-4; - struct sk_buff *skb; - - if(pkt_len<60) - { - printk("%s: Runt packet!\n",dev->name); - lp->stats.rx_errors++; - } - else - { - skb = dev_alloc_skb(pkt_len+2); - if (skb == NULL) - { - printk("%s: Memory squeeze, deferring packet.\n", dev->name); - for (i=0; i < RX_RING_SIZE; i++) - if (lp->rx_ring[(entry+i) & RX_RING_MOD_MASK].base < 0) - break; - - if (i > RX_RING_SIZE -2) - { - lp->stats.rx_dropped++; - lp->rx_ring[entry].base |= 0x80000000; - lp->cur_rx++; - } - break; - } - skb->dev = dev; - skb_reserve(skb,2); /* 16 byte align */ - skb_put(skb,pkt_len); /* Make room */ - eth_copy_and_sum(skb, - (unsigned char *)(lp->rx_ring[entry].base & 0x00ffffff), - pkt_len,0); - skb->protocol=eth_type_trans(skb,dev); - netif_rx(skb); - lp->stats.rx_packets++; - } - } - /* The docs say that the buffer length isn't touched, but Andrew Boyd - of QNX reports that some revs of the 79C965 clear it. */ - lp->rx_ring[entry].buf_length = -PKT_BUF_SZ; - lp->rx_ring[entry].base |= 0x80000000; - entry = (++lp->cur_rx) & RX_RING_MOD_MASK; - } - - /* We should check that at least two ring entries are free. If not, - we should free one and mark stats->rx_dropped++. */ - - return 0; -} - -static int -lance_close(struct device *dev) -{ - int ioaddr = dev->base_addr; - struct lance_private *lp = (struct lance_private *)dev->priv; - - dev->start = 0; - dev->tbusy = 1; - - if (chip_table[lp->chip_version].flags & LANCE_HAS_MISSED_FRAME) { - outw(112, ioaddr+LANCE_ADDR); - lp->stats.rx_missed_errors = inw(ioaddr+LANCE_DATA); - } - outw(0, ioaddr+LANCE_ADDR); - - if (lance_debug > 1) - printk("%s: Shutting down ethercard, status was %2.2x.\n", - dev->name, inw(ioaddr+LANCE_DATA)); - - /* We stop the LANCE here -- it occasionally polls - memory if we don't. */ - outw(0x0004, ioaddr+LANCE_DATA); - - if (dev->dma != 4) - disable_dma(dev->dma); - - free_irq(dev->irq); - - irq2dev_map[dev->irq] = 0; - - return 0; -} - -static struct enet_statistics * -lance_get_stats(struct device *dev) -{ - struct lance_private *lp = (struct lance_private *)dev->priv; - short ioaddr = dev->base_addr; - short saved_addr; - unsigned long flags; - - if (chip_table[lp->chip_version].flags & LANCE_HAS_MISSED_FRAME) { - save_flags(flags); - cli(); - saved_addr = inw(ioaddr+LANCE_ADDR); - outw(112, ioaddr+LANCE_ADDR); - lp->stats.rx_missed_errors = inw(ioaddr+LANCE_DATA); - outw(saved_addr, ioaddr+LANCE_ADDR); - restore_flags(flags); - } - - return &lp->stats; -} - -/* Set or clear the multicast filter for this adaptor. - */ - -static void set_multicast_list(struct device *dev) -{ - short ioaddr = dev->base_addr; - - outw(0, ioaddr+LANCE_ADDR); - outw(0x0004, ioaddr+LANCE_DATA); /* Temporarily stop the lance. */ - - if (dev->flags&IFF_PROMISC) { - /* Log any net taps. */ - printk("%s: Promiscuous mode enabled.\n", dev->name); - outw(15, ioaddr+LANCE_ADDR); - outw(0x8000, ioaddr+LANCE_DATA); /* Set promiscuous mode */ - } else { - short multicast_table[4]; - int i; - int num_addrs=dev->mc_count; - if(dev->flags&IFF_ALLMULTI) - num_addrs=1; - /* FIXIT: We don't use the multicast table, but rely on upper-layer filtering. */ - memset(multicast_table, (num_addrs == 0) ? 0 : -1, sizeof(multicast_table)); - for (i = 0; i < 4; i++) { - outw(8 + i, ioaddr+LANCE_ADDR); - outw(multicast_table[i], ioaddr+LANCE_DATA); - } - outw(15, ioaddr+LANCE_ADDR); - outw(0x0000, ioaddr+LANCE_DATA); /* Unset promiscuous mode */ - } - - lance_restart(dev, 0x0142, 0); /* Resume normal operation */ - -} - - -/* - * Local variables: - * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c lance.c" - * c-indent-level: 4 - * tab-width: 4 - * End: - */ diff --git a/i386/i386at/gpl/linux/net/ne.c b/i386/i386at/gpl/linux/net/ne.c deleted file mode 100644 index 4da4efb7..00000000 --- a/i386/i386at/gpl/linux/net/ne.c +++ /dev/null @@ -1,733 +0,0 @@ -/* ne.c: A general non-shared-memory NS8390 ethernet driver for linux. */ -/* - Written 1992-94 by Donald Becker. - - Copyright 1993 United States Government as represented by the - Director, National Security Agency. - - This software may be used and distributed according to the terms - of the GNU Public License, incorporated herein by reference. - - The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O - Center of Excellence in Space Data and Information Sciences - Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771 - - This driver should work with many programmed-I/O 8390-based ethernet - boards. Currently it supports the NE1000, NE2000, many clones, - and some Cabletron products. - - Changelog: - - Paul Gortmaker : use ENISR_RDC to monitor Tx PIO uploads, made - sanity checks and bad clone support optional. - Paul Gortmaker : new reset code, reset card after probe at boot. - Paul Gortmaker : multiple card support for module users. - Paul Gortmaker : Support for PCI ne2k clones, similar to lance.c - -*/ - -/* Routines for the NatSemi-based designs (NE[12]000). */ - -static const char *version = - "ne.c:v1.10 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n"; - - -#include <linux/module.h> -#include <linux/config.h> -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/errno.h> -#include <linux/pci.h> -#include <linux/bios32.h> -#include <asm/system.h> -#include <asm/io.h> - -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include "8390.h" - -/* Some defines that people can play with if so inclined. */ - -/* Do we support clones that don't adhere to 14,15 of the SAprom ? */ -#define SUPPORT_NE_BAD_CLONES - -/* Do we perform extra sanity checks on stuff ? */ -/* #define NE_SANITY_CHECK */ - -/* Do we implement the read before write bugfix ? */ -/* #define NE_RW_BUGFIX */ - -/* Do we have a non std. amount of memory? (in units of 256 byte pages) */ -/* #define PACKETBUF_MEMSIZE 0x40 */ - -/* ---- No user-serviceable parts below ---- */ - -/* A zero-terminated list of I/O addresses to be probed. */ -static unsigned int netcard_portlist[] = -{ 0x300, 0x280, 0x320, 0x340, 0x360, 0}; - -#ifdef SUPPORT_NE_BAD_CLONES -/* A list of bad clones that we none-the-less recognize. */ -static struct { const char *name8, *name16; unsigned char SAprefix[4];} -bad_clone_list[] = { - {"DE100", "DE200", {0x00, 0xDE, 0x01,}}, - {"DE120", "DE220", {0x00, 0x80, 0xc8,}}, - {"DFI1000", "DFI2000", {'D', 'F', 'I',}}, /* Original, eh? */ - {"EtherNext UTP8", "EtherNext UTP16", {0x00, 0x00, 0x79}}, - {"NE1000","NE2000-invalid", {0x00, 0x00, 0xd8}}, /* Ancient real NE1000. */ - {"NN1000", "NN2000", {0x08, 0x03, 0x08}}, /* Outlaw no-name clone. */ - {"4-DIM8","4-DIM16", {0x00,0x00,0x4d,}}, /* Outlaw 4-Dimension cards. */ - {"Con-Intl_8", "Con-Intl_16", {0x00, 0x00, 0x24}}, /* Connect Int'nl */ - {0,} -}; -#endif - -#define NE_BASE (dev->base_addr) -#define NE_CMD 0x00 -#define NE_DATAPORT 0x10 /* NatSemi-defined port window offset. */ -#define NE_RESET 0x1f /* Issue a read to reset, a write to clear. */ -#define NE_IO_EXTENT 0x20 - -#define NE1SM_START_PG 0x20 /* First page of TX buffer */ -#define NE1SM_STOP_PG 0x40 /* Last page +1 of RX ring */ -#define NESM_START_PG 0x40 /* First page of TX buffer */ -#define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */ - -/* Non-zero only if the current card is a PCI with BIOS-set IRQ. */ -static unsigned char pci_irq_line = 0; - -int ne_probe(struct device *dev); -static int ne_probe1(struct device *dev, int ioaddr); - -static int ne_open(struct device *dev); -static int ne_close(struct device *dev); - -static void ne_reset_8390(struct device *dev); -static void ne_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, - int ring_page); -static void ne_block_input(struct device *dev, int count, - struct sk_buff *skb, int ring_offset); -static void ne_block_output(struct device *dev, const int count, - const unsigned char *buf, const int start_page); - - -/* Probe for various non-shared-memory ethercards. - - NEx000-clone boards have a Station Address PROM (SAPROM) in the packet - buffer memory space. NE2000 clones have 0x57,0x57 in bytes 0x0e,0x0f of - the SAPROM, while other supposed NE2000 clones must be detected by their - SA prefix. - - Reading the SAPROM from a word-wide card with the 8390 set in byte-wide - mode results in doubled values, which can be detected and compensated for. - - The probe is also responsible for initializing the card and filling - in the 'dev' and 'ei_status' structures. - - We use the minimum memory size for some ethercard product lines, iff we can't - distinguish models. You can increase the packet buffer size by setting - PACKETBUF_MEMSIZE. Reported Cabletron packet buffer locations are: - E1010 starts at 0x100 and ends at 0x2000. - E1010-x starts at 0x100 and ends at 0x8000. ("-x" means "more memory") - E2010 starts at 0x100 and ends at 0x4000. - E2010-x starts at 0x100 and ends at 0xffff. */ - -#ifdef HAVE_DEVLIST -struct netdev_entry netcard_drv = -{"ne", ne_probe1, NE_IO_EXTENT, netcard_portlist}; -#else - -/* Note that this probe only picks up one card at a time, even for multiple - PCI ne2k cards. Use "ether=0,0,eth1" if you have a second PCI ne2k card. - This keeps things consistent regardless of the bus type of the card. */ - -int ne_probe(struct device *dev) -{ - int i; - int base_addr = dev ? dev->base_addr : 0; - - /* First check any supplied i/o locations. User knows best. <cough> */ - if (base_addr > 0x1ff) /* Check a single specified location. */ - return ne_probe1(dev, base_addr); - else if (base_addr != 0) /* Don't probe at all. */ - return ENXIO; - - /* Then look for any installed PCI clones */ -#if defined(CONFIG_PCI) - if (pcibios_present()) { - int pci_index; - for (pci_index = 0; pci_index < 8; pci_index++) { - unsigned char pci_bus, pci_device_fn; - unsigned int pci_ioaddr; - - /* Currently only Realtek are making PCI ne2k clones. */ - if (pcibios_find_device (PCI_VENDOR_ID_REALTEK, - PCI_DEVICE_ID_REALTEK_8029, pci_index, - &pci_bus, &pci_device_fn) != 0) - break; /* OK, now try to probe for std. ISA card */ - pcibios_read_config_byte(pci_bus, pci_device_fn, - PCI_INTERRUPT_LINE, &pci_irq_line); - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_0, &pci_ioaddr); - /* Strip the I/O address out of the returned value */ - pci_ioaddr &= PCI_BASE_ADDRESS_IO_MASK; - /* Avoid already found cards from previous ne_probe() calls */ - if (check_region(pci_ioaddr, NE_IO_EXTENT)) - continue; - printk("ne.c: PCI BIOS reports ne2000 clone at i/o %#x, irq %d.\n", - pci_ioaddr, pci_irq_line); - if (ne_probe1(dev, pci_ioaddr) != 0) { /* Shouldn't happen. */ - printk(KERN_ERR "ne.c: Probe of PCI card at %#x failed.\n", pci_ioaddr); - break; /* Hrmm, try to probe for ISA card... */ - } - pci_irq_line = 0; - return 0; - } - } -#endif /* defined(CONFIG_PCI) */ - - /* Last resort. The semi-risky ISA auto-probe. */ - for (i = 0; netcard_portlist[i]; i++) { - int ioaddr = netcard_portlist[i]; - if (check_region(ioaddr, NE_IO_EXTENT)) - continue; - if (ne_probe1(dev, ioaddr) == 0) - return 0; - } - - return ENODEV; -} -#endif - -static int ne_probe1(struct device *dev, int ioaddr) -{ - int i; - unsigned char SA_prom[32]; - int wordlength = 2; - const char *name = NULL; - int start_page, stop_page; - int neX000, ctron; - int reg0 = inb_p(ioaddr); - static unsigned version_printed = 0; - - if (reg0 == 0xFF) - return ENODEV; - - /* Do a preliminary verification that we have a 8390. */ - { int regd; - outb_p(E8390_NODMA+E8390_PAGE1+E8390_STOP, ioaddr + E8390_CMD); - regd = inb_p(ioaddr + 0x0d); - outb_p(0xff, ioaddr + 0x0d); - outb_p(E8390_NODMA+E8390_PAGE0, ioaddr + E8390_CMD); - inb_p(ioaddr + EN0_COUNTER0); /* Clear the counter by reading. */ - if (inb_p(ioaddr + EN0_COUNTER0) != 0) { - outb_p(reg0, ioaddr); - outb_p(regd, ioaddr + 0x0d); /* Restore the old values. */ - return ENODEV; - } - } - - if (ei_debug && version_printed++ == 0) - printk(version); - - printk("NE*000 ethercard probe at %#3x:", ioaddr); - - /* Reset card. Who knows what dain-bramaged state it was left in. */ - { unsigned long reset_start_time = jiffies; - - /* DON'T change these to inb_p/outb_p or reset will fail on clones. */ - outb(inb(ioaddr + NE_RESET), ioaddr + NE_RESET); - - while ((inb_p(ioaddr + EN0_ISR) & ENISR_RESET) == 0) - if (jiffies - reset_start_time > 2*HZ/100) { - printk(" not found (no reset ack).\n"); - return ENODEV; - } - - outb_p(0xff, ioaddr + EN0_ISR); /* Ack all intr. */ - } - - /* Read the 16 bytes of station address PROM. - We must first initialize registers, similar to NS8390_init(eifdev, 0). - We can't reliably read the SAPROM address without this. - (I learned the hard way!). */ - { - struct {unsigned char value, offset; } program_seq[] = { - {E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/ - {0x48, EN0_DCFG}, /* Set byte-wide (0x48) access. */ - {0x00, EN0_RCNTLO}, /* Clear the count regs. */ - {0x00, EN0_RCNTHI}, - {0x00, EN0_IMR}, /* Mask completion irq. */ - {0xFF, EN0_ISR}, - {E8390_RXOFF, EN0_RXCR}, /* 0x20 Set to monitor */ - {E8390_TXOFF, EN0_TXCR}, /* 0x02 and loopback mode. */ - {32, EN0_RCNTLO}, - {0x00, EN0_RCNTHI}, - {0x00, EN0_RSARLO}, /* DMA starting at 0x0000. */ - {0x00, EN0_RSARHI}, - {E8390_RREAD+E8390_START, E8390_CMD}, - }; - for (i = 0; i < sizeof(program_seq)/sizeof(program_seq[0]); i++) - outb_p(program_seq[i].value, ioaddr + program_seq[i].offset); - - } - for(i = 0; i < 32 /*sizeof(SA_prom)*/; i+=2) { - SA_prom[i] = inb(ioaddr + NE_DATAPORT); - SA_prom[i+1] = inb(ioaddr + NE_DATAPORT); - if (SA_prom[i] != SA_prom[i+1]) - wordlength = 1; - } - - if (wordlength == 2) { - /* We must set the 8390 for word mode. */ - outb_p(0x49, ioaddr + EN0_DCFG); - /* We used to reset the ethercard here, but it doesn't seem - to be necessary. */ - /* Un-double the SA_prom values. */ - for (i = 0; i < 16; i++) - SA_prom[i] = SA_prom[i+i]; - start_page = NESM_START_PG; - stop_page = NESM_STOP_PG; - } else { - start_page = NE1SM_START_PG; - stop_page = NE1SM_STOP_PG; - } - - neX000 = (SA_prom[14] == 0x57 && SA_prom[15] == 0x57); - ctron = (SA_prom[0] == 0x00 && SA_prom[1] == 0x00 && SA_prom[2] == 0x1d); - - /* Set up the rest of the parameters. */ - if (neX000) { - name = (wordlength == 2) ? "NE2000" : "NE1000"; - } else if (ctron) { - name = (wordlength == 2) ? "Ctron-8" : "Ctron-16"; - start_page = 0x01; - stop_page = (wordlength == 2) ? 0x40 : 0x20; - } else { -#ifdef SUPPORT_NE_BAD_CLONES - /* Ack! Well, there might be a *bad* NE*000 clone there. - Check for total bogus addresses. */ - for (i = 0; bad_clone_list[i].name8; i++) { - if (SA_prom[0] == bad_clone_list[i].SAprefix[0] && - SA_prom[1] == bad_clone_list[i].SAprefix[1] && - SA_prom[2] == bad_clone_list[i].SAprefix[2]) { - if (wordlength == 2) { - name = bad_clone_list[i].name16; - } else { - name = bad_clone_list[i].name8; - } - break; - } - } - if (bad_clone_list[i].name8 == NULL) { - printk(" not found (invalid signature %2.2x %2.2x).\n", - SA_prom[14], SA_prom[15]); - return ENXIO; - } -#else - printk(" not found.\n"); - return ENXIO; -#endif - - } - - /* We should have a "dev" from Space.c or the static module table. */ - if (dev == NULL) { - printk("ne.c: Passed a NULL device.\n"); - dev = init_etherdev(0, 0); - } - - if (pci_irq_line) { - dev->irq = pci_irq_line; - } - - if (dev->irq < 2) { - autoirq_setup(0); - outb_p(0x50, ioaddr + EN0_IMR); /* Enable one interrupt. */ - outb_p(0x00, ioaddr + EN0_RCNTLO); - outb_p(0x00, ioaddr + EN0_RCNTHI); - outb_p(E8390_RREAD+E8390_START, ioaddr); /* Trigger it... */ - outb_p(0x00, ioaddr + EN0_IMR); /* Mask it again. */ - dev->irq = autoirq_report(0); - if (ei_debug > 2) - printk(" autoirq is %d\n", dev->irq); - } else if (dev->irq == 2) - /* Fixup for users that don't know that IRQ 2 is really IRQ 9, - or don't know which one to set. */ - dev->irq = 9; - - if (! dev->irq) { - printk(" failed to detect IRQ line.\n"); - return EAGAIN; - } - - /* Snarf the interrupt now. There's no point in waiting since we cannot - share and the board will usually be enabled. */ - { - int irqval = request_irq(dev->irq, ei_interrupt, 0, name); - if (irqval) { - printk (" unable to get IRQ %d (irqval=%d).\n", dev->irq, irqval); - return EAGAIN; - } - } - - dev->base_addr = ioaddr; - - /* Allocate dev->priv and fill in 8390 specific dev fields. */ - if (ethdev_init(dev)) { - printk (" unable to get memory for dev->priv.\n"); - free_irq(dev->irq); - return -ENOMEM; - } - - request_region(ioaddr, NE_IO_EXTENT, name); - - for(i = 0; i < ETHER_ADDR_LEN; i++) { - printk(" %2.2x", SA_prom[i]); - dev->dev_addr[i] = SA_prom[i]; - } - - printk("\n%s: %s found at %#x, using IRQ %d.\n", - dev->name, name, ioaddr, dev->irq); - - ei_status.name = name; - ei_status.tx_start_page = start_page; - ei_status.stop_page = stop_page; - ei_status.word16 = (wordlength == 2); - - ei_status.rx_start_page = start_page + TX_PAGES; -#ifdef PACKETBUF_MEMSIZE - /* Allow the packet buffer size to be overridden by know-it-alls. */ - ei_status.stop_page = ei_status.tx_start_page + PACKETBUF_MEMSIZE; -#endif - - ei_status.reset_8390 = &ne_reset_8390; - ei_status.block_input = &ne_block_input; - ei_status.block_output = &ne_block_output; - ei_status.get_8390_hdr = &ne_get_8390_hdr; - dev->open = &ne_open; - dev->stop = &ne_close; - NS8390_init(dev, 0); - return 0; -} - -static int -ne_open(struct device *dev) -{ - ei_open(dev); - MOD_INC_USE_COUNT; - return 0; -} - -static int -ne_close(struct device *dev) -{ - if (ei_debug > 1) - printk("%s: Shutting down ethercard.\n", dev->name); - ei_close(dev); - MOD_DEC_USE_COUNT; - return 0; -} - -/* Hard reset the card. This used to pause for the same period that a - 8390 reset command required, but that shouldn't be necessary. */ -static void -ne_reset_8390(struct device *dev) -{ - unsigned long reset_start_time = jiffies; - - if (ei_debug > 1) printk("resetting the 8390 t=%ld...", jiffies); - - /* DON'T change these to inb_p/outb_p or reset will fail on clones. */ - outb(inb(NE_BASE + NE_RESET), NE_BASE + NE_RESET); - - ei_status.txing = 0; - ei_status.dmaing = 0; - - /* This check _should_not_ be necessary, omit eventually. */ - while ((inb_p(NE_BASE+EN0_ISR) & ENISR_RESET) == 0) - if (jiffies - reset_start_time > 2*HZ/100) { - printk("%s: ne_reset_8390() did not complete.\n", dev->name); - break; - } - outb_p(ENISR_RESET, NE_BASE + EN0_ISR); /* Ack intr. */ -} - -/* Grab the 8390 specific header. Similar to the block_input routine, but - we don't need to be concerned with ring wrap as the header will be at - the start of a page, so we optimize accordingly. */ - -static void -ne_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page) -{ - - int nic_base = dev->base_addr; - - /* This *shouldn't* happen. If it does, it's the last thing you'll see */ - if (ei_status.dmaing) { - printk("%s: DMAing conflict in ne_get_8390_hdr " - "[DMAstat:%d][irqlock:%d][intr:%d].\n", - dev->name, ei_status.dmaing, ei_status.irqlock, - dev->interrupt); - return; - } - - ei_status.dmaing |= 0x01; - outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD); - outb_p(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO); - outb_p(0, nic_base + EN0_RCNTHI); - outb_p(0, nic_base + EN0_RSARLO); /* On page boundary */ - outb_p(ring_page, nic_base + EN0_RSARHI); - outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD); - - if (ei_status.word16) - insw(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1); - else - insb(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)); - - outb_p(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */ - ei_status.dmaing &= ~0x01; -} - -/* Block input and output, similar to the Crynwr packet driver. If you - are porting to a new ethercard, look at the packet driver source for hints. - The NEx000 doesn't share the on-board packet memory -- you have to put - the packet out through the "remote DMA" dataport using outb. */ - -static void -ne_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset) -{ -#ifdef NE_SANITY_CHECK - int xfer_count = count; -#endif - int nic_base = dev->base_addr; - char *buf = skb->data; - - /* This *shouldn't* happen. If it does, it's the last thing you'll see */ - if (ei_status.dmaing) { - printk("%s: DMAing conflict in ne_block_input " - "[DMAstat:%d][irqlock:%d][intr:%d].\n", - dev->name, ei_status.dmaing, ei_status.irqlock, - dev->interrupt); - return; - } - ei_status.dmaing |= 0x01; - outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD); - outb_p(count & 0xff, nic_base + EN0_RCNTLO); - outb_p(count >> 8, nic_base + EN0_RCNTHI); - outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO); - outb_p(ring_offset >> 8, nic_base + EN0_RSARHI); - outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD); - if (ei_status.word16) { - insw(NE_BASE + NE_DATAPORT,buf,count>>1); - if (count & 0x01) { - buf[count-1] = inb(NE_BASE + NE_DATAPORT); -#ifdef NE_SANITY_CHECK - xfer_count++; -#endif - } - } else { - insb(NE_BASE + NE_DATAPORT, buf, count); - } - -#ifdef NE_SANITY_CHECK - /* This was for the ALPHA version only, but enough people have - been encountering problems so it is still here. If you see - this message you either 1) have a slightly incompatible clone - or 2) have noise/speed problems with your bus. */ - if (ei_debug > 1) { /* DMA termination address check... */ - int addr, tries = 20; - do { - /* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here - -- it's broken for Rx on some cards! */ - int high = inb_p(nic_base + EN0_RSARHI); - int low = inb_p(nic_base + EN0_RSARLO); - addr = (high << 8) + low; - if (((ring_offset + xfer_count) & 0xff) == low) - break; - } while (--tries > 0); - if (tries <= 0) - printk("%s: RX transfer address mismatch," - "%#4.4x (expected) vs. %#4.4x (actual).\n", - dev->name, ring_offset + xfer_count, addr); - } -#endif - outb_p(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */ - ei_status.dmaing &= ~0x01; -} - -static void -ne_block_output(struct device *dev, int count, - const unsigned char *buf, const int start_page) -{ - int nic_base = NE_BASE; - unsigned long dma_start; -#ifdef NE_SANITY_CHECK - int retries = 0; -#endif - - /* Round the count up for word writes. Do we need to do this? - What effect will an odd byte count have on the 8390? - I should check someday. */ - if (ei_status.word16 && (count & 0x01)) - count++; - - /* This *shouldn't* happen. If it does, it's the last thing you'll see */ - if (ei_status.dmaing) { - printk("%s: DMAing conflict in ne_block_output." - "[DMAstat:%d][irqlock:%d][intr:%d]\n", - dev->name, ei_status.dmaing, ei_status.irqlock, - dev->interrupt); - return; - } - ei_status.dmaing |= 0x01; - /* We should already be in page 0, but to be safe... */ - outb_p(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD); - -#ifdef NE_SANITY_CHECK - retry: -#endif - -#ifdef NE8390_RW_BUGFIX - /* Handle the read-before-write bug the same way as the - Crynwr packet driver -- the NatSemi method doesn't work. - Actually this doesn't always work either, but if you have - problems with your NEx000 this is better than nothing! */ - outb_p(0x42, nic_base + EN0_RCNTLO); - outb_p(0x00, nic_base + EN0_RCNTHI); - outb_p(0x42, nic_base + EN0_RSARLO); - outb_p(0x00, nic_base + EN0_RSARHI); - outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD); - /* Make certain that the dummy read has occurred. */ - SLOW_DOWN_IO; - SLOW_DOWN_IO; - SLOW_DOWN_IO; -#endif - - outb_p(ENISR_RDC, nic_base + EN0_ISR); - - /* Now the normal output. */ - outb_p(count & 0xff, nic_base + EN0_RCNTLO); - outb_p(count >> 8, nic_base + EN0_RCNTHI); - outb_p(0x00, nic_base + EN0_RSARLO); - outb_p(start_page, nic_base + EN0_RSARHI); - - outb_p(E8390_RWRITE+E8390_START, nic_base + NE_CMD); - if (ei_status.word16) { - outsw(NE_BASE + NE_DATAPORT, buf, count>>1); - } else { - outsb(NE_BASE + NE_DATAPORT, buf, count); - } - - dma_start = jiffies; - -#ifdef NE_SANITY_CHECK - /* This was for the ALPHA version only, but enough people have - been encountering problems so it is still here. */ - if (ei_debug > 1) { /* DMA termination address check... */ - int addr, tries = 20; - do { - int high = inb_p(nic_base + EN0_RSARHI); - int low = inb_p(nic_base + EN0_RSARLO); - addr = (high << 8) + low; - if ((start_page << 8) + count == addr) - break; - } while (--tries > 0); - if (tries <= 0) { - printk("%s: Tx packet transfer address mismatch," - "%#4.4x (expected) vs. %#4.4x (actual).\n", - dev->name, (start_page << 8) + count, addr); - if (retries++ == 0) - goto retry; - } - } -#endif - - while ((inb_p(nic_base + EN0_ISR) & ENISR_RDC) == 0) - if (jiffies - dma_start > 2*HZ/100) { /* 20ms */ - printk("%s: timeout waiting for Tx RDC.\n", dev->name); - ne_reset_8390(dev); - NS8390_init(dev,1); - break; - } - - outb_p(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */ - ei_status.dmaing &= ~0x01; - return; -} - - -#ifdef MODULE -#define MAX_NE_CARDS 4 /* Max number of NE cards per module */ -#define NAMELEN 8 /* # of chars for storing dev->name */ -static char namelist[NAMELEN * MAX_NE_CARDS] = { 0, }; -static struct device dev_ne[MAX_NE_CARDS] = { - { - NULL, /* assign a chunk of namelist[] below */ - 0, 0, 0, 0, - 0, 0, - 0, 0, 0, NULL, NULL - }, -}; - -static int io[MAX_NE_CARDS] = { 0, }; -static int irq[MAX_NE_CARDS] = { 0, }; - -/* This is set up so that no autoprobe takes place. We can't guarantee -that the ne2k probe is the last 8390 based probe to take place (as it -is at boot) and so the probe will get confused by any other 8390 cards. -ISA device autoprobes on a running machine are not recommended anyway. */ - -int -init_module(void) -{ - int this_dev, found = 0; - - for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) { - struct device *dev = &dev_ne[this_dev]; - dev->name = namelist+(NAMELEN*this_dev); - dev->irq = irq[this_dev]; - dev->base_addr = io[this_dev]; - dev->init = ne_probe; - if (io[this_dev] == 0) { - if (this_dev != 0) break; /* only complain once */ - printk(KERN_NOTICE "ne.c: Module autoprobing not allowed. Append \"io=0xNNN\" value(s).\n"); - return -EPERM; - } - if (register_netdev(dev) != 0) { - printk(KERN_WARNING "ne.c: No NE*000 card found (i/o = 0x%x).\n", io[this_dev]); - if (found != 0) return 0; /* Got at least one. */ - return -ENXIO; - } - found++; - } - - return 0; -} - -void -cleanup_module(void) -{ - int this_dev; - - for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) { - struct device *dev = &dev_ne[this_dev]; - if (dev->priv != NULL) { - kfree(dev->priv); - dev->priv = NULL; - free_irq(dev->irq); - irq2dev_map[dev->irq] = NULL; - release_region(dev->base_addr, NE_IO_EXTENT); - unregister_netdev(dev); - } - } -} -#endif /* MODULE */ - -/* - * Local variables: - * compile-command: "gcc -DKERNEL -Wall -O6 -fomit-frame-pointer -I/usr/src/linux/net/tcp -c ne.c" - * version-control: t - * kept-new-versions: 5 - * End: - */ diff --git a/i386/i386at/gpl/linux/net/net_init.c b/i386/i386at/gpl/linux/net/net_init.c deleted file mode 100644 index cedee941..00000000 --- a/i386/i386at/gpl/linux/net/net_init.c +++ /dev/null @@ -1,380 +0,0 @@ -/* netdrv_init.c: Initialization for network devices. */ -/* - Written 1993,1994,1995 by Donald Becker. - - The author may be reached as becker@cesdis.gsfc.nasa.gov or - C/O Center of Excellence in Space Data and Information Sciences - Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771 - - This file contains the initialization for the "pl14+" style ethernet - drivers. It should eventually replace most of drivers/net/Space.c. - It's primary advantage is that it's able to allocate low-memory buffers. - A secondary advantage is that the dangerous NE*000 netcards can reserve - their I/O port region before the SCSI probes start. - - Modifications/additions by Bjorn Ekwall <bj0rn@blox.se>: - ethdev_index[MAX_ETH_CARDS] - register_netdev() / unregister_netdev() - - Modifications by Wolfgang Walter - Use dev_close cleanly so we always shut things down tidily. - - Changed 29/10/95, Alan Cox to pass sockaddr's around for mac addresses. -*/ - -#include <linux/config.h> -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/types.h> -#include <linux/fs.h> -#include <linux/malloc.h> -#include <linux/if_ether.h> -#include <linux/if_arp.h> -#include <linux/string.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/trdevice.h> -#ifdef CONFIG_NET_ALIAS -#include <linux/net_alias.h> -#endif - -/* The network devices currently exist only in the socket namespace, so these - entries are unused. The only ones that make sense are - open start the ethercard - close stop the ethercard - ioctl To get statistics, perhaps set the interface port (AUI, BNC, etc.) - One can also imagine getting raw packets using - read & write - but this is probably better handled by a raw packet socket. - - Given that almost all of these functions are handled in the current - socket-based scheme, putting ethercard devices in /dev/ seems pointless. - - [Removed all support for /dev network devices. When someone adds - streams then by magic we get them, but otherwise they are un-needed - and a space waste] -*/ - -/* The list of used and available "eth" slots (for "eth0", "eth1", etc.) */ -#define MAX_ETH_CARDS 16 /* same as the number if irq's in irq2dev[] */ -static struct device *ethdev_index[MAX_ETH_CARDS]; - -/* Fill in the fields of the device structure with ethernet-generic values. - - If no device structure is passed, a new one is constructed, complete with - a SIZEOF_PRIVATE private data area. - - If an empty string area is passed as dev->name, or a new structure is made, - a new name string is constructed. The passed string area should be 8 bytes - long. - */ - -struct device * -init_etherdev(struct device *dev, int sizeof_priv) -{ - int new_device = 0; - int i; - - /* Use an existing correctly named device in Space.c:dev_base. */ - if (dev == NULL) { - int alloc_size = sizeof(struct device) + sizeof("eth%d ") - + sizeof_priv + 3; - struct device *cur_dev; - char pname[8]; /* Putative name for the device. */ - - for (i = 0; i < MAX_ETH_CARDS; ++i) - if (ethdev_index[i] == NULL) { - sprintf(pname, "eth%d", i); - for (cur_dev = dev_base; cur_dev; cur_dev = cur_dev->next) - if (strcmp(pname, cur_dev->name) == 0) { - dev = cur_dev; - dev->init = NULL; - sizeof_priv = (sizeof_priv + 3) & ~3; - dev->priv = sizeof_priv - ? kmalloc(sizeof_priv, GFP_KERNEL) - : NULL; - if (dev->priv) memset(dev->priv, 0, sizeof_priv); - goto found; - } - } - - alloc_size &= ~3; /* Round to dword boundary. */ - - dev = (struct device *)kmalloc(alloc_size, GFP_KERNEL); - memset(dev, 0, alloc_size); - if (sizeof_priv) - dev->priv = (void *) (dev + 1); - dev->name = sizeof_priv + (char *)(dev + 1); - new_device = 1; - } - - found: /* From the double loop above. */ - - if (dev->name && - ((dev->name[0] == '\0') || (dev->name[0] == ' '))) { - for (i = 0; i < MAX_ETH_CARDS; ++i) - if (ethdev_index[i] == NULL) { - sprintf(dev->name, "eth%d", i); - ethdev_index[i] = dev; - break; - } - } - - ether_setup(dev); /* Hmmm, should this be called here? */ - - if (new_device) { - /* Append the device to the device queue. */ - struct device **old_devp = &dev_base; - while ((*old_devp)->next) - old_devp = & (*old_devp)->next; - (*old_devp)->next = dev; - dev->next = 0; - } - return dev; -} - - -static int eth_mac_addr(struct device *dev, void *p) -{ - struct sockaddr *addr=p; - if(dev->start) - return -EBUSY; - memcpy(dev->dev_addr, addr->sa_data,dev->addr_len); - return 0; -} - -void ether_setup(struct device *dev) -{ - int i; - - /* Fill in the fields of the device structure with ethernet-generic values. - This should be in a common file instead of per-driver. */ - for (i = 0; i < DEV_NUMBUFFS; i++) - skb_queue_head_init(&dev->buffs[i]); - - /* register boot-defined "eth" devices */ - if (dev->name && (strncmp(dev->name, "eth", 3) == 0)) { - i = simple_strtoul(dev->name + 3, NULL, 0); - if (ethdev_index[i] == NULL) { - ethdev_index[i] = dev; - } - else if (dev != ethdev_index[i]) { - /* Really shouldn't happen! */ -#ifdef MACH - panic ("ether_setup: Ouch! Someone else took %s, i = %d\n", - dev->name, i); -#else - printk("ether_setup: Ouch! Someone else took %s, i = %d\n", - dev->name, i); -#endif - } - } - -#ifndef MACH - dev->hard_header = eth_header; - dev->rebuild_header = eth_rebuild_header; - dev->set_mac_address = eth_mac_addr; - dev->header_cache_bind = eth_header_cache_bind; - dev->header_cache_update= eth_header_cache_update; -#endif - - dev->type = ARPHRD_ETHER; - dev->hard_header_len = ETH_HLEN; - dev->mtu = 1500; /* eth_mtu */ - dev->addr_len = ETH_ALEN; - dev->tx_queue_len = 100; /* Ethernet wants good queues */ - - memset(dev->broadcast,0xFF, ETH_ALEN); - - /* New-style flags. */ - dev->flags = IFF_BROADCAST|IFF_MULTICAST; - dev->family = AF_INET; - dev->pa_addr = 0; - dev->pa_brdaddr = 0; - dev->pa_mask = 0; - dev->pa_alen = 4; -} - -#ifdef CONFIG_TR - -void tr_setup(struct device *dev) -{ - int i; - /* Fill in the fields of the device structure with ethernet-generic values. - This should be in a common file instead of per-driver. */ - for (i = 0; i < DEV_NUMBUFFS; i++) - skb_queue_head_init(&dev->buffs[i]); - - dev->hard_header = tr_header; - dev->rebuild_header = tr_rebuild_header; - - dev->type = ARPHRD_IEEE802; - dev->hard_header_len = TR_HLEN; - dev->mtu = 2000; /* bug in fragmenter...*/ - dev->addr_len = TR_ALEN; - dev->tx_queue_len = 100; /* Long queues on tr */ - - memset(dev->broadcast,0xFF, TR_ALEN); - - /* New-style flags. */ - dev->flags = IFF_BROADCAST; - dev->family = AF_INET; - dev->pa_addr = 0; - dev->pa_brdaddr = 0; - dev->pa_mask = 0; - dev->pa_alen = 4; -} - -#endif - -int ether_config(struct device *dev, struct ifmap *map) -{ - if (map->mem_start != (u_long)(-1)) - dev->mem_start = map->mem_start; - if (map->mem_end != (u_long)(-1)) - dev->mem_end = map->mem_end; - if (map->base_addr != (u_short)(-1)) - dev->base_addr = map->base_addr; - if (map->irq != (u_char)(-1)) - dev->irq = map->irq; - if (map->dma != (u_char)(-1)) - dev->dma = map->dma; - if (map->port != (u_char)(-1)) - dev->if_port = map->port; - return 0; -} - -int register_netdev(struct device *dev) -{ - struct device *d = dev_base; - unsigned long flags; - int i=MAX_ETH_CARDS; - - save_flags(flags); - cli(); - - if (dev && dev->init) { - if (dev->name && - ((dev->name[0] == '\0') || (dev->name[0] == ' '))) { - for (i = 0; i < MAX_ETH_CARDS; ++i) - if (ethdev_index[i] == NULL) { - sprintf(dev->name, "eth%d", i); - printk("loading device '%s'...\n", dev->name); - ethdev_index[i] = dev; - break; - } - } - - sti(); /* device probes assume interrupts enabled */ - if (dev->init(dev) != 0) { - if (i < MAX_ETH_CARDS) ethdev_index[i] = NULL; - restore_flags(flags); - return -EIO; - } - cli(); - - /* Add device to end of chain */ - if (dev_base) { - while (d->next) - d = d->next; - d->next = dev; - } - else - dev_base = dev; - dev->next = NULL; - } - restore_flags(flags); - return 0; -} - -void unregister_netdev(struct device *dev) -{ - struct device *d = dev_base; - unsigned long flags; - int i; - - save_flags(flags); - cli(); - - if (dev == NULL) - { - printk("was NULL\n"); - restore_flags(flags); - return; - } - /* else */ - if (dev->start) - printk("ERROR '%s' busy and not MOD_IN_USE.\n", dev->name); - - /* - * must jump over main_device+aliases - * avoid alias devices unregistration so that only - * net_alias module manages them - */ -#ifdef CONFIG_NET_ALIAS - if (dev_base == dev) - dev_base = net_alias_nextdev(dev); - else - { - while(d && (net_alias_nextdev(d) != dev)) /* skip aliases */ - d = net_alias_nextdev(d); - - if (d && (net_alias_nextdev(d) == dev)) - { - /* - * Critical: Bypass by consider devices as blocks (maindev+aliases) - */ - net_alias_nextdev_set(d, net_alias_nextdev(dev)); - } -#else - if (dev_base == dev) - dev_base = dev->next; - else - { - while (d && (d->next != dev)) - d = d->next; - - if (d && (d->next == dev)) - { - d->next = dev->next; - } -#endif - else - { - printk("unregister_netdev: '%s' not found\n", dev->name); - restore_flags(flags); - return; - } - } - for (i = 0; i < MAX_ETH_CARDS; ++i) - { - if (ethdev_index[i] == dev) - { - ethdev_index[i] = NULL; - break; - } - } - - restore_flags(flags); - - /* - * You can i.e use a interfaces in a route though it is not up. - * We call close_dev (which is changed: it will down a device even if - * dev->flags==0 (but it will not call dev->stop if IFF_UP - * is not set). - * This will call notifier_call_chain(&netdev_chain, NETDEV_DOWN, dev), - * dev_mc_discard(dev), .... - */ - - dev_close(dev); -} - - -/* - * Local variables: - * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c net_init.c" - * version-control: t - * kept-new-versions: 5 - * tab-width: 4 - * End: - */ diff --git a/i386/i386at/gpl/linux/net/ni52.c b/i386/i386at/gpl/linux/net/ni52.c deleted file mode 100644 index 13d12359..00000000 --- a/i386/i386at/gpl/linux/net/ni52.c +++ /dev/null @@ -1,1110 +0,0 @@ -/* - * net-3-driver for the NI5210 card (i82586 Ethernet chip) - * - * This is an extension to the Linux operating system, and is covered by the - * same Gnu Public License that covers that work. - * - * Alphacode 0.62 (95/01/19) for Linux 1.1.82 (or later) - * Copyrights (c) 1994,1995 by M.Hipp (Michael.Hipp@student.uni-tuebingen.de) - * [feel free to mail ....] - * - * CAN YOU PLEASE REPORT ME YOUR PERFORMANCE EXPERIENCES !!. - * - * If you find a bug, please report me: - * The kernel panic output and any kmsg from the ni52 driver - * the ni5210-driver-version and the linux-kernel version - * how many shared memory (memsize) on the netcard, - * bootprom: yes/no, base_addr, mem_start - * maybe the ni5210-card revision and the i82586 version - * - * autoprobe for: base_addr: 0x300,0x280,0x360,0x320,0x340 - * mem_start: 0xc8000,0xd0000,0xd4000,0xd8000 (8K and 16K) - * - * sources: - * skeleton.c from Donald Becker - * - * I have also done a look in the following sources: (mail me if you need them) - * crynwr-packet-driver by Russ Nelson - * Garret A. Wollman's (fourth) i82586-driver for BSD - * (before getting an i82596 (yes 596 not 586) manual, the existing drivers helped - * me a lot to understand this tricky chip.) - * - * Known Problems: - * The internal sysbus seems to be slow. So we often lose packets because of - * overruns while receiving from a fast remote host. - * This can slow down TCP connections. Maybe the newer ni5210 cards are better. - * - * IMPORTANT NOTE: - * On fast networks, it's a (very) good idea to have 16K shared memory. With - * 8K, we can store only 4 receive frames, so it can (easily) happen that a remote - * machine 'overruns' our system. - * - * Known i82586 bugs (I'm sure, there are many more!): - * Running the NOP-mode, the i82586 sometimes seems to forget to report - * every xmit-interrupt until we restart the CU. - * Another MAJOR bug is, that the RU sometimes seems to ignore the EL-Bit - * in the RBD-Struct which indicates an end of the RBD queue. - * Instead, the RU fetches another (randomly selected and - * usually used) RBD and begins to fill it. (Maybe, this happens only if - * the last buffer from the previous RFD fits exact into the queue and - * the next RFD can't fetch an initial RBD. Anyone knows more? ) - */ - -/* - * 18.Nov.95: Mcast changes (AC). - * - * 19.Jan.95: verified (MH) - * - * 19.Sep.94: Added Multicast support (not tested yet) (MH) - * - * 18.Sep.94: Workaround for 'EL-Bug'. Removed flexible RBD-handling. - * Now, every RFD has exact one RBD. (MH) - * - * 14.Sep.94: added promiscuous mode, a few cleanups (MH) - * - * 19.Aug.94: changed request_irq() parameter (MH) - * - * 20.July.94: removed cleanup bugs, removed a 16K-mem-probe-bug (MH) - * - * 19.July.94: lotsa cleanups .. (MH) - * - * 17.July.94: some patches ... verified to run with 1.1.29 (MH) - * - * 4.July.94: patches for Linux 1.1.24 (MH) - * - * 26.March.94: patches for Linux 1.0 and iomem-auto-probe (MH) - * - * 30.Sep.93: Added nop-chain .. driver now runs with only one Xmit-Buff, too (MH) - * - * < 30.Sep.93: first versions - */ - -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/string.h> -#include <linux/errno.h> -#include <linux/ioport.h> -#include <linux/malloc.h> -#include <linux/interrupt.h> -#include <linux/delay.h> -#include <asm/bitops.h> -#include <asm/io.h> - -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> - -#include "ni52.h" - -#define DEBUG /* debug on */ -#define SYSBUSVAL 1 /* 8 Bit */ - -#define ni_attn586() {outb(0,dev->base_addr+NI52_ATTENTION);} -#define ni_reset586() {outb(0,dev->base_addr+NI52_RESET);} - -#define make32(ptr16) (p->memtop + (short) (ptr16) ) -#define make24(ptr32) ((char *) (ptr32) - p->base) -#define make16(ptr32) ((unsigned short) ((unsigned long) (ptr32) - (unsigned long) p->memtop )) - -/******************* how to calculate the buffers ***************************** - - * IMPORTANT NOTE: if you configure only one NUM_XMIT_BUFFS, the driver works - * --------------- in a different (more stable?) mode. Only in this mode it's - * possible to configure the driver with 'NO_NOPCOMMANDS' - -sizeof(scp)=12; sizeof(scb)=16; sizeof(iscp)=8; -sizeof(scp)+sizeof(iscp)+sizeof(scb) = 36 = INIT -sizeof(rfd) = 24; sizeof(rbd) = 12; -sizeof(tbd) = 8; sizeof(transmit_cmd) = 16; -sizeof(nop_cmd) = 8; - - * if you don't know the driver, better do not change this values: */ - -#define RECV_BUFF_SIZE 1524 /* slightly oversized */ -#define XMIT_BUFF_SIZE 1524 /* slightly oversized */ -#define NUM_XMIT_BUFFS 1 /* config for both, 8K and 16K shmem */ -#define NUM_RECV_BUFFS_8 4 /* config for 8K shared mem */ -#define NUM_RECV_BUFFS_16 9 /* config for 16K shared mem */ -#define NO_NOPCOMMANDS /* only possible with NUM_XMIT_BUFFS=1 */ - -/**************************************************************************/ - -#define DELAY(x) {int i=jiffies; \ - if(loops_per_sec == 1) \ - while(i+(x)>jiffies); \ - else \ - __delay((loops_per_sec>>5)*x); \ - } - -/* a much shorter delay: */ -#define DELAY_16(); { __delay( (loops_per_sec>>16)+1 ); } - -/* wait for command with timeout: */ -#define WAIT_4_SCB_CMD() { int i; \ - for(i=0;i<1024;i++) { \ - if(!p->scb->cmd) break; \ - DELAY_16(); \ - if(i == 1023) { \ - printk("%s: scb_cmd timed out .. resetting i82586\n",dev->name); \ - ni_reset586(); } } } - - -#define NI52_TOTAL_SIZE 16 -#define NI52_ADDR0 0x02 -#define NI52_ADDR1 0x07 -#define NI52_ADDR2 0x01 - -#ifndef HAVE_PORTRESERVE -#define check_region(ioaddr, size) 0 -#define request_region(ioaddr, size,name) do ; while (0) -#endif - -static int ni52_probe1(struct device *dev,int ioaddr); -static void ni52_interrupt(int irq,struct pt_regs *reg_ptr); -static int ni52_open(struct device *dev); -static int ni52_close(struct device *dev); -static int ni52_send_packet(struct sk_buff *,struct device *); -static struct enet_statistics *ni52_get_stats(struct device *dev); -static void set_multicast_list(struct device *dev); - -/* helper-functions */ -static int init586(struct device *dev); -static int check586(struct device *dev,char *where,unsigned size); -static void alloc586(struct device *dev); -static void startrecv586(struct device *dev); -static void *alloc_rfa(struct device *dev,void *ptr); -static void ni52_rcv_int(struct device *dev); -static void ni52_xmt_int(struct device *dev); -static void ni52_rnr_int(struct device *dev); - -struct priv -{ - struct enet_statistics stats; - unsigned long base; - char *memtop; - volatile struct rfd_struct *rfd_last,*rfd_top,*rfd_first; - volatile struct scp_struct *scp; /* volatile is important */ - volatile struct iscp_struct *iscp; /* volatile is important */ - volatile struct scb_struct *scb; /* volatile is important */ - volatile struct tbd_struct *xmit_buffs[NUM_XMIT_BUFFS]; - volatile struct transmit_cmd_struct *xmit_cmds[NUM_XMIT_BUFFS]; -#if (NUM_XMIT_BUFFS == 1) - volatile struct nop_cmd_struct *nop_cmds[2]; -#else - volatile struct nop_cmd_struct *nop_cmds[NUM_XMIT_BUFFS]; -#endif - volatile int nop_point,num_recv_buffs; - volatile char *xmit_cbuffs[NUM_XMIT_BUFFS]; - volatile int xmit_count,xmit_last; -}; - - -/********************************************** - * close device - */ - -static int ni52_close(struct device *dev) -{ - free_irq(dev->irq); - irq2dev_map[dev->irq] = 0; - - ni_reset586(); /* the hard way to stop the receiver */ - - dev->start = 0; - dev->tbusy = 0; - - return 0; -} - -/********************************************** - * open device - */ - -static int ni52_open(struct device *dev) -{ - alloc586(dev); - init586(dev); - startrecv586(dev); - - if(request_irq(dev->irq, &ni52_interrupt,0,"ni52")) - { - ni_reset586(); - return -EAGAIN; - } - irq2dev_map[dev->irq] = dev; - - dev->interrupt = 0; - dev->tbusy = 0; - dev->start = 1; - - return 0; /* most done by init */ -} - -/********************************************** - * Check to see if there's an 82586 out there. - */ - -static int check586(struct device *dev,char *where,unsigned size) -{ - struct priv *p = (struct priv *) dev->priv; - char *iscp_addrs[2]; - int i; - - p->base = (unsigned long) where + size - 0x01000000; - p->memtop = where + size; - p->scp = (struct scp_struct *)(p->base + SCP_DEFAULT_ADDRESS); - memset((char *)p->scp,0, sizeof(struct scp_struct)); - p->scp->sysbus = SYSBUSVAL; /* 1 = 8Bit-Bus, 0 = 16 Bit */ - - iscp_addrs[0] = where; - iscp_addrs[1]= (char *) p->scp - sizeof(struct iscp_struct); - - for(i=0;i<2;i++) - { - p->iscp = (struct iscp_struct *) iscp_addrs[i]; - memset((char *)p->iscp,0, sizeof(struct iscp_struct)); - - p->scp->iscp = make24(p->iscp); - p->iscp->busy = 1; - - ni_reset586(); - ni_attn586(); - DELAY(2); /* wait a while... */ - - if(p->iscp->busy) /* i82586 clears 'busy' after successful init */ - return 0; - } - return 1; -} - -/****************************************************************** - * set iscp at the right place, called by ni52_probe1 and open586. - */ - -void alloc586(struct device *dev) -{ - struct priv *p = (struct priv *) dev->priv; - - ni_reset586(); - DELAY(2); - - p->scp = (struct scp_struct *) (p->base + SCP_DEFAULT_ADDRESS); - p->scb = (struct scb_struct *) (dev->mem_start); - p->iscp = (struct iscp_struct *) ((char *)p->scp - sizeof(struct iscp_struct)); - - memset((char *) p->iscp,0,sizeof(struct iscp_struct)); - memset((char *) p->scp ,0,sizeof(struct scp_struct)); - - p->scp->iscp = make24(p->iscp); - p->scp->sysbus = SYSBUSVAL; - p->iscp->scb_offset = make16(p->scb); - - p->iscp->busy = 1; - ni_reset586(); - ni_attn586(); - - DELAY(2); - - if(p->iscp->busy) - printk("%s: Init-Problems (alloc).\n",dev->name); - - memset((char *)p->scb,0,sizeof(struct scb_struct)); -} - -/********************************************** - * probe the ni5210-card - */ - -int ni52_probe(struct device *dev) -{ - int *port, ports[] = {0x300, 0x280, 0x360 , 0x320 , 0x340, 0}; - int base_addr = dev->base_addr; - - if (base_addr > 0x1ff) /* Check a single specified location. */ - if( (inb(base_addr+NI52_MAGIC1) == NI52_MAGICVAL1) && - (inb(base_addr+NI52_MAGIC2) == NI52_MAGICVAL2)) - return ni52_probe1(dev, base_addr); - else if (base_addr > 0) /* Don't probe at all. */ - return ENXIO; - - for (port = ports; *port; port++) { - int ioaddr = *port; - if (check_region(ioaddr, NI52_TOTAL_SIZE)) - continue; - if( !(inb(ioaddr+NI52_MAGIC1) == NI52_MAGICVAL1) || - !(inb(ioaddr+NI52_MAGIC2) == NI52_MAGICVAL2)) - continue; - - dev->base_addr = ioaddr; - if (ni52_probe1(dev, ioaddr) == 0) - return 0; - } - - dev->base_addr = base_addr; - return ENODEV; -} - -static int ni52_probe1(struct device *dev,int ioaddr) -{ - long memaddrs[] = { 0xd0000,0xd2000,0xc8000,0xca000,0xd4000,0xd6000,0xd8000, 0 }; - int i,size; - - for(i=0;i<ETH_ALEN;i++) - dev->dev_addr[i] = inb(dev->base_addr+i); - - if(dev->dev_addr[0] != NI52_ADDR0 || dev->dev_addr[1] != NI52_ADDR1 - || dev->dev_addr[2] != NI52_ADDR2) - return ENODEV; - - printk("%s: Ni52 found at %#3lx, ",dev->name,dev->base_addr); - - request_region(ioaddr,NI52_TOTAL_SIZE,"ni52"); - - dev->priv = (void *) kmalloc(sizeof(struct priv),GFP_KERNEL); - /* warning: we don't free it on errors */ - if (dev->priv == NULL) - return -ENOMEM; - memset((char *) dev->priv,0,sizeof(struct priv)); - - /* - * check (or search) IO-Memory, 8K and 16K - */ - if(dev->mem_start != 0) /* no auto-mem-probe */ - { - size = 0x4000; /* check for 16K mem */ - if(!check586(dev,(char *) dev->mem_start,size)) { - size = 0x2000; /* check for 8K mem */ - if(!check586(dev,(char *) dev->mem_start,size)) { - printk("?memprobe, Can't find memory at 0x%lx!\n",dev->mem_start); - return ENODEV; - } - } - } - else - { - for(i=0;;i++) - { - if(!memaddrs[i]) { - printk("?memprobe, Can't find io-memory!\n"); - return ENODEV; - } - dev->mem_start = memaddrs[i]; - size = 0x2000; /* check for 8K mem */ - if(check586(dev,(char *)dev->mem_start,size)) /* 8K-check */ - break; - size = 0x4000; /* check for 16K mem */ - if(check586(dev,(char *)dev->mem_start,size)) /* 16K-check */ - break; - } - } - dev->mem_end = dev->mem_start + size; /* set mem_end showed by 'ifconfig' */ - - ((struct priv *) (dev->priv))->base = dev->mem_start + size - 0x01000000; - alloc586(dev); - - /* set number of receive-buffs according to memsize */ - if(size == 0x2000) - ((struct priv *) dev->priv)->num_recv_buffs = NUM_RECV_BUFFS_8; - else - ((struct priv *) dev->priv)->num_recv_buffs = NUM_RECV_BUFFS_16; - - printk("Memaddr: 0x%lx, Memsize: %d, ",dev->mem_start,size); - - if(dev->irq < 2) - { - autoirq_setup(0); - ni_reset586(); - ni_attn586(); - if(!(dev->irq = autoirq_report(2))) - { - printk("?autoirq, Failed to detect IRQ line!\n"); - return 1; - } - } - else if(dev->irq == 2) - dev->irq = 9; - - printk("IRQ %d.\n",dev->irq); - - dev->open = &ni52_open; - dev->stop = &ni52_close; - dev->get_stats = &ni52_get_stats; - dev->hard_start_xmit = &ni52_send_packet; - dev->set_multicast_list = &set_multicast_list; - - dev->if_port = 0; - - ether_setup(dev); - - dev->tbusy = 0; - dev->interrupt = 0; - dev->start = 0; - - return 0; -} - -/********************************************** - * init the chip (ni52-interrupt should be disabled?!) - * needs a correct 'allocated' memory - */ - -static int init586(struct device *dev) -{ - void *ptr; - unsigned long s; - int i,result=0; - struct priv *p = (struct priv *) dev->priv; - volatile struct configure_cmd_struct *cfg_cmd; - volatile struct iasetup_cmd_struct *ias_cmd; - volatile struct tdr_cmd_struct *tdr_cmd; - volatile struct mcsetup_cmd_struct *mc_cmd; - struct dev_mc_list *dmi=dev->mc_list; - int num_addrs=dev->mc_count; - - ptr = (void *) ((char *)p->scb + sizeof(struct scb_struct)); - - cfg_cmd = (struct configure_cmd_struct *)ptr; /* configure-command */ - cfg_cmd->cmd_status = 0; - cfg_cmd->cmd_cmd = CMD_CONFIGURE | CMD_LAST; - cfg_cmd->cmd_link = 0xffff; - - cfg_cmd->byte_cnt = 0x0a; /* number of cfg bytes */ - cfg_cmd->fifo = 0x08; /* fifo-limit (8=tx:32/rx:64) */ - cfg_cmd->sav_bf = 0x40; /* hold or discard bad recv frames (bit 7) */ - cfg_cmd->adr_len = 0x2e; /* addr_len |!src_insert |pre-len |loopback */ - cfg_cmd->priority = 0x00; - cfg_cmd->ifs = 0x60; - cfg_cmd->time_low = 0x00; - cfg_cmd->time_high = 0xf2; - cfg_cmd->promisc = 0; - if(dev->flags&(IFF_ALLMULTI|IFF_PROMISC)) - { - cfg_cmd->promisc=1; - dev->flags|=IFF_PROMISC; - } - cfg_cmd->carr_coll = 0x00; - - p->scb->cbl_offset = make16(cfg_cmd); - - p->scb->cmd = CUC_START; /* cmd.-unit start */ - ni_attn586(); - - s = jiffies; /* warning: only active with interrupts on !! */ - while(!(cfg_cmd->cmd_status & STAT_COMPL)) - if(jiffies-s > 30) break; - - if((cfg_cmd->cmd_status & (STAT_OK|STAT_COMPL)) != (STAT_COMPL|STAT_OK)) - { - printk("%s (ni52): configure command failed: %x\n",dev->name,cfg_cmd->cmd_status); - return 1; - } - - /* - * individual address setup - */ - ias_cmd = (struct iasetup_cmd_struct *)ptr; - - ias_cmd->cmd_status = 0; - ias_cmd->cmd_cmd = CMD_IASETUP | CMD_LAST; - ias_cmd->cmd_link = 0xffff; - - memcpy((char *)&ias_cmd->iaddr,(char *) dev->dev_addr,ETH_ALEN); - - p->scb->cbl_offset = make16(ias_cmd); - - p->scb->cmd = CUC_START; /* cmd.-unit start */ - ni_attn586(); - - s = jiffies; - while(!(ias_cmd->cmd_status & STAT_COMPL)) - if(jiffies-s > 30) break; - - if((ias_cmd->cmd_status & (STAT_OK|STAT_COMPL)) != (STAT_OK|STAT_COMPL)) { - printk("%s (ni52): individual address setup command failed: %04x\n",dev->name,ias_cmd->cmd_status); - return 1; - } - - /* - * TDR, wire check .. e.g. no resistor e.t.c - */ - tdr_cmd = (struct tdr_cmd_struct *)ptr; - - tdr_cmd->cmd_status = 0; - tdr_cmd->cmd_cmd = CMD_TDR | CMD_LAST; - tdr_cmd->cmd_link = 0xffff; - tdr_cmd->status = 0; - - p->scb->cbl_offset = make16(tdr_cmd); - - p->scb->cmd = CUC_START; /* cmd.-unit start */ - ni_attn586(); - - s = jiffies; - while(!(tdr_cmd->cmd_status & STAT_COMPL)) - if(jiffies - s > 30) { - printk("%s: Problems while running the TDR.\n",dev->name); - result = 1; - } - - if(!result) - { - DELAY(2); /* wait for result */ - result = tdr_cmd->status; - - p->scb->cmd = p->scb->status & STAT_MASK; - ni_attn586(); /* ack the interrupts */ - - if(result & TDR_LNK_OK) ; - else if(result & TDR_XCVR_PRB) - printk("%s: TDR: Transceiver problem!\n",dev->name); - else if(result & TDR_ET_OPN) - printk("%s: TDR: No correct termination %d clocks away.\n",dev->name,result & TDR_TIMEMASK); - else if(result & TDR_ET_SRT) - { - if (result & TDR_TIMEMASK) /* time == 0 -> strange :-) */ - printk("%s: TDR: Detected a short circuit %d clocks away.\n",dev->name,result & TDR_TIMEMASK); - } - else - printk("%s: TDR: Unknown status %04x\n",dev->name,result); - } - - /* - * ack interrupts - */ - p->scb->cmd = p->scb->status & STAT_MASK; - ni_attn586(); - - /* - * alloc nop/xmit-cmds - */ -#if (NUM_XMIT_BUFFS == 1) - for(i=0;i<2;i++) - { - p->nop_cmds[i] = (struct nop_cmd_struct *)ptr; - p->nop_cmds[i]->cmd_cmd = CMD_NOP; - p->nop_cmds[i]->cmd_status = 0; - p->nop_cmds[i]->cmd_link = make16((p->nop_cmds[i])); - ptr = (char *) ptr + sizeof(struct nop_cmd_struct); - } - p->xmit_cmds[0] = (struct transmit_cmd_struct *)ptr; /* transmit cmd/buff 0 */ - ptr = (char *) ptr + sizeof(struct transmit_cmd_struct); -#else - for(i=0;i<NUM_XMIT_BUFFS;i++) - { - p->nop_cmds[i] = (struct nop_cmd_struct *)ptr; - p->nop_cmds[i]->cmd_cmd = CMD_NOP; - p->nop_cmds[i]->cmd_status = 0; - p->nop_cmds[i]->cmd_link = make16((p->nop_cmds[i])); - ptr = (char *) ptr + sizeof(struct nop_cmd_struct); - p->xmit_cmds[i] = (struct transmit_cmd_struct *)ptr; /*transmit cmd/buff 0*/ - ptr = (char *) ptr + sizeof(struct transmit_cmd_struct); - } -#endif - - ptr = alloc_rfa(dev,(void *)ptr); /* init receive-frame-area */ - - /* - * Multicast setup - */ - - if(dev->mc_count) - { /* I don't understand this: do we really need memory after the init? */ - int len = ((char *) p->iscp - (char *) ptr - 8) / 6; - if(len <= 0) - { - printk("%s: Ooooops, no memory for MC-Setup!\n",dev->name); - } - else - { - if(len < num_addrs) - { - /* BUG - should go ALLMULTI in this case */ - num_addrs = len; - printk("%s: Sorry, can only apply %d MC-Address(es).\n",dev->name,num_addrs); - } - mc_cmd = (struct mcsetup_cmd_struct *) ptr; - mc_cmd->cmd_status = 0; - mc_cmd->cmd_cmd = CMD_MCSETUP | CMD_LAST; - mc_cmd->cmd_link = 0xffff; - mc_cmd->mc_cnt = num_addrs * 6; - for(i=0;i<num_addrs;i++) - { - memcpy((char *) mc_cmd->mc_list[i], dmi->dmi_addr,6); - dmi=dmi->next; - } - p->scb->cbl_offset = make16(mc_cmd); - p->scb->cmd = CUC_START; - ni_attn586(); - s = jiffies; - while(!(mc_cmd->cmd_status & STAT_COMPL)) - if(jiffies - s > 30) - break; - if(!(mc_cmd->cmd_status & STAT_COMPL)) - printk("%s: Can't apply multicast-address-list.\n",dev->name); - } - } - - /* - * alloc xmit-buffs / init xmit_cmds - */ - for(i=0;i<NUM_XMIT_BUFFS;i++) - { - p->xmit_cbuffs[i] = (char *)ptr; /* char-buffs */ - ptr = (char *) ptr + XMIT_BUFF_SIZE; - p->xmit_buffs[i] = (struct tbd_struct *)ptr; /* TBD */ - ptr = (char *) ptr + sizeof(struct tbd_struct); - if((void *)ptr > (void *)p->iscp) - { - printk("%s: not enough shared-mem for your configuration!\n",dev->name); - return 1; - } - memset((char *)(p->xmit_cmds[i]) ,0, sizeof(struct transmit_cmd_struct)); - memset((char *)(p->xmit_buffs[i]),0, sizeof(struct tbd_struct)); - p->xmit_cmds[i]->cmd_status = STAT_COMPL; - p->xmit_cmds[i]->cmd_cmd = CMD_XMIT | CMD_INT; - p->xmit_cmds[i]->tbd_offset = make16((p->xmit_buffs[i])); - p->xmit_buffs[i]->next = 0xffff; - p->xmit_buffs[i]->buffer = make24((p->xmit_cbuffs[i])); - } - - p->xmit_count = 0; - p->xmit_last = 0; -#ifndef NO_NOPCOMMANDS - p->nop_point = 0; -#endif - - /* - * 'start transmitter' (nop-loop) - */ -#ifndef NO_NOPCOMMANDS - p->scb->cbl_offset = make16(p->nop_cmds[0]); - p->scb->cmd = CUC_START; - ni_attn586(); - WAIT_4_SCB_CMD(); -#else - p->xmit_cmds[0]->cmd_link = 0xffff; - p->xmit_cmds[0]->cmd_cmd = CMD_XMIT | CMD_LAST | CMD_INT; -#endif - - return 0; -} - -/****************************************************** - * This is a helper routine for ni52_rnr_int() and init586(). - * It sets up the Receive Frame Area (RFA). - */ - -static void *alloc_rfa(struct device *dev,void *ptr) -{ - volatile struct rfd_struct *rfd = (struct rfd_struct *)ptr; - volatile struct rbd_struct *rbd; - int i; - struct priv *p = (struct priv *) dev->priv; - - memset((char *) rfd,0,sizeof(struct rfd_struct)*p->num_recv_buffs); - p->rfd_first = rfd; - - for(i = 0; i < p->num_recv_buffs; i++) - rfd[i].next = make16(rfd + (i+1) % p->num_recv_buffs); - rfd[p->num_recv_buffs-1].last = RFD_SUSP; /* RU suspend */ - - ptr = (void *) (rfd + p->num_recv_buffs); - - rbd = (struct rbd_struct *) ptr; - ptr = (void *) (rbd + p->num_recv_buffs); - - /* clr descriptors */ - memset((char *) rbd,0,sizeof(struct rbd_struct)*p->num_recv_buffs); - - for(i=0;i<p->num_recv_buffs;i++) - { - rbd[i].next = make16((rbd + (i+1) % p->num_recv_buffs)); - rbd[i].size = RECV_BUFF_SIZE; - rbd[i].buffer = make24(ptr); - ptr = (char *) ptr + RECV_BUFF_SIZE; - } - - p->rfd_top = p->rfd_first; - p->rfd_last = p->rfd_first + p->num_recv_buffs - 1; - - p->scb->rfa_offset = make16(p->rfd_first); - p->rfd_first->rbd_offset = make16(rbd); - - return ptr; -} - - -/************************************************** - * Interrupt Handler ... - */ - -static void ni52_interrupt(int irq,struct pt_regs *reg_ptr) -{ - struct device *dev = (struct device *) irq2dev_map[irq]; - unsigned short stat; - struct priv *p; - - if (dev == NULL) { - printk ("ni52-interrupt: irq %d for unknown device.\n",(int) -(((struct pt_regs *)reg_ptr)->orig_eax+2)); - return; - } - p = (struct priv *) dev->priv; - - dev->interrupt = 1; - - while((stat=p->scb->status & STAT_MASK)) - { - p->scb->cmd = stat; - ni_attn586(); /* ack inter. */ - - if(stat & STAT_CX) /* command with I-bit set complete */ - ni52_xmt_int(dev); - - if(stat & STAT_FR) /* received a frame */ - ni52_rcv_int(dev); - -#ifndef NO_NOPCOMMANDS - if(stat & STAT_CNA) /* CU went 'not ready' */ - { - if(dev->start) - printk("%s: oops! CU has left active state. stat: %04x/%04x.\n",dev->name,(int) stat,(int) p->scb->status); - } -#endif - - if(stat & STAT_RNR) /* RU went 'not ready' */ - { - if(p->scb->status & RU_SUSPEND) /* special case: RU_SUSPEND */ - { - WAIT_4_SCB_CMD(); - p->scb->cmd = RUC_RESUME; - ni_attn586(); - } - else - { - printk("%s: Receiver-Unit went 'NOT READY': %04x/%04x.\n",dev->name,(int) stat,(int) p->scb->status); - ni52_rnr_int(dev); - } - } - WAIT_4_SCB_CMD(); /* wait for ack. (ni52_xmt_int can be faster than ack!!) */ - if(p->scb->cmd) /* timed out? */ - break; - } - - dev->interrupt = 0; -} - -/******************************************************* - * receive-interrupt - */ - -static void ni52_rcv_int(struct device *dev) -{ - int status; - unsigned short totlen; - struct sk_buff *skb; - struct rbd_struct *rbd; - struct priv *p = (struct priv *) dev->priv; - - for(;(status = p->rfd_top->status) & STAT_COMPL;) - { - rbd = (struct rbd_struct *) make32(p->rfd_top->rbd_offset); - - if(status & STAT_OK) /* frame received without error? */ - { - if( (totlen = rbd->status) & RBD_LAST) /* the first and the last buffer? */ - { - totlen &= RBD_MASK; /* length of this frame */ - rbd->status = 0; - skb = (struct sk_buff *) dev_alloc_skb(totlen+2); - if(skb != NULL) - { - skb->dev = dev; - skb_reserve(skb,2); /* 16 byte alignment */ - memcpy(skb_put(skb,totlen),(char *) p->base+(unsigned long) rbd->buffer, totlen); - skb->protocol=eth_type_trans(skb,dev); - netif_rx(skb); - p->stats.rx_packets++; - } - else - p->stats.rx_dropped++; - } - else - { - printk("%s: received oversized frame.\n",dev->name); - p->stats.rx_dropped++; - } - } - else /* frame !(ok), only with 'save-bad-frames' */ - { - printk("%s: oops! rfd-error-status: %04x\n",dev->name,status); - p->stats.rx_errors++; - } - p->rfd_top->status = 0; - p->rfd_top->last = RFD_SUSP; - p->rfd_last->last = 0; /* delete RU_SUSP */ - p->rfd_last = p->rfd_top; - p->rfd_top = (struct rfd_struct *) make32(p->rfd_top->next); /* step to next RFD */ - } -} - -/********************************************************** - * handle 'Receiver went not ready'. - */ - -static void ni52_rnr_int(struct device *dev) -{ - struct priv *p = (struct priv *) dev->priv; - - p->stats.rx_errors++; - - WAIT_4_SCB_CMD(); /* wait for the last cmd */ - p->scb->cmd = RUC_ABORT; /* usually the RU is in the 'no resource'-state .. abort it now. */ - ni_attn586(); - WAIT_4_SCB_CMD(); /* wait for accept cmd. */ - - alloc_rfa(dev,(char *)p->rfd_first); - startrecv586(dev); /* restart RU */ - - printk("%s: Receive-Unit restarted. Status: %04x\n",dev->name,p->scb->status); - -} - -/********************************************************** - * handle xmit - interrupt - */ - -static void ni52_xmt_int(struct device *dev) -{ - int status; - struct priv *p = (struct priv *) dev->priv; - - status = p->xmit_cmds[p->xmit_last]->cmd_status; - if(!(status & STAT_COMPL)) - printk("%s: strange .. xmit-int without a 'COMPLETE'\n",dev->name); - - if(status & STAT_OK) - { - p->stats.tx_packets++; - p->stats.collisions += (status & TCMD_MAXCOLLMASK); - } - else - { - p->stats.tx_errors++; - if(status & TCMD_LATECOLL) { - printk("%s: late collision detected.\n",dev->name); - p->stats.collisions++; - } - else if(status & TCMD_NOCARRIER) { - p->stats.tx_carrier_errors++; - printk("%s: no carrier detected.\n",dev->name); - } - else if(status & TCMD_LOSTCTS) - printk("%s: loss of CTS detected.\n",dev->name); - else if(status & TCMD_UNDERRUN) { - p->stats.tx_fifo_errors++; - printk("%s: DMA underrun detected.\n",dev->name); - } - else if(status & TCMD_MAXCOLL) { - printk("%s: Max. collisions exceeded.\n",dev->name); - p->stats.collisions += 16; - } - } - -#if (NUM_XMIT_BUFFS != 1) - if( (++p->xmit_last) == NUM_XMIT_BUFFS) - p->xmit_last = 0; -#endif - - dev->tbusy = 0; - mark_bh(NET_BH); -} - -/*********************************************************** - * (re)start the receiver - */ - -static void startrecv586(struct device *dev) -{ - struct priv *p = (struct priv *) dev->priv; - - p->scb->rfa_offset = make16(p->rfd_first); - p->scb->cmd = RUC_START; - ni_attn586(); /* start cmd. */ - WAIT_4_SCB_CMD(); /* wait for accept cmd. (no timeout!!) */ -} - -/****************************************************** - * send frame - */ - -static int ni52_send_packet(struct sk_buff *skb, struct device *dev) -{ - int len,i; -#ifndef NO_NOPCOMMANDS - int next_nop; -#endif - struct priv *p = (struct priv *) dev->priv; - - if(dev->tbusy) - { - int tickssofar = jiffies - dev->trans_start; - if (tickssofar < 5) - return 1; - - if(p->scb->status & CU_ACTIVE) /* COMMAND-UNIT active? */ - { - dev->tbusy = 0; -#ifdef DEBUG - printk("%s: strange ... timeout with CU active?!?\n",dev->name); - printk("%s: X0: %04x N0: %04x N1: %04x %d\n",dev->name,(int)p->xmit_cmds[0]->cmd_status,(int)p->nop_cmds[0]->cmd_status,(int)p->nop_cmds[1]->cmd_status,(int)p->nop_point); -#endif - p->scb->cmd = CUC_ABORT; - ni_attn586(); - WAIT_4_SCB_CMD(); - p->scb->cbl_offset = make16(p->nop_cmds[p->nop_point]); - p->scb->cmd = CUC_START; - ni_attn586(); - WAIT_4_SCB_CMD(); - dev->trans_start = jiffies; - return 0; - } - else - { -#ifdef DEBUG - printk("%s: xmitter timed out, try to restart! stat: %04x\n",dev->name,p->scb->status); - printk("%s: command-stats: %04x %04x\n",dev->name,p->xmit_cmds[0]->cmd_status,p->xmit_cmds[1]->cmd_status); -#endif - ni52_close(dev); - ni52_open(dev); - } - dev->trans_start = jiffies; - return 0; - } - - if(skb == NULL) - { - dev_tint(dev); - return 0; - } - - if (skb->len <= 0) - return 0; - if(skb->len > XMIT_BUFF_SIZE) - { - printk("%s: Sorry, max. framelength is %d bytes. The length of your frame is %ld bytes.\n",dev->name,XMIT_BUFF_SIZE,skb->len); - return 0; - } - - if (set_bit(0, (void*)&dev->tbusy) != 0) - printk("%s: Transmitter access conflict.\n", dev->name); - else - { - memcpy((char *)p->xmit_cbuffs[p->xmit_count],(char *)(skb->data),skb->len); - len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN; - -#if (NUM_XMIT_BUFFS == 1) -# ifdef NO_NOPCOMMANDS - p->xmit_buffs[0]->size = TBD_LAST | len; - for(i=0;i<16;i++) - { - p->scb->cbl_offset = make16(p->xmit_cmds[0]); - p->scb->cmd = CUC_START; - p->xmit_cmds[0]->cmd_status = 0; - - ni_attn586(); - dev->trans_start = jiffies; - if(!i) - dev_kfree_skb(skb,FREE_WRITE); - WAIT_4_SCB_CMD(); - if( (p->scb->status & CU_ACTIVE)) /* test it, because CU sometimes doesn't start immediately */ - break; - if(p->xmit_cmds[0]->cmd_status) - break; - if(i==15) - printk("%s: Can't start transmit-command.\n",dev->name); - } -# else - next_nop = (p->nop_point + 1) & 0x1; - p->xmit_buffs[0]->size = TBD_LAST | len; - - p->xmit_cmds[0]->cmd_link = p->nop_cmds[next_nop]->cmd_link - = make16((p->nop_cmds[next_nop])); - p->xmit_cmds[0]->cmd_status = p->nop_cmds[next_nop]->cmd_status = 0; - - p->nop_cmds[p->nop_point]->cmd_link = make16((p->xmit_cmds[0])); - dev->trans_start = jiffies; - p->nop_point = next_nop; - dev_kfree_skb(skb,FREE_WRITE); -# endif -#else - p->xmit_buffs[p->xmit_count]->size = TBD_LAST | len; - if( (next_nop = p->xmit_count + 1) == NUM_XMIT_BUFFS ) - next_nop = 0; - - p->xmit_cmds[p->xmit_count]->cmd_status = 0; - p->xmit_cmds[p->xmit_count]->cmd_link = p->nop_cmds[next_nop]->cmd_link - = make16((p->nop_cmds[next_nop])); - p->nop_cmds[next_nop]->cmd_status = 0; - - p->nop_cmds[p->xmit_count]->cmd_link = make16((p->xmit_cmds[p->xmit_count])); - dev->trans_start = jiffies; - p->xmit_count = next_nop; - - cli(); - if(p->xmit_count != p->xmit_last) - dev->tbusy = 0; - sti(); - dev_kfree_skb(skb,FREE_WRITE); -#endif - } - return 0; -} - -/******************************************* - * Someone wanna have the statistics - */ - -static struct enet_statistics *ni52_get_stats(struct device *dev) -{ - struct priv *p = (struct priv *) dev->priv; - unsigned short crc,aln,rsc,ovrn; - - crc = p->scb->crc_errs; /* get error-statistic from the ni82586 */ - p->scb->crc_errs -= crc; - aln = p->scb->aln_errs; - p->scb->aln_errs -= aln; - rsc = p->scb->rsc_errs; - p->scb->rsc_errs -= rsc; - ovrn = p->scb->ovrn_errs; - p->scb->ovrn_errs -= ovrn; - - p->stats.rx_crc_errors += crc; - p->stats.rx_fifo_errors += ovrn; - p->stats.rx_frame_errors += aln; - p->stats.rx_dropped += rsc; - - return &p->stats; -} - -/******************************************************** - * Set MC list .. - */ - -static void set_multicast_list(struct device *dev) -{ - if(!dev->start) - { - printk("%s: Can't apply promiscuous/multicastmode to a not running interface.\n",dev->name); - return; - } - - dev->start = 0; - alloc586(dev); - init586(dev); - startrecv586(dev); - dev->start = 1; -} - -/* - * END: linux/drivers/net/ni52.c - */ diff --git a/i386/i386at/gpl/linux/net/ni52.h b/i386/i386at/gpl/linux/net/ni52.h deleted file mode 100644 index 23b0a0e8..00000000 --- a/i386/i386at/gpl/linux/net/ni52.h +++ /dev/null @@ -1,284 +0,0 @@ -/* - * Intel i82586 Ethernet definitions - * - * This is an extension to the Linux operating system, and is covered by the - * same Gnu Public License that covers that work. - * - * copyrights (c) 1994 by Michael Hipp (mhipp@student.uni-tuebingen.de) - * - * I have done a look in the following sources: - * crynwr-packet-driver by Russ Nelson - * Garret A. Wollman's i82586-driver for BSD - */ - - -#define NI52_RESET 0 /* writing to this address, resets the i82586 */ -#define NI52_ATTENTION 1 /* channel attention, kick the 586 */ -#define NI52_TENA 3 /* 2-5 possibly wrong, Xmit enable */ -#define NI52_TDIS 2 /* Xmit disable */ -#define NI52_INTENA 5 /* Interrupt enable */ -#define NI52_INTDIS 4 /* Interrupt disable */ -#define NI52_MAGIC1 6 /* dunno exact function */ -#define NI52_MAGIC2 7 /* dunno exact function */ - -#define NI52_MAGICVAL1 0x00 /* magic-values for ni5210 card */ -#define NI52_MAGICVAL2 0x55 - -/* - * where to find the System Configuration Pointer (SCP) - */ -#define SCP_DEFAULT_ADDRESS 0xfffff4 - - -/* - * System Configuration Pointer Struct - */ - -struct scp_struct -{ - unsigned short zero_dum0; /* has to be zero */ - unsigned char sysbus; /* 0=16Bit,1=8Bit */ - unsigned char zero_dum1; /* has to be zero for 586 */ - unsigned short zero_dum2; - unsigned short zero_dum3; - char *iscp; /* pointer to the iscp-block */ -}; - - -/* - * Intermediate System Configuration Pointer (ISCP) - */ -struct iscp_struct -{ - unsigned char busy; /* 586 clears after successful init */ - unsigned char zero_dummy; /* hast to be zero */ - unsigned short scb_offset; /* pointeroffset to the scb_base */ - char *scb_base; /* base-address of all 16-bit offsets */ -}; - -/* - * System Control Block (SCB) - */ -struct scb_struct -{ - unsigned short status; /* status word */ - unsigned short cmd; /* command word */ - unsigned short cbl_offset; /* pointeroffset, command block list */ - unsigned short rfa_offset; /* pointeroffset, receive frame area */ - unsigned short crc_errs; /* CRC-Error counter */ - unsigned short aln_errs; /* allignmenterror counter */ - unsigned short rsc_errs; /* Resourceerror counter */ - unsigned short ovrn_errs; /* OVerrunerror counter */ -}; - -/* - * possible command values for the command word - */ -#define RUC_MASK 0x0070 /* mask for RU commands */ -#define RUC_NOP 0x0000 /* NOP-command */ -#define RUC_START 0x0010 /* start RU */ -#define RUC_RESUME 0x0020 /* resume RU after suspend */ -#define RUC_SUSPEND 0x0030 /* suspend RU */ -#define RUC_ABORT 0x0040 /* abort receiver operation immediately */ - -#define CUC_MASK 0x0700 /* mask for CU command */ -#define CUC_NOP 0x0000 /* NOP-command */ -#define CUC_START 0x0100 /* start execution of 1. cmd on the CBL */ -#define CUC_RESUME 0x0200 /* resume after suspend */ -#define CUC_SUSPEND 0x0300 /* Suspend CU */ -#define CUC_ABORT 0x0400 /* abort command operation immediately */ - -#define ACK_MASK 0xf000 /* mask for ACK command */ -#define ACK_CX 0x8000 /* acknowledges STAT_CX */ -#define ACK_FR 0x4000 /* ack. STAT_FR */ -#define ACK_CNA 0x2000 /* ack. STAT_CNA */ -#define ACK_RNR 0x1000 /* ack. STAT_RNR */ - -/* - * possible status values for the status word - */ -#define STAT_MASK 0xf000 /* mask for cause of interrupt */ -#define STAT_CX 0x8000 /* CU finished cmd with its I bit set */ -#define STAT_FR 0x4000 /* RU finished receiving a frame */ -#define STAT_CNA 0x2000 /* CU left active state */ -#define STAT_RNR 0x1000 /* RU left ready state */ - -#define CU_STATUS 0x700 /* CU status, 0=idle */ -#define CU_SUSPEND 0x100 /* CU is suspended */ -#define CU_ACTIVE 0x200 /* CU is active */ - -#define RU_STATUS 0x70 /* RU status, 0=idle */ -#define RU_SUSPEND 0x10 /* RU suspended */ -#define RU_NOSPACE 0x20 /* RU no resources */ -#define RU_READY 0x40 /* RU is ready */ - -/* - * Receive Frame Descriptor (RFD) - */ -struct rfd_struct -{ - unsigned short status; /* status word */ - unsigned short last; /* Bit15,Last Frame on List / Bit14,suspend */ - unsigned short next; /* linkoffset to next RFD */ - unsigned short rbd_offset; /* pointeroffset to RBD-buffer */ - unsigned char dest[6]; /* ethernet-address, destination */ - unsigned char source[6]; /* ethernet-address, source */ - unsigned short length; /* 802.3 frame-length */ - unsigned short zero_dummy; /* dummy */ -}; - -#define RFD_LAST 0x8000 /* last: last rfd in the list */ -#define RFD_SUSP 0x4000 /* last: suspend RU after */ -#define RFD_ERRMASK 0x0fe1 /* status: errormask */ -#define RFD_MATCHADD 0x0002 /* status: Destinationaddress !matches IA */ -#define RFD_RNR 0x0200 /* status: receiver out of resources */ - -/* - * Receive Buffer Descriptor (RBD) - */ -struct rbd_struct -{ - unsigned short status; /* status word,number of used bytes in buff */ - unsigned short next; /* pointeroffset to next RBD */ - char *buffer; /* receive buffer address pointer */ - unsigned short size; /* size of this buffer */ - unsigned short zero_dummy; /* dummy */ -}; - -#define RBD_LAST 0x8000 /* last buffer */ -#define RBD_USED 0x4000 /* this buffer has data */ -#define RBD_MASK 0x3fff /* size-mask for length */ - -/* - * Statusvalues for Commands/RFD - */ -#define STAT_COMPL 0x8000 /* status: frame/command is complete */ -#define STAT_BUSY 0x4000 /* status: frame/command is busy */ -#define STAT_OK 0x2000 /* status: frame/command is ok */ - -/* - * Action-Commands - */ -#define CMD_NOP 0x0000 /* NOP */ -#define CMD_IASETUP 0x0001 /* initial address setup command */ -#define CMD_CONFIGURE 0x0002 /* configure command */ -#define CMD_MCSETUP 0x0003 /* MC setup command */ -#define CMD_XMIT 0x0004 /* transmit command */ -#define CMD_TDR 0x0005 /* time domain reflectometer (TDR) command */ -#define CMD_DUMP 0x0006 /* dump command */ -#define CMD_DIAGNOSE 0x0007 /* diagnose command */ - -/* - * Action command bits - */ -#define CMD_LAST 0x8000 /* indicates last command in the CBL */ -#define CMD_SUSPEND 0x4000 /* suspend CU after this CB */ -#define CMD_INT 0x2000 /* generate interrupt after execution */ - -/* - * NOP - command - */ -struct nop_cmd_struct -{ - unsigned short cmd_status; /* status of this command */ - unsigned short cmd_cmd; /* the command itself (+bits) */ - unsigned short cmd_link; /* offsetpointer to next command */ -}; - -/* - * IA Setup command - */ -struct iasetup_cmd_struct -{ - unsigned short cmd_status; - unsigned short cmd_cmd; - unsigned short cmd_link; - unsigned char iaddr[6]; -}; - -/* - * Configure command - */ -struct configure_cmd_struct -{ - unsigned short cmd_status; - unsigned short cmd_cmd; - unsigned short cmd_link; - unsigned char byte_cnt; /* size of the config-cmd */ - unsigned char fifo; /* fifo/recv monitor */ - unsigned char sav_bf; /* save bad frames (bit7=1)*/ - unsigned char adr_len; /* adr_len(0-2),al_loc(3),pream(4-5),loopbak(6-7)*/ - unsigned char priority; /* lin_prio(0-2),exp_prio(4-6),bof_metd(7) */ - unsigned char ifs; /* inter frame spacing */ - unsigned char time_low; /* slot time low */ - unsigned char time_high; /* slot time high(0-2) and max. retries(4-7) */ - unsigned char promisc; /* promisc-mode(0) , et al (1-7) */ - unsigned char carr_coll; /* carrier(0-3)/collision(4-7) stuff */ - unsigned char fram_len; /* minimal frame len */ - unsigned char dummy; /* dummy */ -}; - -/* - * Multicast Setup command - */ -struct mcsetup_cmd_struct -{ - unsigned short cmd_status; - unsigned short cmd_cmd; - unsigned short cmd_link; - unsigned short mc_cnt; /* number of bytes in the MC-List */ - unsigned char mc_list[0][6]; /* pointer to 6 bytes entries */ -}; - -/* - * transmit command - */ -struct transmit_cmd_struct -{ - unsigned short cmd_status; - unsigned short cmd_cmd; - unsigned short cmd_link; - unsigned short tbd_offset; /* pointeroffset to TBD */ - unsigned char dest[6]; /* destination address of the frame */ - unsigned short length; /* user defined: 802.3 length / Ether type */ -}; - -#define TCMD_ERRMASK 0x0fa0 -#define TCMD_MAXCOLLMASK 0x000f -#define TCMD_MAXCOLL 0x0020 -#define TCMD_HEARTBEAT 0x0040 -#define TCMD_DEFERRED 0x0080 -#define TCMD_UNDERRUN 0x0100 -#define TCMD_LOSTCTS 0x0200 -#define TCMD_NOCARRIER 0x0400 -#define TCMD_LATECOLL 0x0800 - -struct tdr_cmd_struct -{ - unsigned short cmd_status; - unsigned short cmd_cmd; - unsigned short cmd_link; - unsigned short status; -}; - -#define TDR_LNK_OK 0x8000 /* No link problem identified */ -#define TDR_XCVR_PRB 0x4000 /* indicates a transceiver problem */ -#define TDR_ET_OPN 0x2000 /* open, no correct termination */ -#define TDR_ET_SRT 0x1000 /* TDR detected a short circuit */ -#define TDR_TIMEMASK 0x07ff /* mask for the time field */ - -/* - * Transmit Buffer Descriptor (TBD) - */ -struct tbd_struct -{ - unsigned short size; /* size + EOF-Flag(15) */ - unsigned short next; /* pointeroffset to next TBD */ - char *buffer; /* pointer to buffer */ -}; - -#define TBD_LAST 0x8000 /* EOF-Flag, indicates last buffer in list */ - - - - diff --git a/i386/i386at/gpl/linux/net/ni65.c b/i386/i386at/gpl/linux/net/ni65.c deleted file mode 100644 index 44a58112..00000000 --- a/i386/i386at/gpl/linux/net/ni65.c +++ /dev/null @@ -1,648 +0,0 @@ -/* - * ni6510 (am7990 'lance' chip) driver for Linux-net-3 by MH - * Alphacode v0.33 (94/08/22) for 1.1.47 (or later) - * - * ---------------------------------------------------------- - * WARNING: DOESN'T WORK ON MACHINES WITH MORE THAN 16MB !!!! - * ---------------------------------------------------------- - * - * copyright (c) 1994 M.Hipp - * - * This is an extension to the Linux operating system, and is covered by the - * same Gnu Public License that covers the Linux-kernel. - * - * comments/bugs/suggestions can be sent to: - * Michael Hipp - * email: mhipp@student.uni-tuebingen.de - * - * sources: - * some things are from the 'ni6510-packet-driver for dos by Russ Nelson' - * and from the original drivers by D.Becker - */ - -/* - * Nov.18: multicast tweaked (AC). - * - * Aug.22: changes in xmit_intr (ack more than one xmitted-packet), ni65_send_packet (p->lock) (MH) - * - * July.16: fixed bugs in recv_skb and skb-alloc stuff (MH) - */ - -/* - * known BUGS: 16MB limit - */ - -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/string.h> -#include <linux/ptrace.h> -#include <linux/errno.h> -#include <linux/ioport.h> -#include <linux/malloc.h> -#include <linux/interrupt.h> -#include <asm/bitops.h> -#include <asm/io.h> -#include <asm/dma.h> - -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> - -#include "ni65.h" - -/************************************ - * skeleton-stuff - */ - -#ifndef HAVE_PORTRESERVE -#define check_region(ioaddr, size) 0 -#define request_region(ioaddr, size,name) do ; while (0) -#endif - -#ifndef NET_DEBUG -#define NET_DEBUG 2 -#endif -/* -static unsigned int net_debug = NET_DEBUG; -*/ - -#define NI65_TOTAL_SIZE 16 - -#define SA_ADDR0 0x02 -#define SA_ADDR1 0x07 -#define SA_ADDR2 0x01 -#define CARD_ID0 0x00 -#define CARD_ID1 0x55 - -/*****************************************/ - -#define PORT dev->base_addr - -#define RMDNUM 8 -#define RMDNUMMASK 0x6000 /* log2(RMDNUM)<<13 */ -#define TMDNUM 4 -#define TMDNUMMASK 0x4000 /* log2(TMDNUM)<<13 */ - -#define R_BUF_SIZE 1518 -#define T_BUF_SIZE 1518 - -#define MEMSIZE 8+RMDNUM*8+TMDNUM*8 - -#define L_DATAREG 0x00 -#define L_ADDRREG 0x02 - -#define L_RESET 0x04 -#define L_CONFIG 0x05 -#define L_EBASE 0x08 - -/* - * to access the am7990-regs, you have to write - * reg-number into L_ADDRREG, then you can access it using L_DATAREG - */ -#define CSR0 0x00 -#define CSR1 0x01 -#define CSR2 0x02 -#define CSR3 0x03 - -/* if you #define NO_STATIC the driver is faster but you will have (more) problems with >16MB memory */ -#undef NO_STATIC - -#define writereg(val,reg) {outw(reg,PORT+L_ADDRREG);inw(PORT+L_ADDRREG); \ - outw(val,PORT+L_DATAREG);inw(PORT+L_DATAREG);} -#define readreg(reg) (outw(reg,PORT+L_ADDRREG),inw(PORT+L_ADDRREG),\ - inw(PORT+L_DATAREG)) -#define writedatareg(val) {outw(val,PORT+L_DATAREG);inw(PORT+L_DATAREG);} - -static int ni65_probe1(struct device *dev,int); -static void ni65_interrupt(int irq, struct pt_regs *regs); - static void recv_intr(struct device *dev); - static void xmit_intr(struct device *dev); -static int ni65_open(struct device *dev); - static int am7990_reinit(struct device *dev); -static int ni65_send_packet(struct sk_buff *skb, struct device *dev); -static int ni65_close(struct device *dev); -static struct enet_statistics *ni65_get_stats(struct device *); - -static void set_multicast_list(struct device *dev); - -struct priv -{ - struct init_block ib; - void *memptr; - struct rmd *rmdhead; - struct tmd *tmdhead; - int rmdnum; - int tmdnum,tmdlast; - struct sk_buff *recv_skb[RMDNUM]; - void *tmdbufs[TMDNUM]; - int lock,xmit_queued; - struct enet_statistics stats; -}; - -int irqtab[] = { 9,12,15,5 }; /* irq config-translate */ -int dmatab[] = { 0,3,5,6 }; /* dma config-translate */ - -/* - * open (most done by init) - */ - -static int ni65_open(struct device *dev) -{ - if(am7990_reinit(dev)) - { - dev->tbusy = 0; - dev->interrupt = 0; - dev->start = 1; - return 0; - } - else - { - dev->start = 0; - return -EAGAIN; - } -} - -static int ni65_close(struct device *dev) -{ - outw(0,PORT+L_RESET); /* that's the hard way */ - dev->tbusy = 1; - dev->start = 0; - return 0; -} - -/* - * Probe The Card (not the lance-chip) - * and set hardaddress - */ - -int ni65_probe(struct device *dev) -{ - int *port, ports[] = {0x300,0x320,0x340,0x360, 0}; - int base_addr = dev->base_addr; - - if (base_addr > 0x1ff) /* Check a single specified location. */ - return ni65_probe1(dev, base_addr); - else if (base_addr > 0) /* Don't probe at all. */ - return ENXIO; - - for (port = ports; *port; port++) - { - int ioaddr = *port; - if (check_region(ioaddr, NI65_TOTAL_SIZE)) - continue; - if( !(inb(ioaddr+L_EBASE+6) == CARD_ID0) || - !(inb(ioaddr+L_EBASE+7) == CARD_ID1) ) - continue; - dev->base_addr = ioaddr; - if (ni65_probe1(dev, ioaddr) == 0) - return 0; - } - - dev->base_addr = base_addr; - return ENODEV; -} - - -static int ni65_probe1(struct device *dev,int ioaddr) -{ - int i; - unsigned char station_addr[6]; - struct priv *p; - - for(i=0;i<6;i++) - station_addr[i] = dev->dev_addr[i] = inb(PORT+L_EBASE+i); - - if(station_addr[0] != SA_ADDR0 || station_addr[1] != SA_ADDR1) - { - printk("%s: wrong Hardaddress \n",dev->name); - return ENODEV; - } - - if(dev->irq == 0) - dev->irq = irqtab[(inw(PORT+L_CONFIG)>>2)&3]; - if(dev->dma == 0) - dev->dma = dmatab[inw(PORT+L_CONFIG)&3]; - - printk("%s: %s found at %#3lx, IRQ %d DMA %d.\n", dev->name, - "network card", dev->base_addr, dev->irq,dev->dma); - - { - int irqval = request_irq(dev->irq, &ni65_interrupt,0,"ni65"); - if (irqval) { - printk ("%s: unable to get IRQ %d (irqval=%d).\n", - dev->name,dev->irq, irqval); - return EAGAIN; - } - if(request_dma(dev->dma, "ni65") != 0) - { - printk("%s: Can't request dma-channel %d\n",dev->name,(int) dev->dma); - free_irq(dev->irq); - return EAGAIN; - } - } - irq2dev_map[dev->irq] = dev; - - /* Grab the region so we can find another board if autoIRQ fails. */ - request_region(ioaddr,NI65_TOTAL_SIZE,"ni65"); - - p = dev->priv = (void *) kmalloc(sizeof(struct priv),GFP_KERNEL); - if (p == NULL) - return -ENOMEM; - memset((char *) dev->priv,0,sizeof(struct priv)); - - dev->open = ni65_open; - dev->stop = ni65_close; - dev->hard_start_xmit = ni65_send_packet; - dev->get_stats = ni65_get_stats; - dev->set_multicast_list = set_multicast_list; - - ether_setup(dev); - - dev->flags &= ~IFF_MULTICAST; - dev->interrupt = 0; - dev->tbusy = 0; - dev->start = 0; - - if( (p->memptr = kmalloc(MEMSIZE,GFP_KERNEL)) == NULL) { - printk("%s: Can't alloc TMD/RMD-buffer.\n",dev->name); - return EAGAIN; - } - if( (unsigned long) (p->memptr + MEMSIZE) & 0xff000000) { - printk("%s: Can't alloc TMD/RMD buffer in lower 16MB!\n",dev->name); - return EAGAIN; - } - p->tmdhead = (struct tmd *) ((( (unsigned long)p->memptr ) + 8) & 0xfffffff8); - p->rmdhead = (struct rmd *) (p->tmdhead + TMDNUM); - -#ifndef NO_STATIC - for(i=0;i<TMDNUM;i++) - { - if( (p->tmdbufs[i] = kmalloc(T_BUF_SIZE,GFP_ATOMIC)) == NULL) { - printk("%s: Can't alloc Xmit-Mem.\n",dev->name); - return EAGAIN; - } - if( (unsigned long) (p->tmdbufs[i]+T_BUF_SIZE) & 0xff000000) { - printk("%s: Can't alloc Xmit-Mem in lower 16MB!\n",dev->name); - return EAGAIN; - } - } -#endif - - for(i=0;i<RMDNUM;i++) - { - if( (p->recv_skb[i] = dev_alloc_skb(R_BUF_SIZE)) == NULL) { - printk("%s: unable to alloc recv-mem\n",dev->name); - return EAGAIN; - } - if( (unsigned long) (p->recv_skb[i]->data + R_BUF_SIZE) & 0xff000000) { - printk("%s: unable to alloc receive-memory in lower 16MB!\n",dev->name); - return EAGAIN; - } - } - - return 0; /* we've found everything */ -} - -/* - * init lance (write init-values .. init-buffers) (open-helper) - */ - -static int am7990_reinit(struct device *dev) -{ - int i,j; - struct tmd *tmdp; - struct rmd *rmdp; - struct priv *p = (struct priv *) dev->priv; - - p->lock = 0; - p->xmit_queued = 0; - - disable_dma(dev->dma); /* I've never worked with dma, but we do it like the packetdriver */ - set_dma_mode(dev->dma,DMA_MODE_CASCADE); - enable_dma(dev->dma); - - outw(0,PORT+L_RESET); /* first: reset the card */ - if(inw(PORT+L_DATAREG) != 0x4) - { - printk("%s: can't RESET ni6510 card: %04x\n",dev->name,(int) inw(PORT+L_DATAREG)); - disable_dma(dev->dma); - free_dma(dev->dma); - free_irq(dev->irq); - return 0; - } - - /* here: memset all buffs to zero */ - - memset(p->memptr,0,MEMSIZE); - - p->tmdnum = 0; p->tmdlast = 0; - for(i=0;i<TMDNUM;i++) - { - tmdp = p->tmdhead + i; -#ifndef NO_STATIC - tmdp->u.buffer = (unsigned long) p->tmdbufs[i]; -#endif - tmdp->u.s.status = XMIT_START | XMIT_END; - } - - p->rmdnum = 0; - for(i=0;i<RMDNUM;i++) - { - rmdp = p->rmdhead + i; - rmdp->u.buffer = (unsigned long) p->recv_skb[i]->data; - rmdp->u.s.status = RCV_OWN; - rmdp->blen = -R_BUF_SIZE; - rmdp->mlen = 0; - } - - for(i=0;i<6;i++) - { - p->ib.eaddr[i] = dev->dev_addr[i]; - } - p->ib.mode = 0; - for(i=0;i<8;i++) - p->ib.filter[i] = 0; - p->ib.trplow = (unsigned short) (( (unsigned long) p->tmdhead ) & 0xffff); - p->ib.trphigh = (unsigned short) ((( (unsigned long) p->tmdhead )>>16) & 0x00ff) | TMDNUMMASK; - p->ib.rrplow = (unsigned short) (( (unsigned long) p->rmdhead ) & 0xffff); - p->ib.rrphigh = (unsigned short) ((( (unsigned long) p->rmdhead )>>16) & 0x00ff) | RMDNUMMASK; - - writereg(0,CSR3); /* busmaster/no word-swap */ - writereg((unsigned short) (((unsigned long) &(p->ib)) & 0xffff),CSR1); - writereg((unsigned short) (((unsigned long) &(p->ib))>>16),CSR2); - - writereg(CSR0_INIT,CSR0); /* this changes L_ADDRREG to CSR0 */ - - /* - * NOW, WE NEVER WILL CHANGE THE L_ADDRREG, CSR0 IS ALWAYS SELECTED - */ - - for(i=0;i<5;i++) - { - for(j=0;j<2000000;j++); /* wait a while */ - if(inw(PORT+L_DATAREG) & CSR0_IDON) break; /* init ok ? */ - } - if(i == 5) - { - printk("%s: can't init am7990, status: %04x\n",dev->name,(int) inw(PORT+L_DATAREG)); - disable_dma(dev->dma); - free_dma(dev->dma); - free_irq(dev->irq); - return 0; /* false */ - } - - writedatareg(CSR0_CLRALL | CSR0_INEA | CSR0_STRT); /* start lance , enable interrupts */ - - return 1; /* OK */ -} - -/* - * interrupt handler - */ - -static void ni65_interrupt(int irq, struct pt_regs * regs) -{ - int csr0; - struct device *dev = (struct device *) irq2dev_map[irq]; - - if (dev == NULL) { - printk ("net_interrupt(): irq %d for unknown device.\n", irq); - return; - } - - csr0 = inw(PORT+L_DATAREG); - writedatareg(csr0 & CSR0_CLRALL); /* ack interrupts, disable int. */ - - dev->interrupt = 1; - - if(csr0 & CSR0_ERR) - { - struct priv *p = (struct priv *) dev->priv; - - if(csr0 & CSR0_BABL) - p->stats.tx_errors++; - if(csr0 & CSR0_MISS) - p->stats.rx_errors++; - } - - if(csr0 & CSR0_RINT) /* RECV-int? */ - { - recv_intr(dev); - } - if(csr0 & CSR0_TINT) /* XMIT-int? */ - { - xmit_intr(dev); - } - - writedatareg(CSR0_INEA); /* reenable inter. */ - dev->interrupt = 0; - - return; -} - -/* - * We have received an Xmit-Interrupt .. - * send a new packet if necessary - */ - -static void xmit_intr(struct device *dev) -{ - int tmdstat; - struct tmd *tmdp; - struct priv *p = (struct priv *) dev->priv; - -#ifdef NO_STATIC - struct sk_buff *skb; -#endif - - while(p->xmit_queued) - { - tmdp = p->tmdhead + p->tmdlast; - tmdstat = tmdp->u.s.status; - if(tmdstat & XMIT_OWN) - break; -#ifdef NO_STATIC - skb = (struct sk_buff *) p->tmdbufs[p->tmdlast]; - dev_kfree_skb(skb,FREE_WRITE); -#endif - - if(tmdstat & XMIT_ERR) - { - printk("%s: xmit-error: %04x %04x\n",dev->name,(int) tmdstat,(int) tmdp->status2); - if(tmdp->status2 & XMIT_TDRMASK) - printk("%s: tdr-problems (e.g. no resistor)\n",dev->name); - - /* checking some errors */ - if(tmdp->status2 & XMIT_RTRY) - p->stats.tx_aborted_errors++; - if(tmdp->status2 & XMIT_LCAR) - p->stats.tx_carrier_errors++; - p->stats.tx_errors++; - tmdp->status2 = 0; - } - else - p->stats.tx_packets++; - - p->tmdlast = (p->tmdlast + 1) & (TMDNUM-1); - if(p->tmdlast == p->tmdnum) - p->xmit_queued = 0; - } - - dev->tbusy = 0; - mark_bh(NET_BH); -} - -/* - * We have received a packet - */ - -static void recv_intr(struct device *dev) -{ - struct rmd *rmdp; - int rmdstat,len; - struct sk_buff *skb,*skb1; - struct priv *p = (struct priv *) dev->priv; - - rmdp = p->rmdhead + p->rmdnum; - while(!( (rmdstat = rmdp->u.s.status) & RCV_OWN)) - { - if( (rmdstat & (RCV_START | RCV_END)) != (RCV_START | RCV_END) ) /* is packet start & end? */ - { - if(rmdstat & RCV_START) - { - p->stats.rx_errors++; - p->stats.rx_length_errors++; - printk("%s: packet too long\n",dev->name); - } - rmdp->u.s.status = RCV_OWN; /* change owner */ - } - else if(rmdstat & RCV_ERR) - { - printk("%s: receive-error: %04x\n",dev->name,(int) rmdstat ); - p->stats.rx_errors++; - if(rmdstat & RCV_FRAM) p->stats.rx_frame_errors++; - if(rmdstat & RCV_OFLO) p->stats.rx_over_errors++; - if(rmdstat & RCV_CRC) p->stats.rx_crc_errors++; - rmdp->u.s.status = RCV_OWN; - printk("%s: lance-status: %04x\n",dev->name,(int) inw(PORT+L_DATAREG)); - } - else - { - len = (rmdp->mlen & 0x0fff) - 4; /* -4: ignore FCS */ - skb = dev_alloc_skb(R_BUF_SIZE); - if(skb != NULL) - { - if( (unsigned long) (skb->data + R_BUF_SIZE) & 0xff000000) { - memcpy(skb_put(skb,len),p->recv_skb[p->rmdnum]->data,len); - skb1 = skb; - } - else { - skb1 = p->recv_skb[p->rmdnum]; - p->recv_skb[p->rmdnum] = skb; - rmdp->u.buffer = (unsigned long) skb_put(skb1,len); - } - rmdp->u.s.status = RCV_OWN; - rmdp->mlen = 0; /* not necc ???? */ - skb1->dev = dev; - p->stats.rx_packets++; - skb1->protocol=eth_type_trans(skb1,dev); - netif_rx(skb1); - } - else - { - rmdp->u.s.status = RCV_OWN; - printk("%s: can't alloc new sk_buff\n",dev->name); - p->stats.rx_dropped++; - } - } - p->rmdnum++; p->rmdnum &= RMDNUM-1; - rmdp = p->rmdhead + p->rmdnum; - } -} - -/* - * kick xmitter .. - */ - -static int ni65_send_packet(struct sk_buff *skb, struct device *dev) -{ - struct priv *p = (struct priv *) dev->priv; - struct tmd *tmdp; - - if(dev->tbusy) - { - int tickssofar = jiffies - dev->trans_start; - if (tickssofar < 25) - return 1; - - printk("%s: xmitter timed out, try to restart!\n",dev->name); - am7990_reinit(dev); - dev->tbusy=0; - dev->trans_start = jiffies; - } - - if(skb == NULL) - { - dev_tint(dev); - return 0; - } - - if (skb->len <= 0) - return 0; - - if (set_bit(0, (void*)&dev->tbusy) != 0) - { - printk("%s: Transmitter access conflict.\n", dev->name); - return 1; - } - if(set_bit(0,(void*) &p->lock) != 0) - { - printk("%s: Queue was locked!\n",dev->name); - return 1; - } - - { - short len = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; - - tmdp = p->tmdhead + p->tmdnum; - -#ifdef NO_STATIC - tmdp->u.buffer = (unsigned long) (skb->data); - p->tmdbufs[p->tmdnum] = skb; -#else - memcpy((char *) (tmdp->u.buffer & 0x00ffffff),(char *)skb->data,skb->len); - dev_kfree_skb (skb, FREE_WRITE); -#endif - tmdp->blen = -len; - tmdp->u.s.status = XMIT_OWN | XMIT_START | XMIT_END; - - cli(); - p->xmit_queued = 1; - writedatareg(CSR0_TDMD | CSR0_INEA); /* enable xmit & interrupt */ - p->tmdnum++; p->tmdnum &= TMDNUM-1; - - if( !((p->tmdhead + p->tmdnum)->u.s.status & XMIT_OWN) ) - dev->tbusy = 0; - p->lock = 0; - sti(); - - dev->trans_start = jiffies; - - } - - return 0; -} - -static struct enet_statistics *ni65_get_stats(struct device *dev) -{ - return &((struct priv *) dev->priv)->stats; -} - -static void set_multicast_list(struct device *dev) -{ -} - -/* - * END of ni65.c - */ - diff --git a/i386/i386at/gpl/linux/net/ni65.h b/i386/i386at/gpl/linux/net/ni65.h deleted file mode 100644 index 144523fa..00000000 --- a/i386/i386at/gpl/linux/net/ni65.h +++ /dev/null @@ -1,130 +0,0 @@ -/* am7990 (lance) definitions - * - * This is a extension to the Linux operating system, and is covered by - * same Gnu Public License that covers that work. - * - * Michael Hipp - * email: mhipp@student.uni-tuebingen.de - * - * sources: (mail me or ask archie if you need them) - * crynwr-packet-driver - */ - -/* - * Control and Status Register 0 (CSR0) bit definitions - * (R=Readable) (W=Writeable) (S=Set on write) (C-Clear on write) - * - */ - -#define CSR0_ERR 0x8000 /* Error summary (R) */ -#define CSR0_BABL 0x4000 /* Babble transmitter timeout error (RC) */ -#define CSR0_CERR 0x2000 /* Collision Error (RC) */ -#define CSR0_MISS 0x1000 /* Missed packet (RC) */ -#define CSR0_MERR 0x0800 /* Memory Error (RC) */ -#define CSR0_RINT 0x0400 /* Receiver Interrupt (RC) */ -#define CSR0_TINT 0x0200 /* Transmit Interrupt (RC) */ -#define CSR0_IDON 0x0100 /* Initialization Done (RC) */ -#define CSR0_INTR 0x0080 /* Interrupt Flag (R) */ -#define CSR0_INEA 0x0040 /* Interrupt Enable (RW) */ -#define CSR0_RXON 0x0020 /* Receiver on (R) */ -#define CSR0_TXON 0x0010 /* Transmitter on (R) */ -#define CSR0_TDMD 0x0008 /* Transmit Demand (RS) */ -#define CSR0_STOP 0x0004 /* Stop (RS) */ -#define CSR0_STRT 0x0002 /* Start (RS) */ -#define CSR0_INIT 0x0001 /* Initialize (RS) */ - -#define CSR0_CLRALL 0x7f00 /* mask for all clearable bits */ -/* - * Initialization Block Mode operation Bit Definitions. - */ - -#define M_PROM 0x8000 /* Promiscuous Mode */ -#define M_INTL 0x0040 /* Internal Loopback */ -#define M_DRTY 0x0020 /* Disable Retry */ -#define M_COLL 0x0010 /* Force Collision */ -#define M_DTCR 0x0008 /* Disable Transmit CRC) */ -#define M_LOOP 0x0004 /* Loopback */ -#define M_DTX 0x0002 /* Disable the Transmitter */ -#define M_DRX 0x0001 /* Disable the Receiver */ - - -/* - * Receive message descriptor bit definitions. - */ - -#define RCV_OWN 0x80 /* owner bit 0 = host, 1 = lance */ -#define RCV_ERR 0x40 /* Error Summary */ -#define RCV_FRAM 0x20 /* Framing Error */ -#define RCV_OFLO 0x10 /* Overflow Error */ -#define RCV_CRC 0x08 /* CRC Error */ -#define RCV_BUF_ERR 0x04 /* Buffer Error */ -#define RCV_START 0x02 /* Start of Packet */ -#define RCV_END 0x01 /* End of Packet */ - - -/* - * Transmit message descriptor bit definitions. - */ - -#define XMIT_OWN 0x80 /* owner bit 0 = host, 1 = lance */ -#define XMIT_ERR 0x40 /* Error Summary */ -#define XMIT_RETRY 0x10 /* more the 1 retry needed to Xmit */ -#define XMIT_1_RETRY 0x08 /* one retry needed to Xmit */ -#define XMIT_DEF 0x04 /* Deferred */ -#define XMIT_START 0x02 /* Start of Packet */ -#define XMIT_END 0x01 /* End of Packet */ - -/* - * transmit status (2) (valid if XMIT_ERR == 1) - */ - -#define XMIT_RTRY 0x0200 /* Failed after 16 retransmissions */ -#define XMIT_LCAR 0x0400 /* Loss of Carrier */ -#define XMIT_LCOL 0x1000 /* Late collision */ -#define XMIT_RESERV 0x2000 /* Reserved */ -#define XMIT_UFLO 0x4000 /* Underflow (late memory) */ -#define XMIT_BUFF 0x8000 /* Buffering error (no ENP) */ -#define XMIT_TDRMASK 0x003f /* time-domain-reflectometer-value */ - -struct init_block -{ - unsigned short mode; - unsigned char eaddr[6]; - unsigned char filter[8]; - unsigned short rrplow; /* receive ring pointer (align 8) */ - unsigned short rrphigh; /* bit 13-15: number of rmd's (power of 2) */ - unsigned short trplow; /* transmit ring pointer (align 8) */ - unsigned short trphigh; /* bit 13-15: number of tmd's (power of 2) */ -}; - -struct rmd /* Receive Message Descriptor */ -{ - union - { - volatile unsigned long buffer; - struct - { - volatile unsigned char dummy[3]; - volatile unsigned char status; - } s; - } u; - short blen; - volatile unsigned short mlen; -}; - -struct tmd -{ - union - { - volatile unsigned long buffer; - struct - { - volatile unsigned char dummy[3]; - volatile unsigned char status; - } s; - } u; - unsigned short blen; - volatile unsigned short status2; -}; - - diff --git a/i386/i386at/gpl/linux/net/seeq8005.c b/i386/i386at/gpl/linux/net/seeq8005.c deleted file mode 100644 index 5799d80c..00000000 --- a/i386/i386at/gpl/linux/net/seeq8005.c +++ /dev/null @@ -1,760 +0,0 @@ -/* seeq8005.c: A network driver for linux. */ -/* - Based on skeleton.c, - Written 1993-94 by Donald Becker. - See the skeleton.c file for further copyright information. - - This software may be used and distributed according to the terms - of the GNU Public License, incorporated herein by reference. - - The author may be reached as hamish@zot.apana.org.au - - This file is a network device driver for the SEEQ 8005 chipset and - the Linux operating system. - -*/ - -static const char *version = - "seeq8005.c:v1.00 8/07/95 Hamish Coleman (hamish@zot.apana.org.au)\n"; - -/* - Sources: - SEEQ 8005 databook - - Version history: - 1.00 Public release. cosmetic changes (no warnings now) - 0.68 Turning per- packet,interrupt debug messages off - testing for release. - 0.67 timing problems/bad buffer reads seem to be fixed now - 0.63 *!@$ protocol=eth_type_trans -- now packets flow - 0.56 Send working - 0.48 Receive working -*/ - -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/types.h> -#include <linux/fcntl.h> -#include <linux/interrupt.h> -#include <linux/ptrace.h> -#include <linux/ioport.h> -#include <linux/in.h> -#include <linux/malloc.h> -#include <linux/string.h> -#include <asm/system.h> -#include <asm/bitops.h> -#include <asm/io.h> -#include <asm/dma.h> -#include <linux/errno.h> - -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> -#include "seeq8005.h" - -/* First, a few definitions that the brave might change. */ -/* A zero-terminated list of I/O addresses to be probed. */ -static unsigned int seeq8005_portlist[] = - { 0x300, 0x320, 0x340, 0x360, 0}; - -/* use 0 for production, 1 for verification, >2 for debug */ -#ifndef NET_DEBUG -#define NET_DEBUG 1 -#endif -static unsigned int net_debug = NET_DEBUG; - -/* Information that need to be kept for each board. */ -struct net_local { - struct enet_statistics stats; - unsigned short receive_ptr; /* What address in packet memory do we expect a recv_pkt_header? */ - long open_time; /* Useless example local info. */ -}; - -/* The station (ethernet) address prefix, used for IDing the board. */ -#define SA_ADDR0 0x00 -#define SA_ADDR1 0x80 -#define SA_ADDR2 0x4b - -/* Index to functions, as function prototypes. */ - -extern int seeq8005_probe(struct device *dev); - -static int seeq8005_probe1(struct device *dev, int ioaddr); -static int seeq8005_open(struct device *dev); -static int seeq8005_send_packet(struct sk_buff *skb, struct device *dev); -static void seeq8005_interrupt(int irq, struct pt_regs *regs); -static void seeq8005_rx(struct device *dev); -static int seeq8005_close(struct device *dev); -static struct enet_statistics *seeq8005_get_stats(struct device *dev); -static void set_multicast_list(struct device *dev); - -/* Example routines you must write ;->. */ -#define tx_done(dev) (inw(SEEQ_STATUS) & SEEQSTAT_TX_ON) -extern void hardware_send_packet(struct device *dev, char *buf, int length); -extern void seeq8005_init(struct device *dev, int startp); -inline void wait_for_buffer(struct device *dev); - - -/* Check for a network adaptor of this type, and return '0' iff one exists. - If dev->base_addr == 0, probe all likely locations. - If dev->base_addr == 1, always return failure. - If dev->base_addr == 2, allocate space for the device and return success - (detachable devices only). - */ -#ifdef HAVE_DEVLIST -/* Support for a alternate probe manager, which will eliminate the - boilerplate below. */ -struct netdev_entry seeq8005_drv = -{"seeq8005", seeq8005_probe1, SEEQ8005_IO_EXTENT, seeq8005_portlist}; -#else -int -seeq8005_probe(struct device *dev) -{ - int i; - int base_addr = dev ? dev->base_addr : 0; - - if (base_addr > 0x1ff) /* Check a single specified location. */ - return seeq8005_probe1(dev, base_addr); - else if (base_addr != 0) /* Don't probe at all. */ - return ENXIO; - - for (i = 0; seeq8005_portlist[i]; i++) { - int ioaddr = seeq8005_portlist[i]; - if (check_region(ioaddr, SEEQ8005_IO_EXTENT)) - continue; - if (seeq8005_probe1(dev, ioaddr) == 0) - return 0; - } - - return ENODEV; -} -#endif - -/* This is the real probe routine. Linux has a history of friendly device - probes on the ISA bus. A good device probes avoids doing writes, and - verifies that the correct device exists and functions. */ - -static int seeq8005_probe1(struct device *dev, int ioaddr) -{ - static unsigned version_printed = 0; - int i,j; - unsigned char SA_prom[32]; - int old_cfg1; - int old_cfg2; - int old_stat; - int old_dmaar; - int old_rear; - - if (net_debug>1) - printk("seeq8005: probing at 0x%x\n",ioaddr); - - old_stat = inw(SEEQ_STATUS); /* read status register */ - if (old_stat == 0xffff) - return ENODEV; /* assume that 0xffff == no device */ - if ( (old_stat & 0x1800) != 0x1800 ) { /* assume that unused bits are 1, as my manual says */ - if (net_debug>1) { - printk("seeq8005: reserved stat bits != 0x1800\n"); - printk(" == 0x%04x\n",old_stat); - } - return ENODEV; - } - - old_rear = inw(SEEQ_REA); - if (old_rear == 0xffff) { - outw(0,SEEQ_REA); - if (inw(SEEQ_REA) == 0xffff) { /* assume that 0xffff == no device */ - return ENODEV; - } - } else if ((old_rear & 0xff00) != 0xff00) { /* assume that unused bits are 1 */ - if (net_debug>1) { - printk("seeq8005: unused rear bits != 0xff00\n"); - printk(" == 0x%04x\n",old_rear); - } - return ENODEV; - } - - old_cfg2 = inw(SEEQ_CFG2); /* read CFG2 register */ - old_cfg1 = inw(SEEQ_CFG1); - old_dmaar = inw(SEEQ_DMAAR); - - if (net_debug>4) { - printk("seeq8005: stat = 0x%04x\n",old_stat); - printk("seeq8005: cfg1 = 0x%04x\n",old_cfg1); - printk("seeq8005: cfg2 = 0x%04x\n",old_cfg2); - printk("seeq8005: raer = 0x%04x\n",old_rear); - printk("seeq8005: dmaar= 0x%04x\n",old_dmaar); - } - - outw( SEEQCMD_FIFO_WRITE | SEEQCMD_SET_ALL_OFF, SEEQ_CMD); /* setup for reading PROM */ - outw( 0, SEEQ_DMAAR); /* set starting PROM address */ - outw( SEEQCFG1_BUFFER_PROM, SEEQ_CFG1); /* set buffer to look at PROM */ - - - j=0; - for(i=0; i <32; i++) { - j+= SA_prom[i] = inw(SEEQ_BUFFER) & 0xff; - } - -#if 0 - /* untested because I only have the one card */ - if ( (j&0xff) != 0 ) { /* checksum appears to be 8bit = 0 */ - if (net_debug>1) { /* check this before deciding that we have a card */ - printk("seeq8005: prom sum error\n"); - } - outw( old_stat, SEEQ_STATUS); - outw( old_dmaar, SEEQ_DMAAR); - outw( old_cfg1, SEEQ_CFG1); - return ENODEV; - } -#endif - - outw( SEEQCFG2_RESET, SEEQ_CFG2); /* reset the card */ - SLOW_DOWN_IO; /* have to wait 4us after a reset - should be fixed */ - SLOW_DOWN_IO; - SLOW_DOWN_IO; - SLOW_DOWN_IO; - outw( SEEQCMD_SET_ALL_OFF, SEEQ_CMD); - - if (net_debug) { - printk("seeq8005: prom sum = 0x%08x\n",j); - for(j=0; j<32; j+=16) { - printk("seeq8005: prom %02x: ",j); - for(i=0;i<16;i++) { - printk("%02x ",SA_prom[j|i]); - } - printk(" "); - for(i=0;i<16;i++) { - if ((SA_prom[j|i]>31)&&(SA_prom[j|i]<127)) { - printk("%c", SA_prom[j|i]); - } else { - printk(" "); - } - } - printk("\n"); - } - } - -#if 0 - /* - * testing the packet buffer memory doesnt work yet - * but all other buffer accesses do - * - fixing is not a priority - */ - if (net_debug>1) { /* test packet buffer memory */ - printk("seeq8005: testing packet buffer ... "); - outw( SEEQCFG1_BUFFER_BUFFER, SEEQ_CFG1); - outw( SEEQCMD_FIFO_WRITE | SEEQCMD_SET_ALL_OFF, SEEQ_CMD); - outw( 0 , SEEQ_DMAAR); - for(i=0;i<32768;i++) { - outw(0x5a5a, SEEQ_BUFFER); - } - j=jiffies+HZ; - while ( ((inw(SEEQ_STATUS) & SEEQSTAT_FIFO_EMPTY) != SEEQSTAT_FIFO_EMPTY) && jiffies < j ) - mb(); - outw( 0 , SEEQ_DMAAR); - while ( ((inw(SEEQ_STATUS) & SEEQSTAT_WINDOW_INT) != SEEQSTAT_WINDOW_INT) && jiffies < j+HZ) - mb(); - if ( (inw(SEEQ_STATUS) & SEEQSTAT_WINDOW_INT) == SEEQSTAT_WINDOW_INT) - outw( SEEQCMD_WINDOW_INT_ACK | (inw(SEEQ_STATUS)& SEEQCMD_INT_MASK), SEEQ_CMD); - outw( SEEQCMD_FIFO_READ | SEEQCMD_SET_ALL_OFF, SEEQ_CMD); - j=0; - for(i=0;i<32768;i++) { - if (inw(SEEQ_BUFFER) != 0x5a5a) - j++; - } - if (j) { - printk("%i\n",j); - } else { - printk("ok.\n"); - } - } -#endif - - /* Allocate a new 'dev' if needed. */ - if (dev == NULL) - dev = init_etherdev(0, sizeof(struct net_local)); - - if (net_debug && version_printed++ == 0) - printk(version); - - printk("%s: %s found at %#3x, ", dev->name, "seeq8005", ioaddr); - - /* Fill in the 'dev' fields. */ - dev->base_addr = ioaddr; - - /* Retrieve and print the ethernet address. */ - for (i = 0; i < 6; i++) - printk(" %2.2x", dev->dev_addr[i] = SA_prom[i+6]); - - if (dev->irq == 0xff) - ; /* Do nothing: a user-level program will set it. */ - else if (dev->irq < 2) { /* "Auto-IRQ" */ - autoirq_setup(0); - - outw( SEEQCMD_RX_INT_EN | SEEQCMD_SET_RX_ON | SEEQCMD_SET_RX_OFF, SEEQ_CMD ); - - dev->irq = autoirq_report(0); - - if (net_debug >= 2) - printk(" autoirq is %d\n", dev->irq); - } else if (dev->irq == 2) - /* Fixup for users that don't know that IRQ 2 is really IRQ 9, - * or don't know which one to set. - */ - dev->irq = 9; - -#if 0 - { - int irqval = request_irq(dev->irq, &seeq8005_interrupt, 0, "seeq8005"); - if (irqval) { - printk ("%s: unable to get IRQ %d (irqval=%d).\n", dev->name, - dev->irq, irqval); - return EAGAIN; - } - } -#endif - - /* Grab the region so we can find another board if autoIRQ fails. */ - request_region(ioaddr, SEEQ8005_IO_EXTENT,"seeq8005"); - - /* Initialize the device structure. */ - dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL); - if (dev->priv == NULL) - return -ENOMEM; - memset(dev->priv, 0, sizeof(struct net_local)); - - dev->open = seeq8005_open; - dev->stop = seeq8005_close; - dev->hard_start_xmit = seeq8005_send_packet; - dev->get_stats = seeq8005_get_stats; - dev->set_multicast_list = &set_multicast_list; - - /* Fill in the fields of the device structure with ethernet values. */ - ether_setup(dev); - - dev->flags &= ~IFF_MULTICAST; - - return 0; -} - - -/* Open/initialize the board. This is called (in the current kernel) - sometime after booting when the 'ifconfig' program is run. - - This routine should set everything up anew at each open, even - registers that "should" only need to be set once at boot, so that - there is non-reboot way to recover if something goes wrong. - */ -static int -seeq8005_open(struct device *dev) -{ - struct net_local *lp = (struct net_local *)dev->priv; - - { - int irqval = request_irq(dev->irq, &seeq8005_interrupt, 0, "seeq8005"); - if (irqval) { - printk ("%s: unable to get IRQ %d (irqval=%d).\n", dev->name, - dev->irq, irqval); - return EAGAIN; - } - } - irq2dev_map[dev->irq] = dev; - - /* Reset the hardware here. Don't forget to set the station address. */ - seeq8005_init(dev, 1); - - lp->open_time = jiffies; - - dev->tbusy = 0; - dev->interrupt = 0; - dev->start = 1; - return 0; -} - -static int -seeq8005_send_packet(struct sk_buff *skb, struct device *dev) -{ - int ioaddr = dev->base_addr; - - if (dev->tbusy) { - /* If we get here, some higher level has decided we are broken. - There should really be a "kick me" function call instead. */ - int tickssofar = jiffies - dev->trans_start; - if (tickssofar < 5) - return 1; - printk("%s: transmit timed out, %s?\n", dev->name, - tx_done(dev) ? "IRQ conflict" : "network cable problem"); - /* Try to restart the adaptor. */ - seeq8005_init(dev, 1); - dev->tbusy=0; - dev->trans_start = jiffies; - } - - /* If some higher layer thinks we've missed an tx-done interrupt - we are passed NULL. Caution: dev_tint() handles the cli()/sti() - itself. */ - if (skb == NULL) { - dev_tint(dev); - return 0; - } - - /* Block a timer-based transmit from overlapping. This could better be - done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ - if (set_bit(0, (void*)&dev->tbusy) != 0) - printk("%s: Transmitter access conflict.\n", dev->name); - else { - short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; - unsigned char *buf = skb->data; - - hardware_send_packet(dev, buf, length); - dev->trans_start = jiffies; - } - dev_kfree_skb (skb, FREE_WRITE); - - /* You might need to clean up and record Tx statistics here. */ - - return 0; -} - -/* The typical workload of the driver: - Handle the network interface interrupts. */ -static void -seeq8005_interrupt(int irq, struct pt_regs * regs) -{ - struct device *dev = (struct device *)(irq2dev_map[irq]); - struct net_local *lp; - int ioaddr, status, boguscount = 0; - - if (dev == NULL) { - printk ("net_interrupt(): irq %d for unknown device.\n", irq); - return; - } - - if (dev->interrupt) - printk ("%s: Re-entering the interrupt handler.\n", dev->name); - dev->interrupt = 1; - - ioaddr = dev->base_addr; - lp = (struct net_local *)dev->priv; - - status = inw(SEEQ_STATUS); - do { - if (net_debug >2) { - printk("%s: int, status=0x%04x\n",dev->name,status); - } - - if (status & SEEQSTAT_WINDOW_INT) { - outw( SEEQCMD_WINDOW_INT_ACK | (status & SEEQCMD_INT_MASK), SEEQ_CMD); - if (net_debug) { - printk("%s: window int!\n",dev->name); - } - } - if (status & SEEQSTAT_TX_INT) { - outw( SEEQCMD_TX_INT_ACK | (status & SEEQCMD_INT_MASK), SEEQ_CMD); - lp->stats.tx_packets++; - dev->tbusy = 0; - mark_bh(NET_BH); /* Inform upper layers. */ - } - if (status & SEEQSTAT_RX_INT) { - /* Got a packet(s). */ - seeq8005_rx(dev); - } - status = inw(SEEQ_STATUS); - } while ( (++boguscount < 10) && (status & SEEQSTAT_ANY_INT)) ; - - if(net_debug>2) { - printk("%s: eoi\n",dev->name); - } - dev->interrupt = 0; - return; -} - -/* We have a good packet(s), get it/them out of the buffers. */ -static void -seeq8005_rx(struct device *dev) -{ - struct net_local *lp = (struct net_local *)dev->priv; - int boguscount = 10; - int pkt_hdr; - int ioaddr = dev->base_addr; - - do { - int next_packet; - int pkt_len; - int i; - int status; - - status = inw(SEEQ_STATUS); - outw( lp->receive_ptr, SEEQ_DMAAR); - outw(SEEQCMD_FIFO_READ | SEEQCMD_RX_INT_ACK | (status & SEEQCMD_INT_MASK), SEEQ_CMD); - wait_for_buffer(dev); - next_packet = ntohs(inw(SEEQ_BUFFER)); - pkt_hdr = inw(SEEQ_BUFFER); - - if (net_debug>2) { - printk("%s: 0x%04x recv next=0x%04x, hdr=0x%04x\n",dev->name,lp->receive_ptr,next_packet,pkt_hdr); - } - - if ((next_packet == 0) || ((pkt_hdr & SEEQPKTH_CHAIN)==0)) { /* Read all the frames? */ - return; /* Done for now */ - } - - if ((pkt_hdr & SEEQPKTS_DONE)==0) - break; - - if (next_packet < lp->receive_ptr) { - pkt_len = (next_packet + 0x10000 - ((DEFAULT_TEA+1)<<8)) - lp->receive_ptr - 4; - } else { - pkt_len = next_packet - lp->receive_ptr - 4; - } - - if (next_packet < ((DEFAULT_TEA+1)<<8)) { /* is the next_packet address sane? */ - printk("%s: recv packet ring corrupt, resetting board\n",dev->name); - seeq8005_init(dev,1); - return; - } - - lp->receive_ptr = next_packet; - - if (net_debug>2) { - printk("%s: recv len=0x%04x\n",dev->name,pkt_len); - } - - if (pkt_hdr & SEEQPKTS_ANY_ERROR) { /* There was an error. */ - lp->stats.rx_errors++; - if (pkt_hdr & SEEQPKTS_SHORT) lp->stats.rx_frame_errors++; - if (pkt_hdr & SEEQPKTS_DRIB) lp->stats.rx_frame_errors++; - if (pkt_hdr & SEEQPKTS_OVERSIZE) lp->stats.rx_over_errors++; - if (pkt_hdr & SEEQPKTS_CRC_ERR) lp->stats.rx_crc_errors++; - /* skip over this packet */ - outw( SEEQCMD_FIFO_WRITE | SEEQCMD_DMA_INT_ACK | (status & SEEQCMD_INT_MASK), SEEQ_CMD); - outw( (lp->receive_ptr & 0xff00)>>8, SEEQ_REA); - } else { - /* Malloc up new buffer. */ - struct sk_buff *skb; - unsigned char *buf; - - skb = dev_alloc_skb(pkt_len); - if (skb == NULL) { - printk("%s: Memory squeeze, dropping packet.\n", dev->name); - lp->stats.rx_dropped++; - break; - } - skb->dev = dev; - skb_reserve(skb, 2); /* align data on 16 byte */ - buf = skb_put(skb,pkt_len); - - insw(SEEQ_BUFFER, buf, (pkt_len + 1) >> 1); - - if (net_debug>2) { - char * p = buf; - printk("%s: recv ",dev->name); - for(i=0;i<14;i++) { - printk("%02x ",*(p++)&0xff); - } - printk("\n"); - } - - skb->protocol=eth_type_trans(skb,dev); - netif_rx(skb); - lp->stats.rx_packets++; - } - } while ((--boguscount) && (pkt_hdr & SEEQPKTH_CHAIN)); - - /* If any worth-while packets have been received, netif_rx() - has done a mark_bh(NET_BH) for us and will work on them - when we get to the bottom-half routine. */ - return; -} - -/* The inverse routine to net_open(). */ -static int -seeq8005_close(struct device *dev) -{ - struct net_local *lp = (struct net_local *)dev->priv; - int ioaddr = dev->base_addr; - - lp->open_time = 0; - - dev->tbusy = 1; - dev->start = 0; - - /* Flush the Tx and disable Rx here. */ - outw( SEEQCMD_SET_ALL_OFF, SEEQ_CMD); - - free_irq(dev->irq); - - irq2dev_map[dev->irq] = 0; - - /* Update the statistics here. */ - - return 0; - -} - -/* Get the current statistics. This may be called with the card open or - closed. */ -static struct enet_statistics * -seeq8005_get_stats(struct device *dev) -{ - struct net_local *lp = (struct net_local *)dev->priv; - - return &lp->stats; -} - -/* Set or clear the multicast filter for this adaptor. - num_addrs == -1 Promiscuous mode, receive all packets - num_addrs == 0 Normal mode, clear multicast list - num_addrs > 0 Multicast mode, receive normal and MC packets, and do - best-effort filtering. - */ -static void -set_multicast_list(struct device *dev) -{ -/* - * I _could_ do upto 6 addresses here, but wont (yet?) - */ - -#if 0 - int ioaddr = dev->base_addr; -/* - * hmm, not even sure if my matching works _anyway_ - seem to be receiving - * _everything_ . . . - */ - - if (num_addrs) { /* Enable promiscuous mode */ - outw( (inw(SEEQ_CFG1) & ~SEEQCFG1_MATCH_MASK)| SEEQCFG1_MATCH_ALL, SEEQ_CFG1); - dev->flags|=IFF_PROMISC; - } else { /* Disable promiscuous mode, use normal mode */ - outw( (inw(SEEQ_CFG1) & ~SEEQCFG1_MATCH_MASK)| SEEQCFG1_MATCH_BROAD, SEEQ_CFG1); - } -#endif -} - -void seeq8005_init(struct device *dev, int startp) -{ - struct net_local *lp = (struct net_local *)dev->priv; - int ioaddr = dev->base_addr; - int i; - - outw(SEEQCFG2_RESET, SEEQ_CFG2); /* reset device */ - SLOW_DOWN_IO; /* have to wait 4us after a reset - should be fixed */ - SLOW_DOWN_IO; - SLOW_DOWN_IO; - SLOW_DOWN_IO; - - outw( SEEQCMD_FIFO_WRITE | SEEQCMD_SET_ALL_OFF, SEEQ_CMD); - outw( 0, SEEQ_DMAAR); /* load start address into both low and high byte */ -/* wait_for_buffer(dev); */ /* I think that you only need a wait for memory buffer */ - outw( SEEQCFG1_BUFFER_MAC0, SEEQ_CFG1); - - for(i=0;i<6;i++) { /* set Station address */ - outb(dev->dev_addr[i], SEEQ_BUFFER); - SLOW_DOWN_IO; - } - - outw( SEEQCFG1_BUFFER_TEA, SEEQ_CFG1); /* set xmit end area pointer to 16K */ - outb( DEFAULT_TEA, SEEQ_BUFFER); /* this gives us 16K of send buffer and 48K of recv buffer */ - - lp->receive_ptr = (DEFAULT_TEA+1)<<8; /* so we can find our packet_header */ - outw( lp->receive_ptr, SEEQ_RPR); /* Receive Pointer Register is set to recv buffer memory */ - - outw( 0x00ff, SEEQ_REA); /* Receive Area End */ - - if (net_debug>4) { - printk("%s: SA0 = ",dev->name); - - outw( SEEQCMD_FIFO_READ | SEEQCMD_SET_ALL_OFF, SEEQ_CMD); - outw( 0, SEEQ_DMAAR); - outw( SEEQCFG1_BUFFER_MAC0, SEEQ_CFG1); - - for(i=0;i<6;i++) { - printk("%02x ",inb(SEEQ_BUFFER)); - } - printk("\n"); - } - - outw( SEEQCFG1_MAC0_EN | SEEQCFG1_MATCH_BROAD | SEEQCFG1_BUFFER_BUFFER, SEEQ_CFG1); - outw( SEEQCFG2_AUTO_REA | SEEQCFG2_CTRLO, SEEQ_CFG2); - outw( SEEQCMD_SET_RX_ON | SEEQCMD_TX_INT_EN | SEEQCMD_RX_INT_EN, SEEQ_CMD); - - if (net_debug>4) { - int old_cfg1; - old_cfg1 = inw(SEEQ_CFG1); - printk("%s: stat = 0x%04x\n",dev->name,inw(SEEQ_STATUS)); - printk("%s: cfg1 = 0x%04x\n",dev->name,old_cfg1); - printk("%s: cfg2 = 0x%04x\n",dev->name,inw(SEEQ_CFG2)); - printk("%s: raer = 0x%04x\n",dev->name,inw(SEEQ_REA)); - printk("%s: dmaar= 0x%04x\n",dev->name,inw(SEEQ_DMAAR)); - - } -} - - -void hardware_send_packet(struct device * dev, char *buf, int length) -{ - int ioaddr = dev->base_addr; - int status = inw(SEEQ_STATUS); - int transmit_ptr = 0; - int tmp; - - if (net_debug>4) { - printk("%s: send 0x%04x\n",dev->name,length); - } - - /* Set FIFO to writemode and set packet-buffer address */ - outw( SEEQCMD_FIFO_WRITE | (status & SEEQCMD_INT_MASK), SEEQ_CMD); - outw( transmit_ptr, SEEQ_DMAAR); - - /* output SEEQ Packet header barfage */ - outw( htons(length + 4), SEEQ_BUFFER); - outw( SEEQPKTH_XMIT | SEEQPKTH_DATA_FOLLOWS | SEEQPKTH_XMIT_INT_EN, SEEQ_BUFFER ); - - /* blat the buffer */ - outsw( SEEQ_BUFFER, buf, (length +1) >> 1); - /* paranoia !! */ - outw( 0, SEEQ_BUFFER); - outw( 0, SEEQ_BUFFER); - - /* set address of start of transmit chain */ - outw( transmit_ptr, SEEQ_TPR); - - /* drain FIFO */ - tmp = jiffies; - while ( (((status=inw(SEEQ_STATUS)) & SEEQSTAT_FIFO_EMPTY) == 0) && (jiffies < tmp + HZ)) - mb(); - - /* doit ! */ - outw( SEEQCMD_WINDOW_INT_ACK | SEEQCMD_SET_TX_ON | (status & SEEQCMD_INT_MASK), SEEQ_CMD); - -} - - -/* - * wait_for_buffer - * - * This routine waits for the SEEQ chip to assert that the FIFO is ready - * by checking for a window interrupt, and then clearing it - */ -inline void wait_for_buffer(struct device * dev) -{ - int ioaddr = dev->base_addr; - int tmp; - int status; - - tmp = jiffies + HZ; - while ( ( ((status=inw(SEEQ_STATUS)) & SEEQSTAT_WINDOW_INT) != SEEQSTAT_WINDOW_INT) && jiffies < tmp) - mb(); - - if ( (status & SEEQSTAT_WINDOW_INT) == SEEQSTAT_WINDOW_INT) - outw( SEEQCMD_WINDOW_INT_ACK | (status & SEEQCMD_INT_MASK), SEEQ_CMD); -} - - -/* - * Local variables: - * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c skeleton.c" - * version-control: t - * kept-new-versions: 5 - * tab-width: 4 - * End: - */ diff --git a/i386/i386at/gpl/linux/net/seeq8005.h b/i386/i386at/gpl/linux/net/seeq8005.h deleted file mode 100644 index 7122340c..00000000 --- a/i386/i386at/gpl/linux/net/seeq8005.h +++ /dev/null @@ -1,156 +0,0 @@ -/* - * defines, etc for the seeq8005 - */ - -/* - * This file is distributed under GPL. - * - * This style and layout of this file is also copied - * from many of the other linux network device drivers. - */ - -/* The number of low I/O ports used by the ethercard. */ -#define SEEQ8005_IO_EXTENT 16 - -#define SEEQ_B (ioaddr) - -#define SEEQ_CMD (SEEQ_B) /* Write only */ -#define SEEQ_STATUS (SEEQ_B) /* Read only */ -#define SEEQ_CFG1 (SEEQ_B + 2) -#define SEEQ_CFG2 (SEEQ_B + 4) -#define SEEQ_REA (SEEQ_B + 6) /* Receive End Area Register */ -#define SEEQ_RPR (SEEQ_B + 10) /* Receive Pointer Register */ -#define SEEQ_TPR (SEEQ_B + 12) /* Transmit Pointer Register */ -#define SEEQ_DMAAR (SEEQ_B + 14) /* DMA Address Register */ -#define SEEQ_BUFFER (SEEQ_B + 8) /* Buffer Window Register */ - -#define DEFAULT_TEA (0x3f) - -#define SEEQCMD_DMA_INT_EN (0x0001) /* DMA Interrupt Enable */ -#define SEEQCMD_RX_INT_EN (0x0002) /* Receive Interrupt Enable */ -#define SEEQCMD_TX_INT_EN (0x0004) /* Transmit Interrupt Enable */ -#define SEEQCMD_WINDOW_INT_EN (0x0008) /* What the hell is this for?? */ -#define SEEQCMD_INT_MASK (0x000f) - -#define SEEQCMD_DMA_INT_ACK (0x0010) /* DMA ack */ -#define SEEQCMD_RX_INT_ACK (0x0020) -#define SEEQCMD_TX_INT_ACK (0x0040) -#define SEEQCMD_WINDOW_INT_ACK (0x0080) -#define SEEQCMD_ACK_ALL (0x00f0) - -#define SEEQCMD_SET_DMA_ON (0x0100) /* Enables DMA Request logic */ -#define SEEQCMD_SET_RX_ON (0x0200) /* Enables Packet RX */ -#define SEEQCMD_SET_TX_ON (0x0400) /* Starts TX run */ -#define SEEQCMD_SET_DMA_OFF (0x0800) -#define SEEQCMD_SET_RX_OFF (0x1000) -#define SEEQCMD_SET_TX_OFF (0x2000) -#define SEEQCMD_SET_ALL_OFF (0x3800) /* set all logic off */ - -#define SEEQCMD_FIFO_READ (0x4000) /* Set FIFO to read mode (read from Buffer) */ -#define SEEQCMD_FIFO_WRITE (0x8000) /* Set FIFO to write mode */ - -#define SEEQSTAT_DMA_INT_EN (0x0001) /* Status of interrupt enable */ -#define SEEQSTAT_RX_INT_EN (0x0002) -#define SEEQSTAT_TX_INT_EN (0x0004) -#define SEEQSTAT_WINDOW_INT_EN (0x0008) - -#define SEEQSTAT_DMA_INT (0x0010) /* Interrupt flagged */ -#define SEEQSTAT_RX_INT (0x0020) -#define SEEQSTAT_TX_INT (0x0040) -#define SEEQSTAT_WINDOW_INT (0x0080) -#define SEEQSTAT_ANY_INT (0x00f0) - -#define SEEQSTAT_DMA_ON (0x0100) /* DMA logic on */ -#define SEEQSTAT_RX_ON (0x0200) /* Packet RX on */ -#define SEEQSTAT_TX_ON (0x0400) /* TX running */ - -#define SEEQSTAT_FIFO_FULL (0x2000) -#define SEEQSTAT_FIFO_EMPTY (0x4000) -#define SEEQSTAT_FIFO_DIR (0x8000) /* 1=read, 0=write */ - -#define SEEQCFG1_BUFFER_MASK (0x000f) /* define what mapps into the BUFFER register */ -#define SEEQCFG1_BUFFER_MAC0 (0x0000) /* MAC station addresses 0-5 */ -#define SEEQCFG1_BUFFER_MAC1 (0x0001) -#define SEEQCFG1_BUFFER_MAC2 (0x0002) -#define SEEQCFG1_BUFFER_MAC3 (0x0003) -#define SEEQCFG1_BUFFER_MAC4 (0x0004) -#define SEEQCFG1_BUFFER_MAC5 (0x0005) -#define SEEQCFG1_BUFFER_PROM (0x0006) /* The Address/CFG PROM */ -#define SEEQCFG1_BUFFER_TEA (0x0007) /* Transmit end area */ -#define SEEQCFG1_BUFFER_BUFFER (0x0008) /* Packet buffer memory */ -#define SEEQCFG1_BUFFER_INT_VEC (0x0009) /* Interrupt Vector */ - -#define SEEQCFG1_DMA_INTVL_MASK (0x0030) -#define SEEQCFG1_DMA_CONT (0x0000) -#define SEEQCFG1_DMA_800ns (0x0010) -#define SEEQCFG1_DMA_1600ns (0x0020) -#define SEEQCFG1_DMA_3200ns (0x0030) - -#define SEEQCFG1_DMA_LEN_MASK (0x00c0) -#define SEEQCFG1_DMA_LEN1 (0x0000) -#define SEEQCFG1_DMA_LEN2 (0x0040) -#define SEEQCFG1_DMA_LEN4 (0x0080) -#define SEEQCFG1_DMA_LEN8 (0x00c0) - -#define SEEQCFG1_MAC_MASK (0x3f00) /* Dis/enable bits for MAC addresses */ -#define SEEQCFG1_MAC0_EN (0x0100) -#define SEEQCFG1_MAC1_EN (0x0200) -#define SEEQCFG1_MAC2_EN (0x0400) -#define SEEQCFG1_MAC3_EN (0x0800) -#define SEEQCFG1_MAC4_EN (0x1000) -#define SEEQCFG1_MAC5_EN (0x2000) - -#define SEEQCFG1_MATCH_MASK (0xc000) /* Packet matching logic cfg bits */ -#define SEEQCFG1_MATCH_SPECIFIC (0x0000) /* only matching MAC addresses */ -#define SEEQCFG1_MATCH_BROAD (0x4000) /* matching and broadcast addresses */ -#define SEEQCFG1_MATCH_MULTI (0x8000) /* matching, broadcast and multicast */ -#define SEEQCFG1_MATCH_ALL (0xc000) /* Promiscuous mode */ - -#define SEEQCFG1_DEFAULT (SEEQCFG1_BUFFER_BUFFER | SEEQCFG1_MAC0_EN | SEEQCFG1_MATCH_BROAD) - -#define SEEQCFG2_BYTE_SWAP (0x0001) /* 0=Intel byte-order */ -#define SEEQCFG2_AUTO_REA (0x0002) /* if set, Receive End Area will be updated when reading from Buffer */ - -#define SEEQCFG2_CRC_ERR_EN (0x0008) /* enables receiving of packets with CRC errors */ -#define SEEQCFG2_DRIBBLE_EN (0x0010) /* enables receiving of non-aligned packets */ -#define SEEQCFG2_SHORT_EN (0x0020) /* enables receiving of short packets */ - -#define SEEQCFG2_SLOTSEL (0x0040) /* 0= standard IEEE802.3, 1= smaller,faster, non-standard */ -#define SEEQCFG2_NO_PREAM (0x0080) /* 1= user supplies Xmit preamble bytes */ -#define SEEQCFG2_ADDR_LEN (0x0100) /* 1= 2byte addresses */ -#define SEEQCFG2_REC_CRC (0x0200) /* 0= received packets will have CRC stripped from them */ -#define SEEQCFG2_XMIT_NO_CRC (0x0400) /* dont xmit CRC with each packet (user supplies it) */ -#define SEEQCFG2_LOOPBACK (0x0800) -#define SEEQCFG2_CTRLO (0x1000) -#define SEEQCFG2_RESET (0x8000) /* software Hard-reset bit */ - -struct seeq_pkt_hdr { - unsigned short next; /* address of next packet header */ - unsigned char babble_int:1, /* enable int on >1514 byte packet */ - coll_int:1, /* enable int on collision */ - coll_16_int:1, /* enable int on >15 collision */ - xmit_int:1, /* enable int on success (or xmit with <15 collision) */ - unused:1, - data_follows:1, /* if not set, process this as a header and pointer only */ - chain_cont:1, /* if set, more headers in chain only cmd bit valid in recv header */ - xmit_recv:1; /* if set, a xmit packet, else a receive packet.*/ - unsigned char status; -}; - -#define SEEQPKTH_BAB_INT_EN (0x01) /* xmit only */ -#define SEEQPKTH_COL_INT_EN (0x02) /* xmit only */ -#define SEEQPKTH_COL16_INT_EN (0x04) /* xmit only */ -#define SEEQPKTH_XMIT_INT_EN (0x08) /* xmit only */ -#define SEEQPKTH_DATA_FOLLOWS (0x20) /* supposedly in xmit only */ -#define SEEQPKTH_CHAIN (0x40) /* more headers follow */ -#define SEEQPKTH_XMIT (0x80) - -#define SEEQPKTS_BABBLE (0x0100) /* xmit only */ -#define SEEQPKTS_OVERSIZE (0x0100) /* recv only */ -#define SEEQPKTS_COLLISION (0x0200) /* xmit only */ -#define SEEQPKTS_CRC_ERR (0x0200) /* recv only */ -#define SEEQPKTS_COLL16 (0x0400) /* xmit only */ -#define SEEQPKTS_DRIB (0x0400) /* recv only */ -#define SEEQPKTS_SHORT (0x0800) /* recv only */ -#define SEEQPKTS_DONE (0x8000) -#define SEEQPKTS_ANY_ERROR (0x0f00) diff --git a/i386/i386at/gpl/linux/net/sk_g16.c b/i386/i386at/gpl/linux/net/sk_g16.c deleted file mode 100644 index 83989485..00000000 --- a/i386/i386at/gpl/linux/net/sk_g16.c +++ /dev/null @@ -1,2111 +0,0 @@ -/*- - * Copyright (C) 1994 by PJD Weichmann & SWS Bern, Switzerland - * - * This software may be used and distributed according to the terms - * of the GNU Public License, incorporated herein by reference. - * - * Module : sk_g16.c - * - * Version : $Revision: 1.1.1.1 $ - * - * Author : Patrick J.D. Weichmann - * - * Date Created : 94/05/26 - * Last Updated : $Date: 1997/02/25 21:27:39 $ - * - * Description : Schneider & Koch G16 Ethernet Device Driver for - * Linux Kernel >= 1.1.22 - * Update History : - * --*/ - -static const char *rcsid = "$Id: sk_g16.c,v 1.1.1.1 1997/02/25 21:27:39 thomas Exp $"; - -/* - * The Schneider & Koch (SK) G16 Network device driver is based - * on the 'ni6510' driver from Michael Hipp which can be found at - * ftp://sunsite.unc.edu/pub/Linux/system/Network/drivers/nidrivers.tar.gz - * - * Sources: 1) ni6510.c by M. Hipp - * 2) depca.c by D.C. Davies - * 3) skeleton.c by D. Becker - * 4) Am7990 Local Area Network Controller for Ethernet (LANCE), - * AMD, Pub. #05698, June 1989 - * - * Many Thanks for helping me to get things working to: - * - * A. Cox (A.Cox@swansea.ac.uk) - * M. Hipp (mhipp@student.uni-tuebingen.de) - * R. Bolz (Schneider & Koch, Germany) - * - * See README.sk_g16 for details about limitations and bugs for the - * current version. - * - * To Do: - * - Support of SK_G8 and other SK Network Cards. - * - Autoset memory mapped RAM. Check for free memory and then - * configure RAM correctly. - * - SK_close should really set card in to initial state. - * - Test if IRQ 3 is not switched off. Use autoirq() functionality. - * (as in /drivers/net/skeleton.c) - * - Implement Multicast addressing. At minimum something like - * in depca.c. - * - Redo the statistics part. - * - Try to find out if the board is in 8 Bit or 16 Bit slot. - * If in 8 Bit mode don't use IRQ 11. - * - (Try to make it slightly faster.) - */ - -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/ptrace.h> -#include <linux/fcntl.h> -#include <linux/ioport.h> -#include <linux/interrupt.h> -#include <linux/malloc.h> -#include <linux/ioport.h> -#include <linux/string.h> -#include <asm/system.h> -#include <asm/io.h> -#include <asm/bitops.h> -#include <linux/errno.h> - -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> - -#include "sk_g16.h" - -/* - * Schneider & Koch Card Definitions - * ================================= - */ - -#define SK_NAME "SK_G16" - -/* - * SK_G16 Configuration - * -------------------- - */ - -/* - * Abbreviations - * ------------- - * - * RAM - used for the 16KB shared memory - * Boot_ROM, ROM - are used for referencing the BootEPROM - * - * SK_BOOT_ROM and SK_ADDR are symbolic constants used to configure - * the behaviour of the driver and the SK_G16. - * - * ! See sk_g16.install on how to install and configure the driver ! - * - * SK_BOOT_ROM defines if the Boot_ROM should be switched off or not. - * - * SK_ADDR defines the address where the RAM will be mapped into the real - * host memory. - * valid addresses are from 0xa0000 to 0xfc000 in 16Kbyte steps. - */ - -#define SK_BOOT_ROM 1 /* 1=BootROM on 0=off */ - -#define SK_ADDR 0xcc000 - -/* - * In POS3 are bits A14-A19 of the address bus. These bits can be set - * to choose the RAM address. Thats why we only can choose the RAM address - * in 16KB steps. - */ - -#define POS_ADDR (rom_addr>>14) /* Do not change this line */ - -/* - * SK_G16 I/O PORT's + IRQ's + Boot_ROM locations - * ---------------------------------------------- - */ - -/* - * As nearly every card has also SK_G16 a specified I/O Port region and - * only a few possible IRQ's. - * In the Installation Guide from Schneider & Koch is listed a possible - * Interrupt IRQ2. IRQ2 is always IRQ9 in boards with two cascaded interrupt - * controllers. So we use in SK_IRQS IRQ9. - */ - -/* Don't touch any of the following #defines. */ - -#define SK_IO_PORTS { 0x100, 0x180, 0x208, 0x220, 0x288, 0x320, 0x328, 0x390, 0 } - -#define SK_IRQS { 3, 5, 9, 11, 0 } - -#define SK_BOOT_ROM_LOCATIONS { 0xc0000, 0xc4000, 0xc8000, 0xcc000, 0xd0000, 0xd4000, 0xd8000, 0xdc000, 0 } - -#define SK_BOOT_ROM_ID { 0x55, 0xaa, 0x10, 0x50, 0x06, 0x33 } - -/* - * SK_G16 POS REGISTERS - * -------------------- - */ - -/* - * SK_G16 has a Programmable Option Select (POS) Register. - * The POS is composed of 8 separate registers (POS0-7) which - * are I/O mapped on an address set by the W1 switch. - * - */ - -#define SK_POS_SIZE 8 /* 8 I/O Ports are used by SK_G16 */ - -#define SK_POS0 ioaddr /* Card-ID Low (R) */ -#define SK_POS1 ioaddr+1 /* Card-ID High (R) */ -#define SK_POS2 ioaddr+2 /* Card-Enable, Boot-ROM Disable (RW) */ -#define SK_POS3 ioaddr+3 /* Base address of RAM */ -#define SK_POS4 ioaddr+4 /* IRQ */ - -/* POS5 - POS7 are unused */ - -/* - * SK_G16 MAC PREFIX - * ----------------- - */ - -/* - * Scheider & Koch manufacturer code (00:00:a5). - * This must be checked, that we are sure it is a SK card. - */ - -#define SK_MAC0 0x00 -#define SK_MAC1 0x00 -#define SK_MAC2 0x5a - -/* - * SK_G16 ID - * --------- - */ - -/* - * If POS0,POS1 contain the following ID, then we know - * at which I/O Port Address we are. - */ - -#define SK_IDLOW 0xfd -#define SK_IDHIGH 0x6a - - -/* - * LANCE POS Bit definitions - * ------------------------- - */ - -#define SK_ROM_RAM_ON (POS2_CARD) -#define SK_ROM_RAM_OFF (POS2_EPROM) -#define SK_ROM_ON (inb(SK_POS2) & POS2_CARD) -#define SK_ROM_OFF (inb(SK_POS2) | POS2_EPROM) -#define SK_RAM_ON (inb(SK_POS2) | POS2_CARD) -#define SK_RAM_OFF (inb(SK_POS2) & POS2_EPROM) - -#define POS2_CARD 0x0001 /* 1 = SK_G16 on 0 = off */ -#define POS2_EPROM 0x0002 /* 1 = Boot EPROM off 0 = on */ - -/* - * SK_G16 Memory mapped Registers - * ------------------------------ - * - */ - -#define SK_IOREG (board->ioreg) /* LANCE data registers. */ -#define SK_PORT (board->port) /* Control, Status register */ -#define SK_IOCOM (board->iocom) /* I/O Command */ - -/* - * SK_G16 Status/Control Register bits - * ----------------------------------- - * - * (C) Controlreg (S) Statusreg - */ - -/* - * Register transfer: 0 = no transfer - * 1 = transferring data between LANCE and I/O reg - */ -#define SK_IORUN 0x20 - -/* - * LANCE interrupt: 0 = LANCE interrupt occurred - * 1 = no LANCE interrupt occurred - */ -#define SK_IRQ 0x10 - -#define SK_RESET 0x08 /* Reset SK_CARD: 0 = RESET 1 = normal */ -#define SK_RW 0x02 /* 0 = write to 1 = read from */ -#define SK_ADR 0x01 /* 0 = REG DataPort 1 = RAP Reg addr port */ - - -#define SK_RREG SK_RW /* Transferdirection to read from lance */ -#define SK_WREG 0 /* Transferdirection to write to lance */ -#define SK_RAP SK_ADR /* Destination Register RAP */ -#define SK_RDATA 0 /* Destination Register REG DataPort */ - -/* - * SK_G16 I/O Command - * ------------------ - */ - -/* - * Any bitcombination sets the internal I/O bit (transfer will start) - * when written to I/O Command - */ - -#define SK_DOIO 0x80 /* Do Transfer */ - -/* - * LANCE RAP (Register Address Port). - * --------------------------------- - */ - -/* - * The LANCE internal registers are selected through the RAP. - * The Registers are: - * - * CSR0 - Status and Control flags - * CSR1 - Low order bits of initialize block (bits 15:00) - * CSR2 - High order bits of initialize block (bits 07:00, 15:08 are reserved) - * CSR3 - Allows redefinition of the Bus Master Interface. - * This register must be set to 0x0002, which means BSWAP = 0, - * ACON = 1, BCON = 0; - * - */ - -#define CSR0 0x00 -#define CSR1 0x01 -#define CSR2 0x02 -#define CSR3 0x03 - -/* - * General Definitions - * =================== - */ - -/* - * Set the number of Tx and Rx buffers, using Log_2(# buffers). - * We have 16KB RAM which can be accessed by the LANCE. In the - * memory are not only the buffers but also the ring descriptors and - * the initialize block. - * Don't change anything unless you really know what you do. - */ - -#define LC_LOG_TX_BUFFERS 1 /* (2 == 2^^1) 2 Transmit buffers */ -#define LC_LOG_RX_BUFFERS 3 /* (8 == 2^^3) 8 Receive buffers */ - -/* Descriptor ring sizes */ - -#define TMDNUM (1 << (LC_LOG_TX_BUFFERS)) /* 2 Transmit descriptor rings */ -#define RMDNUM (1 << (LC_LOG_RX_BUFFERS)) /* 8 Receive Buffers */ - -/* Define Mask for setting RMD, TMD length in the LANCE init_block */ - -#define TMDNUMMASK (LC_LOG_TX_BUFFERS << 29) -#define RMDNUMMASK (LC_LOG_RX_BUFFERS << 29) - -/* - * Data Buffer size is set to maximum packet length. - */ - -#define PKT_BUF_SZ 1518 - -/* - * The number of low I/O ports used by the ethercard. - */ - -#define ETHERCARD_TOTAL_SIZE SK_POS_SIZE - -/* - * Portreserve is there to mark the Card I/O Port region as used. - * Check_region is to check if the region at ioaddr with the size "size" - * is free or not. - * Snarf_region allocates the I/O Port region. - */ - -#ifndef HAVE_PORTRESERVE - -#define check_region(ioaddr, size) 0 -#define request_region(ioaddr, size,name) do ; while (0) - -#endif - -/* - * SK_DEBUG - * - * Here you can choose what level of debugging wanted. - * - * If SK_DEBUG and SK_DEBUG2 are undefined, then only the - * necessary messages will be printed. - * - * If SK_DEBUG is defined, there will be many debugging prints - * which can help to find some mistakes in configuration or even - * in the driver code. - * - * If SK_DEBUG2 is defined, many many messages will be printed - * which normally you don't need. I used this to check the interrupt - * routine. - * - * (If you define only SK_DEBUG2 then only the messages for - * checking interrupts will be printed!) - * - * Normal way of live is: - * - * For the whole thing get going let both symbolic constants - * undefined. If you face any problems and you know what's going - * on (you know something about the card and you can interpret some - * hex LANCE register output) then define SK_DEBUG - * - */ - -#undef SK_DEBUG /* debugging */ -#undef SK_DEBUG2 /* debugging with more verbose report */ - -#ifdef SK_DEBUG -#define PRINTK(x) printk x -#else -#define PRINTK(x) /**/ -#endif - -#ifdef SK_DEBUG2 -#define PRINTK2(x) printk x -#else -#define PRINTK2(x) /**/ -#endif - -/* - * SK_G16 RAM - * - * The components are memory mapped and can be set in a region from - * 0x00000 through 0xfc000 in 16KB steps. - * - * The Network components are: dual ported RAM, Prom, I/O Reg, Status-, - * Controlregister and I/O Command. - * - * dual ported RAM: This is the only memory region which the LANCE chip - * has access to. From the Lance it is addressed from 0x0000 to - * 0x3fbf. The host accesses it normally. - * - * PROM: The PROM obtains the ETHERNET-MAC-Address. It is realised as a - * 8-Bit PROM, this means only the 16 even addresses are used of the - * 32 Byte Address region. Access to a odd address results in invalid - * data. - * - * LANCE I/O Reg: The I/O Reg is build of 4 single Registers, Low-Byte Write, - * Hi-Byte Write, Low-Byte Read, Hi-Byte Read. - * Transfer from or to the LANCE is always in 16Bit so Low and High - * registers are always relevant. - * - * The Data from the Readregister is not the data in the Writeregister!! - * - * Port: Status- and Controlregister. - * Two different registers which share the same address, Status is - * read-only, Control is write-only. - * - * I/O Command: - * Any bitcombination written in here starts the transmission between - * Host and LANCE. - */ - -typedef struct -{ - unsigned char ram[0x3fc0]; /* 16KB dual ported ram */ - unsigned char rom[0x0020]; /* 32Byte PROM containing 6Byte MAC */ - unsigned char res1[0x0010]; /* reserved */ - unsigned volatile short ioreg;/* LANCE I/O Register */ - unsigned volatile char port; /* Statusregister and Controlregister */ - unsigned char iocom; /* I/O Command Register */ -} SK_RAM; - -/* struct */ - -/* - * This is the structure for the dual ported ram. We - * have exactly 16 320 Bytes. In here there must be: - * - * - Initialize Block (starting at a word boundary) - * - Receive and Transmit Descriptor Rings (quadword boundary) - * - Data Buffers (arbitrary boundary) - * - * This is because LANCE has on SK_G16 only access to the dual ported - * RAM and nowhere else. - */ - -struct SK_ram -{ - struct init_block ib; - struct tmd tmde[TMDNUM]; - struct rmd rmde[RMDNUM]; - char tmdbuf[TMDNUM][PKT_BUF_SZ]; - char rmdbuf[RMDNUM][PKT_BUF_SZ]; -}; - -/* - * Structure where all necessary information is for ring buffer - * management and statistics. - */ - -struct priv -{ - struct SK_ram *ram; /* dual ported ram structure */ - struct rmd *rmdhead; /* start of receive ring descriptors */ - struct tmd *tmdhead; /* start of transmit ring descriptors */ - int rmdnum; /* actual used ring descriptor */ - int tmdnum; /* actual transmit descriptor for transmitting data */ - int tmdlast; /* last sent descriptor used for error handling, etc */ - void *rmdbufs[RMDNUM]; /* pointer to the receive buffers */ - void *tmdbufs[TMDNUM]; /* pointer to the transmit buffers */ - struct enet_statistics stats; /* Device driver statistics */ -}; - -/* global variable declaration */ - -/* IRQ map used to reserve a IRQ (see SK_open()) */ - -/* extern void *irq2dev_map[16]; */ /* Declared in <linux/ioport.h> */ - -/* static variables */ - -static SK_RAM *board; /* pointer to our memory mapped board components */ - -/* Macros */ - - -/* Function Prototypes */ - -/* - * Device Driver functions - * ----------------------- - * See for short explanation of each function its definitions header. - */ - -int SK_init(struct device *dev); -static int SK_probe(struct device *dev, short ioaddr); - -static int SK_open(struct device *dev); -static int SK_send_packet(struct sk_buff *skb, struct device *dev); -static void SK_interrupt(int irq, struct pt_regs * regs); -static void SK_rxintr(struct device *dev); -static void SK_txintr(struct device *dev); -static int SK_close(struct device *dev); - -static struct enet_statistics *SK_get_stats(struct device *dev); - -unsigned int SK_rom_addr(void); - -static void set_multicast_list(struct device *dev); - -/* - * LANCE Functions - * --------------- - */ - -static int SK_lance_init(struct device *dev, unsigned short mode); -void SK_reset_board(void); -void SK_set_RAP(int reg_number); -int SK_read_reg(int reg_number); -int SK_rread_reg(void); -void SK_write_reg(int reg_number, int value); - -/* - * Debugging functions - * ------------------- - */ - -void SK_print_pos(struct device *dev, char *text); -void SK_print_dev(struct device *dev, char *text); -void SK_print_ram(struct device *dev); - - -/*- - * Function : SK_init - * Author : Patrick J.D. Weichmann - * Date Created : 94/05/26 - * - * Description : Check for a SK_G16 network adaptor and initialize it. - * This function gets called by dev_init which initializes - * all Network devices. - * - * Parameters : I : struct device *dev - structure preconfigured - * from Space.c - * Return Value : 0 = Driver Found and initialized - * Errors : ENODEV - no device found - * ENXIO - not probed - * Globals : None - * Update History : - * YY/MM/DD uid Description --*/ - -/* - * Check for a network adaptor of this type, and return '0' if one exists. - * If dev->base_addr == 0, probe all likely locations. - * If dev->base_addr == 1, always return failure. - * If dev->base_addr == 2, allocate space for the device and return success - * (detachable devices only). - */ - -int SK_init(struct device *dev) -{ - int ioaddr = 0; /* I/O port address used for POS regs */ - int *port, ports[] = SK_IO_PORTS; /* SK_G16 supported ports */ - - /* get preconfigured base_addr from dev which is done in Space.c */ - int base_addr = dev->base_addr; - - PRINTK(("%s: %s", SK_NAME, rcsid)); - rcsid = NULL; /* We do not want to use this further */ - - if (base_addr > 0x0ff) /* Check a single specified address */ - { - /* Check if on specified address is a SK_G16 */ - - if ( (inb(SK_POS0) == SK_IDLOW) || - (inb(SK_POS1) == SK_IDHIGH) ) - { - return SK_probe(dev, base_addr); - } - - return ENODEV; /* Sorry, but on specified address NO SK_G16 */ - } - else if (base_addr > 0) /* Don't probe at all */ - { - return ENXIO; - } - - /* Autoprobe base_addr */ - - for (port = &ports[0]; *port; port++) - { - ioaddr = *port; /* we need ioaddr for accessing POS regs */ - - /* Check if I/O Port region is used by another board */ - - if (check_region(ioaddr, ETHERCARD_TOTAL_SIZE)) - { - continue; /* Try next Port address */ - } - - /* Check if at ioaddr is a SK_G16 */ - - if ( !(inb(SK_POS0) == SK_IDLOW) || - !(inb(SK_POS1) == SK_IDHIGH) ) - { - continue; /* Try next Port address */ - } - - dev->base_addr = ioaddr; /* Set I/O Port Address */ - - if (SK_probe(dev, ioaddr) == 0) - { - return 0; /* Card found and initialized */ - } - } - - dev->base_addr = base_addr; /* Write back original base_addr */ - - return ENODEV; /* Failed to find or init driver */ - -} /* End of SK_init */ - - -/*- - * Function : SK_probe - * Author : Patrick J.D. Weichmann - * Date Created : 94/05/26 - * - * Description : This function is called by SK_init and - * does the main part of initialization. - * - * Parameters : I : struct device *dev - SK_G16 device structure - * I : short ioaddr - I/O Port address where POS is. - * Return Value : 0 = Initialization done - * Errors : ENODEV - No SK_G16 found - * -1 - Configuration problem - * Globals : irq2dev_map - Which device uses which IRQ - * : board - pointer to SK_RAM - * Update History : - * YY/MM/DD uid Description - * 94/06/30 pwe SK_ADDR now checked and at the correct place --*/ - -int SK_probe(struct device *dev, short ioaddr) -{ - int i,j; /* Counters */ - int sk_addr_flag = 0; /* SK ADDR correct? 1 - no, 0 - yes */ - unsigned int rom_addr; /* used to store RAM address used for POS_ADDR */ - - struct priv *p; /* SK_G16 private structure */ - - if (SK_ADDR & 0x3fff || SK_ADDR < 0xa0000) - { - - sk_addr_flag = 1; - - /* - * Now here we could use a routine which searches for a free - * place in the ram and set SK_ADDR if found. TODO. - */ - } - - if (SK_BOOT_ROM) /* Shall we keep Boot_ROM on ? */ - { - PRINTK(("## %s: SK_BOOT_ROM is set.\n", SK_NAME)); - - rom_addr = SK_rom_addr(); - - if (rom_addr == 0) /* No Boot_ROM found */ - { - if (sk_addr_flag) /* No or Invalid SK_ADDR is defined */ - { - printk("%s: SK_ADDR %#08x is not valid. Check configuration.\n", - dev->name, SK_ADDR); - return -1; - } - - rom_addr = SK_ADDR; /* assign predefined address */ - - PRINTK(("## %s: NO Bootrom found \n", SK_NAME)); - - outb(SK_ROM_RAM_OFF, SK_POS2); /* Boot_ROM + RAM off */ - outb(POS_ADDR, SK_POS3); /* Set RAM address */ - outb(SK_RAM_ON, SK_POS2); /* enable RAM */ - } - else if (rom_addr == SK_ADDR) - { - printk("%s: RAM + ROM are set to the same address %#08x\n" - " Check configuration. Now switching off Boot_ROM\n", - SK_NAME, rom_addr); - - outb(SK_ROM_RAM_OFF, SK_POS2); /* Boot_ROM + RAM off*/ - outb(POS_ADDR, SK_POS3); /* Set RAM address */ - outb(SK_RAM_ON, SK_POS2); /* enable RAM */ - } - else - { - PRINTK(("## %s: Found ROM at %#08x\n", SK_NAME, rom_addr)); - PRINTK(("## %s: Keeping Boot_ROM on\n", SK_NAME)); - - if (sk_addr_flag) /* No or Invalid SK_ADDR is defined */ - { - printk("%s: SK_ADDR %#08x is not valid. Check configuration.\n", - dev->name, SK_ADDR); - return -1; - } - - rom_addr = SK_ADDR; - - outb(SK_ROM_RAM_OFF, SK_POS2); /* Boot_ROM + RAM off */ - outb(POS_ADDR, SK_POS3); /* Set RAM address */ - outb(SK_ROM_RAM_ON, SK_POS2); /* RAM on, BOOT_ROM on */ - } - } - else /* Don't keep Boot_ROM */ - { - PRINTK(("## %s: SK_BOOT_ROM is not set.\n", SK_NAME)); - - if (sk_addr_flag) /* No or Invalid SK_ADDR is defined */ - { - printk("%s: SK_ADDR %#08x is not valid. Check configuration.\n", - dev->name, SK_ADDR); - return -1; - } - - rom_addr = SK_rom_addr(); /* Try to find a Boot_ROM */ - - /* IF we find a Boot_ROM disable it */ - - outb(SK_ROM_RAM_OFF, SK_POS2); /* Boot_ROM + RAM off */ - - /* We found a Boot_ROM and it's gone. Set RAM address on - * Boot_ROM address. - */ - - if (rom_addr) - { - printk("%s: We found Boot_ROM at %#08x. Now setting RAM on" - "that address\n", SK_NAME, rom_addr); - - outb(POS_ADDR, SK_POS3); /* Set RAM on Boot_ROM address */ - } - else /* We did not find a Boot_ROM, use predefined SK_ADDR for ram */ - { - if (sk_addr_flag) /* No or Invalid SK_ADDR is defined */ - { - printk("%s: SK_ADDR %#08x is not valid. Check configuration.\n", - dev->name, SK_ADDR); - return -1; - } - - rom_addr = SK_ADDR; - - outb(POS_ADDR, SK_POS3); /* Set RAM address */ - } - outb(SK_RAM_ON, SK_POS2); /* enable RAM */ - } - -#ifdef SK_DEBUG - SK_print_pos(dev, "POS registers after ROM, RAM config"); -#endif - - board = (SK_RAM *) rom_addr; - - /* Read in station address */ - for (i = 0, j = 0; i < ETH_ALEN; i++, j+=2) - { - dev->dev_addr[i] = board->rom[j]; - } - - /* Check for manufacturer code */ - if (!(dev->dev_addr[0] == SK_MAC0 && - dev->dev_addr[1] == SK_MAC1 && - dev->dev_addr[2] == SK_MAC2) ) - { - PRINTK(("## %s: We did not find SK_G16 at RAM location.\n", - SK_NAME)); - return ENODEV; /* NO SK_G16 found */ - } - - printk("%s: %s found at %#3x, HW addr: %#04x:%02x:%02x:%02x:%02x:%02x\n", - dev->name, - "Schneider & Koch Netcard", - (unsigned int) dev->base_addr, - dev->dev_addr[0], - dev->dev_addr[1], - dev->dev_addr[2], - dev->dev_addr[3], - dev->dev_addr[4], - dev->dev_addr[5]); - - /* Grab the I/O Port region */ - request_region(ioaddr, ETHERCARD_TOTAL_SIZE,"sk_g16"); - - /* Initialize device structure */ - - /* Allocate memory for private structure */ - p = dev->priv = (void *) kmalloc(sizeof(struct priv), GFP_KERNEL); - if (p == NULL) - return -ENOMEM; - memset((char *) dev->priv, 0, sizeof(struct priv)); /* clear memory */ - - /* Assign our Device Driver functions */ - - dev->open = &SK_open; - dev->stop = &SK_close; - dev->hard_start_xmit = &SK_send_packet; - dev->get_stats = &SK_get_stats; - dev->set_multicast_list = &set_multicast_list; - - - /* Set the generic fields of the device structure */ - - ether_setup(dev); - - dev->flags &= ~IFF_MULTICAST; - - /* Initialize private structure */ - - p->ram = (struct SK_ram *) rom_addr; /* Set dual ported RAM addr */ - p->tmdhead = &(p->ram)->tmde[0]; /* Set TMD head */ - p->rmdhead = &(p->ram)->rmde[0]; /* Set RMD head */ - - /* Initialize buffer pointers */ - - for (i = 0; i < TMDNUM; i++) - { - p->tmdbufs[i] = &(p->ram)->tmdbuf[i]; - } - - for (i = 0; i < RMDNUM; i++) - { - p->rmdbufs[i] = &(p->ram)->rmdbuf[i]; - } - -#ifdef SK_DEBUG - SK_print_pos(dev, "End of SK_probe"); - SK_print_ram(dev); -#endif - - return 0; /* Initialization done */ - -} /* End of SK_probe() */ - - -/*- - * Function : SK_open - * Author : Patrick J.D. Weichmann - * Date Created : 94/05/26 - * - * Description : This function is called sometimes after booting - * when ifconfig program is run. - * - * This function requests an IRQ, sets the correct - * IRQ in the card. Then calls SK_lance_init() to - * init and start the LANCE chip. Then if everything is - * ok returns with 0 (OK), which means SK_G16 is now - * opened and operational. - * - * (Called by dev_open() /net/inet/dev.c) - * - * Parameters : I : struct device *dev - SK_G16 device structure - * Return Value : 0 - Device opened - * Errors : -EAGAIN - Open failed - * Globals : irq2dev_map - which device uses which irq - * Side Effects : None - * Update History : - * YY/MM/DD uid Description --*/ - -static int SK_open(struct device *dev) -{ - int i = 0; - int irqval = 0; - int ioaddr = dev->base_addr; - - int irqtab[] = SK_IRQS; - - struct priv *p = (struct priv *)dev->priv; - - PRINTK(("## %s: At beginning of SK_open(). CSR0: %#06x\n", - SK_NAME, SK_read_reg(CSR0))); - - if (dev->irq == 0) /* Autoirq */ - { - i = 0; - - /* - * Check if one IRQ out of SK_IRQS is free and install - * interrupt handler. - * Most done by request_irq(). - * irqval: 0 - interrupt handler installed for IRQ irqtab[i] - * -EBUSY - interrupt busy - * -EINVAL - irq > 15 or handler = NULL - */ - - do - { - irqval = request_irq(irqtab[i], &SK_interrupt, 0, "sk_g16"); - i++; - } while (irqval && irqtab[i]); - - if (irqval) /* We tried every possible IRQ but no success */ - { - printk("%s: unable to get an IRQ\n", dev->name); - return -EAGAIN; - } - - dev->irq = irqtab[--i]; - - outb(i<<2, SK_POS4); /* Set Card on probed IRQ */ - - } - else if (dev->irq == 2) /* IRQ2 is always IRQ9 */ - { - if (request_irq(9, &SK_interrupt, 0, "sk_g16")) - { - printk("%s: unable to get IRQ 9\n", dev->name); - return -EAGAIN; - } - dev->irq = 9; - - /* - * Now we set card on IRQ2. - * This can be confusing, but remember that IRQ2 on the network - * card is in reality IRQ9 - */ - outb(0x08, SK_POS4); /* set card to IRQ2 */ - - } - else /* Check IRQ as defined in Space.c */ - { - int i = 0; - - /* check if IRQ free and valid. Then install Interrupt handler */ - - if (request_irq(dev->irq, &SK_interrupt, 0, "sk_g16")) - { - printk("%s: unable to get selected IRQ\n", dev->name); - return -EAGAIN; - } - - switch(dev->irq) - { - case 3: i = 0; - break; - case 5: i = 1; - break; - case 2: i = 2; - break; - case 11:i = 3; - break; - default: - printk("%s: Preselected IRQ %d is invalid for %s boards", - dev->name, - dev->irq, - SK_NAME); - return -EAGAIN; - } - - outb(i<<2, SK_POS4); /* Set IRQ on card */ - } - - irq2dev_map[dev->irq] = dev; /* Set IRQ as used by us */ - - printk("%s: Schneider & Koch G16 at %#3x, IRQ %d, shared mem at %#08x\n", - dev->name, (unsigned int)dev->base_addr, - (int) dev->irq, (unsigned int) p->ram); - - if (!(i = SK_lance_init(dev, 0))) /* LANCE init OK? */ - { - - - dev->tbusy = 0; - dev->interrupt = 0; - dev->start = 1; - -#ifdef SK_DEBUG - - /* - * This debug block tries to stop LANCE, - * reinit LANCE with transmitter and receiver disabled, - * then stop again and reinit with NORMAL_MODE - */ - - printk("## %s: After lance init. CSR0: %#06x\n", - SK_NAME, SK_read_reg(CSR0)); - SK_write_reg(CSR0, CSR0_STOP); - printk("## %s: LANCE stopped. CSR0: %#06x\n", - SK_NAME, SK_read_reg(CSR0)); - SK_lance_init(dev, MODE_DTX | MODE_DRX); - printk("## %s: Reinit with DTX + DRX off. CSR0: %#06x\n", - SK_NAME, SK_read_reg(CSR0)); - SK_write_reg(CSR0, CSR0_STOP); - printk("## %s: LANCE stopped. CSR0: %#06x\n", - SK_NAME, SK_read_reg(CSR0)); - SK_lance_init(dev, MODE_NORMAL); - printk("## %s: LANCE back to normal mode. CSR0: %#06x\n", - SK_NAME, SK_read_reg(CSR0)); - SK_print_pos(dev, "POS regs before returning OK"); - -#endif /* SK_DEBUG */ - - return 0; /* SK_open() is successful */ - } - else /* LANCE init failed */ - { - - PRINTK(("## %s: LANCE init failed: CSR0: %#06x\n", - SK_NAME, SK_read_reg(CSR0))); - - dev->start = 0; /* Device not ready */ - return -EAGAIN; - } - -} /* End of SK_open() */ - - -/*- - * Function : SK_lance_init - * Author : Patrick J.D. Weichmann - * Date Created : 94/05/26 - * - * Description : Reset LANCE chip, fill RMD, TMD structures with - * start values and Start LANCE. - * - * Parameters : I : struct device *dev - SK_G16 device structure - * I : int mode - put LANCE into "mode" see data-sheet for - * more info. - * Return Value : 0 - Init done - * Errors : -1 - Init failed - * Update History : - * YY/MM/DD uid Description --*/ - -static int SK_lance_init(struct device *dev, unsigned short mode) -{ - int i; - struct priv *p = (struct priv *) dev->priv; - struct tmd *tmdp; - struct rmd *rmdp; - - PRINTK(("## %s: At beginning of LANCE init. CSR0: %#06x\n", - SK_NAME, SK_read_reg(CSR0))); - - /* Reset LANCE */ - SK_reset_board(); - - /* Initialize TMD's with start values */ - p->tmdnum = 0; /* First descriptor for transmitting */ - p->tmdlast = 0; /* First descriptor for reading stats */ - - for (i = 0; i < TMDNUM; i++) /* Init all TMD's */ - { - tmdp = p->tmdhead + i; - - tmdp->u.buffer = (unsigned long) p->tmdbufs[i]; /* assign buffer */ - - /* Mark TMD as start and end of packet */ - tmdp->u.s.status = TX_STP | TX_ENP; - } - - - /* Initialize RMD's with start values */ - - p->rmdnum = 0; /* First RMD which will be used */ - - for (i = 0; i < RMDNUM; i++) /* Init all RMD's */ - { - rmdp = p->rmdhead + i; - - - rmdp->u.buffer = (unsigned long) p->rmdbufs[i]; /* assign buffer */ - - /* - * LANCE must be owner at beginning so that he can fill in - * receiving packets, set status and release RMD - */ - - rmdp->u.s.status = RX_OWN; - - rmdp->blen = -PKT_BUF_SZ; /* Buffer Size in a two's complement */ - - rmdp->mlen = 0; /* init message length */ - - } - - /* Fill LANCE Initialize Block */ - - (p->ram)->ib.mode = mode; /* Set operation mode */ - - for (i = 0; i < ETH_ALEN; i++) /* Set physical address */ - { - (p->ram)->ib.paddr[i] = dev->dev_addr[i]; - } - - for (i = 0; i < 8; i++) /* Set multicast, logical address */ - { - (p->ram)->ib.laddr[i] = 0; /* We do not use logical addressing */ - } - - /* Set ring descriptor pointers and set number of descriptors */ - - (p->ram)->ib.rdrp = (int) p->rmdhead | RMDNUMMASK; - (p->ram)->ib.tdrp = (int) p->tmdhead | TMDNUMMASK; - - /* Prepare LANCE Control and Status Registers */ - - cli(); - - SK_write_reg(CSR3, CSR3_ACON); /* Ale Control !!!THIS MUST BE SET!!!! */ - - /* - * LANCE addresses the RAM from 0x0000 to 0x3fbf and has no access to - * PC Memory locations. - * - * In structure SK_ram is defined that the first thing in ram - * is the initialization block. So his address is for LANCE always - * 0x0000 - * - * CSR1 contains low order bits 15:0 of initialization block address - * CSR2 is built of: - * 7:0 High order bits 23:16 of initialization block address - * 15:8 reserved, must be 0 - */ - - /* Set initialization block address (must be on word boundary) */ - SK_write_reg(CSR1, 0); /* Set low order bits 15:0 */ - SK_write_reg(CSR2, 0); /* Set high order bits 23:16 */ - - - PRINTK(("## %s: After setting CSR1-3. CSR0: %#06x\n", - SK_NAME, SK_read_reg(CSR0))); - - /* Initialize LANCE */ - - /* - * INIT = Initialize, when set, causes the LANCE to begin the - * initialization procedure and access the Init Block. - */ - - SK_write_reg(CSR0, CSR0_INIT); - - sti(); - - /* Wait until LANCE finished initialization */ - - SK_set_RAP(CSR0); /* Register Address Pointer to CSR0 */ - - for (i = 0; (i < 100) && !(SK_rread_reg() & CSR0_IDON); i++) - ; /* Wait until init done or go ahead if problems (i>=100) */ - - if (i >= 100) /* Something is wrong ! */ - { - printk("%s: can't init am7990, status: %04x " - "init_block: %#08x\n", - dev->name, (int) SK_read_reg(CSR0), - (unsigned int) &(p->ram)->ib); - -#ifdef SK_DEBUG - SK_print_pos(dev, "LANCE INIT failed"); - SK_print_dev(dev,"Device Structure:"); -#endif - - return -1; /* LANCE init failed */ - } - - PRINTK(("## %s: init done after %d ticks\n", SK_NAME, i)); - - /* Clear Initialize done, enable Interrupts, start LANCE */ - - SK_write_reg(CSR0, CSR0_IDON | CSR0_INEA | CSR0_STRT); - - PRINTK(("## %s: LANCE started. CSR0: %#06x\n", SK_NAME, - SK_read_reg(CSR0))); - - return 0; /* LANCE is up and running */ - -} /* End of SK_lance_init() */ - - - -/*- - * Function : SK_send_packet - * Author : Patrick J.D. Weichmann - * Date Created : 94/05/27 - * - * Description : Writes an socket buffer into a transmit descriptor - * and starts transmission. - * - * Parameters : I : struct sk_buff *skb - packet to transfer - * I : struct device *dev - SK_G16 device structure - * Return Value : 0 - OK - * 1 - Could not transmit (dev_queue_xmit will queue it) - * and try to sent it later - * Globals : None - * Side Effects : None - * Update History : - * YY/MM/DD uid Description --*/ - -static int SK_send_packet(struct sk_buff *skb, struct device *dev) -{ - struct priv *p = (struct priv *) dev->priv; - struct tmd *tmdp; - - if (dev->tbusy) - { - /* if Transmitter more than 150ms busy -> time_out */ - - int tickssofar = jiffies - dev->trans_start; - if (tickssofar < 15) - { - return 1; /* We have to try transmit later */ - } - - printk("%s: xmitter timed out, try to restart!\n", dev->name); - - SK_lance_init(dev, MODE_NORMAL); /* Reinit LANCE */ - - dev->tbusy = 0; /* Clear Transmitter flag */ - - dev->trans_start = jiffies; /* Mark Start of transmission */ - - } - - /* - * If some upper Layer thinks we missed a transmit done interrupt - * we are passed NULL. - * (dev_queue_xmit net/inet/dev.c - */ - - if (skb == NULL) - { - /* - * Dequeue packets from transmit queue and send them. - */ - dev_tint(dev); - - return 0; - } - - PRINTK2(("## %s: SK_send_packet() called, CSR0 %#04x.\n", - SK_NAME, SK_read_reg(CSR0))); - - - /* - * Block a timer-based transmit from overlapping. - * This means check if we are already in. - */ - - if (set_bit(0, (void *) &dev->tbusy) != 0) /* dev->tbusy already set ? */ - { - printk("%s: Transmitter access conflict.\n", dev->name); - } - else - { - /* Evaluate Packet length */ - short len = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; - - tmdp = p->tmdhead + p->tmdnum; /* Which descriptor for transmitting */ - - /* Fill in Transmit Message Descriptor */ - - /* Copy data into dual ported ram */ - - memcpy((char *) (tmdp->u.buffer & 0x00ffffff), (char *)skb->data, - skb->len); - - tmdp->blen = -len; /* set length to transmit */ - - /* - * Packet start and end is always set because we use the maximum - * packet length as buffer length. - * Relinquish ownership to LANCE - */ - - tmdp->u.s.status = TX_OWN | TX_STP | TX_ENP; - - /* Start Demand Transmission */ - SK_write_reg(CSR0, CSR0_TDMD | CSR0_INEA); - - dev->trans_start = jiffies; /* Mark start of transmission */ - - /* Set pointer to next transmit buffer */ - p->tmdnum++; - p->tmdnum &= TMDNUM-1; - - /* Do we own the next transmit buffer ? */ - if (! ((p->tmdhead + p->tmdnum)->u.s.status & TX_OWN) ) - { - /* - * We own next buffer and are ready to transmit, so - * clear busy flag - */ - dev->tbusy = 0; - } - } - dev_kfree_skb(skb, FREE_WRITE); - return 0; -} /* End of SK_send_packet */ - - -/*- - * Function : SK_interrupt - * Author : Patrick J.D. Weichmann - * Date Created : 94/05/27 - * - * Description : SK_G16 interrupt handler which checks for LANCE - * Errors, handles transmit and receive interrupts - * - * Parameters : I : int irq, struct pt_regs * regs - - * Return Value : None - * Errors : None - * Globals : None - * Side Effects : None - * Update History : - * YY/MM/DD uid Description --*/ - -static void SK_interrupt(int irq, struct pt_regs * regs) -{ - int csr0; - struct device *dev = (struct device *) irq2dev_map[irq]; - struct priv *p = (struct priv *) dev->priv; - - - PRINTK2(("## %s: SK_interrupt(). status: %#06x\n", - SK_NAME, SK_read_reg(CSR0))); - - if (dev == NULL) - { - printk("SK_interrupt(): IRQ %d for unknown device.\n", irq); - } - - - if (dev->interrupt) - { - printk("%s: Re-entering the interrupt handler.\n", dev->name); - } - - csr0 = SK_read_reg(CSR0); /* store register for checking */ - - dev->interrupt = 1; /* We are handling an interrupt */ - - /* - * Acknowledge all of the current interrupt sources, disable - * Interrupts (INEA = 0) - */ - - SK_write_reg(CSR0, csr0 & CSR0_CLRALL); - - if (csr0 & CSR0_ERR) /* LANCE Error */ - { - printk("%s: error: %04x\n", dev->name, csr0); - - if (csr0 & CSR0_MISS) /* No place to store packet ? */ - { - p->stats.rx_dropped++; - } - } - - if (csr0 & CSR0_RINT) /* Receive Interrupt (packet arrived) */ - { - SK_rxintr(dev); - } - - if (csr0 & CSR0_TINT) /* Transmit interrupt (packet sent) */ - { - SK_txintr(dev); - } - - SK_write_reg(CSR0, CSR0_INEA); /* Enable Interrupts */ - - dev->interrupt = 0; /* We are out */ -} /* End of SK_interrupt() */ - - -/*- - * Function : SK_txintr - * Author : Patrick J.D. Weichmann - * Date Created : 94/05/27 - * - * Description : After sending a packet we check status, update - * statistics and relinquish ownership of transmit - * descriptor ring. - * - * Parameters : I : struct device *dev - SK_G16 device structure - * Return Value : None - * Errors : None - * Globals : None - * Update History : - * YY/MM/DD uid Description --*/ - -static void SK_txintr(struct device *dev) -{ - int tmdstat; - struct tmd *tmdp; - struct priv *p = (struct priv *) dev->priv; - - - PRINTK2(("## %s: SK_txintr() status: %#06x\n", - SK_NAME, SK_read_reg(CSR0))); - - tmdp = p->tmdhead + p->tmdlast; /* Which buffer we sent at last ? */ - - /* Set next buffer */ - p->tmdlast++; - p->tmdlast &= TMDNUM-1; - - tmdstat = tmdp->u.s.status & 0xff00; /* filter out status bits 15:08 */ - - /* - * We check status of transmitted packet. - * see LANCE data-sheet for error explanation - */ - if (tmdstat & TX_ERR) /* Error occurred */ - { - printk("%s: TX error: %04x %04x\n", dev->name, (int) tmdstat, - (int) tmdp->status2); - - if (tmdp->status2 & TX_TDR) /* TDR problems? */ - { - printk("%s: tdr-problems \n", dev->name); - } - - if (tmdp->status2 & TX_RTRY) /* Failed in 16 attempts to transmit ? */ - p->stats.tx_aborted_errors++; - if (tmdp->status2 & TX_LCOL) /* Late collision ? */ - p->stats.tx_window_errors++; - if (tmdp->status2 & TX_LCAR) /* Loss of Carrier ? */ - p->stats.tx_carrier_errors++; - if (tmdp->status2 & TX_UFLO) /* Underflow error ? */ - { - p->stats.tx_fifo_errors++; - - /* - * If UFLO error occurs it will turn transmitter of. - * So we must reinit LANCE - */ - - SK_lance_init(dev, MODE_NORMAL); - } - - p->stats.tx_errors++; - - tmdp->status2 = 0; /* Clear error flags */ - } - else if (tmdstat & TX_MORE) /* Collisions occurred ? */ - { - /* - * Here I have a problem. - * I only know that there must be one or up to 15 collisions. - * Thats why TX_MORE is set, because after 16 attempts TX_RTRY - * will be set which means couldn't send packet aborted transfer. - * - * First I did not have this in but then I thought at minimum - * we see that something was not ok. - * If anyone knows something better than this to handle this - * please report it. (see Email addresses in the README file) - */ - - p->stats.collisions++; - } - else /* Packet sent without any problems */ - { - p->stats.tx_packets++; - } - - /* - * We mark transmitter not busy anymore, because now we have a free - * transmit descriptor which can be filled by SK_send_packet and - * afterwards sent by the LANCE - */ - - dev->tbusy = 0; - - /* - * mark_bh(NET_BH); - * This will cause net_bh() to run after this interrupt handler. - * - * The function which do handle slow IRQ parts is do_bottom_half() - * which runs at normal kernel priority, that means all interrupt are - * enabled. (see kernel/irq.c) - * - * net_bh does something like this: - * - check if already in net_bh - * - try to transmit something from the send queue - * - if something is in the receive queue send it up to higher - * levels if it is a known protocol - * - try to transmit something from the send queue - */ - - mark_bh(NET_BH); - -} /* End of SK_txintr() */ - - -/*- - * Function : SK_rxintr - * Author : Patrick J.D. Weichmann - * Date Created : 94/05/27 - * - * Description : Buffer sent, check for errors, relinquish ownership - * of the receive message descriptor. - * - * Parameters : I : SK_G16 device structure - * Return Value : None - * Globals : None - * Update History : - * YY/MM/DD uid Description --*/ - -static void SK_rxintr(struct device *dev) -{ - - struct rmd *rmdp; - int rmdstat; - struct priv *p = (struct priv *) dev->priv; - - PRINTK2(("## %s: SK_rxintr(). CSR0: %#06x\n", - SK_NAME, SK_read_reg(CSR0))); - - rmdp = p->rmdhead + p->rmdnum; - - /* As long as we own the next entry, check status and send - * it up to higher layer - */ - - while (!( (rmdstat = rmdp->u.s.status) & RX_OWN)) - { - /* - * Start and end of packet must be set, because we use - * the ethernet maximum packet length (1518) as buffer size. - * - * Because our buffers are at maximum OFLO and BUFF errors are - * not to be concerned (see Data sheet) - */ - - if ((rmdstat & (RX_STP | RX_ENP)) != (RX_STP | RX_ENP)) - { - /* Start of a frame > 1518 Bytes ? */ - - if (rmdstat & RX_STP) - { - p->stats.rx_errors++; /* bad packet received */ - p->stats.rx_length_errors++; /* packet to long */ - - printk("%s: packet too long\n", dev->name); - } - - /* - * All other packets will be ignored until a new frame with - * start (RX_STP) set follows. - * - * What we do is just give descriptor free for new incoming - * packets. - */ - - rmdp->u.s.status = RX_OWN; /* Relinquish ownership to LANCE */ - - } - else if (rmdstat & RX_ERR) /* Receive Error ? */ - { - printk("%s: RX error: %04x\n", dev->name, (int) rmdstat); - - p->stats.rx_errors++; - - if (rmdstat & RX_FRAM) p->stats.rx_frame_errors++; - if (rmdstat & RX_CRC) p->stats.rx_crc_errors++; - - rmdp->u.s.status = RX_OWN; /* Relinquish ownership to LANCE */ - - } - else /* We have a packet which can be queued for the upper layers */ - { - - int len = (rmdp->mlen & 0x0fff); /* extract message length from receive buffer */ - struct sk_buff *skb; - - skb = dev_alloc_skb(len+2); /* allocate socket buffer */ - - if (skb == NULL) /* Could not get mem ? */ - { - - /* - * Couldn't allocate sk_buffer so we give descriptor back - * to Lance, update statistics and go ahead. - */ - - rmdp->u.s.status = RX_OWN; /* Relinquish ownership to LANCE */ - printk("%s: Couldn't allocate sk_buff, deferring packet.\n", - dev->name); - p->stats.rx_dropped++; - - break; /* Jump out */ - } - - /* Prepare sk_buff to queue for upper layers */ - - skb->dev = dev; - skb_reserve(skb,2); /* Align IP header on 16 byte boundary */ - - /* - * Copy data out of our receive descriptor into sk_buff. - * - * (rmdp->u.buffer & 0x00ffffff) -> get address of buffer and - * ignore status fields) - */ - - memcpy(skb_put(skb,len), (unsigned char *) (rmdp->u.buffer & 0x00ffffff), - len); - - - /* - * Notify the upper protocol layers that there is another packet - * to handle - * - * netif_rx() always succeeds. see /net/inet/dev.c for more. - */ - - skb->protocol=eth_type_trans(skb,dev); - netif_rx(skb); /* queue packet and mark it for processing */ - - /* - * Packet is queued and marked for processing so we - * free our descriptor and update statistics - */ - - rmdp->u.s.status = RX_OWN; - p->stats.rx_packets++; - - - p->rmdnum++; - p->rmdnum %= RMDNUM; - - rmdp = p->rmdhead + p->rmdnum; - } - } -} /* End of SK_rxintr() */ - - -/*- - * Function : SK_close - * Author : Patrick J.D. Weichmann - * Date Created : 94/05/26 - * - * Description : close gets called from dev_close() and should - * deinstall the card (free_irq, mem etc). - * - * Parameters : I : struct device *dev - our device structure - * Return Value : 0 - closed device driver - * Errors : None - * Globals : None - * Update History : - * YY/MM/DD uid Description --*/ - -/* I have tried to set BOOT_ROM on and RAM off but then, after a 'ifconfig - * down' the system stops. So I don't shut set card to init state. - */ - -static int SK_close(struct device *dev) -{ - - PRINTK(("## %s: SK_close(). CSR0: %#06x\n", - SK_NAME, SK_read_reg(CSR0))); - - dev->tbusy = 1; /* Transmitter busy */ - dev->start = 0; /* Card down */ - - printk("%s: Shutting %s down CSR0 %#06x\n", dev->name, SK_NAME, - (int) SK_read_reg(CSR0)); - - SK_write_reg(CSR0, CSR0_STOP); /* STOP the LANCE */ - - free_irq(dev->irq); /* Free IRQ */ - irq2dev_map[dev->irq] = 0; /* Mark IRQ as unused */ - - return 0; /* always succeed */ - -} /* End of SK_close() */ - - -/*- - * Function : SK_get_stats - * Author : Patrick J.D. Weichmann - * Date Created : 94/05/26 - * - * Description : Return current status structure to upper layers. - * It is called by sprintf_stats (dev.c). - * - * Parameters : I : struct device *dev - our device structure - * Return Value : struct enet_statistics * - our current statistics - * Errors : None - * Side Effects : None - * Update History : - * YY/MM/DD uid Description --*/ - -static struct enet_statistics *SK_get_stats(struct device *dev) -{ - - struct priv *p = (struct priv *) dev->priv; - - PRINTK(("## %s: SK_get_stats(). CSR0: %#06x\n", - SK_NAME, SK_read_reg(CSR0))); - - return &p->stats; /* Return Device status */ - -} /* End of SK_get_stats() */ - - -/*- - * Function : set_multicast_list - * Author : Patrick J.D. Weichmann - * Date Created : 94/05/26 - * - * Description : This function gets called when a program performs - * a SIOCSIFFLAGS call. Ifconfig does this if you call - * 'ifconfig [-]allmulti' which enables or disables the - * Promiscuous mode. - * Promiscuous mode is when the Network card accepts all - * packets, not only the packets which match our MAC - * Address. It is useful for writing a network monitor, - * but it is also a security problem. You have to remember - * that all information on the net is not encrypted. - * - * Parameters : I : struct device *dev - SK_G16 device Structure - * Return Value : None - * Errors : None - * Globals : None - * Update History : - * YY/MM/DD uid Description - * 95/10/18 ACox Noew multicast calling scheme --*/ - - -/* Set or clear the multicast filter for SK_G16. - */ - -static void set_multicast_list(struct device *dev) -{ - - if (dev->flags&IFF_PROMISC) - { - /* Reinitialize LANCE with MODE_PROM set */ - SK_lance_init(dev, MODE_PROM); - } - else if (dev->mc_count==0 && !(dev->flags&IFF_ALLMULTI)) - { - /* Reinitialize LANCE without MODE_PROM */ - SK_lance_init(dev, MODE_NORMAL); - } - else - { - /* Multicast with logical address filter on */ - /* Reinitialize LANCE without MODE_PROM */ - SK_lance_init(dev, MODE_NORMAL); - - /* Not implemented yet. */ - } -} /* End of set_multicast_list() */ - - - -/*- - * Function : SK_rom_addr - * Author : Patrick J.D. Weichmann - * Date Created : 94/06/01 - * - * Description : Try to find a Boot_ROM at all possible locations - * - * Parameters : None - * Return Value : Address where Boot_ROM is - * Errors : 0 - Did not find Boot_ROM - * Globals : None - * Update History : - * YY/MM/DD uid Description --*/ - -unsigned int SK_rom_addr(void) -{ - int i,j; - int rom_found = 0; - unsigned int rom_location[] = SK_BOOT_ROM_LOCATIONS; - unsigned char rom_id[] = SK_BOOT_ROM_ID; - unsigned char *test_byte; - - /* Autodetect Boot_ROM */ - PRINTK(("## %s: Autodetection of Boot_ROM\n", SK_NAME)); - - for (i = 0; (rom_location[i] != 0) && (rom_found == 0); i++) - { - - PRINTK(("## Trying ROM location %#08x", rom_location[i])); - - rom_found = 1; - for (j = 0; j < 6; j++) - { - test_byte = (unsigned char *) (rom_location[i]+j); - PRINTK((" %02x ", *test_byte)); - - if(!(*test_byte == rom_id[j])) - { - rom_found = 0; - } - } - PRINTK(("\n")); - } - - if (rom_found == 1) - { - PRINTK(("## %s: Boot_ROM found at %#08x\n", - SK_NAME, rom_location[(i-1)])); - - return (rom_location[--i]); - } - else - { - PRINTK(("%s: No Boot_ROM found\n", SK_NAME)); - return 0; - } -} /* End of SK_rom_addr() */ - - - -/* LANCE access functions - * - * ! CSR1-3 can only be accessed when in CSR0 the STOP bit is set ! - */ - - -/*- - * Function : SK_reset_board - * - * Author : Patrick J.D. Weichmann - * - * Date Created : 94/05/25 - * - * Description : This function resets SK_G16 and all components, but - * POS registers are not changed - * - * Parameters : None - * Return Value : None - * Errors : None - * Globals : SK_RAM *board - SK_RAM structure pointer - * - * Update History : - * YY/MM/DD uid Description --*/ - -void SK_reset_board(void) -{ - int i; - - SK_PORT = 0x00; /* Reset active */ - for (i = 0; i < 10 ; i++) /* Delay min 5ms */ - ; - SK_PORT = SK_RESET; /* Set back to normal operation */ - -} /* End of SK_reset_board() */ - - -/*- - * Function : SK_set_RAP - * Author : Patrick J.D. Weichmann - * Date Created : 94/05/25 - * - * Description : Set LANCE Register Address Port to register - * for later data transfer. - * - * Parameters : I : reg_number - which CSR to read/write from/to - * Return Value : None - * Errors : None - * Globals : SK_RAM *board - SK_RAM structure pointer - * Update History : - * YY/MM/DD uid Description --*/ - -void SK_set_RAP(int reg_number) -{ - SK_IOREG = reg_number; - SK_PORT = SK_RESET | SK_RAP | SK_WREG; - SK_IOCOM = SK_DOIO; - - while (SK_PORT & SK_IORUN) - ; -} /* End of SK_set_RAP() */ - - -/*- - * Function : SK_read_reg - * Author : Patrick J.D. Weichmann - * Date Created : 94/05/25 - * - * Description : Set RAP and read data from a LANCE CSR register - * - * Parameters : I : reg_number - which CSR to read from - * Return Value : Register contents - * Errors : None - * Globals : SK_RAM *board - SK_RAM structure pointer - * Update History : - * YY/MM/DD uid Description --*/ - -int SK_read_reg(int reg_number) -{ - SK_set_RAP(reg_number); - - SK_PORT = SK_RESET | SK_RDATA | SK_RREG; - SK_IOCOM = SK_DOIO; - - while (SK_PORT & SK_IORUN) - ; - return (SK_IOREG); - -} /* End of SK_read_reg() */ - - -/*- - * Function : SK_rread_reg - * Author : Patrick J.D. Weichmann - * Date Created : 94/05/28 - * - * Description : Read data from preseted register. - * This function requires that you know which - * Register is actually set. Be aware that CSR1-3 - * can only be accessed when in CSR0 STOP is set. - * - * Return Value : Register contents - * Errors : None - * Globals : SK_RAM *board - SK_RAM structure pointer - * Update History : - * YY/MM/DD uid Description --*/ - -int SK_rread_reg(void) -{ - SK_PORT = SK_RESET | SK_RDATA | SK_RREG; - - SK_IOCOM = SK_DOIO; - - while (SK_PORT & SK_IORUN) - ; - return (SK_IOREG); - -} /* End of SK_rread_reg() */ - - -/*- - * Function : SK_write_reg - * Author : Patrick J.D. Weichmann - * Date Created : 94/05/25 - * - * Description : This function sets the RAP then fills in the - * LANCE I/O Reg and starts Transfer to LANCE. - * It waits until transfer has ended which is max. 7 ms - * and then it returns. - * - * Parameters : I : reg_number - which CSR to write to - * I : value - what value to fill into register - * Return Value : None - * Errors : None - * Globals : SK_RAM *board - SK_RAM structure pointer - * Update History : - * YY/MM/DD uid Description --*/ - -void SK_write_reg(int reg_number, int value) -{ - SK_set_RAP(reg_number); - - SK_IOREG = value; - SK_PORT = SK_RESET | SK_RDATA | SK_WREG; - SK_IOCOM = SK_DOIO; - - while (SK_PORT & SK_IORUN) - ; -} /* End of SK_write_reg */ - - - -/* - * Debugging functions - * ------------------- - */ - -/*- - * Function : SK_print_pos - * Author : Patrick J.D. Weichmann - * Date Created : 94/05/25 - * - * Description : This function prints out the 4 POS (Programmable - * Option Select) Registers. Used mainly to debug operation. - * - * Parameters : I : struct device *dev - SK_G16 device structure - * I : char * - Text which will be printed as title - * Return Value : None - * Errors : None - * Update History : - * YY/MM/DD uid Description --*/ - -void SK_print_pos(struct device *dev, char *text) -{ - int ioaddr = dev->base_addr; - - unsigned char pos0 = inb(SK_POS0), - pos1 = inb(SK_POS1), - pos2 = inb(SK_POS2), - pos3 = inb(SK_POS3), - pos4 = inb(SK_POS4); - - - printk("## %s: %s.\n" - "## pos0=%#4x pos1=%#4x pos2=%#04x pos3=%#08x pos4=%#04x\n", - SK_NAME, text, pos0, pos1, pos2, (pos3<<14), pos4); - -} /* End of SK_print_pos() */ - - - -/*- - * Function : SK_print_dev - * Author : Patrick J.D. Weichmann - * Date Created : 94/05/25 - * - * Description : This function simply prints out the important fields - * of the device structure. - * - * Parameters : I : struct device *dev - SK_G16 device structure - * I : char *text - Title for printing - * Return Value : None - * Errors : None - * Update History : - * YY/MM/DD uid Description --*/ - -void SK_print_dev(struct device *dev, char *text) -{ - if (dev == NULL) - { - printk("## %s: Device Structure. %s\n", SK_NAME, text); - printk("## DEVICE == NULL\n"); - } - else - { - printk("## %s: Device Structure. %s\n", SK_NAME, text); - printk("## Device Name: %s Base Address: %#06lx IRQ: %d\n", - dev->name, dev->base_addr, dev->irq); - - printk("## FLAGS: start: %d tbusy: %ld int: %d\n", - dev->start, dev->tbusy, dev->interrupt); - - printk("## next device: %#08x init function: %#08x\n", - (int) dev->next, (int) dev->init); - } - -} /* End of SK_print_dev() */ - - - -/*- - * Function : SK_print_ram - * Author : Patrick J.D. Weichmann - * Date Created : 94/06/02 - * - * Description : This function is used to check how are things set up - * in the 16KB RAM. Also the pointers to the receive and - * transmit descriptor rings and rx and tx buffers locations. - * It contains a minor bug in printing, but has no effect to the values - * only newlines are not correct. - * - * Parameters : I : struct device *dev - SK_G16 device structure - * Return Value : None - * Errors : None - * Globals : None - * Update History : - * YY/MM/DD uid Description --*/ - -void SK_print_ram(struct device *dev) -{ - - int i; - struct priv *p = (struct priv *) dev->priv; - - printk("## %s: RAM Details.\n" - "## RAM at %#08x tmdhead: %#08x rmdhead: %#08x initblock: %#08x\n", - SK_NAME, - (unsigned int) p->ram, - (unsigned int) p->tmdhead, - (unsigned int) p->rmdhead, - (unsigned int) &(p->ram)->ib); - - printk("## "); - - for(i = 0; i < TMDNUM; i++) - { - if (!(i % 3)) /* Every third line do a newline */ - { - printk("\n## "); - } - printk("tmdbufs%d: %#08x ", (i+1), (int) p->tmdbufs[i]); - } - printk("## "); - - for(i = 0; i < RMDNUM; i++) - { - if (!(i % 3)) /* Every third line do a newline */ - { - printk("\n## "); - } - printk("rmdbufs%d: %#08x ", (i+1), (int) p->rmdbufs[i]); - } - printk("\n"); - -} /* End of SK_print_ram() */ - diff --git a/i386/i386at/gpl/linux/net/sk_g16.h b/i386/i386at/gpl/linux/net/sk_g16.h deleted file mode 100644 index 3a92f1f9..00000000 --- a/i386/i386at/gpl/linux/net/sk_g16.h +++ /dev/null @@ -1,171 +0,0 @@ -/*- - * - * This software may be used and distributed according to the terms - * of the GNU Public License, incorporated herein by reference. - * - * Module : sk_g16.h - * Version : $Revision: 1.1.1.1 $ - * - * Author : M.Hipp (mhipp@student.uni-tuebingen.de) - * changes by : Patrick J.D. Weichmann - * - * Date Created : 94/05/25 - * - * Description : In here are all necessary definitions of - * the am7990 (LANCE) chip used for writing a - * network device driver which uses this chip - * - * $Log: sk_g16.h,v $ - * Revision 1.1.1.1 1996/10/30 01:39:56 thomas - * Imported from UK22 - * - * Revision 1.3 1996/03/25 20:24:35 goel - * Linux driver merge. - * --*/ - -#ifndef SK_G16_H - -#define SK_G16_H - - -/* - * Control and Status Register 0 (CSR0) bit definitions - * - * (R=Readable) (W=Writeable) (S=Set on write) (C-Clear on write) - * - */ - -#define CSR0_ERR 0x8000 /* Error summary (R) */ -#define CSR0_BABL 0x4000 /* Babble transmitter timeout error (RC) */ -#define CSR0_CERR 0x2000 /* Collision Error (RC) */ -#define CSR0_MISS 0x1000 /* Missed packet (RC) */ -#define CSR0_MERR 0x0800 /* Memory Error (RC) */ -#define CSR0_RINT 0x0400 /* Receiver Interrupt (RC) */ -#define CSR0_TINT 0x0200 /* Transmit Interrupt (RC) */ -#define CSR0_IDON 0x0100 /* Initialization Done (RC) */ -#define CSR0_INTR 0x0080 /* Interrupt Flag (R) */ -#define CSR0_INEA 0x0040 /* Interrupt Enable (RW) */ -#define CSR0_RXON 0x0020 /* Receiver on (R) */ -#define CSR0_TXON 0x0010 /* Transmitter on (R) */ -#define CSR0_TDMD 0x0008 /* Transmit Demand (RS) */ -#define CSR0_STOP 0x0004 /* Stop (RS) */ -#define CSR0_STRT 0x0002 /* Start (RS) */ -#define CSR0_INIT 0x0001 /* Initialize (RS) */ - -#define CSR0_CLRALL 0x7f00 /* mask for all clearable bits */ - -/* - * Control and Status Register 3 (CSR3) bit definitions - * - */ - -#define CSR3_BSWAP 0x0004 /* Byte Swap (RW) */ -#define CSR3_ACON 0x0002 /* ALE Control (RW) */ -#define CSR3_BCON 0x0001 /* Byte Control (RW) */ - -/* - * Initialization Block Mode operation Bit Definitions. - */ - -#define MODE_PROM 0x8000 /* Promiscuous Mode */ -#define MODE_INTL 0x0040 /* Internal Loopback */ -#define MODE_DRTY 0x0020 /* Disable Retry */ -#define MODE_COLL 0x0010 /* Force Collision */ -#define MODE_DTCR 0x0008 /* Disable Transmit CRC) */ -#define MODE_LOOP 0x0004 /* Loopback */ -#define MODE_DTX 0x0002 /* Disable the Transmitter */ -#define MODE_DRX 0x0001 /* Disable the Receiver */ - -#define MODE_NORMAL 0x0000 /* Normal operation mode */ - -/* - * Receive message descriptor status bit definitions. - */ - -#define RX_OWN 0x80 /* Owner bit 0 = host, 1 = lance */ -#define RX_ERR 0x40 /* Error Summary */ -#define RX_FRAM 0x20 /* Framing Error */ -#define RX_OFLO 0x10 /* Overflow Error */ -#define RX_CRC 0x08 /* CRC Error */ -#define RX_BUFF 0x04 /* Buffer Error */ -#define RX_STP 0x02 /* Start of Packet */ -#define RX_ENP 0x01 /* End of Packet */ - - -/* - * Transmit message descriptor status bit definitions. - */ - -#define TX_OWN 0x80 /* Owner bit 0 = host, 1 = lance */ -#define TX_ERR 0x40 /* Error Summary */ -#define TX_MORE 0x10 /* More the 1 retry needed to Xmit */ -#define TX_ONE 0x08 /* One retry needed to Xmit */ -#define TX_DEF 0x04 /* Deferred */ -#define TX_STP 0x02 /* Start of Packet */ -#define TX_ENP 0x01 /* End of Packet */ - -/* - * Transmit status (2) (valid if TX_ERR == 1) - */ - -#define TX_BUFF 0x8000 /* Buffering error (no ENP) */ -#define TX_UFLO 0x4000 /* Underflow (late memory) */ -#define TX_LCOL 0x1000 /* Late collision */ -#define TX_LCAR 0x0400 /* Loss of Carrier */ -#define TX_RTRY 0x0200 /* Failed after 16 retransmissions */ -#define TX_TDR 0x003f /* Time-domain-reflectometer-value */ - - -/* - * Structures used for Communication with the LANCE - */ - -/* LANCE Initialize Block */ - -struct init_block -{ - unsigned short mode; /* Mode Register */ - unsigned char paddr[6]; /* Physical Address (MAC) */ - unsigned char laddr[8]; /* Logical Filter Address (not used) */ - unsigned int rdrp; /* Receive Descriptor Ring pointer */ - unsigned int tdrp; /* Transmit Descriptor Ring pointer */ -}; - - -/* Receive Message Descriptor Entry */ - -struct rmd -{ - union - { - unsigned long buffer; /* Address of buffer */ - struct - { - unsigned char unused[3]; - unsigned volatile char status; /* Status Bits */ - } s; - } u; - volatile short blen; /* Buffer Length (two's complement) */ - unsigned short mlen; /* Message Byte Count */ -}; - - -/* Transmit Message Descriptor Entry */ - -struct tmd -{ - union - { - unsigned long buffer; /* Address of buffer */ - struct - { - unsigned char unused[3]; - unsigned volatile char status; /* Status Bits */ - } s; - } u; - unsigned short blen; /* Buffer Length (two's complement) */ - unsigned volatile short status2; /* Error Status Bits */ -}; - -#endif /* End of SK_G16_H */ diff --git a/i386/i386at/gpl/linux/net/smc-ultra.c b/i386/i386at/gpl/linux/net/smc-ultra.c deleted file mode 100644 index f13cd0a7..00000000 --- a/i386/i386at/gpl/linux/net/smc-ultra.c +++ /dev/null @@ -1,419 +0,0 @@ -/* smc-ultra.c: A SMC Ultra ethernet driver for linux. */ -/* - Written 1993,1994,1995 by Donald Becker. - - Copyright 1993 United States Government as represented by the - Director, National Security Agency. - - This software may be used and distributed according to the terms - of the GNU Public License, incorporated herein by reference. - - The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O - Center of Excellence in Space Data and Information Sciences - Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771 - - This is a driver for the SMC Ultra and SMC EtherEZ ethercards. - - This driver uses the cards in the 8390-compatible, shared memory mode. - Most of the run-time complexity is handled by the generic code in - 8390.c. The code in this file is responsible for - - ultra_probe() Detecting and initializing the card. - ultra_probe1() - - ultra_open() The card-specific details of starting, stopping - ultra_reset_8390() and resetting the 8390 NIC core. - ultra_close() - - ultra_block_input() Routines for reading and writing blocks of - ultra_block_output() packet buffer memory. - - This driver enables the shared memory only when doing the actual data - transfers to avoid a bug in early version of the card that corrupted - data transferred by a AHA1542. - - This driver does not support the programmed-I/O data transfer mode of - the EtherEZ. That support (if available) is smc-ez.c. Nor does it - use the non-8390-compatible "Altego" mode. (No support currently planned.) - - Changelog: - - Paul Gortmaker : multiple card support for module users. -*/ - -static const char *version = - "smc-ultra.c:v1.12 1/18/95 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n"; - - -#include <linux/module.h> - -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/errno.h> -#include <linux/string.h> -#include <asm/io.h> -#include <asm/system.h> - -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include "8390.h" - -/* A zero-terminated list of I/O addresses to be probed. */ -static unsigned int ultra_portlist[] = -{0x200, 0x220, 0x240, 0x280, 0x300, 0x340, 0x380, 0}; - -int ultra_probe(struct device *dev); -int ultra_probe1(struct device *dev, int ioaddr); - -static int ultra_open(struct device *dev); -static void ultra_reset_8390(struct device *dev); -static void ultra_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, - int ring_page); -static void ultra_block_input(struct device *dev, int count, - struct sk_buff *skb, int ring_offset); -static void ultra_block_output(struct device *dev, int count, - const unsigned char *buf, const start_page); -static int ultra_close_card(struct device *dev); - - -#define START_PG 0x00 /* First page of TX buffer */ - -#define ULTRA_CMDREG 0 /* Offset to ASIC command register. */ -#define ULTRA_RESET 0x80 /* Board reset, in ULTRA_CMDREG. */ -#define ULTRA_MEMENB 0x40 /* Enable the shared memory. */ -#define ULTRA_NIC_OFFSET 16 /* NIC register offset from the base_addr. */ -#define ULTRA_IO_EXTENT 32 - -/* Probe for the Ultra. This looks like a 8013 with the station - address PROM at I/O ports <base>+8 to <base>+13, with a checksum - following. -*/ -#ifdef HAVE_DEVLIST -struct netdev_entry ultra_drv = -{"ultra", ultra_probe1, NETCARD_IO_EXTENT, netcard_portlist}; -#else - -int ultra_probe(struct device *dev) -{ - int i; - int base_addr = dev ? dev->base_addr : 0; - - if (base_addr > 0x1ff) /* Check a single specified location. */ - return ultra_probe1(dev, base_addr); - else if (base_addr != 0) /* Don't probe at all. */ - return ENXIO; - - for (i = 0; ultra_portlist[i]; i++) { - int ioaddr = ultra_portlist[i]; - if (check_region(ioaddr, ULTRA_IO_EXTENT)) - continue; - if (ultra_probe1(dev, ioaddr) == 0) - return 0; - } - - return ENODEV; -} -#endif - -int ultra_probe1(struct device *dev, int ioaddr) -{ - int i; - int checksum = 0; - const char *model_name; - unsigned char eeprom_irq = 0; - static unsigned version_printed = 0; - /* Values from various config regs. */ - unsigned char num_pages, irqreg, addr; - unsigned char idreg = inb(ioaddr + 7); - unsigned char reg4 = inb(ioaddr + 4) & 0x7f; - - /* Check the ID nibble. */ - if ((idreg & 0xF0) != 0x20 /* SMC Ultra */ - && (idreg & 0xF0) != 0x40) /* SMC EtherEZ */ - return ENODEV; - - /* Select the station address register set. */ - outb(reg4, ioaddr + 4); - - for (i = 0; i < 8; i++) - checksum += inb(ioaddr + 8 + i); - if ((checksum & 0xff) != 0xFF) - return ENODEV; - - /* We should have a "dev" from Space.c or the static module table. */ - if (dev == NULL) { - printk("smc-ultra.c: Passed a NULL device.\n"); - dev = init_etherdev(0, 0); - } - - if (ei_debug && version_printed++ == 0) - printk(version); - - model_name = (idreg & 0xF0) == 0x20 ? "SMC Ultra" : "SMC EtherEZ"; - - printk("%s: %s at %#3x,", dev->name, model_name, ioaddr); - - for (i = 0; i < 6; i++) - printk(" %2.2X", dev->dev_addr[i] = inb(ioaddr + 8 + i)); - - /* Switch from the station address to the alternate register set and - read the useful registers there. */ - outb(0x80 | reg4, ioaddr + 4); - - /* Enabled FINE16 mode to avoid BIOS ROM width mismatches @ reboot. */ - outb(0x80 | inb(ioaddr + 0x0c), ioaddr + 0x0c); - irqreg = inb(ioaddr + 0xd); - addr = inb(ioaddr + 0xb); - - /* Switch back to the station address register set so that the MS-DOS driver - can find the card after a warm boot. */ - outb(reg4, ioaddr + 4); - - if (dev->irq < 2) { - unsigned char irqmap[] = {0, 9, 3, 5, 7, 10, 11, 15}; - int irq; - - /* The IRQ bits are split. */ - irq = irqmap[((irqreg & 0x40) >> 4) + ((irqreg & 0x0c) >> 2)]; - - if (irq == 0) { - printk(", failed to detect IRQ line.\n"); - return -EAGAIN; - } - dev->irq = irq; - eeprom_irq = 1; - } - - /* Allocate dev->priv and fill in 8390 specific dev fields. */ - if (ethdev_init(dev)) { - printk (", no memory for dev->priv.\n"); - return -ENOMEM; - } - - /* OK, we are certain this is going to work. Setup the device. */ - request_region(ioaddr, ULTRA_IO_EXTENT, model_name); - - /* The 8390 isn't at the base address, so fake the offset */ - dev->base_addr = ioaddr+ULTRA_NIC_OFFSET; - - { - int addr_tbl[4] = {0x0C0000, 0x0E0000, 0xFC0000, 0xFE0000}; - short num_pages_tbl[4] = {0x20, 0x40, 0x80, 0xff}; - - dev->mem_start = ((addr & 0x0f) << 13) + addr_tbl[(addr >> 6) & 3] ; - num_pages = num_pages_tbl[(addr >> 4) & 3]; - } - - ei_status.name = model_name; - ei_status.word16 = 1; - ei_status.tx_start_page = START_PG; - ei_status.rx_start_page = START_PG + TX_PAGES; - ei_status.stop_page = num_pages; - - dev->rmem_start = dev->mem_start + TX_PAGES*256; - dev->mem_end = dev->rmem_end - = dev->mem_start + (ei_status.stop_page - START_PG)*256; - - printk(",%s IRQ %d memory %#lx-%#lx.\n", eeprom_irq ? "" : "assigned ", - dev->irq, dev->mem_start, dev->mem_end-1); - - ei_status.reset_8390 = &ultra_reset_8390; - ei_status.block_input = &ultra_block_input; - ei_status.block_output = &ultra_block_output; - ei_status.get_8390_hdr = &ultra_get_8390_hdr; - dev->open = &ultra_open; - dev->stop = &ultra_close_card; - NS8390_init(dev, 0); - - return 0; -} - -static int -ultra_open(struct device *dev) -{ - int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */ - - if (request_irq(dev->irq, ei_interrupt, 0, ei_status.name)) - return -EAGAIN; - - outb(ULTRA_MEMENB, ioaddr); /* Enable memory, 16 bit mode. */ - outb(0x80, ioaddr + 5); - outb(0x01, ioaddr + 6); /* Enable interrupts and memory. */ - ei_open(dev); - MOD_INC_USE_COUNT; - return 0; -} - -static void -ultra_reset_8390(struct device *dev) -{ - int cmd_port = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC base addr */ - - outb(ULTRA_RESET, cmd_port); - if (ei_debug > 1) printk("resetting Ultra, t=%ld...", jiffies); - ei_status.txing = 0; - - outb(ULTRA_MEMENB, cmd_port); - - if (ei_debug > 1) printk("reset done\n"); - return; -} - -/* Grab the 8390 specific header. Similar to the block_input routine, but - we don't need to be concerned with ring wrap as the header will be at - the start of a page, so we optimize accordingly. */ - -static void -ultra_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page) -{ - - unsigned long hdr_start = dev->mem_start + ((ring_page - START_PG)<<8); - - outb(ULTRA_MEMENB, dev->base_addr - ULTRA_NIC_OFFSET); /* shmem on */ -#ifdef notdef - /* Officially this is what we are doing, but the readl() is faster */ - memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr)); -#else - ((unsigned int*)hdr)[0] = readl(hdr_start); -#endif - outb(0x00, dev->base_addr - ULTRA_NIC_OFFSET); /* shmem off */ -} - -/* Block input and output are easy on shared memory ethercards, the only - complication is when the ring buffer wraps. */ - -static void -ultra_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset) -{ - unsigned long xfer_start = dev->mem_start + ring_offset - (START_PG<<8); - - /* Enable shared memory. */ - outb(ULTRA_MEMENB, dev->base_addr - ULTRA_NIC_OFFSET); - - if (xfer_start + count > dev->rmem_end) { - /* We must wrap the input move. */ - int semi_count = dev->rmem_end - xfer_start; - memcpy_fromio(skb->data, xfer_start, semi_count); - count -= semi_count; - memcpy_fromio(skb->data + semi_count, dev->rmem_start, count); - } else { - /* Packet is in one chunk -- we can copy + cksum. */ - eth_io_copy_and_sum(skb, xfer_start, count, 0); - } - - outb(0x00, dev->base_addr - ULTRA_NIC_OFFSET); /* Disable memory. */ -} - -static void -ultra_block_output(struct device *dev, int count, const unsigned char *buf, - int start_page) -{ - unsigned long shmem = dev->mem_start + ((start_page - START_PG)<<8); - - /* Enable shared memory. */ - outb(ULTRA_MEMENB, dev->base_addr - ULTRA_NIC_OFFSET); - - memcpy_toio(shmem, buf, count); - - outb(0x00, dev->base_addr - ULTRA_NIC_OFFSET); /* Disable memory. */ -} - -static int -ultra_close_card(struct device *dev) -{ - int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* CMDREG */ - - dev->start = 0; - dev->tbusy = 1; - - if (ei_debug > 1) - printk("%s: Shutting down ethercard.\n", dev->name); - - outb(0x00, ioaddr + 6); /* Disable interrupts. */ - free_irq(dev->irq); - irq2dev_map[dev->irq] = 0; - - NS8390_init(dev, 0); - - /* We should someday disable shared memory and change to 8-bit mode - "just in case"... */ - - MOD_DEC_USE_COUNT; - - return 0; -} - - -#ifdef MODULE -#define MAX_ULTRA_CARDS 4 /* Max number of Ultra cards per module */ -#define NAMELEN 8 /* # of chars for storing dev->name */ -static char namelist[NAMELEN * MAX_ULTRA_CARDS] = { 0, }; -static struct device dev_ultra[MAX_ULTRA_CARDS] = { - { - NULL, /* assign a chunk of namelist[] below */ - 0, 0, 0, 0, - 0, 0, - 0, 0, 0, NULL, NULL - }, -}; - -static int io[MAX_ULTRA_CARDS] = { 0, }; -static int irq[MAX_ULTRA_CARDS] = { 0, }; - -/* This is set up so that only a single autoprobe takes place per call. -ISA device autoprobes on a running machine are not recommended. */ -int -init_module(void) -{ - int this_dev, found = 0; - - for (this_dev = 0; this_dev < MAX_ULTRA_CARDS; this_dev++) { - struct device *dev = &dev_ultra[this_dev]; - dev->name = namelist+(NAMELEN*this_dev); - dev->irq = irq[this_dev]; - dev->base_addr = io[this_dev]; - dev->init = ultra_probe; - if (io[this_dev] == 0) { - if (this_dev != 0) break; /* only autoprobe 1st one */ - printk(KERN_NOTICE "smc-ultra.c: Presently autoprobing (not recommended) for a single card.\n"); - } - if (register_netdev(dev) != 0) { - printk(KERN_WARNING "smc-ultra.c: No SMC Ultra card found (i/o = 0x%x).\n", io[this_dev]); - if (found != 0) return 0; /* Got at least one. */ - return -ENXIO; - } - found++; - } - - return 0; -} - -void -cleanup_module(void) -{ - int this_dev; - - for (this_dev = 0; this_dev < MAX_ULTRA_CARDS; this_dev++) { - struct device *dev = &dev_ultra[this_dev]; - if (dev->priv != NULL) { - /* NB: ultra_close_card() does free_irq + irq2dev */ - int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; - kfree(dev->priv); - dev->priv = NULL; - release_region(ioaddr, ULTRA_IO_EXTENT); - unregister_netdev(dev); - } - } -} -#endif /* MODULE */ - - -/* - * Local variables: - * compile-command: "gcc -D__KERNEL__ -Wall -O6 -I/usr/src/linux/net/inet -c smc-ultra.c" - * version-control: t - * kept-new-versions: 5 - * c-indent-level: 4 - * tab-width: 4 - * End: - */ diff --git a/i386/i386at/gpl/linux/net/tulip.c b/i386/i386at/gpl/linux/net/tulip.c deleted file mode 100644 index 3386a9b8..00000000 --- a/i386/i386at/gpl/linux/net/tulip.c +++ /dev/null @@ -1,782 +0,0 @@ -/* tulip.c: A DEC 21040 ethernet driver for linux. */ -/* - NOTICE: this version works with kernels 1.1.82 and later only! - Written 1994,1995 by Donald Becker. - - This software may be used and distributed according to the terms - of the GNU Public License, incorporated herein by reference. - - This driver is for the SMC EtherPower PCI ethernet adapter. - It should work with most other DEC 21*40-based ethercards. - - The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O - Center of Excellence in Space Data and Information Sciences - Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771 -*/ - -static const char *version = "tulip.c:v0.05 1/20/95 becker@cesdis.gsfc.nasa.gov\n"; - -#include <linux/module.h> - -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/string.h> -#include <linux/ptrace.h> -#include <linux/errno.h> -#include <linux/ioport.h> -#include <linux/malloc.h> -#include <linux/interrupt.h> -#include <linux/pci.h> -#include <linux/bios32.h> -#include <asm/bitops.h> -#include <asm/io.h> -#include <asm/dma.h> - -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> - -/* The total size is unusually large: The 21040 aligns each of its 16 - longword-wide registers on a quadword boundary. */ -#define TULIP_TOTAL_SIZE 0x80 - -#ifdef HAVE_DEVLIST -struct netdev_entry tulip_drv = -{"Tulip", tulip_pci_probe, TULIP_TOTAL_SIZE, NULL}; -#endif - -#define TULIP_DEBUG 1 -#ifdef TULIP_DEBUG -int tulip_debug = TULIP_DEBUG; -#else -int tulip_debug = 1; -#endif - -/* - Theory of Operation - -I. Board Compatibility - -This device driver is designed for the DECchip 21040 "Tulip", Digital's -single-chip ethernet controller for PCI, as used on the SMC EtherPower -ethernet adapter. - -II. Board-specific settings - -PCI bus devices are configured by the system at boot time, so no jumpers -need to be set on the board. The system BIOS should be set to assign the -PCI INTA signal to an otherwise unused system IRQ line. While it's -physically possible to shared PCI interrupt lines, the kernel doesn't -support it. - -III. Driver operation - -IIIa. Ring buffers -The Tulip can use either ring buffers or lists of Tx and Rx descriptors. -The current driver uses a statically allocated Rx ring of descriptors and -buffers, and a list of the Tx buffers. - -IIIC. Synchronization -The driver runs as two independent, single-threaded flows of control. One -is the send-packet routine, which enforces single-threaded use by the -dev->tbusy flag. The other thread is the interrupt handler, which is single -threaded by the hardware and other software. - -The send packet thread has partial control over the Tx ring and 'dev->tbusy' -flag. It sets the tbusy flag whenever it's queuing a Tx packet. If the next -queue slot is empty, it clears the tbusy flag when finished otherwise it sets -the 'tp->tx_full' flag. - -The interrupt handler has exclusive control over the Rx ring and records stats -from the Tx ring. (The Tx-done interrupt can't be selectively turned off, so -we can't avoid the interrupt overhead by having the Tx routine reap the Tx -stats.) After reaping the stats, it marks the queue entry as empty by setting -the 'base' to zero. Iff the 'tp->tx_full' flag is set, it clears both the -tx_full and tbusy flags. - -IV. Notes - -Thanks to Duke Kamstra of SMC for providing an EtherPower board. - -The DEC databook doesn't document which Rx filter settings accept broadcast -packets. Nor does it document how to configure the part to configure the -serial subsystem for normal (vs. loopback) operation or how to have it -autoswitch between internal 10baseT, SIA and AUI transceivers. - -The databook claims that CSR13, CSR14, and CSR15 should each be the last -register of the set CSR12-15 written. Hmmm, now how is that possible? -*/ - -#define DEC_VENDOR_ID 0x1011 /* Hex 'D' :-> */ -#define DEC_21040_ID 0x0002 /* Change for 21140. */ - -/* Keep the ring sizes a power of two for efficiency. */ -#define TX_RING_SIZE 4 -#define RX_RING_SIZE 4 -#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/ - -/* Offsets to the Command and Status Registers, "CSRs". All accesses - must be longword instructions and quadword aligned. */ -enum tulip_offsets { - CSR0=0, CSR1=0x08, CSR2=0x10, CSR3=0x18, CSR4=0x20, CSR5=0x28, - CSR6=0x30, CSR7=0x38, CSR8=0x40, CSR9=0x48, CSR10=0x50, CSR11=0x58, - CSR12=0x60, CSR13=0x68, CSR14=0x70, CSR15=0x78 }; - -/* The Tulip Rx and Tx buffer descriptors. */ -struct tulip_rx_desc { - int status; - int length; - char *buffer1, *buffer2; /* We use only buffer 1. */ -}; - -struct tulip_tx_desc { - int status; - int length; - char *buffer1, *buffer2; /* We use only buffer 1. */ -}; - -struct tulip_private { - char devname[8]; /* Used only for kernel debugging. */ - struct tulip_rx_desc rx_ring[RX_RING_SIZE]; - struct tulip_tx_desc tx_ring[TX_RING_SIZE]; - /* The saved address of a sent-in-place packet/buffer, for skfree(). */ - struct sk_buff* tx_skbuff[TX_RING_SIZE]; - long rx_buffs; /* Address of temporary Rx buffers. */ - struct enet_statistics stats; - int setup_frame[48]; /* Pseudo-Tx frame to init address table. */ - unsigned int cur_rx, cur_tx; /* The next free ring entry */ - unsigned int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */ - unsigned int tx_full:1; - int pad0, pad1; /* Used for 8-byte alignment */ -}; - -static void tulip_probe1(int ioaddr, int irq); -static int tulip_open(struct device *dev); -static void tulip_init_ring(struct device *dev); -static int tulip_start_xmit(struct sk_buff *skb, struct device *dev); -static int tulip_rx(struct device *dev); -static void tulip_interrupt(int irq, struct pt_regs *regs); -static int tulip_close(struct device *dev); -static struct enet_statistics *tulip_get_stats(struct device *dev); -static void set_multicast_list(struct device *dev); -static int set_mac_address(struct device *dev, void *addr); - - - -#ifndef MODULE -/* This 21040 probe is unlike most other board probes. We can use memory - efficiently by allocating a large contiguous region and dividing it - ourselves. This is done by having the initialization occur before - the 'kmalloc()' memory management system is started. */ - -int dec21040_init(void) -{ - - if (pcibios_present()) { - int pci_index; - for (pci_index = 0; pci_index < 8; pci_index++) { - unsigned char pci_bus, pci_device_fn, pci_irq_line; - unsigned long pci_ioaddr; - - if (pcibios_find_device (DEC_VENDOR_ID, DEC_21040_ID, pci_index, - &pci_bus, &pci_device_fn) != 0) - break; - pcibios_read_config_byte(pci_bus, pci_device_fn, - PCI_INTERRUPT_LINE, &pci_irq_line); - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_0, &pci_ioaddr); - /* Remove I/O space marker in bit 0. */ - pci_ioaddr &= ~3; - if (tulip_debug > 2) - printk("Found DEC PCI Tulip at I/O %#lx, IRQ %d.\n", - pci_ioaddr, pci_irq_line); - tulip_probe1(pci_ioaddr, pci_irq_line); - } - } - - return 0; -} -#endif -#ifdef MODULE -static int tulip_probe(struct device *dev) -{ - printk("tulip: This driver does not yet install properly from module!\n"); - return -1; -} -#endif - -static void tulip_probe1(int ioaddr, int irq) -{ - static int did_version = 0; /* Already printed version info. */ - struct device *dev; - struct tulip_private *tp; - int i; - - if (tulip_debug > 0 && did_version++ == 0) - printk(version); - - dev = init_etherdev(0, 0); - - printk("%s: DEC 21040 Tulip at %#3x,", dev->name, ioaddr); - - /* Stop the chip's Tx and Rx processes. */ - outl(inl(ioaddr + CSR6) & ~0x2002, ioaddr + CSR6); - /* Clear the missed-packet counter. */ - inl(ioaddr + CSR8) & 0xffff; - - /* The station address ROM is read byte serially. The register must - be polled, waiting for the value to be read bit serially from the - EEPROM. - */ - outl(0, ioaddr + CSR9); /* Reset the pointer with a dummy write. */ - for (i = 0; i < 6; i++) { - int value, boguscnt = 100000; - do - value = inl(ioaddr + CSR9); - while (value < 0 && --boguscnt > 0); - printk(" %2.2x", dev->dev_addr[i] = value); - } - printk(", IRQ %d\n", irq); - - /* We do a request_region() only to register /proc/ioports info. */ - request_region(ioaddr, TULIP_TOTAL_SIZE, "DEC Tulip Ethernet"); - - dev->base_addr = ioaddr; - dev->irq = irq; - - /* Make certain the data structures are quadword aligned. */ - tp = kmalloc(sizeof(*tp), GFP_KERNEL | GFP_DMA); - dev->priv = tp; - tp->rx_buffs = kmalloc(PKT_BUF_SZ*RX_RING_SIZE, GFP_KERNEL | GFP_DMA); - - /* The Tulip-specific entries in the device structure. */ - dev->open = &tulip_open; - dev->hard_start_xmit = &tulip_start_xmit; - dev->stop = &tulip_close; - dev->get_stats = &tulip_get_stats; - dev->set_multicast_list = &set_multicast_list; - dev->set_mac_address = &set_mac_address; - - return; -} - - -static int -tulip_open(struct device *dev) -{ - struct tulip_private *tp = (struct tulip_private *)dev->priv; - int ioaddr = dev->base_addr; - - /* Reset the chip, holding bit 0 set at least 10 PCI cycles. */ - outl(0xfff80001, ioaddr + CSR0); - SLOW_DOWN_IO; - /* Deassert reset. Set 8 longword cache alignment, 8 longword burst. - Cache alignment bits 15:14 Burst length 13:8 - 0000 No alignment 0x00000000 unlimited 0800 8 longwords - 4000 8 longwords 0100 1 longword 1000 16 longwords - 8000 16 longwords 0200 2 longwords 2000 32 longwords - C000 32 longwords 0400 4 longwords - Wait the specified 50 PCI cycles after a reset by initializing - Tx and Rx queues and the address filter list. */ - outl(0xfff84800, ioaddr + CSR0); - - if (irq2dev_map[dev->irq] != NULL - || (irq2dev_map[dev->irq] = dev) == NULL - || dev->irq == 0 - || request_irq(dev->irq, &tulip_interrupt, 0, "DEC 21040 Tulip")) { - return -EAGAIN; - } - - if (tulip_debug > 1) - printk("%s: tulip_open() irq %d.\n", dev->name, dev->irq); - - tulip_init_ring(dev); - - /* Fill the whole address filter table with our physical address. */ - { - unsigned short *eaddrs = (unsigned short *)dev->dev_addr; - int *setup_frm = tp->setup_frame, i; - - /* You must add the broadcast address when doing perfect filtering! */ - *setup_frm++ = 0xffff; - *setup_frm++ = 0xffff; - *setup_frm++ = 0xffff; - /* Fill the rest of the accept table with our physical address. */ - for (i = 1; i < 16; i++) { - *setup_frm++ = eaddrs[0]; - *setup_frm++ = eaddrs[1]; - *setup_frm++ = eaddrs[2]; - } - /* Put the setup frame on the Tx list. */ - tp->tx_ring[0].length = 0x08000000 | 192; - tp->tx_ring[0].buffer1 = (char *)tp->setup_frame; - tp->tx_ring[0].buffer2 = 0; - tp->tx_ring[0].status = 0x80000000; - - tp->cur_tx++, tp->dirty_tx++; - } - - outl((int)tp->rx_ring, ioaddr + CSR3); - outl((int)tp->tx_ring, ioaddr + CSR4); - - /* Turn on the xcvr interface. */ - outl(0x00000000, ioaddr + CSR13); - outl(0x00000004, ioaddr + CSR13); - - /* Start the chip's Tx and Rx processes. */ - outl(0xfffe2002, ioaddr + CSR6); - - /* Trigger an immediate transmit demand to process the setup frame. */ - outl(0, ioaddr + CSR1); - - dev->tbusy = 0; - dev->interrupt = 0; - dev->start = 1; - - /* Enable interrupts by setting the interrupt mask. */ - outl(0xFFFFFFFF, ioaddr + CSR7); - - if (tulip_debug > 2) { - printk("%s: Done tulip_open(), CSR0 %8.8x, CSR13 %8.8x.\n", - dev->name, inl(ioaddr + CSR0), inl(ioaddr + CSR13)); - } - MOD_INC_USE_COUNT; - return 0; -} - -/* Initialize the Rx and Tx rings, along with various 'dev' bits. */ -static void -tulip_init_ring(struct device *dev) -{ - struct tulip_private *tp = (struct tulip_private *)dev->priv; - int i; - - tp->tx_full = 0; - tp->cur_rx = tp->cur_tx = 0; - tp->dirty_rx = tp->dirty_tx = 0; - - for (i = 0; i < RX_RING_SIZE; i++) { - tp->rx_ring[i].status = 0x80000000; /* Owned by Tulip chip */ - tp->rx_ring[i].length = PKT_BUF_SZ; - tp->rx_ring[i].buffer1 = (char *)(tp->rx_buffs + i*PKT_BUF_SZ); - tp->rx_ring[i].buffer2 = (char *)&tp->rx_ring[i+1]; - } - /* Mark the last entry as wrapping the ring. */ - tp->rx_ring[i-1].length = PKT_BUF_SZ | 0x02000000; - tp->rx_ring[i-1].buffer2 = (char *)&tp->rx_ring[0]; - - /* The Tx buffer descriptor is filled in as needed, but we - do need to clear the ownership bit. */ - for (i = 0; i < TX_RING_SIZE; i++) { - tp->tx_ring[i].status = 0x00000000; - } -} - -static int -tulip_start_xmit(struct sk_buff *skb, struct device *dev) -{ - struct tulip_private *tp = (struct tulip_private *)dev->priv; - int ioaddr = dev->base_addr; - int entry; - - /* Transmitter timeout, serious problems. */ - if (dev->tbusy) { - int tickssofar = jiffies - dev->trans_start; - int i; - if (tickssofar < 20) - return 1; - printk("%s: transmit timed out, status %8.8x, SIA %8.8x %8.8x %8.8x %8.8x, resetting...\n", - dev->name, inl(ioaddr + CSR5), inl(ioaddr + CSR12), - inl(ioaddr + CSR13), inl(ioaddr + CSR14), inl(ioaddr + CSR15)); - printk(" Rx ring %8.8x: ", (int)tp->rx_ring); - for (i = 0; i < RX_RING_SIZE; i++) - printk(" %8.8x", (unsigned int)tp->rx_ring[i].status); - printk("\n Tx ring %8.8x: ", (int)tp->tx_ring); - for (i = 0; i < TX_RING_SIZE; i++) - printk(" %8.8x", (unsigned int)tp->tx_ring[i].status); - printk("\n"); - - tp->stats.tx_errors++; - /* We should reinitialize the hardware here. */ - dev->tbusy=0; - dev->trans_start = jiffies; - return 0; - } - - if (skb == NULL || skb->len <= 0) { - printk("%s: Obsolete driver layer request made: skbuff==NULL.\n", - dev->name); - dev_tint(dev); - return 0; - } - - /* Block a timer-based transmit from overlapping. This could better be - done with atomic_swap(1, dev->tbusy), but set_bit() works as well. - If this ever occurs the queue layer is doing something evil! */ - if (set_bit(0, (void*)&dev->tbusy) != 0) { - printk("%s: Transmitter access conflict.\n", dev->name); - return 1; - } - - /* Caution: the write order is important here, set the base address - with the "ownership" bits last. */ - - /* Calculate the next Tx descriptor entry. */ - entry = tp->cur_tx % TX_RING_SIZE; - - tp->tx_full = 1; - tp->tx_skbuff[entry] = skb; - tp->tx_ring[entry].length = skb->len | - (entry == TX_RING_SIZE-1 ? 0xe2000000 : 0xe0000000); - tp->tx_ring[entry].buffer1 = skb->data; - tp->tx_ring[entry].buffer2 = 0; - tp->tx_ring[entry].status = 0x80000000; /* Pass ownership to the chip. */ - - tp->cur_tx++; - - /* Trigger an immediate transmit demand. */ - outl(0, ioaddr + CSR1); - - dev->trans_start = jiffies; - - return 0; -} - -/* The interrupt handler does all of the Rx thread work and cleans up - after the Tx thread. */ -static void tulip_interrupt(int irq, struct pt_regs *regs) -{ - struct device *dev = (struct device *)(irq2dev_map[irq]); - struct tulip_private *lp; - int csr5, ioaddr, boguscnt=10; - - if (dev == NULL) { - printk ("tulip_interrupt(): irq %d for unknown device.\n", irq); - return; - } - - ioaddr = dev->base_addr; - lp = (struct tulip_private *)dev->priv; - if (dev->interrupt) - printk("%s: Re-entering the interrupt handler.\n", dev->name); - - dev->interrupt = 1; - - do { - csr5 = inl(ioaddr + CSR5); - /* Acknowledge all of the current interrupt sources ASAP. */ - outl(csr5 & 0x0001ffff, ioaddr + CSR5); - - if (tulip_debug > 4) - printk("%s: interrupt csr5=%#8.8x new csr5=%#8.8x.\n", - dev->name, csr5, inl(dev->base_addr + CSR5)); - - if ((csr5 & 0x00018000) == 0) - break; - - if (csr5 & 0x0040) /* Rx interrupt */ - tulip_rx(dev); - - if (csr5 & 0x0001) { /* Tx-done interrupt */ - int dirty_tx = lp->dirty_tx; - - while (dirty_tx < lp->cur_tx) { - int entry = dirty_tx % TX_RING_SIZE; - int status = lp->tx_ring[entry].status; - - if (status < 0) - break; /* It still hasn't been Txed */ - - if (status & 0x8000) { - /* There was an major error, log it. */ - lp->stats.tx_errors++; - if (status & 0x4104) lp->stats.tx_aborted_errors++; - if (status & 0x0C00) lp->stats.tx_carrier_errors++; - if (status & 0x0200) lp->stats.tx_window_errors++; - if (status & 0x0002) lp->stats.tx_fifo_errors++; - if (status & 0x0080) lp->stats.tx_heartbeat_errors++; -#ifdef ETHER_STATS - if (status & 0x0100) lp->stats.collisions16++; -#endif - } else { -#ifdef ETHER_STATS - if (status & 0x0001) lp->stats.tx_deferred++; -#endif - lp->stats.collisions += (status >> 3) & 15; - lp->stats.tx_packets++; - } - - /* Free the original skb. */ - dev_kfree_skb(lp->tx_skbuff[entry], FREE_WRITE); - dirty_tx++; - } - -#ifndef final_version - if (lp->cur_tx - dirty_tx >= TX_RING_SIZE) { - printk("out-of-sync dirty pointer, %d vs. %d, full=%d.\n", - dirty_tx, lp->cur_tx, lp->tx_full); - dirty_tx += TX_RING_SIZE; - } -#endif - - if (lp->tx_full && dev->tbusy - && dirty_tx > lp->cur_tx - TX_RING_SIZE + 2) { - /* The ring is no longer full, clear tbusy. */ - lp->tx_full = 0; - dev->tbusy = 0; - mark_bh(NET_BH); - } - - lp->dirty_tx = dirty_tx; - } - - /* Log errors. */ - if (csr5 & 0x8000) { /* Abnormal error summary bit. */ - if (csr5 & 0x0008) lp->stats.tx_errors++; /* Tx babble. */ - if (csr5 & 0x0100) { /* Missed a Rx frame. */ - lp->stats.rx_errors++; - lp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff; - } - if (csr5 & 0x0800) { - printk("%s: Something Wicked happened! %8.8x.\n", - dev->name, csr5); - /* Hmmmmm, it's not clear what to do here. */ - } - } - if (--boguscnt < 0) { - printk("%s: Too much work at interrupt, csr5=0x%8.8x.\n", - dev->name, csr5); - /* Clear all interrupt sources. */ - outl(0x0001ffff, ioaddr + CSR5); - break; - } - } while (1); - - if (tulip_debug > 3) - printk("%s: exiting interrupt, csr5=%#4.4x.\n", - dev->name, inl(ioaddr + CSR5)); - - /* Special code for testing *only*. */ - { - static int stopit = 10; - if (dev->start == 0 && --stopit < 0) { - printk("%s: Emergency stop, looping startup interrupt.\n", - dev->name); - free_irq(irq); - } - } - - dev->interrupt = 0; - return; -} - -static int -tulip_rx(struct device *dev) -{ - struct tulip_private *lp = (struct tulip_private *)dev->priv; - int entry = lp->cur_rx % RX_RING_SIZE; - int i; - - if (tulip_debug > 4) - printk(" In tulip_rx().\n"); - /* If we own the next entry, it's a new packet. Send it up. */ - while (lp->rx_ring[entry].status >= 0) { - int status = lp->rx_ring[entry].status; - - if (tulip_debug > 4) - printk(" tulip_rx() status was %8.8x.\n", status); - if ((status & 0x0300) != 0x0300) { - printk("%s: Ethernet frame spanned multiple buffers, status %8.8x!\n", - dev->name, status); - } else if (status & 0x8000) { - /* There was a fatal error. */ - lp->stats.rx_errors++; /* end of a packet.*/ - if (status & 0x0890) lp->stats.rx_length_errors++; - if (status & 0x0004) lp->stats.rx_frame_errors++; - if (status & 0x0002) lp->stats.rx_crc_errors++; - if (status & 0x0001) lp->stats.rx_fifo_errors++; - } else { - /* Malloc up new buffer, compatible with net-2e. */ - short pkt_len = lp->rx_ring[entry].status >> 16; - struct sk_buff *skb; - - skb = dev_alloc_skb(pkt_len+2); - if (skb == NULL) { - printk("%s: Memory squeeze, deferring packet.\n", dev->name); - /* Check that at least two ring entries are free. - If not, free one and mark stats->rx_dropped++. */ - for (i=0; i < RX_RING_SIZE; i++) - if (lp->rx_ring[(entry+i) % RX_RING_SIZE].status < 0) - break; - - if (i > RX_RING_SIZE -2) { - lp->stats.rx_dropped++; - lp->rx_ring[entry].status = 0x80000000; - lp->cur_rx++; - } - break; - } - skb->dev = dev; - skb_reserve(skb,2); /* 16 byte align the data fields */ - memcpy(skb_put(skb,pkt_len), lp->rx_ring[entry].buffer1, pkt_len); - skb->protocol=eth_type_trans(skb,dev); - netif_rx(skb); - lp->stats.rx_packets++; - } - - lp->rx_ring[entry].status = 0x80000000; - entry = (++lp->cur_rx) % RX_RING_SIZE; - } - - return 0; -} - -static int -tulip_close(struct device *dev) -{ - int ioaddr = dev->base_addr; - struct tulip_private *tp = (struct tulip_private *)dev->priv; - - dev->start = 0; - dev->tbusy = 1; - - if (tulip_debug > 1) - printk("%s: Shutting down ethercard, status was %2.2x.\n", - dev->name, inl(ioaddr + CSR5)); - - /* Disable interrupts by clearing the interrupt mask. */ - outl(0x00000000, ioaddr + CSR7); - /* Stop the chip's Tx and Rx processes. */ - outl(inl(ioaddr + CSR6) & ~0x2002, ioaddr + CSR6); - - tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff; - - free_irq(dev->irq); - irq2dev_map[dev->irq] = 0; - - MOD_DEC_USE_COUNT; - return 0; -} - -static struct enet_statistics * -tulip_get_stats(struct device *dev) -{ - struct tulip_private *tp = (struct tulip_private *)dev->priv; - short ioaddr = dev->base_addr; - - tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff; - - return &tp->stats; -} - -/* - * Set or clear the multicast filter for this adaptor. - */ - -static void set_multicast_list(struct device *dev) -{ - short ioaddr = dev->base_addr; - int csr6 = inl(ioaddr + CSR6) & ~0x00D5; - - if (dev->flags&IFF_PROMISC) - { /* Set promiscuous. */ - outl(csr6 | 0x00C0, ioaddr + CSR6); - /* Log any net taps. */ - printk("%s: Promiscuous mode enabled.\n", dev->name); - } - else if (dev->mc_count > 15 || (dev->flags&IFF_ALLMULTI)) - { - /* Too many to filter perfectly -- accept all multicasts. */ - outl(csr6 | 0x0080, ioaddr + CSR6); - } - else - { - struct tulip_private *tp = (struct tulip_private *)dev->priv; - struct dev_mc_list *dmi=dev->mc_list; - int *setup_frm = tp->setup_frame; - unsigned short *eaddrs; - int i; - - /* We have <= 15 addresses that we can use the wonderful - 16 address perfect filtering of the Tulip. Note that only - the low shortword of setup_frame[] is valid. */ - outl(csr6 | 0x0000, ioaddr + CSR6); - i=0; - while(dmi) - { - eaddrs=(unsigned short *)dmi->dmi_addr; - dmi=dmi->next; - i++; - *setup_frm++ = *eaddrs++; - *setup_frm++ = *eaddrs++; - *setup_frm++ = *eaddrs++; - } - /* Fill the rest of the table with our physical address. */ - eaddrs = (unsigned short *)dev->dev_addr; - do { - *setup_frm++ = eaddrs[0]; - *setup_frm++ = eaddrs[1]; - *setup_frm++ = eaddrs[2]; - } while (++i < 16); - - /* Now add this frame to the Tx list. */ - } -} - -static int -set_mac_address(struct device *dev, void *addr) -{ - int i; - struct sockaddr *sa=(struct sockaddr *)addr; - if (dev->start) - return -EBUSY; - printk("%s: Setting MAC address to ", dev->name); - for (i = 0; i < 6; i++) - printk(" %2.2x", dev->dev_addr[i] = sa->sa_data[i]); - printk(".\n"); - return 0; -} - -#ifdef MODULE -static char devicename[9] = { 0, }; -static struct device dev_tulip = { - devicename, /* device name is inserted by linux/drivers/net/net_init.c */ - 0, 0, 0, 0, - 0, 0, - 0, 0, 0, NULL, tulip_probe -}; - -static int io = 0; -static int irq = 0; - -int init_module(void) -{ - printk("tulip: Sorry, modularization is not completed\n"); - return -EIO; -#if 0 - if (io == 0) - printk("tulip: You should not use auto-probing with insmod!\n"); - dev_tulip.base_addr = io; - dev_tulip.irq = irq; - if (register_netdev(&dev_tulip) != 0) { - printk("tulip: register_netdev() returned non-zero.\n"); - return -EIO; - } - return 0; -#endif -} - -void -cleanup_module(void) -{ - unregister_netdev(&dev_tulip); -} -#endif /* MODULE */ - -/* - * Local variables: - * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c tulip.c" - * c-indent-level: 4 - * tab-width: 4 - * End: - */ diff --git a/i386/i386at/gpl/linux/net/wavelan.c b/i386/i386at/gpl/linux/net/wavelan.c deleted file mode 100644 index 4d09badd..00000000 --- a/i386/i386at/gpl/linux/net/wavelan.c +++ /dev/null @@ -1,2526 +0,0 @@ -/* - * AT&T GIS (nee NCR) WaveLAN card: - * An Ethernet-like radio transceiver - * controlled by an Intel 82586 coprocessor. - */ - -#include <linux/module.h> - -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/types.h> -#include <linux/fcntl.h> -#include <linux/interrupt.h> -#include <linux/stat.h> -#include <linux/ptrace.h> -#include <linux/ioport.h> -#include <linux/in.h> -#include <linux/string.h> -#include <linux/delay.h> -#include <asm/system.h> -#include <asm/bitops.h> -#include <asm/io.h> -#include <asm/dma.h> -#include <linux/errno.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> -#include <linux/malloc.h> -#include <linux/timer.h> -#include <linux/proc_fs.h> -#define STRUCT_CHECK 1 -#ifdef MACH -#include <net/i82586.h> -#else -#include "i82586.h" -#endif -#include "wavelan.h" - -#ifndef WAVELAN_DEBUG -#define WAVELAN_DEBUG 0 -#endif /* WAVELAN_DEBUG */ - -#define WATCHDOG_JIFFIES 512 /* TODO: express in HZ. */ -#define ENABLE_FULL_PROMISCUOUS 0x10000 - -#define nels(a) (sizeof(a) / sizeof(a[0])) - -typedef struct device device; -typedef struct enet_statistics en_stats; -typedef struct net_local net_local; -typedef struct timer_list timer_list; - -struct net_local -{ - en_stats stats; - unsigned int tx_n_in_use; - unsigned char nwid[2]; - unsigned short hacr; - unsigned short rx_head; - unsigned short rx_last; - unsigned short tx_first_free; - unsigned short tx_first_in_use; - unsigned int nresets; - unsigned int correct_nwid; - unsigned int wrong_nwid; - unsigned int promiscuous; - unsigned int full_promiscuous; - timer_list watchdog; - device *dev; - net_local *prev; - net_local *next; -}; - -extern int wavelan_probe(device *); /* See Space.c */ - -static const char *version = "wavelan.c:v7 95/4/8\n"; - -/* - * Entry point forward declarations. - */ -static int wavelan_probe1(device *, unsigned short); -static int wavelan_open(device *); -static int wavelan_send_packet(struct sk_buff *, device *); -static void wavelan_interrupt(int, struct pt_regs *); -static int wavelan_close(device *); -static en_stats *wavelan_get_stats(device *); -static void wavelan_set_multicast_list(device *); -static int wavelan_get_info(char*, char**, off_t, int, int); - -/* - * Other forward declarations. - */ -static void wavelan_cu_show_one(device *, net_local *, int, unsigned short); -static void wavelan_cu_start(device *); -static void wavelan_ru_start(device *); -static void wavelan_watchdog(unsigned long); -#if 0 -static void wavelan_psa_show(psa_t *); -static void wavelan_mmc_show(unsigned short); -#endif /* 0 */ -static void wavelan_scb_show(unsigned short); -static void wavelan_ru_show(device *); -static void wavelan_cu_show(device *); -static void wavelan_dev_show(device *); -static void wavelan_local_show(device *); - -static unsigned int wavelan_debug = WAVELAN_DEBUG; -static net_local *first_wavelan = (net_local *)0; - -static -unsigned long -wavelan_splhi(void) -{ - unsigned long flags; - - save_flags(flags); - cli(); - - return flags; -} - -static -void -wavelan_splx(unsigned long flags) -{ - restore_flags(flags); -} - -static -unsigned short -hasr_read(unsigned short ioaddr) -{ - return inw(HASR(ioaddr)); -} - -static -void -hacr_write(unsigned short ioaddr, int hacr) -{ - outw(hacr, HACR(ioaddr)); -} - -static -void -hacr_write_slow(unsigned short ioaddr, int hacr) -{ - hacr_write(ioaddr, hacr); - /* delay might only be needed sometimes */ - udelay(1000); -} - -/* - * Set the channel attention bit. - */ -static -void -set_chan_attn(unsigned short ioaddr, unsigned short current_hacr) -{ - hacr_write(ioaddr, current_hacr | HACR_CA); -} - -/* - * Reset, and then set host adaptor into default mode. - */ -static -void -wavelan_reset(unsigned short ioaddr) -{ - hacr_write_slow(ioaddr, HACR_RESET); - hacr_write(ioaddr, HACR_DEFAULT); -} - -static -void -wavelan_16_off(unsigned short ioaddr, unsigned short hacr) -{ - hacr &= ~HACR_16BITS; - - hacr_write(ioaddr, hacr); -} - -static -void -wavelan_16_on(unsigned short ioaddr, unsigned short hacr) -{ - hacr |= HACR_16BITS; - - hacr_write(ioaddr, hacr); -} - -static -void -wavelan_ints_off(device *dev) -{ - unsigned short ioaddr; - net_local *lp; - unsigned long x; - - ioaddr = dev->base_addr; - lp = (net_local *)dev->priv; - - x = wavelan_splhi(); - - lp->hacr &= ~HACR_INTRON; - hacr_write(ioaddr, lp->hacr); - - wavelan_splx(x); -} - -static -void -wavelan_ints_on(device *dev) -{ - unsigned short ioaddr; - net_local *lp; - unsigned long x; - - ioaddr = dev->base_addr; - lp = (net_local *)dev->priv; - - x = wavelan_splhi(); - - lp->hacr |= HACR_INTRON; - hacr_write(ioaddr, lp->hacr); - - wavelan_splx(x); -} - -/* - * Read bytes from the PSA. - */ -static -void -psa_read(unsigned short ioaddr, unsigned short hacr, int o, unsigned char *b, int n) -{ - wavelan_16_off(ioaddr, hacr); - - while (n-- > 0) - { - outw(o, PIOR2(ioaddr)); - o++; - *b++ = inb(PIOP2(ioaddr)); - } - - wavelan_16_on(ioaddr, hacr); -} - -#if defined(IRQ_SET_WORKS) -/* - * Write bytes to the PSA. - */ -static -void -psa_write(unsigned short ioaddr, unsigned short hacr, int o, unsigned char *b, int n) -{ - wavelan_16_off(ioaddr, hacr); - - while (n-- > 0) - { - outw(o, PIOR2(ioaddr)); - o++; - outb(*b, PIOP2(ioaddr)); - b++; - } - - wavelan_16_on(ioaddr, hacr); -} -#endif /* defined(IRQ_SET_WORKS) */ - -/* - * Read bytes from the on-board RAM. - */ -static -void -obram_read(unsigned short ioaddr, unsigned short o, unsigned char *b, int n) -{ - n = (n + 1) / (sizeof(unsigned short) / sizeof(unsigned char)); - - outw(o, PIOR1(ioaddr)); - - insw(PIOP1(ioaddr), (unsigned short *)b, n); -} - -/* - * Write bytes to the on-board RAM. - */ -static -void -obram_write(unsigned short ioaddr, unsigned short o, unsigned char *b, int n) -{ - n = (n + 1) / (sizeof(unsigned short) / sizeof(unsigned char)); - - outw(o, PIOR1(ioaddr)); - - outsw(PIOP1(ioaddr), (unsigned short *)b, n); -} - -/* - * Read bytes from the MMC. - */ -static -void -mmc_read(unsigned short ioaddr, unsigned short o, unsigned char *b, int n) -{ - while (n-- > 0) - { - while (inw(HASR(ioaddr)) & HASR_MMC_BUSY) - ; - - outw(o << 1, MMCR(ioaddr)); - o++; - - while (inw(HASR(ioaddr)) & HASR_MMC_BUSY) - ; - - *b++ = (unsigned char)(inw(MMCR(ioaddr)) >> 8); - } -} - -/* - * Write bytes to the MMC. - */ -static -void -mmc_write(unsigned short ioaddr, unsigned short o, unsigned char *b, int n) -{ - while (n-- > 0) - { - while (inw(HASR(ioaddr)) & HASR_MMC_BUSY) - ; - - outw((unsigned short)(((unsigned short)*b << 8) | (o << 1) | 1), MMCR(ioaddr)); - b++; - o++; - } -} - -static int irqvals[] = -{ - 0, 0, 0, 0x01, - 0x02, 0x04, 0, 0x08, - 0, 0, 0x10, 0x20, - 0x40, 0, 0, 0x80, -}; - -#if defined(IRQ_SET_WORKS) -static -int -wavelan_unmap_irq(int irq, unsigned char *irqval) -{ - if (irq < 0 || irq >= nels(irqvals) || irqvals[irq] == 0) - return -1; - - *irqval = (unsigned char)irqvals[irq]; - - return 0; -} -#endif /* defined(IRQ_SET_WORKS) */ - -/* - * Map values from the irq parameter register to irq numbers. - */ -static -int -wavelan_map_irq(unsigned char irqval) -{ - int irq; - - for (irq = 0; irq < nels(irqvals); irq++) - { - if (irqvals[irq] == (int)irqval) - return irq; - } - - return -1; -} - -/* - * Initialize the Modem Management Controller. - */ -static -void -wavelan_mmc_init(device *dev, psa_t *psa) -{ - unsigned short ioaddr; - net_local *lp; - mmw_t m; - int configured; - - ioaddr = dev->base_addr; - lp = (net_local *)dev->priv; - memset(&m, 0x00, sizeof(m)); - - /* - * configured = psa->psa_conf_status & 1; - * - * For now we use the persistent PSA - * information as little as possible, thereby - * allowing us to return to the same known state - * during a hardware reset. - */ - configured = 0; - - /* - * Set default modem control parameters. - * See NCR document 407-0024326 Rev. A. - */ - m.mmw_jabber_enable = 0x01; - m.mmw_anten_sel = MMW_ANTEN_SEL_ALG_EN; - m.mmw_ifs = 0x20; - m.mmw_mod_delay = 0x04; - m.mmw_jam_time = 0x38; - - m.mmw_encr_enable = 0; - m.mmw_des_io_invert = 0; - m.mmw_freeze = 0; - m.mmw_decay_prm = 0; - m.mmw_decay_updat_prm = 0; - - if (configured) - { - /* - * Use configuration defaults from parameter storage area. - */ - if (psa->psa_undefined & 1) - m.mmw_loopt_sel = 0x00; - else - m.mmw_loopt_sel = MMW_LOOPT_SEL_UNDEFINED; - - m.mmw_thr_pre_set = psa->psa_thr_pre_set & 0x3F; - m.mmw_quality_thr = psa->psa_quality_thr & 0x0F; - } - else - { - if (lp->promiscuous && lp->full_promiscuous) - m.mmw_loopt_sel = MMW_LOOPT_SEL_UNDEFINED; - else - m.mmw_loopt_sel = 0x00; - - /* - * 0x04 for AT, - * 0x01 for MCA. - */ - if (psa->psa_comp_number & 1) - m.mmw_thr_pre_set = 0x01; - else - m.mmw_thr_pre_set = 0x04; - - m.mmw_quality_thr = 0x03; - } - - m.mmw_netw_id_l = lp->nwid[1]; - m.mmw_netw_id_h = lp->nwid[0]; - - mmc_write(ioaddr, 0, (unsigned char *)&m, sizeof(m)); -} - -static -void -wavelan_ack(device *dev) -{ - unsigned short ioaddr; - net_local *lp; - unsigned short scb_cs; - int i; - - ioaddr = dev->base_addr; - lp = (net_local *)dev->priv; - - obram_read(ioaddr, scboff(OFFSET_SCB, scb_status), (unsigned char *)&scb_cs, sizeof(scb_cs)); - scb_cs &= SCB_ST_INT; - - if (scb_cs == 0) - return; - - obram_write(ioaddr, scboff(OFFSET_SCB, scb_command), (unsigned char *)&scb_cs, sizeof(scb_cs)); - - set_chan_attn(ioaddr, lp->hacr); - - for (i = 1000; i > 0; i--) - { - obram_read(ioaddr, scboff(OFFSET_SCB, scb_command), (unsigned char *)&scb_cs, sizeof(scb_cs)); - if (scb_cs == 0) - break; - - udelay(1000); - } - - if (i <= 0) - printk("%s: wavelan_ack(): board not accepting command.\n", dev->name); -} - -/* - * Set channel attention bit and busy wait until command has - * completed, then acknowledge the command completion. - */ -static -int -wavelan_synchronous_cmd(device *dev, const char *str) -{ - unsigned short ioaddr; - net_local *lp; - unsigned short scb_cmd; - ach_t cb; - int i; - - ioaddr = dev->base_addr; - lp = (net_local *)dev->priv; - - scb_cmd = SCB_CMD_CUC & SCB_CMD_CUC_GO; - obram_write(ioaddr, scboff(OFFSET_SCB, scb_command), (unsigned char *)&scb_cmd, sizeof(scb_cmd)); - - set_chan_attn(ioaddr, lp->hacr); - - for (i = 64; i > 0; i--) - { - obram_read(ioaddr, OFFSET_CU, (unsigned char *)&cb, sizeof(cb)); - if (cb.ac_status & AC_SFLD_C) - break; - - udelay(1000); - } - - if (i <= 0 || !(cb.ac_status & AC_SFLD_OK)) - { - printk("%s: %s failed; status = 0x%x\n", dev->name, str, cb.ac_status); - wavelan_scb_show(ioaddr); - return -1; - } - - wavelan_ack(dev); - - return 0; -} - -static -int -wavelan_hardware_reset(device *dev) -{ - unsigned short ioaddr; - psa_t psa; - net_local *lp; - scp_t scp; - iscp_t iscp; - scb_t scb; - ach_t cb; - int i; - ac_cfg_t cfg; - ac_ias_t ias; - - if (wavelan_debug > 0) - printk("%s: ->wavelan_hardware_reset(dev=0x%x)\n", dev->name, (unsigned int)dev); - - ioaddr = dev->base_addr; - lp = (net_local *)dev->priv; - - lp->nresets++; - - wavelan_reset(ioaddr); - lp->hacr = HACR_DEFAULT; - - /* - * Clear the onboard RAM. - */ - { - unsigned char zeroes[512]; - - memset(&zeroes[0], 0x00, sizeof(zeroes)); - - for (i = 0; i < I82586_MEMZ; i += sizeof(zeroes)) - obram_write(ioaddr, i, &zeroes[0], sizeof(zeroes)); - } - - psa_read(ioaddr, lp->hacr, 0, (unsigned char *)&psa, sizeof(psa)); - - wavelan_mmc_init(dev, &psa); - - /* - * Construct the command unit structures: - * scp, iscp, scb, cb. - */ - memset(&scp, 0x00, sizeof(scp)); - scp.scp_sysbus = SCP_SY_16BBUS; - scp.scp_iscpl = OFFSET_ISCP; - obram_write(ioaddr, OFFSET_SCP, (unsigned char *)&scp, sizeof(scp)); - - memset(&iscp, 0x00, sizeof(iscp)); - iscp.iscp_busy = 1; - iscp.iscp_offset = OFFSET_SCB; - obram_write(ioaddr, OFFSET_ISCP, (unsigned char *)&iscp, sizeof(iscp)); - - memset(&scb, 0x00, sizeof(scb)); - scb.scb_command = SCB_CMD_RESET; - scb.scb_cbl_offset = OFFSET_CU; - scb.scb_rfa_offset = OFFSET_RU; - obram_write(ioaddr, OFFSET_SCB, (unsigned char *)&scb, sizeof(scb)); - - set_chan_attn(ioaddr, lp->hacr); - - for (i = 1000; i > 0; i--) - { - obram_read(ioaddr, OFFSET_ISCP, (unsigned char *)&iscp, sizeof(iscp)); - - if (iscp.iscp_busy == (unsigned short)0) - break; - - udelay(1000); - } - - if (i <= 0) - { - printk("%s: wavelan_hardware_reset(): iscp_busy timeout.\n", dev->name); - if (wavelan_debug > 0) - printk("%s: <-wavelan_hardware_reset(): -1\n", dev->name); - return -1; - } - - for (i = 15; i > 0; i--) - { - obram_read(ioaddr, OFFSET_SCB, (unsigned char *)&scb, sizeof(scb)); - - if (scb.scb_status == (SCB_ST_CX | SCB_ST_CNA)) - break; - - udelay(1000); - } - - if (i <= 0) - { - printk("%s: wavelan_hardware_reset(): status: expected 0x%02x, got 0x%02x.\n", dev->name, SCB_ST_CX | SCB_ST_CNA, scb.scb_status); - if (wavelan_debug > 0) - printk("%s: <-wavelan_hardware_reset(): -1\n", dev->name); - return -1; - } - - wavelan_ack(dev); - - memset(&cb, 0x00, sizeof(cb)); - cb.ac_command = AC_CFLD_EL | (AC_CFLD_CMD & acmd_diagnose); - cb.ac_link = OFFSET_CU; - obram_write(ioaddr, OFFSET_CU, (unsigned char *)&cb, sizeof(cb)); - - if (wavelan_synchronous_cmd(dev, "diag()") == -1) - { - if (wavelan_debug > 0) - printk("%s: <-wavelan_hardware_reset(): -1\n", dev->name); - return -1; - } - - obram_read(ioaddr, OFFSET_CU, (unsigned char *)&cb, sizeof(cb)); - if (cb.ac_status & AC_SFLD_FAIL) - { - printk("%s: wavelan_hardware_reset(): i82586 Self Test failed.\n", dev->name); - if (wavelan_debug > 0) - printk("%s: <-wavelan_hardware_reset(): -1\n", dev->name); - return -1; - } - - memset(&cfg, 0x00, sizeof(cfg)); - -#if 0 - /* - * The default board configuration. - */ - cfg.fifolim_bytecnt = 0x080c; - cfg.addrlen_mode = 0x2600; - cfg.linprio_interframe = 0x7820; /* IFS=120, ACS=2 */ - cfg.slot_time = 0xf00c; /* slottime=12 */ - cfg.hardware = 0x0008; /* tx even w/o CD */ - cfg.min_frame_len = 0x0040; -#endif /* 0 */ - - /* - * For Linux we invert AC_CFG_ALOC(..) so as to conform - * to the way that net packets reach us from above. - * (See also ac_tx_t.) - */ - cfg.cfg_byte_cnt = AC_CFG_BYTE_CNT(sizeof(ac_cfg_t) - sizeof(ach_t)); - cfg.cfg_fifolim = AC_CFG_FIFOLIM(8); - cfg.cfg_byte8 = AC_CFG_SAV_BF(0) | - AC_CFG_SRDY(0); - cfg.cfg_byte9 = AC_CFG_ELPBCK(0) | - AC_CFG_ILPBCK(0) | - AC_CFG_PRELEN(AC_CFG_PLEN_2) | - AC_CFG_ALOC(1) | - AC_CFG_ADDRLEN(WAVELAN_ADDR_SIZE); - cfg.cfg_byte10 = AC_CFG_BOFMET(0) | - AC_CFG_ACR(0) | - AC_CFG_LINPRIO(0); - cfg.cfg_ifs = 32; - cfg.cfg_slotl = 0; - cfg.cfg_byte13 = AC_CFG_RETRYNUM(15) | - AC_CFG_SLTTMHI(2); - cfg.cfg_byte14 = AC_CFG_FLGPAD(0) | - AC_CFG_BTSTF(0) | - AC_CFG_CRC16(0) | - AC_CFG_NCRC(0) | - AC_CFG_TNCRS(1) | - AC_CFG_MANCH(0) | - AC_CFG_BCDIS(0) | - AC_CFG_PRM(lp->promiscuous); - cfg.cfg_byte15 = AC_CFG_ICDS(0) | - AC_CFG_CDTF(0) | - AC_CFG_ICSS(0) | - AC_CFG_CSTF(0); -/* - cfg.cfg_min_frm_len = AC_CFG_MNFRM(64); -*/ - cfg.cfg_min_frm_len = AC_CFG_MNFRM(8); - - cfg.cfg_h.ac_command = AC_CFLD_EL | (AC_CFLD_CMD & acmd_configure); - cfg.cfg_h.ac_link = OFFSET_CU; - obram_write(ioaddr, OFFSET_CU, (unsigned char *)&cfg, sizeof(cfg)); - - if (wavelan_synchronous_cmd(dev, "reset()-configure") == -1) - { - if (wavelan_debug > 0) - printk("%s: <-wavelan_hardware_reset(): -1\n", dev->name); - - return -1; - } - - memset(&ias, 0x00, sizeof(ias)); - ias.ias_h.ac_command = AC_CFLD_EL | (AC_CFLD_CMD & acmd_ia_setup); - ias.ias_h.ac_link = OFFSET_CU; - memcpy(&ias.ias_addr[0], (unsigned char *)&dev->dev_addr[0], sizeof(ias.ias_addr)); - obram_write(ioaddr, OFFSET_CU, (unsigned char *)&ias, sizeof(ias)); - - if (wavelan_synchronous_cmd(dev, "reset()-address") == -1) - { - if (wavelan_debug > 0) - printk("%s: <-wavelan_hardware_reset(): -1\n", dev->name); - - return -1; - } - - wavelan_ints_on(dev); - - if (wavelan_debug > 4) - wavelan_scb_show(ioaddr); - - wavelan_ru_start(dev); - wavelan_cu_start(dev); - - if (wavelan_debug > 0) - printk("%s: <-wavelan_hardware_reset(): 0\n", dev->name); - - return 0; -} - -#if STRUCT_CHECK == 1 - -static -const char * -wavelan_struct_check(void) -{ -#define SC(t,s,n) if (sizeof(t) != s) return n - SC(psa_t, PSA_SIZE, "psa_t"); - SC(mmw_t, MMW_SIZE, "mmw_t"); - SC(mmr_t, MMR_SIZE, "mmr_t"); - SC(ha_t, HA_SIZE, "ha_t"); -#undef SC - - return (char *)0; -} - -#endif /* STRUCT_CHECK == 1 */ - -/* - * Check for a network adaptor of this type. - * Return '0' iff one exists. - * (There seem to be different interpretations of - * the initial value of dev->base_addr. - * We follow the example in drivers/net/ne.c.) - */ -int -wavelan_probe(device *dev) -{ - int i; - int r; - short base_addr; - static unsigned short iobase[] = - { -#if 0 - Leave out 0x3C0 for now -- seems to clash - with some video controllers. - Leave out the others too -- we will always - use 0x390 and leave 0x300 for the Ethernet device. - 0x300, 0x390, 0x3E0, 0x3C0, -#endif /* 0 */ - 0x390, - }; - - if (wavelan_debug > 0) - printk("%s: ->wavelan_probe(dev=0x%x (base_addr=0x%x))\n", dev->name, (unsigned int)dev, (unsigned int)dev->base_addr); - -#if STRUCT_CHECK == 1 - if (wavelan_struct_check() != (char *)0) - { - printk("%s: structure/compiler botch: \"%s\"\n", dev->name, wavelan_struct_check()); - - if (wavelan_debug > 0) - printk("%s: <-wavelan_probe(): ENODEV\n", dev->name); - - return ENODEV; - } -#endif /* STRUCT_CHECK == 1 */ - - base_addr = dev->base_addr; - - if (base_addr < 0) - { - /* - * Don't probe at all. - */ - if (wavelan_debug > 0) - printk("%s: <-wavelan_probe(): ENXIO\n", dev->name); - return ENXIO; - } - - if (base_addr > 0x100) - { - /* - * Check a single specified location. - */ - r = wavelan_probe1(dev, base_addr); - if (wavelan_debug > 0) - printk("%s: <-wavelan_probe(): %d\n", dev->name, r); - return r; - } - - for (i = 0; i < nels(iobase); i++) - { - if (check_region(iobase[i], sizeof(ha_t))) - continue; - - if (wavelan_probe1(dev, iobase[i]) == 0) - { - if (wavelan_debug > 0) - printk("%s: <-wavelan_probe(): 0\n", dev->name); - proc_net_register(&(struct proc_dir_entry) { - PROC_NET_WAVELAN, 7, "wavelan", - S_IFREG | S_IRUGO, 1, 0, 0, - 0, &proc_net_inode_operations, - wavelan_get_info - }); - - return 0; - } - } - - if (wavelan_debug > 0) - printk("%s: <-wavelan_probe(): ENODEV\n", dev->name); - - return ENODEV; -} - -static -int -wavelan_probe1(device *dev, unsigned short ioaddr) -{ - psa_t psa; - int irq; - int i; - net_local *lp; - int enable_full_promiscuous; - - if (wavelan_debug > 0) - printk("%s: ->wavelan_probe1(dev=0x%x, ioaddr=0x%x)\n", dev->name, (unsigned int)dev, ioaddr); - - wavelan_reset(ioaddr); - - psa_read(ioaddr, HACR_DEFAULT, 0, (unsigned char *)&psa, sizeof(psa)); - - /* - * Check the first three octets of the MAC address - * for the manufacturer's code. - */ - if - ( - psa.psa_univ_mac_addr[0] != SA_ADDR0 - || - psa.psa_univ_mac_addr[1] != SA_ADDR1 - || - psa.psa_univ_mac_addr[2] != SA_ADDR2 - ) - { - if (wavelan_debug > 0) - printk("%s: <-wavelan_probe1(): ENODEV\n", dev->name); - return ENODEV; - } - - printk("%s: WaveLAN at %#x,", dev->name, ioaddr); - - if (dev->irq != 0) - { - printk("[WARNING: explicit IRQ value %d ignored: using PSA value instead]", dev->irq); -#if defined(IRQ_SET_WORKS) -Leave this out until I can get it to work -- BJ. - if (wavelan_unmap_irq(dev->irq, &psa.psa_int_req_no) == -1) - { - printk(" could not wavelan_unmap_irq(%d, ..) -- ignored.\n", dev->irq); - dev->irq = 0; - } - else - { - psa_write(ioaddr, HACR_DEFAULT, (char *)&psa.psa_int_req_no - (char *)&psa, (unsigned char *)&psa.psa_int_req_no, sizeof(psa.psa_int_req_no)); - wavelan_reset(ioaddr); - } -#endif /* defined(IRQ_SET_WORKS) */ - } - - if ((irq = wavelan_map_irq(psa.psa_int_req_no)) == -1) - { - printk(" could not wavelan_map_irq(%d).\n", psa.psa_int_req_no); - if (wavelan_debug > 0) - printk("%s: <-wavelan_probe1(): EAGAIN\n", dev->name); - return EAGAIN; - } - - dev->irq = irq; - - request_region(ioaddr, sizeof(ha_t), "wavelan"); - dev->base_addr = ioaddr; - - /* - * The third numeric argument to LILO's - * `ether=' control line arrives here as `dev->mem_start'. - * - * If bit 16 of dev->mem_start is non-zero we enable - * full promiscuity. - * - * If either of the least significant two bytes of - * dev->mem_start are non-zero we use them instead - * of the PSA NWID. - */ - enable_full_promiscuous = (dev->mem_start & ENABLE_FULL_PROMISCUOUS) == ENABLE_FULL_PROMISCUOUS; - dev->mem_start &= ~ENABLE_FULL_PROMISCUOUS; - - if (dev->mem_start != 0) - { - psa.psa_nwid[0] = (dev->mem_start >> 8) & 0xFF; - psa.psa_nwid[1] = (dev->mem_start >> 0) & 0xFF; - } - - dev->mem_start = 0x0000; - dev->mem_end = 0x0000; - dev->if_port = 0; - - memcpy(&dev->dev_addr[0], &psa.psa_univ_mac_addr[0], WAVELAN_ADDR_SIZE); - - for (i = 0; i < WAVELAN_ADDR_SIZE; i++) - printk("%s%02x", (i == 0) ? " " : ":", dev->dev_addr[i]); - - printk(", IRQ %d", dev->irq); - if (enable_full_promiscuous) - printk(", promisc"); - printk(", nwid 0x%02x%02x", psa.psa_nwid[0], psa.psa_nwid[1]); - - printk(", PC"); - switch (psa.psa_comp_number) - { - case PSA_COMP_PC_AT_915: - case PSA_COMP_PC_AT_2400: - printk("-AT"); - break; - - case PSA_COMP_PC_MC_915: - case PSA_COMP_PC_MC_2400: - printk("-MC"); - break; - - case PSA_COMP_PCMCIA_915: - printk("MCIA"); - break; - - default: - printk("???"); - break; - } - - printk(", "); - switch (psa.psa_subband) - { - case PSA_SUBBAND_915: - printk("915"); - break; - - case PSA_SUBBAND_2425: - printk("2425"); - break; - - case PSA_SUBBAND_2460: - printk("2460"); - break; - - case PSA_SUBBAND_2484: - printk("2484"); - break; - - case PSA_SUBBAND_2430_5: - printk("2430.5"); - break; - - default: - printk("???"); - break; - } - printk(" MHz"); - - printk("\n"); - - if (wavelan_debug > 0) - printk(version); - - dev->priv = kmalloc(sizeof(net_local), GFP_KERNEL); - if (dev->priv == NULL) - return -ENOMEM; - memset(dev->priv, 0x00, sizeof(net_local)); - lp = (net_local *)dev->priv; - - if (first_wavelan == (net_local *)0) - { - first_wavelan = lp; - lp->prev = lp; - lp->next = lp; - } - else - { - lp->prev = first_wavelan->prev; - lp->next = first_wavelan; - first_wavelan->prev->next = lp; - first_wavelan->prev = lp; - } - lp->dev = dev; - - lp->hacr = HACR_DEFAULT; - - lp->full_promiscuous = enable_full_promiscuous; - lp->nwid[0] = psa.psa_nwid[0]; - lp->nwid[1] = psa.psa_nwid[1]; - - lp->watchdog.function = wavelan_watchdog; - lp->watchdog.data = (unsigned long)dev; - - dev->open = wavelan_open; - dev->stop = wavelan_close; - dev->hard_start_xmit = wavelan_send_packet; - dev->get_stats = wavelan_get_stats; - dev->set_multicast_list = &wavelan_set_multicast_list; - - /* - * Fill in the fields of the device structure - * with ethernet-generic values. - */ - ether_setup(dev); - - dev->flags &= ~IFF_MULTICAST; /* Not yet supported */ - - dev->mtu = WAVELAN_MTU; - - if (wavelan_debug > 0) - printk("%s: <-wavelan_probe1(): 0\n", dev->name); - - return 0; -} - -/* - * Construct the fd and rbd structures. - * Start the receive unit. - */ -static -void -wavelan_ru_start(device *dev) -{ - unsigned short ioaddr; - net_local *lp; - unsigned short scb_cs; - fd_t fd; - rbd_t rbd; - unsigned short rx; - unsigned short rx_next; - int i; - - ioaddr = dev->base_addr; - lp = (net_local *)dev->priv; - - obram_read(ioaddr, scboff(OFFSET_SCB, scb_status), (unsigned char *)&scb_cs, sizeof(scb_cs)); - if ((scb_cs & SCB_ST_RUS) == SCB_ST_RUS_RDY) - return; - - lp->rx_head = OFFSET_RU; - - for (i = 0, rx = lp->rx_head; i < NRXBLOCKS; i++, rx = rx_next) - { - rx_next = (i == NRXBLOCKS - 1) ? lp->rx_head : rx + RXBLOCKZ; - - fd.fd_status = 0; - fd.fd_command = (i == NRXBLOCKS - 1) ? FD_COMMAND_EL : 0; - fd.fd_link_offset = rx_next; - fd.fd_rbd_offset = rx + sizeof(fd); - obram_write(ioaddr, rx, (unsigned char *)&fd, sizeof(fd)); - - rbd.rbd_status = 0; - rbd.rbd_next_rbd_offset = I82586NULL; - rbd.rbd_bufl = rx + sizeof(fd) + sizeof(rbd); - rbd.rbd_bufh = 0; - rbd.rbd_el_size = RBD_EL | (RBD_SIZE & MAXDATAZ); - obram_write(ioaddr, rx + sizeof(fd), (unsigned char *)&rbd, sizeof(rbd)); - - lp->rx_last = rx; - } - - obram_write(ioaddr, scboff(OFFSET_SCB, scb_rfa_offset), (unsigned char *)&lp->rx_head, sizeof(lp->rx_head)); - - scb_cs = SCB_CMD_RUC_GO; - obram_write(ioaddr, scboff(OFFSET_SCB, scb_command), (unsigned char *)&scb_cs, sizeof(scb_cs)); - - set_chan_attn(ioaddr, lp->hacr); - - for (i = 1000; i > 0; i--) - { - obram_read(ioaddr, scboff(OFFSET_SCB, scb_command), (unsigned char *)&scb_cs, sizeof(scb_cs)); - if (scb_cs == 0) - break; - - udelay(1000); - } - - if (i <= 0) - printk("%s: wavelan_ru_start(): board not accepting command.\n", dev->name); -} - -/* - * Initialise the transmit blocks. - * Start the command unit executing the NOP - * self-loop of the first transmit block. - */ -static -void -wavelan_cu_start(device *dev) -{ - unsigned short ioaddr; - net_local *lp; - int i; - unsigned short txblock; - unsigned short first_nop; - unsigned short scb_cs; - - ioaddr = dev->base_addr; - lp = (net_local *)dev->priv; - - lp->tx_first_free = OFFSET_CU; - lp->tx_first_in_use = I82586NULL; - - for - ( - i = 0, txblock = OFFSET_CU; - i < NTXBLOCKS; - i++, txblock += TXBLOCKZ - ) - { - ac_tx_t tx; - ac_nop_t nop; - tbd_t tbd; - unsigned short tx_addr; - unsigned short nop_addr; - unsigned short tbd_addr; - unsigned short buf_addr; - - tx_addr = txblock; - nop_addr = tx_addr + sizeof(tx); - tbd_addr = nop_addr + sizeof(nop); - buf_addr = tbd_addr + sizeof(tbd); - - tx.tx_h.ac_status = 0; - tx.tx_h.ac_command = acmd_transmit | AC_CFLD_I; - tx.tx_h.ac_link = nop_addr; - tx.tx_tbd_offset = tbd_addr; - obram_write(ioaddr, tx_addr, (unsigned char *)&tx, sizeof(tx)); - - nop.nop_h.ac_status = 0; - nop.nop_h.ac_command = acmd_nop; - nop.nop_h.ac_link = nop_addr; - obram_write(ioaddr, nop_addr, (unsigned char *)&nop, sizeof(nop)); - - tbd.tbd_status = TBD_STATUS_EOF; - tbd.tbd_next_bd_offset = I82586NULL; - tbd.tbd_bufl = buf_addr; - tbd.tbd_bufh = 0; - obram_write(ioaddr, tbd_addr, (unsigned char *)&tbd, sizeof(tbd)); - } - - first_nop = OFFSET_CU + (NTXBLOCKS - 1) * TXBLOCKZ + sizeof(ac_tx_t); - obram_write(ioaddr, scboff(OFFSET_SCB, scb_cbl_offset), (unsigned char *)&first_nop, sizeof(first_nop)); - - scb_cs = SCB_CMD_CUC_GO; - obram_write(ioaddr, scboff(OFFSET_SCB, scb_command), (unsigned char *)&scb_cs, sizeof(scb_cs)); - - set_chan_attn(ioaddr, lp->hacr); - - for (i = 1000; i > 0; i--) - { - obram_read(ioaddr, scboff(OFFSET_SCB, scb_command), (unsigned char *)&scb_cs, sizeof(scb_cs)); - if (scb_cs == 0) - break; - - udelay(1000); - } - - if (i <= 0) - printk("%s: wavelan_cu_start(): board not accepting command.\n", dev->name); - - lp->tx_n_in_use = 0; - dev->tbusy = 0; -} - -static -int -wavelan_open(device *dev) -{ - unsigned short ioaddr; - net_local *lp; - unsigned long x; - int r; - - if (wavelan_debug > 0) - printk("%s: ->wavelan_open(dev=0x%x)\n", dev->name, (unsigned int)dev); - - ioaddr = dev->base_addr; - lp = (net_local *)dev->priv; - - if (dev->irq == 0) - { - if (wavelan_debug > 0) - printk("%s: <-wavelan_open(): -ENXIO\n", dev->name); - return -ENXIO; - } - - if - ( - irq2dev_map[dev->irq] != (device *)0 - /* This is always true, but avoid the false IRQ. */ - || - (irq2dev_map[dev->irq] = dev) == (device *)0 - || - request_irq(dev->irq, &wavelan_interrupt, 0, "WaveLAN") != 0 - ) - { - irq2dev_map[dev->irq] = (device *)0; - if (wavelan_debug > 0) - printk("%s: <-wavelan_open(): -EAGAIN\n", dev->name); - return -EAGAIN; - } - - x = wavelan_splhi(); - if ((r = wavelan_hardware_reset(dev)) != -1) - { - dev->interrupt = 0; - dev->start = 1; - } - wavelan_splx(x); - - if (r == -1) - { - free_irq(dev->irq); - irq2dev_map[dev->irq] = (device *)0; - if (wavelan_debug > 0) - printk("%s: <-wavelan_open(): -EAGAIN(2)\n", dev->name); - return -EAGAIN; - } - - MOD_INC_USE_COUNT; - - if (wavelan_debug > 0) - printk("%s: <-wavelan_open(): 0\n", dev->name); - - return 0; -} - -static -void -hardware_send_packet(device *dev, void *buf, short length) -{ - unsigned short ioaddr; - net_local *lp; - unsigned short txblock; - unsigned short txpred; - unsigned short tx_addr; - unsigned short nop_addr; - unsigned short tbd_addr; - unsigned short buf_addr; - ac_tx_t tx; - ac_nop_t nop; - tbd_t tbd; - unsigned long x; - - ioaddr = dev->base_addr; - lp = (net_local *)dev->priv; - - x = wavelan_splhi(); - - txblock = lp->tx_first_free; - txpred = txblock - TXBLOCKZ; - if (txpred < OFFSET_CU) - txpred += NTXBLOCKS * TXBLOCKZ; - lp->tx_first_free += TXBLOCKZ; - if (lp->tx_first_free >= OFFSET_CU + NTXBLOCKS * TXBLOCKZ) - lp->tx_first_free -= NTXBLOCKS * TXBLOCKZ; - -/* -if (lp->tx_n_in_use > 0) - printk("%c", "0123456789abcdefghijk"[lp->tx_n_in_use]); -*/ - - lp->tx_n_in_use++; - - tx_addr = txblock; - nop_addr = tx_addr + sizeof(tx); - tbd_addr = nop_addr + sizeof(nop); - buf_addr = tbd_addr + sizeof(tbd); - - /* - * Transmit command. - */ - tx.tx_h.ac_status = 0; - obram_write(ioaddr, toff(ac_tx_t, tx_addr, tx_h.ac_status), (unsigned char *)&tx.tx_h.ac_status, sizeof(tx.tx_h.ac_status)); - - /* - * NOP command. - */ - nop.nop_h.ac_status = 0; - obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_status), (unsigned char *)&nop.nop_h.ac_status, sizeof(nop.nop_h.ac_status)); - nop.nop_h.ac_link = nop_addr; - obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_link), (unsigned char *)&nop.nop_h.ac_link, sizeof(nop.nop_h.ac_link)); - - /* - * Transmit buffer descriptor. - */ - tbd.tbd_status = TBD_STATUS_EOF | (TBD_STATUS_ACNT & length); - tbd.tbd_next_bd_offset = I82586NULL; - tbd.tbd_bufl = buf_addr; - tbd.tbd_bufh = 0; - obram_write(ioaddr, tbd_addr, (unsigned char *)&tbd, sizeof(tbd)); - - /* - * Data. - */ - obram_write(ioaddr, buf_addr, buf, length); - - /* - * Overwrite the predecessor NOP link - * so that it points to this txblock. - */ - nop_addr = txpred + sizeof(tx); - nop.nop_h.ac_status = 0; - obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_status), (unsigned char *)&nop.nop_h.ac_status, sizeof(nop.nop_h.ac_status)); - nop.nop_h.ac_link = txblock; - obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_link), (unsigned char *)&nop.nop_h.ac_link, sizeof(nop.nop_h.ac_link)); - - if (lp->tx_first_in_use == I82586NULL) - lp->tx_first_in_use = txblock; - - if (lp->tx_n_in_use < NTXBLOCKS - 1) - dev->tbusy = 0; - - dev->trans_start = jiffies; - - if (lp->watchdog.next == (timer_list *)0) - wavelan_watchdog((unsigned long)dev); - - wavelan_splx(x); - - if (wavelan_debug > 4) - { - unsigned char *a; - - a = (unsigned char *)buf; - - printk - ( - "%s: tx: dest %02x:%02x:%02x:%02x:%02x:%02x, length %d, tbd.tbd_bufl 0x%x.\n", - dev->name, - a[0], a[1], a[2], a[3], a[4], a[5], - length, - buf_addr - ); - } -} - -static -int -wavelan_send_packet(struct sk_buff *skb, device *dev) -{ - unsigned short ioaddr; - - ioaddr = dev->base_addr; - - if (dev->tbusy) - { - /* - * If we get here, some higher level - * has decided we are broken. - */ - int tickssofar; - - tickssofar = jiffies - dev->trans_start; - - /* - * But for the moment, we will rely on wavelan_watchdog() - * instead as it allows finer control over exactly when we - * make the determination of failure. - * - if (tickssofar < 5) - */ - return 1; - - wavelan_scb_show(ioaddr); - wavelan_ru_show(dev); - wavelan_cu_show(dev); - wavelan_dev_show(dev); - wavelan_local_show(dev); - - printk("%s: transmit timed out -- resetting board.\n", dev->name); - - (void)wavelan_hardware_reset(dev); - } - - /* - * If some higher layer thinks we've missed - * a tx-done interrupt we are passed NULL. - * Caution: dev_tint() handles the cli()/sti() itself. - */ - if (skb == (struct sk_buff *)0) - { - dev_tint(dev); - return 0; - } - - /* - * Block a timer-based transmit from overlapping. - */ - if (set_bit(0, (void *)&dev->tbusy) == 0) - { - short length; - unsigned char *buf; - - length = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN; - buf = skb->data; - - hardware_send_packet(dev, buf, length); - } - else - printk("%s: Transmitter access conflict.\n", dev->name); - - dev_kfree_skb(skb, FREE_WRITE); - - return 0; -} - -#if 0 -static -int -addrcmp(unsigned char *a0, unsigned char *a1) -{ - int i; - - for (i = 0; i < WAVELAN_ADDR_SIZE; i++) - { - if (a0[i] != a1[i]) - return a0[i] - a1[i]; - } - - return 0; -} -#endif /* 0 */ - -/* - * Transfer as many packets as we can - * from the device RAM. - * Called by the interrupt handler. - */ -static -void -wavelan_receive(device *dev) -{ - unsigned short ioaddr; - net_local *lp; - int nreaped; - - ioaddr = dev->base_addr; - lp = (net_local *)dev->priv; - nreaped = 0; - - for (;;) - { - fd_t fd; - rbd_t rbd; - ushort pkt_len; - int sksize; - struct sk_buff *skb; - - obram_read(ioaddr, lp->rx_head, (unsigned char *)&fd, sizeof(fd)); - - if ((fd.fd_status & FD_STATUS_C) != FD_STATUS_C) - break; - - nreaped++; - - if - ( - (fd.fd_status & (FD_STATUS_B | FD_STATUS_OK)) - != - (FD_STATUS_B | FD_STATUS_OK) - ) - { - /* - * Not sure about this one -- it does not seem - * to be an error so we will keep quiet about it. - if ((fd.fd_status & FD_STATUS_B) != FD_STATUS_B) - printk("%s: frame not consumed by RU.\n", dev->name); - */ - - if ((fd.fd_status & FD_STATUS_OK) != FD_STATUS_OK) - printk("%s: frame not received successfully.\n", dev->name); - } - - if ((fd.fd_status & (FD_STATUS_S6 | FD_STATUS_S7 | FD_STATUS_S8 | FD_STATUS_S9 | FD_STATUS_S10 | FD_STATUS_S11)) != 0) - { - lp->stats.rx_errors++; - - if ((fd.fd_status & FD_STATUS_S6) != 0) - printk("%s: no EOF flag.\n", dev->name); - - if ((fd.fd_status & FD_STATUS_S7) != 0) - { - lp->stats.rx_length_errors++; - printk("%s: frame too short.\n", dev->name); - } - - if ((fd.fd_status & FD_STATUS_S8) != 0) - { - lp->stats.rx_over_errors++; - printk("%s: rx DMA overrun.\n", dev->name); - } - - if ((fd.fd_status & FD_STATUS_S9) != 0) - { - lp->stats.rx_fifo_errors++; - printk("%s: ran out of resources.\n", dev->name); - } - - if ((fd.fd_status & FD_STATUS_S10) != 0) - { - lp->stats.rx_frame_errors++; - printk("%s: alignment error.\n", dev->name); - } - - if ((fd.fd_status & FD_STATUS_S11) != 0) - { - lp->stats.rx_crc_errors++; - printk("%s: CRC error.\n", dev->name); - } - } - - if (fd.fd_rbd_offset == I82586NULL) - printk("%s: frame has no data.\n", dev->name); - else - { - obram_read(ioaddr, fd.fd_rbd_offset, (unsigned char *)&rbd, sizeof(rbd)); - - if ((rbd.rbd_status & RBD_STATUS_EOF) != RBD_STATUS_EOF) - printk("%s: missing EOF flag.\n", dev->name); - - if ((rbd.rbd_status & RBD_STATUS_F) != RBD_STATUS_F) - printk("%s: missing F flag.\n", dev->name); - - pkt_len = rbd.rbd_status & RBD_STATUS_ACNT; - -#if 0 - { - unsigned char addr[WAVELAN_ADDR_SIZE]; - int i; - static unsigned char toweraddr[WAVELAN_ADDR_SIZE] = - { - 0x08, 0x00, 0x0e, 0x20, 0x3e, 0xd3, - }; - - obram_read(ioaddr, rbd.rbd_bufl + sizeof(addr), &addr[0], sizeof(addr)); - if - ( - /* - addrcmp(&addr[0], &dev->dev_addr[0]) != 0 - && - */ - addrcmp(&addr[0], toweraddr) != 0 - ) - { - printk("%s: foreign MAC source addr=", dev->name); - for (i = 0; i < WAVELAN_ADDR_SIZE; i++) - printk("%s%02x", (i == 0) ? "" : ":", addr[i]); - printk("\n"); - } - } -#endif /* 0 */ - - if (wavelan_debug > 5) - { - unsigned char addr[WAVELAN_ADDR_SIZE]; - unsigned short ltype; - int i; - -#if 0 - printk("%s: fd_dest=", dev->name); - for (i = 0; i < WAVELAN_ADDR_SIZE; i++) - printk("%s%02x", (i == 0) ? "" : ":", fd.fd_dest[i]); - printk("\n"); - - printk("%s: fd_src=", dev->name); - for (i = 0; i < WAVELAN_ADDR_SIZE; i++) - printk("%s%02x", (i == 0) ? "" : ":", fd.fd_src[i]); - printk("\n"); - printk("%s: fd_length=%d\n", dev->name, fd.fd_length); -#endif /* 0 */ - - obram_read(ioaddr, rbd.rbd_bufl, &addr[0], sizeof(addr)); - printk("%s: dest=", dev->name); - for (i = 0; i < WAVELAN_ADDR_SIZE; i++) - printk("%s%02x", (i == 0) ? "" : ":", addr[i]); - printk("\n"); - - obram_read(ioaddr, rbd.rbd_bufl + sizeof(addr), &addr[0], sizeof(addr)); - printk("%s: src=", dev->name); - for (i = 0; i < WAVELAN_ADDR_SIZE; i++) - printk("%s%02x", (i == 0) ? "" : ":", addr[i]); - printk("\n"); - - obram_read(ioaddr, rbd.rbd_bufl + sizeof(addr) * 2, (unsigned char *)<ype, sizeof(ltype)); - printk("%s: ntohs(length/type)=0x%04x\n", dev->name, ntohs(ltype)); - } - - sksize = pkt_len; - - if ((skb = dev_alloc_skb(sksize)) == (struct sk_buff *)0) - { - printk("%s: could not alloc_skb(%d, GFP_ATOMIC).\n", dev->name, sksize); - lp->stats.rx_dropped++; - } - else - { - skb->dev = dev; - - obram_read(ioaddr, rbd.rbd_bufl, skb_put(skb,pkt_len), pkt_len); - - if (wavelan_debug > 5) - { - int i; - int maxi; - - printk("%s: pkt_len=%d, data=\"", dev->name, pkt_len); - - if ((maxi = pkt_len) > 16) - maxi = 16; - - for (i = 0; i < maxi; i++) - { - unsigned char c; - - c = skb->data[i]; - if (c >= ' ' && c <= '~') - printk(" %c", skb->data[i]); - else - printk("%02x", skb->data[i]); - } - - if (maxi < pkt_len) - printk(".."); - - printk("\"\n\n"); - } - - skb->protocol=eth_type_trans(skb,dev); - netif_rx(skb); - - lp->stats.rx_packets++; - } - } - - fd.fd_status = 0; - obram_write(ioaddr, fdoff(lp->rx_head, fd_status), (unsigned char *)&fd.fd_status, sizeof(fd.fd_status)); - - fd.fd_command = FD_COMMAND_EL; - obram_write(ioaddr, fdoff(lp->rx_head, fd_command), (unsigned char *)&fd.fd_command, sizeof(fd.fd_command)); - - fd.fd_command = 0; - obram_write(ioaddr, fdoff(lp->rx_last, fd_command), (unsigned char *)&fd.fd_command, sizeof(fd.fd_command)); - - lp->rx_last = lp->rx_head; - lp->rx_head = fd.fd_link_offset; - } - -/* - if (nreaped > 1) - printk("r%d", nreaped); -*/ -} - -/* - * Command completion interrupt. - * Reclaim as many freed tx buffers as we can. - */ -static -int -wavelan_complete(device *dev, unsigned short ioaddr, net_local *lp) -{ - int nreaped; - - nreaped = 0; - - for (;;) - { - unsigned short tx_status; - - if (lp->tx_first_in_use == I82586NULL) - break; - - obram_read(ioaddr, acoff(lp->tx_first_in_use, ac_status), (unsigned char *)&tx_status, sizeof(tx_status)); - - if ((tx_status & AC_SFLD_C) == 0) - break; - - nreaped++; - - --lp->tx_n_in_use; - -/* -if (lp->tx_n_in_use > 0) - printk("%c", "0123456789abcdefghijk"[lp->tx_n_in_use]); -*/ - - if (lp->tx_n_in_use <= 0) - lp->tx_first_in_use = I82586NULL; - else - { - lp->tx_first_in_use += TXBLOCKZ; - if (lp->tx_first_in_use >= OFFSET_CU + NTXBLOCKS * TXBLOCKZ) - lp->tx_first_in_use -= NTXBLOCKS * TXBLOCKZ; - } - - if (tx_status & AC_SFLD_OK) - { - int ncollisions; - - lp->stats.tx_packets++; - ncollisions = tx_status & AC_SFLD_MAXCOL; - lp->stats.collisions += ncollisions; - /* - if (ncollisions > 0) - printk("%s: tx completed after %d collisions.\n", dev->name, ncollisions); - */ - } - else - { - lp->stats.tx_errors++; - if (tx_status & AC_SFLD_S10) - { - lp->stats.tx_carrier_errors++; - if (wavelan_debug > 0) - printk("%s: tx error: no CS.\n", dev->name); - } - if (tx_status & AC_SFLD_S9) - { - lp->stats.tx_carrier_errors++; - printk("%s: tx error: lost CTS.\n", dev->name); - } - if (tx_status & AC_SFLD_S8) - { - lp->stats.tx_fifo_errors++; - printk("%s: tx error: slow DMA.\n", dev->name); - } - if (tx_status & AC_SFLD_S6) - { - lp->stats.tx_heartbeat_errors++; - if (wavelan_debug > 0) - printk("%s: tx error: heart beat.\n", dev->name); - } - if (tx_status & AC_SFLD_S5) - { - lp->stats.tx_aborted_errors++; - if (wavelan_debug > 0) - printk("%s: tx error: too many collisions.\n", dev->name); - } - } - - if (wavelan_debug > 5) - printk("%s: tx completed, tx_status 0x%04x.\n", dev->name, tx_status); - } - -/* - if (nreaped > 1) - printk("c%d", nreaped); -*/ - - /* - * Inform upper layers. - */ - if (lp->tx_n_in_use < NTXBLOCKS - 1) - { - dev->tbusy = 0; - mark_bh(NET_BH); - } - - return nreaped; -} - -static -void -wavelan_watchdog(unsigned long a) -{ - device *dev; - net_local *lp; - unsigned short ioaddr; - unsigned long x; - unsigned int nreaped; - - x = wavelan_splhi(); - - dev = (device *)a; - ioaddr = dev->base_addr; - lp = (net_local *)dev->priv; - - if (lp->tx_n_in_use <= 0) - { - wavelan_splx(x); - return; - } - - lp->watchdog.expires = jiffies+WATCHDOG_JIFFIES; - add_timer(&lp->watchdog); - - if (jiffies - dev->trans_start < WATCHDOG_JIFFIES) - { - wavelan_splx(x); - return; - } - - nreaped = wavelan_complete(dev, ioaddr, lp); - - printk("%s: warning: wavelan_watchdog(): %d reaped, %d remain.\n", dev->name, nreaped, lp->tx_n_in_use); - /* - wavelan_scb_show(ioaddr); - wavelan_ru_show(dev); - wavelan_cu_show(dev); - wavelan_dev_show(dev); - wavelan_local_show(dev); - */ - - wavelan_splx(x); -} - -static -void -wavelan_interrupt(int irq, struct pt_regs *regs) -{ - device *dev; - unsigned short ioaddr; - net_local *lp; - unsigned short hasr; - unsigned short status; - unsigned short ack_cmd; - - if ((dev = (device *)(irq2dev_map[irq])) == (device *)0) - { - printk("wavelan_interrupt(): irq %d for unknown device.\n", irq); - return; - } - - ioaddr = dev->base_addr; - lp = (net_local *)dev->priv; - - dev->interrupt = 1; - - if ((hasr = hasr_read(ioaddr)) & HASR_MMC_INTR) - { - unsigned char dce_status; - - /* - * Interrupt from the modem management controller. - * This will clear it -- ignored for now. - */ - mmc_read(ioaddr, mmroff(0, mmr_dce_status), &dce_status, sizeof(dce_status)); - if (wavelan_debug > 0) - printk("%s: warning: wavelan_interrupt(): unexpected mmc interrupt: status 0x%04x.\n", dev->name, dce_status); - } - - if ((hasr & HASR_82586_INTR) == 0) - { - dev->interrupt = 0; - if (wavelan_debug > 0) - printk("%s: warning: wavelan_interrupt() but (hasr & HASR_82586_INTR) == 0.\n", dev->name); - return; - } - - obram_read(ioaddr, scboff(OFFSET_SCB, scb_status), (unsigned char *)&status, sizeof(status)); - - /* - * Acknowledge the interrupt(s). - */ - ack_cmd = status & SCB_ST_INT; - - obram_write(ioaddr, scboff(OFFSET_SCB, scb_command), (unsigned char *)&ack_cmd, sizeof(ack_cmd)); - - set_chan_attn(ioaddr, lp->hacr); - - if (wavelan_debug > 5) - printk("%s: interrupt, status 0x%04x.\n", dev->name, status); - - if ((status & SCB_ST_CX) == SCB_ST_CX) - { - /* - * Command completed. - */ - if (wavelan_debug > 5) - printk("%s: command completed.\n", dev->name); - (void)wavelan_complete(dev, ioaddr, lp); - } - - if ((status & SCB_ST_FR) == SCB_ST_FR) - { - /* - * Frame received. - */ - if (wavelan_debug > 5) - printk("%s: received packet.\n", dev->name); - wavelan_receive(dev); - } - - if - ( - (status & SCB_ST_CNA) == SCB_ST_CNA - || - (((status & SCB_ST_CUS) != SCB_ST_CUS_ACTV) && dev->start) - ) - { - printk("%s: warning: CU inactive -- restarting.\n", dev->name); - - (void)wavelan_hardware_reset(dev); - } - - if - ( - (status & SCB_ST_RNR) == SCB_ST_RNR - || - (((status & SCB_ST_RUS) != SCB_ST_RUS_RDY) && dev->start) - ) - { - printk("%s: warning: RU not ready -- restarting.\n", dev->name); - - (void)wavelan_hardware_reset(dev); - } - - dev->interrupt = 0; -} - -static -int -wavelan_close(device *dev) -{ - unsigned short ioaddr; - net_local *lp; - unsigned short scb_cmd; - - if (wavelan_debug > 0) - printk("%s: ->wavelan_close(dev=0x%x)\n", dev->name, (unsigned int)dev); - - ioaddr = dev->base_addr; - lp = (net_local *)dev->priv; - - dev->tbusy = 1; - dev->start = 0; - - /* - * Flush the Tx and disable Rx. - */ - scb_cmd = (SCB_CMD_CUC & SCB_CMD_CUC_SUS) | (SCB_CMD_RUC & SCB_CMD_RUC_SUS); - obram_write(ioaddr, scboff(OFFSET_SCB, scb_command), (unsigned char *)&scb_cmd, sizeof(scb_cmd)); - set_chan_attn(ioaddr, lp->hacr); - - wavelan_ints_off(dev); - - free_irq(dev->irq); - irq2dev_map[dev->irq] = (device *)0; - - /* - * Release the ioport-region. - */ - release_region(ioaddr, sizeof(ha_t)); - - MOD_DEC_USE_COUNT; - - if (wavelan_debug > 0) - printk("%s: <-wavelan_close(): 0\n", dev->name); - - return 0; -} - -/* - * Get the current statistics. - * This may be called with the card open or closed. - */ -static -en_stats * -wavelan_get_stats(device *dev) -{ - net_local *lp; - - lp = (net_local *)dev->priv; - - return &lp->stats; -} - -static -void -wavelan_set_multicast_list(device *dev) -{ - net_local *lp; - unsigned long x; - - if (wavelan_debug > 0) - printk("%s: ->wavelan_set_multicast_list(dev=0x%x)", dev->name, dev); - - lp = (net_local *)dev->priv; - - if(dev->flags&IFF_PROMISC) - { - /* - * Promiscuous mode: receive all packets. - */ - lp->promiscuous = 1; - x = wavelan_splhi(); - (void)wavelan_hardware_reset(dev); - wavelan_splx(x); - } -#if MULTICAST_IS_ADDED - else if((dev->flags&IFF_ALLMULTI)||dev->mc_list) - { - - - } -#endif - else - { - /* - * Normal mode: disable promiscuous mode, - * clear multicast list. - */ - lp->promiscuous = 0; - x = wavelan_splhi(); - (void)wavelan_hardware_reset(dev); - wavelan_splx(x); - } - - if (wavelan_debug > 0) - printk("%s: <-wavelan_set_multicast_list()\n", dev->name); -} - -/* - * Extra WaveLAN-specific device data. - * "cat /proc/net/wavelan" -- see fs/proc/net.c. - */ -static -int -sprintf_stats(char *buffer, device *dev) -{ - net_local *lp; - unsigned char v; - mmr_t m; - - lp = (net_local *)dev->priv; - - if (lp == (net_local *)0) - return sprintf(buffer, "%6s: No statistics available.\n", dev->name); - - v = (unsigned char)1; - mmc_write(dev->base_addr, mmwoff(0, mmw_freeze), &v, sizeof(v)); - - mmc_read(dev->base_addr, mmroff(0, mmr_dce_status), &m.mmr_dce_status, sizeof(m.mmr_dce_status)); - mmc_read(dev->base_addr, mmroff(0, mmr_correct_nwid_h), &m.mmr_correct_nwid_h, sizeof(m.mmr_correct_nwid_h)); - mmc_read(dev->base_addr, mmroff(0, mmr_correct_nwid_l), &m.mmr_correct_nwid_l, sizeof(m.mmr_correct_nwid_l)); - mmc_read(dev->base_addr, mmroff(0, mmr_wrong_nwid_h), &m.mmr_wrong_nwid_h, sizeof(m.mmr_wrong_nwid_h)); - mmc_read(dev->base_addr, mmroff(0, mmr_wrong_nwid_l), &m.mmr_wrong_nwid_l, sizeof(m.mmr_wrong_nwid_l)); - mmc_read(dev->base_addr, mmroff(0, mmr_signal_lvl), &m.mmr_signal_lvl, sizeof(m.mmr_signal_lvl)); - mmc_read(dev->base_addr, mmroff(0, mmr_silence_lvl), &m.mmr_silence_lvl, sizeof(m.mmr_silence_lvl)); - mmc_read(dev->base_addr, mmroff(0, mmr_sgnl_qual), &m.mmr_sgnl_qual, sizeof(m.mmr_sgnl_qual)); - - v = (unsigned char)0; - mmc_write(dev->base_addr, mmwoff(0, mmw_freeze), &v, sizeof(v)); - - lp->correct_nwid += (m.mmr_correct_nwid_h << 8) | m.mmr_correct_nwid_l; - lp->wrong_nwid += (m.mmr_wrong_nwid_h << 8) | m.mmr_wrong_nwid_l; - - return sprintf - ( - buffer, - "%6s: %02x %08x %08x %02x %02x %02x %02x %u\n", - dev->name, - m.mmr_dce_status, - lp->correct_nwid, - lp->wrong_nwid, - m.mmr_signal_lvl, - m.mmr_silence_lvl, - m.mmr_sgnl_qual, - lp->tx_n_in_use, - lp->nresets - ); -} - -static int -wavelan_get_info(char *buffer, char **start, off_t offset, int length, int dummy) -{ - int len; - off_t begin; - off_t pos; - int size; - unsigned long x; - - len = 0; - begin = 0; - pos = 0; - - size = sprintf(buffer, "%s", "Iface | dce +nwid -nwid lvl slnc qual ntxq nrst\n"); - - pos += size; - len += size; - - x = wavelan_splhi(); - - if (first_wavelan != (net_local *)0) - { - net_local *lp; - - lp = first_wavelan; - do - { - size = sprintf_stats(buffer + len, lp->dev); - - len += size; - pos = begin + len; - - if (pos < offset) - { - len = 0; - begin = pos; - } - - if (pos > offset + length) - break; - } - while ((lp = lp->next) != first_wavelan); - } - - wavelan_splx(x); - - *start = buffer + (offset - begin); /* Start of wanted data */ - len -= (offset - begin); /* Start slop */ - if (len > length) - len = length; /* Ending slop */ - - return len; -} - -#if defined(MODULE) -static char devicename[9] = { 0, }; -static struct device dev_wavelan = -{ - devicename, /* device name is inserted by linux/drivers/net/net_init.c */ - 0, 0, 0, 0, - 0, 0, - 0, 0, 0, NULL, wavelan_probe -}; - -static int io = 0x390; /* Default from above.. */ -static int irq = 0; - -int -init_module(void) -{ - dev_wavelan.base_addr = io; - dev_wavelan.irq = irq; - if (register_netdev(&dev_wavelan) != 0) - return -EIO; - - return 0; -} - -void -cleanup_module(void) -{ - proc_net_unregister(PROC_NET_WAVELAN); - unregister_netdev(&dev_wavelan); - kfree_s(dev_wavelan.priv, sizeof(struct net_local)); - dev_wavelan.priv = NULL; -} -#endif /* defined(MODULE) */ - -static -void -wavelan_cu_show_one(device *dev, net_local *lp, int i, unsigned short p) -{ - unsigned short ioaddr; - ac_tx_t actx; - - ioaddr = dev->base_addr; - - printk("%d: 0x%x:", i, p); - - obram_read(ioaddr, p, (unsigned char *)&actx, sizeof(actx)); - printk(" status=0x%x,", actx.tx_h.ac_status); - printk(" command=0x%x,", actx.tx_h.ac_command); - -/* - { - tbd_t tbd; - - obram_read(ioaddr, actx.tx_tbd_offset, (unsigned char *)&tbd, sizeof(tbd)); - printk(" tbd_status=0x%x,", tbd.tbd_status); - } -*/ - - printk("|"); -} - -#if 0 -static -void -wavelan_psa_show(psa_t *p) -{ - printk("psa:"); - - printk("psa_io_base_addr_1: 0x%02x,", p->psa_io_base_addr_1); - printk("psa_io_base_addr_2: 0x%02x,", p->psa_io_base_addr_2); - printk("psa_io_base_addr_3: 0x%02x,", p->psa_io_base_addr_3); - printk("psa_io_base_addr_4: 0x%02x,", p->psa_io_base_addr_4); - printk("psa_rem_boot_addr_1: 0x%02x,", p->psa_rem_boot_addr_1); - printk("psa_rem_boot_addr_2: 0x%02x,", p->psa_rem_boot_addr_2); - printk("psa_rem_boot_addr_3: 0x%02x,", p->psa_rem_boot_addr_3); - printk("psa_holi_params: 0x%02x,", p->psa_holi_params); - printk("psa_int_req_no: %d,", p->psa_int_req_no); - printk - ( - "psa_univ_mac_addr[]: %02x:%02x:%02x:%02x:%02x:%02x,", - p->psa_univ_mac_addr[0], - p->psa_univ_mac_addr[1], - p->psa_univ_mac_addr[2], - p->psa_univ_mac_addr[3], - p->psa_univ_mac_addr[4], - p->psa_univ_mac_addr[5] - ); - printk - ( - "psa_local_mac_addr[]: %02x:%02x:%02x:%02x:%02x:%02x,", - p->psa_local_mac_addr[0], - p->psa_local_mac_addr[1], - p->psa_local_mac_addr[2], - p->psa_local_mac_addr[3], - p->psa_local_mac_addr[4], - p->psa_local_mac_addr[5] - ); - printk("psa_univ_local_sel: %d,", p->psa_univ_local_sel); - printk("psa_comp_number: %d,", p->psa_comp_number); - printk("psa_thr_pre_set: 0x%02x,", p->psa_thr_pre_set); - printk("psa_feature_select/decay_prm: 0x%02x,", p->psa_feature_select); - printk("psa_subband/decay_update_prm: %d,", p->psa_subband); - printk("psa_quality_thr: 0x%02x,", p->psa_quality_thr); - printk("psa_mod_delay: 0x%02x,", p->psa_mod_delay); - printk("psa_nwid: 0x%02x%02x,", p->psa_nwid[0], p->psa_nwid[1]); - printk("psa_undefined: %d,", p->psa_undefined); - printk("psa_encryption_select: %d,", p->psa_encryption_select); - printk - ( - "psa_encryption_key[]: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x,", - p->psa_encryption_key[0], - p->psa_encryption_key[1], - p->psa_encryption_key[2], - p->psa_encryption_key[3], - p->psa_encryption_key[4], - p->psa_encryption_key[5], - p->psa_encryption_key[6], - p->psa_encryption_key[7] - ); - printk("psa_databus_width: %d,", p->psa_databus_width); - printk("psa_call_code/auto_squelch: 0x%02x,", p->psa_call_code); - printk("psa_no_of_retries: %d,", p->psa_no_of_retries); - printk("psa_acr: %d,", p->psa_acr); - printk("psa_dump_count: %d,", p->psa_dump_count); - printk("psa_nwid_prefix: 0x%02x,", p->psa_nwid_prefix); - printk("psa_conf_status: %d,", p->psa_conf_status); - printk("psa_crc: 0x%02x%02x,", p->psa_crc[0], p->psa_crc[1]); - printk("psa_crc_status: 0x%02x,", p->psa_crc_status); - - printk("\n"); -} - -static -void -wavelan_mmc_show(unsigned short ioaddr) -{ - mmr_t m; - - mmc_read(ioaddr, 0, (unsigned char *)&m, sizeof(m)); - - printk("mmr:"); - printk(" des_status: 0x%x", m.mmr_des_status); - printk(" des_avail: 0x%x", m.mmr_des_avail); - printk(" des_io_invert: 0x%x", m.mmr_des_io_invert); - printk - ( - " dce_status: 0x%x[%s%s%s%s]", - m.mmr_dce_status & 0x0F, - (m.mmr_dce_status & MMR_DCE_STATUS_ENERG_DET) ? "energy detected," : "", - (m.mmr_dce_status & MMR_DCE_STATUS_LOOPT_IND) ? "loop test indicated," : "", - (m.mmr_dce_status & MMR_DCE_STATUS_XMTITR_IND) ? "transmitter on," : "", - (m.mmr_dce_status & MMR_DCE_STATUS_JBR_EXPIRED) ? "jabber timer expired," : "" - ); - printk(" correct_nwid: %d", m.mmr_correct_nwid_h << 8 | m.mmr_correct_nwid_l); - printk(" wrong_nwid: %d", (m.mmr_wrong_nwid_h << 8) | m.mmr_wrong_nwid_l); - printk(" thr_pre_set: 0x%x", m.mmr_thr_pre_set); - printk(" signal_lvl: %d", m.mmr_signal_lvl); - printk(" silence_lvl: %d", m.mmr_silence_lvl); - printk(" sgnl_qual: 0x%x", m.mmr_sgnl_qual); - printk(" netw_id_l: %x", m.mmr_netw_id_l); - - printk("\n"); -} -#endif /* 0 */ - -static -void -wavelan_scb_show(unsigned short ioaddr) -{ - scb_t scb; - - obram_read(ioaddr, OFFSET_SCB, (unsigned char *)&scb, sizeof(scb)); - - printk("scb:"); - - printk(" status:"); - printk - ( - " stat 0x%x[%s%s%s%s]", - (scb.scb_status & (SCB_ST_CX | SCB_ST_FR | SCB_ST_CNA | SCB_ST_RNR)) >> 12, - (scb.scb_status & SCB_ST_CX) ? "cmd completion interrupt," : "", - (scb.scb_status & SCB_ST_FR) ? "frame received," : "", - (scb.scb_status & SCB_ST_CNA) ? "cmd unit not active," : "", - (scb.scb_status & SCB_ST_RNR) ? "rcv unit not ready," : "" - ); - printk - ( - " cus 0x%x[%s%s%s]", - (scb.scb_status & SCB_ST_CUS) >> 8, - ((scb.scb_status & SCB_ST_CUS) == SCB_ST_CUS_IDLE) ? "idle" : "", - ((scb.scb_status & SCB_ST_CUS) == SCB_ST_CUS_SUSP) ? "suspended" : "", - ((scb.scb_status & SCB_ST_CUS) == SCB_ST_CUS_ACTV) ? "active" : "" - ); - printk - ( - " rus 0x%x[%s%s%s%s]", - (scb.scb_status & SCB_ST_RUS) >> 4, - ((scb.scb_status & SCB_ST_RUS) == SCB_ST_RUS_IDLE) ? "idle" : "", - ((scb.scb_status & SCB_ST_RUS) == SCB_ST_RUS_SUSP) ? "suspended" : "", - ((scb.scb_status & SCB_ST_RUS) == SCB_ST_RUS_NRES) ? "no resources" : "", - ((scb.scb_status & SCB_ST_RUS) == SCB_ST_RUS_RDY) ? "ready" : "" - ); - - printk(" command:"); - printk - ( - " ack 0x%x[%s%s%s%s]", - (scb.scb_command & (SCB_CMD_ACK_CX | SCB_CMD_ACK_FR | SCB_CMD_ACK_CNA | SCB_CMD_ACK_RNR)) >> 12, - (scb.scb_command & SCB_CMD_ACK_CX) ? "ack cmd completion," : "", - (scb.scb_command & SCB_CMD_ACK_FR) ? "ack frame received," : "", - (scb.scb_command & SCB_CMD_ACK_CNA) ? "ack CU not active," : "", - (scb.scb_command & SCB_CMD_ACK_RNR) ? "ack RU not ready," : "" - ); - printk - ( - " cuc 0x%x[%s%s%s%s%s]", - (scb.scb_command & SCB_CMD_CUC) >> 8, - ((scb.scb_command & SCB_CMD_CUC) == SCB_CMD_CUC_NOP) ? "nop" : "", - ((scb.scb_command & SCB_CMD_CUC) == SCB_CMD_CUC_GO) ? "start cbl_offset" : "", - ((scb.scb_command & SCB_CMD_CUC) == SCB_CMD_CUC_RES) ? "resume execution" : "", - ((scb.scb_command & SCB_CMD_CUC) == SCB_CMD_CUC_SUS) ? "suspend execution" : "", - ((scb.scb_command & SCB_CMD_CUC) == SCB_CMD_CUC_ABT) ? "abort execution" : "" - ); - printk - ( - " ruc 0x%x[%s%s%s%s%s]", - (scb.scb_command & SCB_CMD_RUC) >> 4, - ((scb.scb_command & SCB_CMD_RUC) == SCB_CMD_RUC_NOP) ? "nop" : "", - ((scb.scb_command & SCB_CMD_RUC) == SCB_CMD_RUC_GO) ? "start rfa_offset" : "", - ((scb.scb_command & SCB_CMD_RUC) == SCB_CMD_RUC_RES) ? "resume reception" : "", - ((scb.scb_command & SCB_CMD_RUC) == SCB_CMD_RUC_SUS) ? "suspend reception" : "", - ((scb.scb_command & SCB_CMD_RUC) == SCB_CMD_RUC_ABT) ? "abort reception" : "" - ); - - printk(" cbl_offset 0x%x", scb.scb_cbl_offset); - printk(" rfa_offset 0x%x", scb.scb_rfa_offset); - - printk(" crcerrs %d", scb.scb_crcerrs); - printk(" alnerrs %d", scb.scb_alnerrs); - printk(" rscerrs %d", scb.scb_rscerrs); - printk(" ovrnerrs %d", scb.scb_ovrnerrs); - - printk("\n"); -} - -static -void -wavelan_ru_show(device *dev) -{ - net_local *lp; - - lp = (net_local *)dev->priv; - - printk("ru:"); - /* - * Not implemented yet... - */ - printk("\n"); -} - -static -void -wavelan_cu_show(device *dev) -{ - net_local *lp; - unsigned int i; - unsigned short p; - - lp = (net_local *)dev->priv; - - printk("cu:"); - printk("\n"); - - for (i = 0, p = lp->tx_first_in_use; i < NTXBLOCKS; i++) - { - wavelan_cu_show_one(dev, lp, i, p); - - p += TXBLOCKZ; - if (p >= OFFSET_CU + NTXBLOCKS * TXBLOCKZ) - p -= NTXBLOCKS * TXBLOCKZ; - } -} - -static -void -wavelan_dev_show(device *dev) -{ - printk("dev:"); - printk(" start=%d,", dev->start); - printk(" tbusy=%ld,", dev->tbusy); - printk(" interrupt=%d,", dev->interrupt); - printk(" trans_start=%ld,", dev->trans_start); - printk(" flags=0x%x,", dev->flags); - printk("\n"); -} - -static -void -wavelan_local_show(device *dev) -{ - net_local *lp; - - lp = (net_local *)dev->priv; - - printk("local:"); - printk(" tx_n_in_use=%d,", lp->tx_n_in_use); - printk(" hacr=0x%x,", lp->hacr); - printk(" rx_head=0x%x,", lp->rx_head); - printk(" rx_last=0x%x,", lp->rx_last); - printk(" tx_first_free=0x%x,", lp->tx_first_free); - printk(" tx_first_in_use=0x%x,", lp->tx_first_in_use); - printk("\n"); -} - -/* - * This software may only be used and distributed - * according to the terms of the GNU Public License. - * - * This software was developed as a component of the - * Linux operating system. - * It is based on other device drivers and information - * either written or supplied by: - * Ajay Bakre (bakre@paul.rutgers.edu), - * Donald Becker (becker@cesdis.gsfc.nasa.gov), - * Loeke Brederveld (Loeke.Brederveld@Utrecht.NCR.com), - * Anders Klemets (klemets@it.kth.se), - * Vladimir V. Kolpakov (w@stier.koenig.ru), - * Marc Meertens (Marc.Meertens@Utrecht.NCR.com), - * Pauline Middelink (middelin@polyware.iaf.nl), - * Robert Morris (rtm@das.harvard.edu), - * Girish Welling (welling@paul.rutgers.edu), - * - * Thanks go also to: - * James Ashton (jaa101@syseng.anu.edu.au), - * Alan Cox (iialan@iiit.swan.ac.uk), - * Allan Creighton (allanc@cs.usyd.edu.au), - * Matthew Geier (matthew@cs.usyd.edu.au), - * Remo di Giovanni (remo@cs.usyd.edu.au), - * Eckhard Grah (grah@wrcs1.urz.uni-wuppertal.de), - * Vipul Gupta (vgupta@cs.binghamton.edu), - * Mark Hagan (mhagan@wtcpost.daytonoh.NCR.COM), - * Tim Nicholson (tim@cs.usyd.edu.au), - * Ian Parkin (ian@cs.usyd.edu.au), - * John Rosenberg (johnr@cs.usyd.edu.au), - * George Rossi (george@phm.gov.au), - * Arthur Scott (arthur@cs.usyd.edu.au), - * Peter Storey, - * for their assistance and advice. - * - * Please send bug reports, updates, comments to: - * - * Bruce Janson Email: bruce@cs.usyd.edu.au - * Basser Department of Computer Science Phone: +61-2-351-3423 - * University of Sydney, N.S.W., 2006, AUSTRALIA Fax: +61-2-351-3838 - */ diff --git a/i386/i386at/gpl/linux/net/wavelan.h b/i386/i386at/gpl/linux/net/wavelan.h deleted file mode 100644 index 3eb221c0..00000000 --- a/i386/i386at/gpl/linux/net/wavelan.h +++ /dev/null @@ -1,252 +0,0 @@ -#define WAVELAN_ADDR_SIZE 6 /* Size of a MAC address */ -#define SA_ADDR0 0x08 /* First octet of WaveLAN MAC addresses */ -#define SA_ADDR1 0x00 /* Second octet of WaveLAN MAC addresses */ -#define SA_ADDR2 0x0E /* Third octet of WaveLAN MAC addresses */ -#define WAVELAN_MTU 1500 /* Maximum size of WaveLAN packet */ - -/* - * Parameter Storage Area (PSA). - */ -typedef struct psa_t psa_t; -struct psa_t -{ - unsigned char psa_io_base_addr_1; /* Base address 1 ??? */ - unsigned char psa_io_base_addr_2; /* Base address 2 */ - unsigned char psa_io_base_addr_3; /* Base address 3 */ - unsigned char psa_io_base_addr_4; /* Base address 4 */ - unsigned char psa_rem_boot_addr_1; /* Remote Boot Address 1 */ - unsigned char psa_rem_boot_addr_2; /* Remote Boot Address 2 */ - unsigned char psa_rem_boot_addr_3; /* Remote Boot Address 3 */ - unsigned char psa_holi_params; /* HOst Lan Interface (HOLI) Parameters */ - unsigned char psa_int_req_no; /* Interrupt Request Line */ - unsigned char psa_unused0[7]; /* unused */ - unsigned char psa_univ_mac_addr[WAVELAN_ADDR_SIZE]; /* Universal (factory) MAC Address */ - unsigned char psa_local_mac_addr[WAVELAN_ADDR_SIZE]; /* Local MAC Address */ - unsigned char psa_univ_local_sel; /* Universal Local Selection */ -#define PSA_UNIVERSAL 0 /* Universal (factory) */ -#define PSA_LOCAL 1 /* Local */ - unsigned char psa_comp_number; /* Compatibility Number: */ -#define PSA_COMP_PC_AT_915 0 /* PC-AT 915 MHz */ -#define PSA_COMP_PC_MC_915 1 /* PC-MC 915 MHz */ -#define PSA_COMP_PC_AT_2400 2 /* PC-AT 2.4 GHz */ -#define PSA_COMP_PC_MC_2400 3 /* PC-MC 2.4 GHz */ -#define PSA_COMP_PCMCIA_915 4 /* PCMCIA 915 MHz */ - unsigned char psa_thr_pre_set; /* Modem Threshold Preset */ - unsigned char psa_feature_select; /* ??? */ -#if 0 - <alias for above> - unsigned char psa_decay_prm; /* Modem Decay */ -#endif /* 0 */ - unsigned char psa_subband; /* Subband */ -#define PSA_SUBBAND_915 0 /* 915 MHz */ -#define PSA_SUBBAND_2425 1 /* 2425 MHz */ -#define PSA_SUBBAND_2460 2 /* 2460 MHz */ -#define PSA_SUBBAND_2484 3 /* 2484 MHz */ -#define PSA_SUBBAND_2430_5 4 /* 2430.5 MHz */ -#if 0 - <alias for above> - unsigned char psa_decay_updat_prm; /* Modem Decay Update ??? */ -#endif /* 0 */ - unsigned char psa_quality_thr; /* Modem Quality Threshold */ - unsigned char psa_mod_delay; /* Modem Delay ??? */ - unsigned char psa_nwid[2]; /* Network ID */ - unsigned char psa_undefined; /* undefined */ - unsigned char psa_encryption_select; /* Encryption On Off */ - unsigned char psa_encryption_key[8]; /* Encryption Key */ - unsigned char psa_databus_width; /* 8/16 bit bus width */ - unsigned char psa_call_code; /* ??? */ -#if 0 - <alias for above> - unsigned char psa_auto_squelch; /* Automatic Squelch level On off ??? */ -#endif /* 0 */ - unsigned char psa_no_of_retries; /* LAN Cont. No of retries */ - unsigned char psa_acr; /* LAN Cont. ACR */ - unsigned char psa_dump_count; /* number of Dump Commands in TFB */ - unsigned char psa_unused1[4]; /* unused */ - unsigned char psa_nwid_prefix; /* ??? */ - unsigned char psa_unused2[3]; /* unused */ - unsigned char psa_conf_status; /* Card Configuration Status */ - unsigned char psa_crc[2]; /* CRC over PSA */ - unsigned char psa_crc_status; /* CRC Valid Flag */ -}; -#if STRUCT_CHECK == 1 -#define PSA_SIZE 64 -#endif /* STRUCT_CHECK == 1 */ - -/* - * Modem Management Controller (MMC) write structure. - */ -typedef struct mmw_t mmw_t; -struct mmw_t -{ - unsigned char mmw_encr_key[8]; /* encryption key */ - unsigned char mmw_encr_enable; /* enable/disable encryption */ - unsigned char mmw_unused0[1]; /* unused */ - unsigned char mmw_des_io_invert; /* ??? */ - unsigned char mmw_unused1[5]; /* unused */ - unsigned char mmw_loopt_sel; /* looptest selection */ -#define MMW_LOOPT_SEL_UNDEFINED 0x40 /* undefined */ -#define MMW_LOOPT_SEL_INT 0x20 /* activate Attention Request */ -#define MMW_LOOPT_SEL_LS 0x10 /* looptest without collision avoidance */ -#define MMW_LOOPT_SEL_LT3A 0x08 /* looptest 3a */ -#define MMW_LOOPT_SEL_LT3B 0x04 /* looptest 3b */ -#define MMW_LOOPT_SEL_LT3C 0x02 /* looptest 3c */ -#define MMW_LOOPT_SEL_LT3D 0x01 /* looptest 3d */ - unsigned char mmw_jabber_enable; /* jabber timer enable */ - unsigned char mmw_freeze; /* freeze / unfreeze signal level */ - unsigned char mmw_anten_sel; /* antenna selection */ -#define MMW_ANTEN_SEL_SEL 0x01 /* direct antenna selection */ -#define MMW_ANTEN_SEL_ALG_EN 0x02 /* antenna selection algorithm enable */ - unsigned char mmw_ifs; /* inter frame spacing */ - unsigned char mmw_mod_delay; /* modem delay */ - unsigned char mmw_jam_time; /* jamming time */ - unsigned char mmw_unused2[1]; /* unused */ - unsigned char mmw_thr_pre_set; /* level threshold preset */ - unsigned char mmw_decay_prm; /* decay parameters */ - unsigned char mmw_decay_updat_prm; /* decay update parameters */ - unsigned char mmw_quality_thr; /* quality (z-quotient) threshold */ - unsigned char mmw_netw_id_l; /* NWID low order byte */ - unsigned char mmw_netw_id_h; /* NWID high order byte */ -}; -#if STRUCT_CHECK == 1 -#define MMW_SIZE 30 -#endif /* STRUCT_CHECK == 1 */ - -#define mmwoff(p,f) (unsigned short)((void *)(&((mmw_t *)((void *)0 + (p)))->f) - (void *)0) - -/* - * Modem Management Controller (MMC) read structure. - */ -typedef struct mmr_t mmr_t; -struct mmr_t -{ - unsigned char mmr_unused0[8]; /* unused */ - unsigned char mmr_des_status; /* encryption status */ - unsigned char mmr_des_avail; /* encryption available (0x55 read) */ - unsigned char mmr_des_io_invert; /* des I/O invert register */ - unsigned char mmr_unused1[5]; /* unused */ - unsigned char mmr_dce_status; /* DCE status */ -#define MMR_DCE_STATUS_ENERG_DET 0x01 /* energy detected */ -#define MMR_DCE_STATUS_LOOPT_IND 0x02 /* loop test indicated */ -#define MMR_DCE_STATUS_XMTITR_IND 0x04 /* transmitter on */ -#define MMR_DCE_STATUS_JBR_EXPIRED 0x08 /* jabber timer expired */ - unsigned char mmr_unused2[3]; /* unused */ - unsigned char mmr_correct_nwid_l; /* no. of correct NWID's rxd (low) */ - unsigned char mmr_correct_nwid_h; /* no. of correct NWID's rxd (high) */ - unsigned char mmr_wrong_nwid_l; /* count of wrong NWID's received (low) */ - unsigned char mmr_wrong_nwid_h; /* count of wrong NWID's received (high) */ - unsigned char mmr_thr_pre_set; /* level threshold preset */ - unsigned char mmr_signal_lvl; /* signal level */ - unsigned char mmr_silence_lvl; /* silence level */ - unsigned char mmr_sgnl_qual; /* signal quality */ -#define MMR_SGNL_QUAL_0 0x01 /* signal quality 0 */ -#define MMR_SGNL_QUAL_1 0x02 /* signal quality 1 */ -#define MMR_SGNL_QUAL_2 0x04 /* signal quality 2 */ -#define MMR_SGNL_QUAL_3 0x08 /* signal quality 3 */ -#define MMR_SGNL_QUAL_S_A 0x80 /* currently selected antenna */ - unsigned char mmr_netw_id_l; /* NWID low order byte ??? */ - unsigned char mmr_unused3[1]; /* unused */ -}; -#if STRUCT_CHECK == 1 -#define MMR_SIZE 30 -#endif /* STRUCT_CHECK == 1 */ - -#define MMR_LEVEL_MASK 0x3F - -#define mmroff(p,f) (unsigned short)((void *)(&((mmr_t *)((void *)0 + (p)))->f) - (void *)0) - -/* - * Host Adaptor structure. - * (base is board port address). - */ -typedef union hacs_u hacs_u; -union hacs_u -{ - unsigned short hu_command; /* Command register */ -#define HACR_RESET 0x0001 /* Reset board */ -#define HACR_CA 0x0002 /* Set Channel Attention for 82586 */ -#define HACR_16BITS 0x0004 /* 16 bits operation (0 => 8bits) */ -#define HACR_OUT0 0x0008 /* General purpose output pin 0 */ - /* not used - must be 1 */ -#define HACR_OUT1 0x0010 /* General purpose output pin 1 */ - /* not used - must be 1 */ -#define HACR_82586_INT_ENABLE 0x0020 /* Enable 82586 interrupts */ -#define HACR_MMC_INT_ENABLE 0x0040 /* Enable MMC interrupts */ -#define HACR_INTR_CLR_ENABLE 0x0080 /* Enable interrupt status read/clear */ - unsigned short hu_status; /* Status Register */ -#define HASR_82586_INTR 0x0001 /* Interrupt request from 82586 */ -#define HASR_MMC_INTR 0x0002 /* Interrupt request from MMC */ -#define HASR_MMC_BUSY 0x0004 /* MMC busy indication */ -#define HASR_PSA_BUSY 0x0008 /* LAN parameter storage area busy */ -}; - -typedef struct ha_t ha_t; -struct ha_t -{ - hacs_u ha_cs; /* Command and status registers */ -#define ha_command ha_cs.hu_command -#define ha_status ha_cs.hu_status - unsigned short ha_mmcr; /* Modem Management Ctrl Register */ - unsigned short ha_pior0; /* Program I/O Address Register Port 0 */ - unsigned short ha_piop0; /* Program I/O Port 0 */ - unsigned short ha_pior1; /* Program I/O Address Register Port 1 */ - unsigned short ha_piop1; /* Program I/O Port 1 */ - unsigned short ha_pior2; /* Program I/O Address Register Port 2 */ - unsigned short ha_piop2; /* Program I/O Port 2 */ -}; -#if STRUCT_CHECK == 1 -#define HA_SIZE 16 -#endif /* STRUCT_CHECK == 1 */ - -#define hoff(p,f) (unsigned short)((void *)(&((ha_t *)((void *)0 + (p)))->f) - (void *)0) -#define HACR(p) hoff(p, ha_command) -#define HASR(p) hoff(p, ha_status) -#define MMCR(p) hoff(p, ha_mmcr) -#define PIOR0(p) hoff(p, ha_pior0) -#define PIOP0(p) hoff(p, ha_piop0) -#define PIOR1(p) hoff(p, ha_pior1) -#define PIOP1(p) hoff(p, ha_piop1) -#define PIOR2(p) hoff(p, ha_pior2) -#define PIOP2(p) hoff(p, ha_piop2) - -/* - * Program I/O Mode Register values. - */ -#define STATIC_PIO 0 /* Mode 1: static mode */ - /* RAM access ??? */ -#define AUTOINCR_PIO 1 /* Mode 2: auto increment mode */ - /* RAM access ??? */ -#define AUTODECR_PIO 2 /* Mode 3: auto decrement mode */ - /* RAM access ??? */ -#define PARAM_ACCESS_PIO 3 /* Mode 4: LAN parameter access mode */ - /* Parameter access. */ -#define PIO_MASK 3 /* register mask */ -#define PIOM(cmd,piono) ((u_short)cmd << 10 << (piono * 2)) - -#define HACR_DEFAULT (HACR_OUT0 | HACR_OUT1 | HACR_16BITS | PIOM(STATIC_PIO, 0) | PIOM(AUTOINCR_PIO, 1) | PIOM(PARAM_ACCESS_PIO, 2)) -#define HACR_INTRON (HACR_82586_INT_ENABLE | HACR_MMC_INT_ENABLE | HACR_INTR_CLR_ENABLE) - -#define MAXDATAZ (WAVELAN_ADDR_SIZE + WAVELAN_ADDR_SIZE + 2 + WAVELAN_MTU) - -/* - * Onboard 64k RAM layout. - * (Offsets from 0x0000.) - */ -#define OFFSET_RU 0x0000 -#define OFFSET_CU 0x8000 -#define OFFSET_SCB (OFFSET_ISCP - sizeof(scb_t)) -#define OFFSET_ISCP (OFFSET_SCP - sizeof(iscp_t)) -#define OFFSET_SCP I82586_SCP_ADDR - -#define RXBLOCKZ (sizeof(fd_t) + sizeof(rbd_t) + MAXDATAZ) -#define TXBLOCKZ (sizeof(ac_tx_t) + sizeof(ac_nop_t) + sizeof(tbd_t) + MAXDATAZ) - -#define NRXBLOCKS ((OFFSET_CU - OFFSET_RU) / RXBLOCKZ) -#define NTXBLOCKS ((OFFSET_SCB - OFFSET_CU) / TXBLOCKZ) - -/* - * This software may only be used and distributed - * according to the terms of the GNU Public License. - * - * For more details, see wavelan.c. - */ diff --git a/i386/i386at/gpl/linux/net/wd.c b/i386/i386at/gpl/linux/net/wd.c deleted file mode 100644 index 5eaa6585..00000000 --- a/i386/i386at/gpl/linux/net/wd.c +++ /dev/null @@ -1,513 +0,0 @@ -/* wd.c: A WD80x3 ethernet driver for linux. */ -/* - Written 1993-94 by Donald Becker. - - Copyright 1993 United States Government as represented by the - Director, National Security Agency. - - This software may be used and distributed according to the terms - of the GNU Public License, incorporated herein by reference. - - The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O - Center of Excellence in Space Data and Information Sciences - Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771 - - This is a driver for WD8003 and WD8013 "compatible" ethercards. - - Thanks to Russ Nelson (nelson@crnwyr.com) for loaning me a WD8013. - - Changelog: - - Paul Gortmaker : multiple card support for module users, support - for non-standard memory sizes. - - -*/ - -static const char *version = - "wd.c:v1.10 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n"; - -#include <linux/module.h> - -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/errno.h> -#include <linux/string.h> -#include <asm/io.h> -#include <asm/system.h> - -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include "8390.h" - -/* A zero-terminated list of I/O addresses to be probed. */ -static unsigned int wd_portlist[] = -{0x300, 0x280, 0x380, 0x240, 0}; - -int wd_probe(struct device *dev); -int wd_probe1(struct device *dev, int ioaddr); - -static int wd_open(struct device *dev); -static void wd_reset_8390(struct device *dev); -static void wd_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, - int ring_page); -static void wd_block_input(struct device *dev, int count, - struct sk_buff *skb, int ring_offset); -static void wd_block_output(struct device *dev, int count, - const unsigned char *buf, const start_page); -static int wd_close_card(struct device *dev); - - -#define WD_START_PG 0x00 /* First page of TX buffer */ -#define WD03_STOP_PG 0x20 /* Last page +1 of RX ring */ -#define WD13_STOP_PG 0x40 /* Last page +1 of RX ring */ - -#define WD_CMDREG 0 /* Offset to ASIC command register. */ -#define WD_RESET 0x80 /* Board reset, in WD_CMDREG. */ -#define WD_MEMENB 0x40 /* Enable the shared memory. */ -#define WD_CMDREG5 5 /* Offset to 16-bit-only ASIC register 5. */ -#define ISA16 0x80 /* Enable 16 bit access from the ISA bus. */ -#define NIC16 0x40 /* Enable 16 bit access from the 8390. */ -#define WD_NIC_OFFSET 16 /* Offset to the 8390 from the base_addr. */ -#define WD_IO_EXTENT 32 - - -/* Probe for the WD8003 and WD8013. These cards have the station - address PROM at I/O ports <base>+8 to <base>+13, with a checksum - following. A Soundblaster can have the same checksum as an WDethercard, - so we have an extra exclusionary check for it. - - The wd_probe1() routine initializes the card and fills the - station address field. */ - -#ifdef HAVE_DEVLIST -struct netdev_entry wd_drv = -{"wd", wd_probe1, WD_IO_EXTENT, wd_portlist}; -#else - -int wd_probe(struct device *dev) -{ - int i; - int base_addr = dev ? dev->base_addr : 0; - - if (base_addr > 0x1ff) /* Check a single specified location. */ - return wd_probe1(dev, base_addr); - else if (base_addr != 0) /* Don't probe at all. */ - return ENXIO; - - for (i = 0; wd_portlist[i]; i++) { - int ioaddr = wd_portlist[i]; - if (check_region(ioaddr, WD_IO_EXTENT)) - continue; - if (wd_probe1(dev, ioaddr) == 0) - return 0; - } - - return ENODEV; -} -#endif - -int wd_probe1(struct device *dev, int ioaddr) -{ - int i; - int checksum = 0; - int ancient = 0; /* An old card without config registers. */ - int word16 = 0; /* 0 = 8 bit, 1 = 16 bit */ - const char *model_name; - static unsigned version_printed = 0; - - for (i = 0; i < 8; i++) - checksum += inb(ioaddr + 8 + i); - if (inb(ioaddr + 8) == 0xff /* Extra check to avoid soundcard. */ - || inb(ioaddr + 9) == 0xff - || (checksum & 0xff) != 0xFF) - return ENODEV; - - /* We should have a "dev" from Space.c or the static module table. */ - if (dev == NULL) { - printk("wd.c: Passed a NULL device.\n"); - dev = init_etherdev(0, 0); - } - - /* Check for semi-valid mem_start/end values if supplied. */ - if ((dev->mem_start % 0x2000) || (dev->mem_end % 0x2000)) { - printk(KERN_WARNING "wd.c: user supplied mem_start or mem_end not on 8kB boundary - ignored.\n"); - dev->mem_start = 0; - dev->mem_end = 0; - } - - if (ei_debug && version_printed++ == 0) - printk(version); - - printk("%s: WD80x3 at %#3x, ", dev->name, ioaddr); - for (i = 0; i < 6; i++) - printk(" %2.2X", dev->dev_addr[i] = inb(ioaddr + 8 + i)); - - /* The following PureData probe code was contributed by - Mike Jagdis <jaggy@purplet.demon.co.uk>. Puredata does software - configuration differently from others so we have to check for them. - This detects an 8 bit, 16 bit or dumb (Toshiba, jumpered) card. - */ - if (inb(ioaddr+0) == 'P' && inb(ioaddr+1) == 'D') { - unsigned char reg5 = inb(ioaddr+5); - - switch (inb(ioaddr+2)) { - case 0x03: word16 = 0; model_name = "PDI8023-8"; break; - case 0x05: word16 = 0; model_name = "PDUC8023"; break; - case 0x0a: word16 = 1; model_name = "PDI8023-16"; break; - /* Either 0x01 (dumb) or they've released a new version. */ - default: word16 = 0; model_name = "PDI8023"; break; - } - dev->mem_start = ((reg5 & 0x1c) + 0xc0) << 12; - dev->irq = (reg5 & 0xe0) == 0xe0 ? 10 : (reg5 >> 5) + 1; - } else { /* End of PureData probe */ - /* This method of checking for a 16-bit board is borrowed from the - we.c driver. A simpler method is just to look in ASIC reg. 0x03. - I'm comparing the two method in alpha test to make certain they - return the same result. */ - /* Check for the old 8 bit board - it has register 0/8 aliasing. - Do NOT check i>=6 here -- it hangs the old 8003 boards! */ - for (i = 0; i < 6; i++) - if (inb(ioaddr+i) != inb(ioaddr+8+i)) - break; - if (i >= 6) { - ancient = 1; - model_name = "WD8003-old"; - word16 = 0; - } else { - int tmp = inb(ioaddr+1); /* fiddle with 16bit bit */ - outb( tmp ^ 0x01, ioaddr+1 ); /* attempt to clear 16bit bit */ - if (((inb( ioaddr+1) & 0x01) == 0x01) /* A 16 bit card */ - && (tmp & 0x01) == 0x01 ) { /* In a 16 slot. */ - int asic_reg5 = inb(ioaddr+WD_CMDREG5); - /* Magic to set ASIC to word-wide mode. */ - outb( NIC16 | (asic_reg5&0x1f), ioaddr+WD_CMDREG5); - outb(tmp, ioaddr+1); - model_name = "WD8013"; - word16 = 1; /* We have a 16bit board here! */ - } else { - model_name = "WD8003"; - word16 = 0; - } - outb(tmp, ioaddr+1); /* Restore original reg1 value. */ - } -#ifndef final_version - if ( !ancient && (inb(ioaddr+1) & 0x01) != (word16 & 0x01)) - printk("\nWD80?3: Bus width conflict, %d (probe) != %d (reg report).", - word16 ? 16 : 8, (inb(ioaddr+1) & 0x01) ? 16 : 8); -#endif - } - -#if defined(WD_SHMEM) && WD_SHMEM > 0x80000 - /* Allow a compile-time override. */ - dev->mem_start = WD_SHMEM; -#else - if (dev->mem_start == 0) { - /* Sanity and old 8003 check */ - int reg0 = inb(ioaddr); - if (reg0 == 0xff || reg0 == 0) { - /* Future plan: this could check a few likely locations first. */ - dev->mem_start = 0xd0000; - printk(" assigning address %#lx", dev->mem_start); - } else { - int high_addr_bits = inb(ioaddr+WD_CMDREG5) & 0x1f; - /* Some boards don't have the register 5 -- it returns 0xff. */ - if (high_addr_bits == 0x1f || word16 == 0) - high_addr_bits = 0x01; - dev->mem_start = ((reg0&0x3f) << 13) + (high_addr_bits << 19); - } - } -#endif - - /* The 8390 isn't at the base address -- the ASIC regs are there! */ - dev->base_addr = ioaddr+WD_NIC_OFFSET; - - if (dev->irq < 2) { - int irqmap[] = {9,3,5,7,10,11,15,4}; - int reg1 = inb(ioaddr+1); - int reg4 = inb(ioaddr+4); - if (ancient || reg1 == 0xff) { /* Ack!! No way to read the IRQ! */ - short nic_addr = ioaddr+WD_NIC_OFFSET; - - /* We have an old-style ethercard that doesn't report its IRQ - line. Do autoirq to find the IRQ line. Note that this IS NOT - a reliable way to trigger an interrupt. */ - outb_p(E8390_NODMA + E8390_STOP, nic_addr); - outb(0x00, nic_addr+EN0_IMR); /* Disable all intrs. */ - autoirq_setup(0); - outb_p(0xff, nic_addr + EN0_IMR); /* Enable all interrupts. */ - outb_p(0x00, nic_addr + EN0_RCNTLO); - outb_p(0x00, nic_addr + EN0_RCNTHI); - outb(E8390_RREAD+E8390_START, nic_addr); /* Trigger it... */ - dev->irq = autoirq_report(2); - outb_p(0x00, nic_addr+EN0_IMR); /* Mask all intrs. again. */ - - if (ei_debug > 2) - printk(" autoirq is %d", dev->irq); - if (dev->irq < 2) - dev->irq = word16 ? 10 : 5; - } else - dev->irq = irqmap[((reg4 >> 5) & 0x03) + (reg1 & 0x04)]; - } else if (dev->irq == 2) /* Fixup bogosity: IRQ2 is really IRQ9 */ - dev->irq = 9; - - /* Snarf the interrupt now. There's no point in waiting since we cannot - share and the board will usually be enabled. */ - if (request_irq(dev->irq, ei_interrupt, 0, model_name)) { - printk (" unable to get IRQ %d.\n", dev->irq); - return EAGAIN; - } - - /* Allocate dev->priv and fill in 8390 specific dev fields. */ - if (ethdev_init(dev)) { - printk (" unable to get memory for dev->priv.\n"); - free_irq(dev->irq); - return -ENOMEM; - } - - /* OK, were are certain this is going to work. Setup the device. */ - request_region(ioaddr, WD_IO_EXTENT, model_name); - - ei_status.name = model_name; - ei_status.word16 = word16; - ei_status.tx_start_page = WD_START_PG; - ei_status.rx_start_page = WD_START_PG + TX_PAGES; - - /* Don't map in the shared memory until the board is actually opened. */ - dev->rmem_start = dev->mem_start + TX_PAGES*256; - - /* Some cards (eg WD8003EBT) can be jumpered for more (32k!) memory. */ - if (dev->mem_end != 0) { - ei_status.stop_page = (dev->mem_end - dev->mem_start)/256; - } else { - ei_status.stop_page = word16 ? WD13_STOP_PG : WD03_STOP_PG; - dev->mem_end = dev->mem_start + (ei_status.stop_page - WD_START_PG)*256; - } - dev->rmem_end = dev->mem_end; - - printk(" %s, IRQ %d, shared memory at %#lx-%#lx.\n", - model_name, dev->irq, dev->mem_start, dev->mem_end-1); - - ei_status.reset_8390 = &wd_reset_8390; - ei_status.block_input = &wd_block_input; - ei_status.block_output = &wd_block_output; - ei_status.get_8390_hdr = &wd_get_8390_hdr; - dev->open = &wd_open; - dev->stop = &wd_close_card; - NS8390_init(dev, 0); - -#if 1 - /* Enable interrupt generation on softconfig cards -- M.U */ - /* .. but possibly potentially unsafe - Donald */ - if (inb(ioaddr+14) & 0x20) - outb(inb(ioaddr+4)|0x80, ioaddr+4); -#endif - - return 0; -} - -static int -wd_open(struct device *dev) -{ - int ioaddr = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */ - - /* Map in the shared memory. Always set register 0 last to remain - compatible with very old boards. */ - ei_status.reg0 = ((dev->mem_start>>13) & 0x3f) | WD_MEMENB; - ei_status.reg5 = ((dev->mem_start>>19) & 0x1f) | NIC16; - - if (ei_status.word16) - outb(ei_status.reg5, ioaddr+WD_CMDREG5); - outb(ei_status.reg0, ioaddr); /* WD_CMDREG */ - - ei_open(dev); - MOD_INC_USE_COUNT; - return 0; -} - -static void -wd_reset_8390(struct device *dev) -{ - int wd_cmd_port = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */ - - outb(WD_RESET, wd_cmd_port); - if (ei_debug > 1) printk("resetting the WD80x3 t=%lu...", jiffies); - ei_status.txing = 0; - - /* Set up the ASIC registers, just in case something changed them. */ - outb((((dev->mem_start>>13) & 0x3f)|WD_MEMENB), wd_cmd_port); - if (ei_status.word16) - outb(NIC16 | ((dev->mem_start>>19) & 0x1f), wd_cmd_port+WD_CMDREG5); - - if (ei_debug > 1) printk("reset done\n"); - return; -} - -/* Grab the 8390 specific header. Similar to the block_input routine, but - we don't need to be concerned with ring wrap as the header will be at - the start of a page, so we optimize accordingly. */ - -static void -wd_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page) -{ - - int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */ - unsigned long hdr_start = dev->mem_start + ((ring_page - WD_START_PG)<<8); - - /* We'll always get a 4 byte header read followed by a packet read, so - we enable 16 bit mode before the header, and disable after the body. */ - if (ei_status.word16) - outb(ISA16 | ei_status.reg5, wd_cmdreg+WD_CMDREG5); - -#ifdef notdef - /* Officially this is what we are doing, but the readl() is faster */ - memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr)); -#else - ((unsigned int*)hdr)[0] = readl(hdr_start); -#endif -} - -/* Block input and output are easy on shared memory ethercards, and trivial - on the Western digital card where there is no choice of how to do it. - The only complications are that the ring buffer wraps, and need to map - switch between 8- and 16-bit modes. */ - -static void -wd_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset) -{ - int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */ - unsigned long xfer_start = dev->mem_start + ring_offset - (WD_START_PG<<8); - - if (xfer_start + count > dev->rmem_end) { - /* We must wrap the input move. */ - int semi_count = dev->rmem_end - xfer_start; - memcpy_fromio(skb->data, xfer_start, semi_count); - count -= semi_count; - memcpy_fromio(skb->data + semi_count, dev->rmem_start, count); - } else { - /* Packet is in one chunk -- we can copy + cksum. */ - eth_io_copy_and_sum(skb, xfer_start, count, 0); - } - - /* Turn off 16 bit access so that reboot works. ISA brain-damage */ - if (ei_status.word16) - outb(ei_status.reg5, wd_cmdreg+WD_CMDREG5); -} - -static void -wd_block_output(struct device *dev, int count, const unsigned char *buf, - int start_page) -{ - int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */ - long shmem = dev->mem_start + ((start_page - WD_START_PG)<<8); - - - if (ei_status.word16) { - /* Turn on and off 16 bit access so that reboot works. */ - outb(ISA16 | ei_status.reg5, wd_cmdreg+WD_CMDREG5); - memcpy_toio(shmem, buf, count); - outb(ei_status.reg5, wd_cmdreg+WD_CMDREG5); - } else - memcpy_toio(shmem, buf, count); -} - - -static int -wd_close_card(struct device *dev) -{ - int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */ - - if (ei_debug > 1) - printk("%s: Shutting down ethercard.\n", dev->name); - ei_close(dev); - - /* Change from 16-bit to 8-bit shared memory so reboot works. */ - if (ei_status.word16) - outb(ei_status.reg5, wd_cmdreg + WD_CMDREG5 ); - - /* And disable the shared memory. */ - outb(ei_status.reg0 & ~WD_MEMENB, wd_cmdreg); - - MOD_DEC_USE_COUNT; - - return 0; -} - - -#ifdef MODULE -#define MAX_WD_CARDS 4 /* Max number of wd cards per module */ -#define NAMELEN 8 /* # of chars for storing dev->name */ -static char namelist[NAMELEN * MAX_WD_CARDS] = { 0, }; -static struct device dev_wd[MAX_WD_CARDS] = { - { - NULL, /* assign a chunk of namelist[] below */ - 0, 0, 0, 0, - 0, 0, - 0, 0, 0, NULL, NULL - }, -}; - -static int io[MAX_WD_CARDS] = { 0, }; -static int irq[MAX_WD_CARDS] = { 0, }; -static int mem[MAX_WD_CARDS] = { 0, }; -static int mem_end[MAX_WD_CARDS] = { 0, }; /* for non std. mem size */ - -/* This is set up so that only a single autoprobe takes place per call. -ISA device autoprobes on a running machine are not recommended. */ -int -init_module(void) -{ - int this_dev, found = 0; - - for (this_dev = 0; this_dev < MAX_WD_CARDS; this_dev++) { - struct device *dev = &dev_wd[this_dev]; - dev->name = namelist+(NAMELEN*this_dev); - dev->irq = irq[this_dev]; - dev->base_addr = io[this_dev]; - dev->mem_start = mem[this_dev]; - dev->mem_end = mem_end[this_dev]; - dev->init = wd_probe; - if (io[this_dev] == 0) { - if (this_dev != 0) break; /* only autoprobe 1st one */ - printk(KERN_NOTICE "wd.c: Presently autoprobing (not recommended) for a single card.\n"); - } - if (register_netdev(dev) != 0) { - printk(KERN_WARNING "wd.c: No wd80x3 card found (i/o = 0x%x).\n", io[this_dev]); - if (found != 0) return 0; /* Got at least one. */ - return -ENXIO; - } - found++; - } - - return 0; -} - -void -cleanup_module(void) -{ - int this_dev; - - for (this_dev = 0; this_dev < MAX_WD_CARDS; this_dev++) { - struct device *dev = &dev_wd[this_dev]; - if (dev->priv != NULL) { - int ioaddr = dev->base_addr - WD_NIC_OFFSET; - kfree(dev->priv); - dev->priv = NULL; - free_irq(dev->irq); - irq2dev_map[dev->irq] = NULL; - release_region(ioaddr, WD_IO_EXTENT); - unregister_netdev(dev); - } - } -} -#endif /* MODULE */ - - -/* - * Local variables: - * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c wd.c" - * version-control: t - * tab-width: 4 - * kept-new-versions: 5 - * End: - */ diff --git a/i386/i386at/gpl/linux/net/znet.c b/i386/i386at/gpl/linux/net/znet.c deleted file mode 100644 index 9f44928e..00000000 --- a/i386/i386at/gpl/linux/net/znet.c +++ /dev/null @@ -1,746 +0,0 @@ -/* znet.c: An Zenith Z-Note ethernet driver for linux. */ - -static const char *version = "znet.c:v1.02 9/23/94 becker@cesdis.gsfc.nasa.gov\n"; - -/* - Written by Donald Becker. - - The author may be reached as becker@cesdis.gsfc.nasa.gov. - This driver is based on the Linux skeleton driver. The copyright of the - skeleton driver is held by the United States Government, as represented - by DIRNSA, and it is released under the GPL. - - Thanks to Mike Hollick for alpha testing and suggestions. - - References: - The Crynwr packet driver. - - "82593 CSMA/CD Core LAN Controller" Intel datasheet, 1992 - Intel Microcommunications Databook, Vol. 1, 1990. - As usual with Intel, the documentation is incomplete and inaccurate. - I had to read the Crynwr packet driver to figure out how to actually - use the i82593, and guess at what register bits matched the loosely - related i82586. - - Theory of Operation - - The i82593 used in the Zenith Z-Note series operates using two(!) slave - DMA channels, one interrupt, and one 8-bit I/O port. - - While there several ways to configure '593 DMA system, I chose the one - that seemed commensurate with the highest system performance in the face - of moderate interrupt latency: Both DMA channels are configured as - recirculating ring buffers, with one channel (#0) dedicated to Rx and - the other channel (#1) to Tx and configuration. (Note that this is - different than the Crynwr driver, where the Tx DMA channel is initialized - before each operation. That approach simplifies operation and Tx error - recovery, but requires additional I/O in normal operation and precludes - transmit buffer chaining.) - - Both rings are set to 8192 bytes using {TX,RX}_RING_SIZE. This provides - a reasonable ring size for Rx, while simplifying DMA buffer allocation -- - DMA buffers must not cross a 128K boundary. (In truth the size selection - was influenced by my lack of '593 documentation. I thus was constrained - to use the Crynwr '593 initialization table, which sets the Rx ring size - to 8K.) - - Despite my usual low opinion about Intel-designed parts, I must admit - that the bulk data handling of the i82593 is a good design for - an integrated system, like a laptop, where using two slave DMA channels - doesn't pose a problem. I still take issue with using only a single I/O - port. In the same controlled environment there are essentially no - limitations on I/O space, and using multiple locations would eliminate - the need for multiple operations when looking at status registers, - setting the Rx ring boundary, or switching to promiscuous mode. - - I also question Zenith's selection of the '593: one of the advertised - advantages of earlier Intel parts was that if you figured out the magic - initialization incantation you could use the same part on many different - network types. Zenith's use of the "FriendlyNet" (sic) connector rather - than an on-board transceiver leads me to believe that they were planning - to take advantage of this. But, uhmmm, the '593 omits all but ethernet - functionality from the serial subsystem. - */ - -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/string.h> -#include <linux/ptrace.h> -#include <linux/errno.h> -#include <linux/interrupt.h> -#include <linux/ioport.h> -#include <asm/system.h> -#include <asm/bitops.h> -#include <asm/io.h> -#include <asm/dma.h> - -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> -#include <linux/if_arp.h> - -#ifndef ZNET_DEBUG -#define ZNET_DEBUG 1 -#endif -static unsigned int znet_debug = ZNET_DEBUG; - -/* The DMA modes we need aren't in <dma.h>. */ -#define DMA_RX_MODE 0x14 /* Auto init, I/O to mem, ++, demand. */ -#define DMA_TX_MODE 0x18 /* Auto init, Mem to I/O, ++, demand. */ -#define dma_page_eq(ptr1, ptr2) ((long)(ptr1)>>17 == (long)(ptr2)>>17) -#define DMA_BUF_SIZE 8192 -#define RX_BUF_SIZE 8192 -#define TX_BUF_SIZE 8192 - -/* Commands to the i82593 channel 0. */ -#define CMD0_CHNL_0 0x00 -#define CMD0_CHNL_1 0x10 /* Switch to channel 1. */ -#define CMD0_NOP (CMD0_CHNL_0) -#define CMD0_PORT_1 CMD0_CHNL_1 -#define CMD1_PORT_0 1 -#define CMD0_IA_SETUP 1 -#define CMD0_CONFIGURE 2 -#define CMD0_MULTICAST_LIST 3 -#define CMD0_TRANSMIT 4 -#define CMD0_DUMP 6 -#define CMD0_DIAGNOSE 7 -#define CMD0_Rx_ENABLE 8 -#define CMD0_Rx_DISABLE 10 -#define CMD0_Rx_STOP 11 -#define CMD0_RETRANSMIT 12 -#define CMD0_ABORT 13 -#define CMD0_RESET 14 - -#define CMD0_ACK 0x80 - -#define CMD0_STAT0 (0 << 5) -#define CMD0_STAT1 (1 << 5) -#define CMD0_STAT2 (2 << 5) -#define CMD0_STAT3 (3 << 5) - -#define net_local znet_private -struct znet_private { - int rx_dma, tx_dma; - struct enet_statistics stats; - /* The starting, current, and end pointers for the packet buffers. */ - ushort *rx_start, *rx_cur, *rx_end; - ushort *tx_start, *tx_cur, *tx_end; - ushort tx_buf_len; /* Tx buffer length, in words. */ -}; - -/* Only one can be built-in;-> */ -static struct znet_private zn; -static ushort dma_buffer1[DMA_BUF_SIZE/2]; -static ushort dma_buffer2[DMA_BUF_SIZE/2]; -static ushort dma_buffer3[DMA_BUF_SIZE/2 + 8]; - -/* The configuration block. What an undocumented nightmare. The first - set of values are those suggested (without explanation) for ethernet - in the Intel 82586 databook. The rest appear to be completely undocumented, - except for cryptic notes in the Crynwr packet driver. This driver uses - the Crynwr values verbatim. */ - -static unsigned char i593_init[] = { - 0xAA, /* 0: 16-byte input & 80-byte output FIFO. */ - /* threshold, 96-byte FIFO, 82593 mode. */ - 0x88, /* 1: Continuous w/interrupts, 128-clock DMA.*/ - 0x2E, /* 2: 8-byte preamble, NO address insertion, */ - /* 6-byte Ethernet address, loopback off.*/ - 0x00, /* 3: Default priorities & backoff methods. */ - 0x60, /* 4: 96-bit interframe spacing. */ - 0x00, /* 5: 512-bit slot time (low-order). */ - 0xF2, /* 6: Slot time (high-order), 15 COLL retries. */ - 0x00, /* 7: Promisc-off, broadcast-on, default CRC. */ - 0x00, /* 8: Default carrier-sense, collision-detect. */ - 0x40, /* 9: 64-byte minimum frame length. */ - 0x5F, /* A: Type/length checks OFF, no CRC input, - "jabber" termination, etc. */ - 0x00, /* B: Full-duplex disabled. */ - 0x3F, /* C: Default multicast addresses & backoff. */ - 0x07, /* D: Default IFS retriggering. */ - 0x31, /* E: Internal retransmit, drop "runt" packets, - synchr. DRQ deassertion, 6 status bytes. */ - 0x22, /* F: Receive ring-buffer size (8K), - receive-stop register enable. */ -}; - -struct netidblk { - char magic[8]; /* The magic number (string) "NETIDBLK" */ - unsigned char netid[8]; /* The physical station address */ - char nettype, globalopt; - char vendor[8]; /* The machine vendor and product name. */ - char product[8]; - char irq1, irq2; /* Interrupts, only one is currently used. */ - char dma1, dma2; - short dma_mem_misc[8]; /* DMA buffer locations (unused in Linux). */ - short iobase1, iosize1; - short iobase2, iosize2; /* Second iobase unused. */ - char driver_options; /* Misc. bits */ - char pad; -}; - -int znet_probe(struct device *dev); -static int znet_open(struct device *dev); -static int znet_send_packet(struct sk_buff *skb, struct device *dev); -static void znet_interrupt(int irq, struct pt_regs *regs); -static void znet_rx(struct device *dev); -static int znet_close(struct device *dev); -static struct enet_statistics *net_get_stats(struct device *dev); -static void set_multicast_list(struct device *dev); -static void hardware_init(struct device *dev); -static void update_stop_hit(short ioaddr, unsigned short rx_stop_offset); - -#ifdef notdef -static struct sigaction znet_sigaction = { &znet_interrupt, 0, 0, NULL, }; -#endif - - -/* The Z-Note probe is pretty easy. The NETIDBLK exists in the safe-to-probe - BIOS area. We just scan for the signature, and pull the vital parameters - out of the structure. */ - -int znet_probe(struct device *dev) -{ - int i; - struct netidblk *netinfo; - char *p; - - /* This code scans the region 0xf0000 to 0xfffff for a "NETIDBLK". */ - for(p = (char *)0xf0000; p < (char *)0x100000; p++) - if (*p == 'N' && strncmp(p, "NETIDBLK", 8) == 0) - break; - - if (p >= (char *)0x100000) { - if (znet_debug > 1) - printk(KERN_INFO "No Z-Note ethernet adaptor found.\n"); - return ENODEV; - } - netinfo = (struct netidblk *)p; - dev->base_addr = netinfo->iobase1; - dev->irq = netinfo->irq1; - - printk(KERN_INFO "%s: ZNET at %#3lx,", dev->name, dev->base_addr); - - /* The station address is in the "netidblk" at 0x0f0000. */ - for (i = 0; i < 6; i++) - printk(" %2.2x", dev->dev_addr[i] = netinfo->netid[i]); - - printk(", using IRQ %d DMA %d and %d.\n", dev->irq, netinfo->dma1, - netinfo->dma2); - - if (znet_debug > 1) { - printk(KERN_INFO "%s: vendor '%16.16s' IRQ1 %d IRQ2 %d DMA1 %d DMA2 %d.\n", - dev->name, netinfo->vendor, - netinfo->irq1, netinfo->irq2, - netinfo->dma1, netinfo->dma2); - printk(KERN_INFO "%s: iobase1 %#x size %d iobase2 %#x size %d net type %2.2x.\n", - dev->name, netinfo->iobase1, netinfo->iosize1, - netinfo->iobase2, netinfo->iosize2, netinfo->nettype); - } - - if (znet_debug > 0) - printk("%s%s", KERN_INFO, version); - - dev->priv = (void *) &zn; - zn.rx_dma = netinfo->dma1; - zn.tx_dma = netinfo->dma2; - - /* These should never fail. You can't add devices to a sealed box! */ - if (request_irq(dev->irq, &znet_interrupt, 0, "ZNet") - || request_dma(zn.rx_dma,"ZNet rx") - || request_dma(zn.tx_dma,"ZNet tx")) { - printk(KERN_WARNING "%s: Not opened -- resource busy?!?\n", dev->name); - return EBUSY; - } - irq2dev_map[dev->irq] = dev; - - /* Allocate buffer memory. We can cross a 128K boundary, so we - must be careful about the allocation. It's easiest to waste 8K. */ - if (dma_page_eq(dma_buffer1, &dma_buffer1[RX_BUF_SIZE/2-1])) - zn.rx_start = dma_buffer1; - else - zn.rx_start = dma_buffer2; - - if (dma_page_eq(dma_buffer3, &dma_buffer3[RX_BUF_SIZE/2-1])) - zn.tx_start = dma_buffer3; - else - zn.tx_start = dma_buffer2; - zn.rx_end = zn.rx_start + RX_BUF_SIZE/2; - zn.tx_buf_len = TX_BUF_SIZE/2; - zn.tx_end = zn.tx_start + zn.tx_buf_len; - - /* The ZNET-specific entries in the device structure. */ - dev->open = &znet_open; - dev->hard_start_xmit = &znet_send_packet; - dev->stop = &znet_close; - dev->get_stats = net_get_stats; - dev->set_multicast_list = &set_multicast_list; - - /* Fill in the 'dev' with ethernet-generic values. */ - ether_setup(dev); - - return 0; -} - - -static int znet_open(struct device *dev) -{ - int ioaddr = dev->base_addr; - - if (znet_debug > 2) - printk(KERN_DEBUG "%s: znet_open() called.\n", dev->name); - - /* Turn on the 82501 SIA, using zenith-specific magic. */ - outb(0x10, 0xe6); /* Select LAN control register */ - outb(inb(0xe7) | 0x84, 0xe7); /* Turn on LAN power (bit 2). */ - /* According to the Crynwr driver we should wait 50 msec. for the - LAN clock to stabilize. My experiments indicates that the '593 can - be initialized immediately. The delay is probably needed for the - DC-to-DC converter to come up to full voltage, and for the oscillator - to be spot-on at 20Mhz before transmitting. - Until this proves to be a problem we rely on the higher layers for the - delay and save allocating a timer entry. */ - - /* This follows the packet driver's lead, and checks for success. */ - if (inb(ioaddr) != 0x10 && inb(ioaddr) != 0x00) - printk(KERN_WARNING "%s: Problem turning on the transceiver power.\n", - dev->name); - - dev->tbusy = 0; - dev->interrupt = 0; - hardware_init(dev); - dev->start = 1; - - return 0; -} - -static int znet_send_packet(struct sk_buff *skb, struct device *dev) -{ - int ioaddr = dev->base_addr; - - if (znet_debug > 4) - printk(KERN_DEBUG "%s: ZNet_send_packet(%ld).\n", dev->name, dev->tbusy); - - /* Transmitter timeout, likely just recovery after suspending the machine. */ - if (dev->tbusy) { - ushort event, tx_status, rx_offset, state; - int tickssofar = jiffies - dev->trans_start; - if (tickssofar < 10) - return 1; - outb(CMD0_STAT0, ioaddr); event = inb(ioaddr); - outb(CMD0_STAT1, ioaddr); tx_status = inw(ioaddr); - outb(CMD0_STAT2, ioaddr); rx_offset = inw(ioaddr); - outb(CMD0_STAT3, ioaddr); state = inb(ioaddr); - printk(KERN_WARNING "%s: transmit timed out, status %02x %04x %04x %02x," - " resetting.\n", dev->name, event, tx_status, rx_offset, state); - if (tx_status == 0x0400) - printk(KERN_WARNING "%s: Tx carrier error, check transceiver cable.\n", - dev->name); - outb(CMD0_RESET, ioaddr); - hardware_init(dev); - } - - if (skb == NULL) { - dev_tint(dev); - return 0; - } - - /* Check that the part hasn't reset itself, probably from suspend. */ - outb(CMD0_STAT0, ioaddr); - if (inw(ioaddr) == 0x0010 - && inw(ioaddr) == 0x0000 - && inw(ioaddr) == 0x0010) - hardware_init(dev); - - /* Block a timer-based transmit from overlapping. This could better be - done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ - if (set_bit(0, (void*)&dev->tbusy) != 0) - printk(KERN_WARNING "%s: Transmitter access conflict.\n", dev->name); - else { - short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; - unsigned char *buf = (void *)skb->data; - ushort *tx_link = zn.tx_cur - 1; - ushort rnd_len = (length + 1)>>1; - - { - short dma_port = ((zn.tx_dma&3)<<2) + IO_DMA2_BASE; - unsigned addr = inb(dma_port); - addr |= inb(dma_port) << 8; - addr <<= 1; - if (((int)zn.tx_cur & 0x1ffff) != addr) - printk(KERN_WARNING "Address mismatch at Tx: %#x vs %#x.\n", - (int)zn.tx_cur & 0xffff, addr); - zn.tx_cur = (ushort *)(((int)zn.tx_cur & 0xfe0000) | addr); - } - - if (zn.tx_cur >= zn.tx_end) - zn.tx_cur = zn.tx_start; - *zn.tx_cur++ = length; - if (zn.tx_cur + rnd_len + 1 > zn.tx_end) { - int semi_cnt = (zn.tx_end - zn.tx_cur)<<1; /* Cvrt to byte cnt. */ - memcpy(zn.tx_cur, buf, semi_cnt); - rnd_len -= semi_cnt>>1; - memcpy(zn.tx_start, buf + semi_cnt, length - semi_cnt); - zn.tx_cur = zn.tx_start + rnd_len; - } else { - memcpy(zn.tx_cur, buf, skb->len); - zn.tx_cur += rnd_len; - } - *zn.tx_cur++ = 0; - cli(); { - *tx_link = CMD0_TRANSMIT + CMD0_CHNL_1; - /* Is this always safe to do? */ - outb(CMD0_TRANSMIT + CMD0_CHNL_1,ioaddr); - } sti(); - - dev->trans_start = jiffies; - if (znet_debug > 4) - printk(KERN_DEBUG "%s: Transmitter queued, length %d.\n", dev->name, length); - } - dev_kfree_skb(skb, FREE_WRITE); - return 0; -} - -/* The ZNET interrupt handler. */ -static void znet_interrupt(int irq, struct pt_regs * regs) -{ - struct device *dev = irq2dev_map[irq]; - int ioaddr; - int boguscnt = 20; - - if (dev == NULL) { - printk(KERN_WARNING "znet_interrupt(): IRQ %d for unknown device.\n", irq); - return; - } - - dev->interrupt = 1; - ioaddr = dev->base_addr; - - outb(CMD0_STAT0, ioaddr); - do { - ushort status = inb(ioaddr); - if (znet_debug > 5) { - ushort result, rx_ptr, running; - outb(CMD0_STAT1, ioaddr); - result = inw(ioaddr); - outb(CMD0_STAT2, ioaddr); - rx_ptr = inw(ioaddr); - outb(CMD0_STAT3, ioaddr); - running = inb(ioaddr); - printk(KERN_DEBUG "%s: interrupt, status %02x, %04x %04x %02x serial %d.\n", - dev->name, status, result, rx_ptr, running, boguscnt); - } - if ((status & 0x80) == 0) - break; - - if ((status & 0x0F) == 4) { /* Transmit done. */ - struct net_local *lp = (struct net_local *)dev->priv; - int tx_status; - outb(CMD0_STAT1, ioaddr); - tx_status = inw(ioaddr); - /* It's undocumented, but tx_status seems to match the i82586. */ - if (tx_status & 0x2000) { - lp->stats.tx_packets++; - lp->stats.collisions += tx_status & 0xf; - } else { - if (tx_status & 0x0600) lp->stats.tx_carrier_errors++; - if (tx_status & 0x0100) lp->stats.tx_fifo_errors++; - if (!(tx_status & 0x0040)) lp->stats.tx_heartbeat_errors++; - if (tx_status & 0x0020) lp->stats.tx_aborted_errors++; - /* ...and the catch-all. */ - if ((tx_status | 0x0760) != 0x0760) - lp->stats.tx_errors++; - } - dev->tbusy = 0; - mark_bh(NET_BH); /* Inform upper layers. */ - } - - if ((status & 0x40) - || (status & 0x0f) == 11) { - znet_rx(dev); - } - /* Clear the interrupts we've handled. */ - outb(CMD0_ACK,ioaddr); - } while (boguscnt--); - - dev->interrupt = 0; - return; -} - -static void znet_rx(struct device *dev) -{ - struct net_local *lp = (struct net_local *)dev->priv; - int ioaddr = dev->base_addr; - int boguscount = 1; - short next_frame_end_offset = 0; /* Offset of next frame start. */ - short *cur_frame_end; - short cur_frame_end_offset; - - outb(CMD0_STAT2, ioaddr); - cur_frame_end_offset = inw(ioaddr); - - if (cur_frame_end_offset == zn.rx_cur - zn.rx_start) { - printk(KERN_WARNING "%s: Interrupted, but nothing to receive, offset %03x.\n", - dev->name, cur_frame_end_offset); - return; - } - - /* Use same method as the Crynwr driver: construct a forward list in - the same area of the backwards links we now have. This allows us to - pass packets to the upper layers in the order they were received -- - important for fast-path sequential operations. */ - while (zn.rx_start + cur_frame_end_offset != zn.rx_cur - && ++boguscount < 5) { - unsigned short hi_cnt, lo_cnt, hi_status, lo_status; - int count, status; - - if (cur_frame_end_offset < 4) { - /* Oh no, we have a special case: the frame trailer wraps around - the end of the ring buffer. We've saved space at the end of - the ring buffer for just this problem. */ - memcpy(zn.rx_end, zn.rx_start, 8); - cur_frame_end_offset += (RX_BUF_SIZE/2); - } - cur_frame_end = zn.rx_start + cur_frame_end_offset - 4; - - lo_status = *cur_frame_end++; - hi_status = *cur_frame_end++; - status = ((hi_status & 0xff) << 8) + (lo_status & 0xff); - lo_cnt = *cur_frame_end++; - hi_cnt = *cur_frame_end++; - count = ((hi_cnt & 0xff) << 8) + (lo_cnt & 0xff); - - if (znet_debug > 5) - printk(KERN_DEBUG "Constructing trailer at location %03x, %04x %04x %04x %04x" - " count %#x status %04x.\n", - cur_frame_end_offset<<1, lo_status, hi_status, lo_cnt, hi_cnt, - count, status); - cur_frame_end[-4] = status; - cur_frame_end[-3] = next_frame_end_offset; - cur_frame_end[-2] = count; - next_frame_end_offset = cur_frame_end_offset; - cur_frame_end_offset -= ((count + 1)>>1) + 3; - if (cur_frame_end_offset < 0) - cur_frame_end_offset += RX_BUF_SIZE/2; - }; - - /* Now step forward through the list. */ - do { - ushort *this_rfp_ptr = zn.rx_start + next_frame_end_offset; - int status = this_rfp_ptr[-4]; - int pkt_len = this_rfp_ptr[-2]; - - if (znet_debug > 5) - printk(KERN_DEBUG "Looking at trailer ending at %04x status %04x length %03x" - " next %04x.\n", next_frame_end_offset<<1, status, pkt_len, - this_rfp_ptr[-3]<<1); - /* Once again we must assume that the i82586 docs apply. */ - if ( ! (status & 0x2000)) { /* There was an error. */ - lp->stats.rx_errors++; - if (status & 0x0800) lp->stats.rx_crc_errors++; - if (status & 0x0400) lp->stats.rx_frame_errors++; - if (status & 0x0200) lp->stats.rx_over_errors++; /* Wrong. */ - if (status & 0x0100) lp->stats.rx_fifo_errors++; - if (status & 0x0080) lp->stats.rx_length_errors++; - } else if (pkt_len > 1536) { - lp->stats.rx_length_errors++; - } else { - /* Malloc up new buffer. */ - struct sk_buff *skb; - - skb = dev_alloc_skb(pkt_len); - if (skb == NULL) { - if (znet_debug) - printk(KERN_WARNING "%s: Memory squeeze, dropping packet.\n", dev->name); - lp->stats.rx_dropped++; - break; - } - skb->dev = dev; - - if (&zn.rx_cur[(pkt_len+1)>>1] > zn.rx_end) { - int semi_cnt = (zn.rx_end - zn.rx_cur)<<1; - memcpy(skb_put(skb,semi_cnt), zn.rx_cur, semi_cnt); - memcpy(skb_put(skb,pkt_len-semi_cnt), zn.rx_start, - pkt_len - semi_cnt); - } else { - memcpy(skb_put(skb,pkt_len), zn.rx_cur, pkt_len); - if (znet_debug > 6) { - unsigned int *packet = (unsigned int *) skb->data; - printk(KERN_DEBUG "Packet data is %08x %08x %08x %08x.\n", packet[0], - packet[1], packet[2], packet[3]); - } - } - skb->protocol=eth_type_trans(skb,dev); - netif_rx(skb); - lp->stats.rx_packets++; - } - zn.rx_cur = this_rfp_ptr; - if (zn.rx_cur >= zn.rx_end) - zn.rx_cur -= RX_BUF_SIZE/2; - update_stop_hit(ioaddr, (zn.rx_cur - zn.rx_start)<<1); - next_frame_end_offset = this_rfp_ptr[-3]; - if (next_frame_end_offset == 0) /* Read all the frames? */ - break; /* Done for now */ - this_rfp_ptr = zn.rx_start + next_frame_end_offset; - } while (--boguscount); - - /* If any worth-while packets have been received, dev_rint() - has done a mark_bh(INET_BH) for us and will work on them - when we get to the bottom-half routine. */ - return; -} - -/* The inverse routine to znet_open(). */ -static int znet_close(struct device *dev) -{ - int ioaddr = dev->base_addr; - - dev->tbusy = 1; - dev->start = 0; - - outb(CMD0_RESET, ioaddr); /* CMD0_RESET */ - - disable_dma(zn.rx_dma); - disable_dma(zn.tx_dma); - - free_irq(dev->irq); - - if (znet_debug > 1) - printk(KERN_DEBUG "%s: Shutting down ethercard.\n", dev->name); - /* Turn off transceiver power. */ - outb(0x10, 0xe6); /* Select LAN control register */ - outb(inb(0xe7) & ~0x84, 0xe7); /* Turn on LAN power (bit 2). */ - - return 0; -} - -/* Get the current statistics. This may be called with the card open or - closed. */ -static struct enet_statistics *net_get_stats(struct device *dev) -{ - struct net_local *lp = (struct net_local *)dev->priv; - - return &lp->stats; -} - -/* Set or clear the multicast filter for this adaptor. - As a side effect this routine must also initialize the device parameters. - This is taken advantage of in open(). - - N.B. that we change i593_init[] in place. This (properly) makes the - mode change persistent, but must be changed if this code is moved to - a multiple adaptor environment. - */ -static void set_multicast_list(struct device *dev) -{ - short ioaddr = dev->base_addr; - - if (dev->flags&IFF_PROMISC) { - /* Enable promiscuous mode */ - i593_init[7] &= ~3; i593_init[7] |= 1; - i593_init[13] &= ~8; i593_init[13] |= 8; - } else if (dev->mc_list || (dev->flags&IFF_ALLMULTI)) { - /* Enable accept-all-multicast mode */ - i593_init[7] &= ~3; i593_init[7] |= 0; - i593_init[13] &= ~8; i593_init[13] |= 8; - } else { /* Enable normal mode. */ - i593_init[7] &= ~3; i593_init[7] |= 0; - i593_init[13] &= ~8; i593_init[13] |= 0; - } - *zn.tx_cur++ = sizeof(i593_init); - memcpy(zn.tx_cur, i593_init, sizeof(i593_init)); - zn.tx_cur += sizeof(i593_init)/2; - outb(CMD0_CONFIGURE+CMD0_CHNL_1, ioaddr); -#ifdef not_tested - if (num_addrs > 0) { - int addrs_len = 6*num_addrs; - *zn.tx_cur++ = addrs_len; - memcpy(zn.tx_cur, addrs, addrs_len); - outb(CMD0_MULTICAST_LIST+CMD0_CHNL_1, ioaddr); - zn.tx_cur += addrs_len>>1; - } -#endif -} - -void show_dma(void) -{ - short dma_port = ((zn.tx_dma&3)<<2) + IO_DMA2_BASE; - unsigned addr = inb(dma_port); - addr |= inb(dma_port) << 8; - printk("Addr: %04x cnt:%3x...", addr<<1, get_dma_residue(zn.tx_dma)); -} - -/* Initialize the hardware. We have to do this when the board is open()ed - or when we come out of suspend mode. */ -static void hardware_init(struct device *dev) -{ - short ioaddr = dev->base_addr; - - zn.rx_cur = zn.rx_start; - zn.tx_cur = zn.tx_start; - - /* Reset the chip, and start it up. */ - outb(CMD0_RESET, ioaddr); - - cli(); { /* Protect against a DMA flip-flop */ - disable_dma(zn.rx_dma); /* reset by an interrupting task. */ - clear_dma_ff(zn.rx_dma); - set_dma_mode(zn.rx_dma, DMA_RX_MODE); - set_dma_addr(zn.rx_dma, (unsigned int) zn.rx_start); - set_dma_count(zn.rx_dma, RX_BUF_SIZE); - enable_dma(zn.rx_dma); - /* Now set up the Tx channel. */ - disable_dma(zn.tx_dma); - clear_dma_ff(zn.tx_dma); - set_dma_mode(zn.tx_dma, DMA_TX_MODE); - set_dma_addr(zn.tx_dma, (unsigned int) zn.tx_start); - set_dma_count(zn.tx_dma, zn.tx_buf_len<<1); - enable_dma(zn.tx_dma); - } sti(); - - if (znet_debug > 1) - printk(KERN_DEBUG "%s: Initializing the i82593, tx buf %p... ", dev->name, - zn.tx_start); - /* Do an empty configure command, just like the Crynwr driver. This - resets to chip to its default values. */ - *zn.tx_cur++ = 0; - *zn.tx_cur++ = 0; - printk("stat:%02x ", inb(ioaddr)); show_dma(); - outb(CMD0_CONFIGURE+CMD0_CHNL_1, ioaddr); - *zn.tx_cur++ = sizeof(i593_init); - memcpy(zn.tx_cur, i593_init, sizeof(i593_init)); - zn.tx_cur += sizeof(i593_init)/2; - printk("stat:%02x ", inb(ioaddr)); show_dma(); - outb(CMD0_CONFIGURE+CMD0_CHNL_1, ioaddr); - *zn.tx_cur++ = 6; - memcpy(zn.tx_cur, dev->dev_addr, 6); - zn.tx_cur += 3; - printk("stat:%02x ", inb(ioaddr)); show_dma(); - outb(CMD0_IA_SETUP + CMD0_CHNL_1, ioaddr); - printk("stat:%02x ", inb(ioaddr)); show_dma(); - - update_stop_hit(ioaddr, 8192); - if (znet_debug > 1) printk("enabling Rx.\n"); - outb(CMD0_Rx_ENABLE+CMD0_CHNL_0, ioaddr); - dev->tbusy = 0; -} - -static void update_stop_hit(short ioaddr, unsigned short rx_stop_offset) -{ - outb(CMD0_PORT_1, ioaddr); - if (znet_debug > 5) - printk(KERN_DEBUG "Updating stop hit with value %02x.\n", - (rx_stop_offset >> 6) | 0x80); - outb((rx_stop_offset >> 6) | 0x80, ioaddr); - outb(CMD1_PORT_0, ioaddr); -} - -/* - * Local variables: - * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c znet.c" - * version-control: t - * kept-new-versions: 5 - * c-indent-level: 4 - * tab-width: 4 - * End: - */ diff --git a/i386/i386at/gpl/linux/pci/bios32.c b/i386/i386at/gpl/linux/pci/bios32.c deleted file mode 100644 index f0717fdb..00000000 --- a/i386/i386at/gpl/linux/pci/bios32.c +++ /dev/null @@ -1,466 +0,0 @@ -/* - * bios32.c - BIOS32, PCI BIOS functions. - * - * Sponsored by - * iX Multiuser Multitasking Magazine - * Hannover, Germany - * hm@ix.de - * - * Copyright 1993, 1994 Drew Eckhardt - * Visionary Computing - * (Unix and Linux consulting and custom programming) - * Drew@Colorado.EDU - * +1 (303) 786-7975 - * - * For more information, please consult - * - * PCI BIOS Specification Revision - * PCI Local Bus Specification - * PCI System Design Guide - * - * PCI Special Interest Group - * M/S HF3-15A - * 5200 N.E. Elam Young Parkway - * Hillsboro, Oregon 97124-6497 - * +1 (503) 696-2000 - * +1 (800) 433-5177 - * - * Manuals are $25 each or $50 for all three, plus $7 shipping - * within the United States, $35 abroad. - * - * - * CHANGELOG : - * Jun 17, 1994 : Modified to accommodate the broken pre-PCI BIOS SPECIFICATION - * Revision 2.0 present on <thys@dennis.ee.up.ac.za>'s ASUS mainboard. - * - * Jan 5, 1995 : Modified to probe PCI hardware at boot time by Frederic - * Potter, potter@cao-vlsi.ibp.fr - * - * Jan 10, 1995 : Modified to store the information about configured pci - * devices into a list, which can be accessed via /proc/pci by - * Curtis Varner, cvarner@cs.ucr.edu - * - * Jan 12, 1995 : CPU-PCI bridge optimization support by Frederic Potter. - * Alpha version. Intel & UMC chipset support only. - * - * Apr 16, 1995 : Source merge with the DEC Alpha PCI support. Most of the code - * moved to drivers/pci/pci.c. - * - * - */ - -#include <linux/config.h> -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/bios32.h> -#include <linux/pci.h> - -#include <asm/segment.h> - -#define PCIBIOS_PCI_FUNCTION_ID 0xb1XX -#define PCIBIOS_PCI_BIOS_PRESENT 0xb101 -#define PCIBIOS_FIND_PCI_DEVICE 0xb102 -#define PCIBIOS_FIND_PCI_CLASS_CODE 0xb103 -#define PCIBIOS_GENERATE_SPECIAL_CYCLE 0xb106 -#define PCIBIOS_READ_CONFIG_BYTE 0xb108 -#define PCIBIOS_READ_CONFIG_WORD 0xb109 -#define PCIBIOS_READ_CONFIG_DWORD 0xb10a -#define PCIBIOS_WRITE_CONFIG_BYTE 0xb10b -#define PCIBIOS_WRITE_CONFIG_WORD 0xb10c -#define PCIBIOS_WRITE_CONFIG_DWORD 0xb10d - - -/* BIOS32 signature: "_32_" */ -#define BIOS32_SIGNATURE (('_' << 0) + ('3' << 8) + ('2' << 16) + ('_' << 24)) - -/* PCI signature: "PCI " */ -#define PCI_SIGNATURE (('P' << 0) + ('C' << 8) + ('I' << 16) + (' ' << 24)) - -/* PCI service signature: "$PCI" */ -#define PCI_SERVICE (('$' << 0) + ('P' << 8) + ('C' << 16) + ('I' << 24)) - -/* - * This is the standard structure used to identify the entry point - * to the BIOS32 Service Directory, as documented in - * Standard BIOS 32-bit Service Directory Proposal - * Revision 0.4 May 24, 1993 - * Phoenix Technologies Ltd. - * Norwood, MA - * and the PCI BIOS specification. - */ - -union bios32 { - struct { - unsigned long signature; /* _32_ */ - unsigned long entry; /* 32 bit physical address */ - unsigned char revision; /* Revision level, 0 */ - unsigned char length; /* Length in paragraphs should be 01 */ - unsigned char checksum; /* All bytes must add up to zero */ - unsigned char reserved[5]; /* Must be zero */ - } fields; - char chars[16]; -}; - -/* - * Physical address of the service directory. I don't know if we're - * allowed to have more than one of these or not, so just in case - * we'll make pcibios_present() take a memory start parameter and store - * the array there. - */ - -static unsigned long bios32_entry = 0; -static struct { - unsigned long address; - unsigned short segment; -} bios32_indirect = { 0, KERNEL_CS }; - -#ifdef CONFIG_PCI -/* - * Returns the entry point for the given service, NULL on error - */ - -static unsigned long bios32_service(unsigned long service) -{ - unsigned char return_code; /* %al */ - unsigned long address; /* %ebx */ - unsigned long length; /* %ecx */ - unsigned long entry; /* %edx */ - - __asm__("lcall (%%edi)" - : "=a" (return_code), - "=b" (address), - "=c" (length), - "=d" (entry) - : "0" (service), - "1" (0), - "D" (&bios32_indirect)); - - switch (return_code) { - case 0: - return address + entry; - case 0x80: /* Not present */ - printk("bios32_service(%ld) : not present\n", service); - return 0; - default: /* Shouldn't happen */ - printk("bios32_service(%ld) : returned 0x%x, mail drew@colorado.edu\n", - service, return_code); - return 0; - } -} - -static long pcibios_entry = 0; -static struct { - unsigned long address; - unsigned short segment; -} pci_indirect = { 0, KERNEL_CS }; - - -extern unsigned long check_pcibios(unsigned long memory_start, unsigned long memory_end) -{ - unsigned long signature; - unsigned char present_status; - unsigned char major_revision; - unsigned char minor_revision; - int pack; - - if ((pcibios_entry = bios32_service(PCI_SERVICE))) { - pci_indirect.address = pcibios_entry; - - __asm__("lcall (%%edi)\n\t" - "jc 1f\n\t" - "xor %%ah, %%ah\n" - "1:\tshl $8, %%eax\n\t" - "movw %%bx, %%ax" - : "=d" (signature), - "=a" (pack) - : "1" (PCIBIOS_PCI_BIOS_PRESENT), - "D" (&pci_indirect) - : "bx", "cx"); - - present_status = (pack >> 16) & 0xff; - major_revision = (pack >> 8) & 0xff; - minor_revision = pack & 0xff; - if (present_status || (signature != PCI_SIGNATURE)) { - printk ("pcibios_init : %s : BIOS32 Service Directory says PCI BIOS is present,\n" - " but PCI_BIOS_PRESENT subfunction fails with present status of 0x%x\n" - " and signature of 0x%08lx (%c%c%c%c). mail drew@Colorado.EDU\n", - (signature == PCI_SIGNATURE) ? "WARNING" : "ERROR", - present_status, signature, - (char) (signature >> 0), (char) (signature >> 8), - (char) (signature >> 16), (char) (signature >> 24)); - - if (signature != PCI_SIGNATURE) - pcibios_entry = 0; - } -#if 0 - if (pcibios_entry) { - printk ("pcibios_init : PCI BIOS revision %x.%02x entry at 0x%lx\n", - major_revision, minor_revision, pcibios_entry); - } -#endif - } - return memory_start; -} - -int pcibios_present(void) -{ - return pcibios_entry ? 1 : 0; -} - -int pcibios_find_class (unsigned int class_code, unsigned short index, - unsigned char *bus, unsigned char *device_fn) -{ - unsigned long bx; - unsigned long ret; - - __asm__ ("lcall (%%edi)\n\t" - "jc 1f\n\t" - "xor %%ah, %%ah\n" - "1:" - : "=b" (bx), - "=a" (ret) - : "1" (PCIBIOS_FIND_PCI_CLASS_CODE), - "c" (class_code), - "S" ((int) index), - "D" (&pci_indirect)); - *bus = (bx >> 8) & 0xff; - *device_fn = bx & 0xff; - return (int) (ret & 0xff00) >> 8; -} - - -int pcibios_find_device (unsigned short vendor, unsigned short device_id, - unsigned short index, unsigned char *bus, unsigned char *device_fn) -{ - unsigned short bx; - unsigned short ret; - - __asm__("lcall (%%edi)\n\t" - "jc 1f\n\t" - "xor %%ah, %%ah\n" - "1:" - : "=b" (bx), - "=a" (ret) - : "1" (PCIBIOS_FIND_PCI_DEVICE), - "c" (device_id), - "d" (vendor), - "S" ((int) index), - "D" (&pci_indirect)); - *bus = (bx >> 8) & 0xff; - *device_fn = bx & 0xff; - return (int) (ret & 0xff00) >> 8; -} - -int pcibios_read_config_byte(unsigned char bus, - unsigned char device_fn, unsigned char where, unsigned char *value) -{ - unsigned long ret; - unsigned long bx = (bus << 8) | device_fn; - - __asm__("lcall (%%esi)\n\t" - "jc 1f\n\t" - "xor %%ah, %%ah\n" - "1:" - : "=c" (*value), - "=a" (ret) - : "1" (PCIBIOS_READ_CONFIG_BYTE), - "b" (bx), - "D" ((long) where), - "S" (&pci_indirect)); - return (int) (ret & 0xff00) >> 8; -} - -int pcibios_read_config_word (unsigned char bus, - unsigned char device_fn, unsigned char where, unsigned short *value) -{ - unsigned long ret; - unsigned long bx = (bus << 8) | device_fn; - - __asm__("lcall (%%esi)\n\t" - "jc 1f\n\t" - "xor %%ah, %%ah\n" - "1:" - : "=c" (*value), - "=a" (ret) - : "1" (PCIBIOS_READ_CONFIG_WORD), - "b" (bx), - "D" ((long) where), - "S" (&pci_indirect)); - return (int) (ret & 0xff00) >> 8; -} - -int pcibios_read_config_dword (unsigned char bus, - unsigned char device_fn, unsigned char where, unsigned int *value) -{ - unsigned long ret; - unsigned long bx = (bus << 8) | device_fn; - - __asm__("lcall (%%esi)\n\t" - "jc 1f\n\t" - "xor %%ah, %%ah\n" - "1:" - : "=c" (*value), - "=a" (ret) - : "1" (PCIBIOS_READ_CONFIG_DWORD), - "b" (bx), - "D" ((long) where), - "S" (&pci_indirect)); - return (int) (ret & 0xff00) >> 8; -} - -int pcibios_write_config_byte (unsigned char bus, - unsigned char device_fn, unsigned char where, unsigned char value) -{ - unsigned long ret; - unsigned long bx = (bus << 8) | device_fn; - - __asm__("lcall (%%esi)\n\t" - "jc 1f\n\t" - "xor %%ah, %%ah\n" - "1:" - : "=a" (ret) - : "0" (PCIBIOS_WRITE_CONFIG_BYTE), - "c" (value), - "b" (bx), - "D" ((long) where), - "S" (&pci_indirect)); - return (int) (ret & 0xff00) >> 8; -} - -int pcibios_write_config_word (unsigned char bus, - unsigned char device_fn, unsigned char where, unsigned short value) -{ - unsigned long ret; - unsigned long bx = (bus << 8) | device_fn; - - __asm__("lcall (%%esi)\n\t" - "jc 1f\n\t" - "xor %%ah, %%ah\n" - "1:" - : "=a" (ret) - : "0" (PCIBIOS_WRITE_CONFIG_WORD), - "c" (value), - "b" (bx), - "D" ((long) where), - "S" (&pci_indirect)); - return (int) (ret & 0xff00) >> 8; -} - -int pcibios_write_config_dword (unsigned char bus, - unsigned char device_fn, unsigned char where, unsigned int value) -{ - unsigned long ret; - unsigned long bx = (bus << 8) | device_fn; - - __asm__("lcall (%%esi)\n\t" - "jc 1f\n\t" - "xor %%ah, %%ah\n" - "1:" - : "=a" (ret) - : "0" (PCIBIOS_WRITE_CONFIG_DWORD), - "c" (value), - "b" (bx), - "D" ((long) where), - "S" (&pci_indirect)); - return (int) (ret & 0xff00) >> 8; -} - -const char *pcibios_strerror (int error) -{ - static char buf[80]; - - switch (error) { - case PCIBIOS_SUCCESSFUL: - return "SUCCESSFUL"; - - case PCIBIOS_FUNC_NOT_SUPPORTED: - return "FUNC_NOT_SUPPORTED"; - - case PCIBIOS_BAD_VENDOR_ID: - return "SUCCESSFUL"; - - case PCIBIOS_DEVICE_NOT_FOUND: - return "DEVICE_NOT_FOUND"; - - case PCIBIOS_BAD_REGISTER_NUMBER: - return "BAD_REGISTER_NUMBER"; - - case PCIBIOS_SET_FAILED: - return "SET_FAILED"; - - case PCIBIOS_BUFFER_TOO_SMALL: - return "BUFFER_TOO_SMALL"; - - default: - sprintf (buf, "UNKNOWN RETURN 0x%x", error); - return buf; - } -} - - -unsigned long pcibios_fixup(unsigned long mem_start, unsigned long mem_end) -{ -return mem_start; -} - - -#endif - -unsigned long pcibios_init(unsigned long memory_start, unsigned long memory_end) -{ - union bios32 *check; - unsigned char sum; - int i, length; - - /* - * Follow the standard procedure for locating the BIOS32 Service - * directory by scanning the permissible address range from - * 0xe0000 through 0xfffff for a valid BIOS32 structure. - * - */ - - for (check = (union bios32 *) 0xe0000; check <= (union bios32 *) 0xffff0; ++check) { - if (check->fields.signature != BIOS32_SIGNATURE) - continue; - length = check->fields.length * 16; - if (!length) - continue; - sum = 0; - for (i = 0; i < length ; ++i) - sum += check->chars[i]; - if (sum != 0) - continue; - if (check->fields.revision != 0) { - printk("pcibios_init : unsupported revision %d at 0x%p, mail drew@colorado.edu\n", - check->fields.revision, check); - continue; - } -#if 0 - printk ("pcibios_init : BIOS32 Service Directory structure at 0x%p\n", check); -#endif - if (!bios32_entry) { - if (check->fields.entry >= 0x100000) { - printk("pcibios_init: entry in high memory, unable to access\n"); - } else { - bios32_indirect.address = bios32_entry = check->fields.entry; -#if 0 - printk ("pcibios_init : BIOS32 Service Directory entry at 0x%lx\n", bios32_entry); -#endif - } - } else { - printk ("pcibios_init : multiple entries, mail drew@colorado.edu\n"); - /* - * Jeremy Fitzhardinge reports at least one PCI BIOS - * with two different service directories, and as both - * worked for him, we'll just mention the fact, and - * not actually disallow it.. - */ - } - } -#ifdef CONFIG_PCI - if (bios32_entry) { - memory_start = check_pcibios (memory_start, memory_end); - } -#endif - return memory_start; -} diff --git a/i386/i386at/gpl/linux/pci/pci.c b/i386/i386at/gpl/linux/pci/pci.c deleted file mode 100644 index e5f59797..00000000 --- a/i386/i386at/gpl/linux/pci/pci.c +++ /dev/null @@ -1,917 +0,0 @@ -/* - * drivers/pci/pci.c - * - * PCI services that are built on top of the BIOS32 service. - * - * Copyright 1993, 1994, 1995 Drew Eckhardt, Frederic Potter, - * David Mosberger-Tang - */ -#include <linux/config.h> -#include <linux/ptrace.h> -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/bios32.h> -#include <linux/pci.h> -#include <linux/string.h> - -#include <asm/page.h> - -struct pci_bus pci_root; -struct pci_dev *pci_devices = 0; - - -/* - * The bridge_id field is an offset of an item into the array - * BRIDGE_MAPPING_TYPE. 0xff indicates that the device is not a PCI - * bridge, or that we don't know for the moment how to configure it. - * I'm trying to do my best so that the kernel stays small. Different - * chipset can have same optimization structure. i486 and pentium - * chipsets from the same manufacturer usually have the same - * structure. - */ -#define DEVICE(vid,did,name) \ - {PCI_VENDOR_ID_##vid, PCI_DEVICE_ID_##did, (name), 0xff} - -#define BRIDGE(vid,did,name,bridge) \ - {PCI_VENDOR_ID_##vid, PCI_DEVICE_ID_##did, (name), (bridge)} - -/* - * Sorted in ascending order by vendor and device. - * Use binary search for lookup. If you add a device make sure - * it is sequential by both vendor and device id. - */ -struct pci_dev_info dev_info[] = { - DEVICE( COMPAQ, COMPAQ_1280, "QVision 1280/p"), - DEVICE( COMPAQ, COMPAQ_THUNDER, "ThunderLAN"), - DEVICE( NCR, NCR_53C810, "53c810"), - DEVICE( NCR, NCR_53C820, "53c820"), - DEVICE( NCR, NCR_53C825, "53c825"), - DEVICE( NCR, NCR_53C815, "53c815"), - DEVICE( ATI, ATI_68800, "68800AX"), - DEVICE( ATI, ATI_215CT222, "215CT222"), - DEVICE( ATI, ATI_210888CX, "210888CX"), - DEVICE( ATI, ATI_210888GX, "210888GX"), - DEVICE( VLSI, VLSI_82C592, "82C592-FC1"), - DEVICE( VLSI, VLSI_82C593, "82C593-FC1"), - DEVICE( VLSI, VLSI_82C594, "82C594-AFC2"), - DEVICE( VLSI, VLSI_82C597, "82C597-AFC2"), - DEVICE( ADL, ADL_2301, "2301"), - DEVICE( NS, NS_87410, "87410"), - DEVICE( TSENG, TSENG_W32P_2, "ET4000W32P"), - DEVICE( TSENG, TSENG_W32P_b, "ET4000W32P rev B"), - DEVICE( TSENG, TSENG_W32P_c, "ET4000W32P rev C"), - DEVICE( TSENG, TSENG_W32P_d, "ET4000W32P rev D"), - DEVICE( WEITEK, WEITEK_P9000, "P9000"), - DEVICE( WEITEK, WEITEK_P9100, "P9100"), - BRIDGE( DEC, DEC_BRD, "DC21050", 0x00), - DEVICE( DEC, DEC_TULIP, "DC21040"), - DEVICE( DEC, DEC_TGA, "DC21030"), - DEVICE( DEC, DEC_TULIP_FAST, "DC21140"), - DEVICE( DEC, DEC_FDDI, "DEFPA"), - DEVICE( DEC, DEC_TULIP_PLUS, "DC21041"), - DEVICE( CIRRUS, CIRRUS_5430, "GD 5430"), - DEVICE( CIRRUS, CIRRUS_5434_4, "GD 5434"), - DEVICE( CIRRUS, CIRRUS_5434_8, "GD 5434"), - DEVICE( CIRRUS, CIRRUS_5436, "GD 5436"), - DEVICE( CIRRUS, CIRRUS_6205, "GD 6205"), - DEVICE( CIRRUS, CIRRUS_6729, "CL 6729"), - DEVICE( CIRRUS, CIRRUS_7542, "CL 7542"), - DEVICE( CIRRUS, CIRRUS_7543, "CL 7543"), - DEVICE( IBM, IBM_82G2675, "82G2675"), - DEVICE( WD, WD_7197, "WD 7197"), - DEVICE( AMD, AMD_LANCE, "79C970"), - DEVICE( AMD, AMD_SCSI, "53C974"), - DEVICE( TRIDENT, TRIDENT_9420, "TG 9420"), - DEVICE( TRIDENT, TRIDENT_9440, "TG 9440"), - DEVICE( TRIDENT, TRIDENT_9660, "TG 9660"), - DEVICE( AI, AI_M1435, "M1435"), - DEVICE( MATROX, MATROX_MGA_2, "Atlas PX2085"), - DEVICE( MATROX, MATROX_MIL ,"Millenium"), - DEVICE( MATROX, MATROX_MGA_IMP, "MGA Impression"), - DEVICE( CT, CT_65545, "65545"), - DEVICE( FD, FD_36C70, "TMC-18C30"), - DEVICE( SI, SI_6201, "6201"), - DEVICE( SI, SI_6202, "6202"), - DEVICE( SI, SI_503, "85C503"), - DEVICE( SI, SI_501, "85C501"), - DEVICE( SI, SI_496, "85C496"), - DEVICE( SI, SI_601, "85C601"), - DEVICE( SI, SI_5511, "85C5511"), - DEVICE( SI, SI_5513, "85C5513"), - DEVICE( HP, HP_J2585A, "J2585A"), - DEVICE( PCTECH, PCTECH_RZ1000, "RZ1000 (buggy)"), - DEVICE( DPT, DPT, "SmartCache/Raid"), - DEVICE( OPTI, OPTI_92C178, "92C178"), - DEVICE( OPTI, OPTI_82C557, "82C557"), - DEVICE( OPTI, OPTI_82C558, "82C558"), - DEVICE( OPTI, OPTI_82C621, "82C621"), - DEVICE( OPTI, OPTI_82C822, "82C822"), - DEVICE( SGS, SGS_2000, "STG 2000X"), - DEVICE( SGS, SGS_1764, "STG 1764X"), - DEVICE( BUSLOGIC, BUSLOGIC_946C_2,"BT-946C"), - DEVICE( BUSLOGIC, BUSLOGIC_946C, "BT-946C"), - DEVICE( BUSLOGIC, BUSLOGIC_930, "BT-930"), - DEVICE( OAK, OAK_OTI107, "OTI107"), - DEVICE( PROMISE, PROMISE_5300, "DC5030"), - DEVICE( N9, N9_I128, "Imagine 128"), - DEVICE( N9, N9_I128_2, "Imagine 128v2"), - DEVICE( UMC, UMC_UM8673F, "UM8673F"), - BRIDGE( UMC, UMC_UM8891A, "UM8891A", 0x01), - DEVICE( UMC, UMC_UM8886BF, "UM8886BF"), - DEVICE( UMC, UMC_UM8886A, "UM8886A"), - BRIDGE( UMC, UMC_UM8881F, "UM8881F", 0x02), - DEVICE( UMC, UMC_UM8886F, "UM8886F"), - DEVICE( UMC, UMC_UM9017F, "UM9017F"), - DEVICE( UMC, UMC_UM8886N, "UM8886N"), - DEVICE( UMC, UMC_UM8891N, "UM8891N"), - DEVICE( X, X_AGX016, "ITT AGX016"), - DEVICE( NEXGEN, NEXGEN_82C501, "82C501"), - DEVICE( QLOGIC, QLOGIC_ISP1020, "ISP1020"), - DEVICE( QLOGIC, QLOGIC_ISP1022, "ISP1022"), - DEVICE( LEADTEK, LEADTEK_805, "S3 805"), - DEVICE( CONTAQ, CONTAQ_82C599, "82C599"), - DEVICE( CMD, CMD_640, "640 (buggy)"), - DEVICE( CMD, CMD_646, "646"), - DEVICE( VISION, VISION_QD8500, "QD-8500"), - DEVICE( VISION, VISION_QD8580, "QD-8580"), - DEVICE( SIERRA, SIERRA_STB, "STB Horizon 64"), - DEVICE( ACC, ACC_2056, "2056"), - DEVICE( WINBOND, WINBOND_83769, "W83769F"), - DEVICE( WINBOND, WINBOND_82C105, "SL82C105"), - DEVICE( 3COM, 3COM_3C590, "3C590 10bT"), - DEVICE( 3COM, 3COM_3C595TX, "3C595 100bTX"), - DEVICE( 3COM, 3COM_3C595T4, "3C595 100bT4"), - DEVICE( 3COM, 3COM_3C595MII, "3C595 100b-MII"), - DEVICE( AL, AL_M1445, "M1445"), - DEVICE( AL, AL_M1449, "M1449"), - DEVICE( AL, AL_M1451, "M1451"), - DEVICE( AL, AL_M1461, "M1461"), - DEVICE( AL, AL_M1489, "M1489"), - DEVICE( AL, AL_M1511, "M1511"), - DEVICE( AL, AL_M1513, "M1513"), - DEVICE( AL, AL_M4803, "M4803"), - DEVICE( ASP, ASP_ABP940, "ABP940"), - DEVICE( IMS, IMS_8849, "8849"), - DEVICE( TEKRAM2, TEKRAM2_690c, "DC690c"), - DEVICE( AMCC, AMCC_MYRINET, "Myrinet PCI (M2-PCI-32)"), - DEVICE( INTERG, INTERG_1680, "IGA-1680"), - DEVICE( REALTEK, REALTEK_8029, "8029"), - DEVICE( INIT, INIT_320P, "320 P"), - DEVICE( VIA, VIA_82C505, "VT 82C505"), - DEVICE( VIA, VIA_82C561, "VT 82C561"), - DEVICE( VIA, VIA_82C576, "VT 82C576 3V"), - DEVICE( VIA, VIA_82C416, "VT 82C416MV"), - DEVICE( VORTEX, VORTEX_GDT, "GDT 6000b"), - DEVICE( EF, EF_ATM_FPGA, "155P-MF1 (FPGA)"), - DEVICE( EF, EF_ATM_ASIC, "155P-MF1 (ASIC)"), - DEVICE( IMAGINGTECH, IMAGINGTECH_ICPCI, "MVC IC-PCI"), - DEVICE( FORE, FORE_PCA200PC, "PCA-200PC"), - DEVICE( PLX, PLX_9060, "PCI9060 i960 bridge"), - DEVICE( ALLIANCE, ALLIANCE_PROMOTIO, "Promotion-6410"), - DEVICE( ALLIANCE, ALLIANCE_PROVIDEO, "Provideo"), - DEVICE( MUTECH, MUTECH_MV1000, "MV-1000"), - DEVICE( ZEITNET, ZEITNET_1221, "1221"), - DEVICE( ZEITNET, ZEITNET_1225, "1225"), - DEVICE( SPECIALIX, SPECIALIX_XIO, "XIO/SIO host"), - DEVICE( SPECIALIX, SPECIALIX_RIO, "RIO host"), - DEVICE( RP, RP8OCTA, "RocketPort 8 Oct"), - DEVICE( RP, RP8INTF, "RocketPort 8 Intf"), - DEVICE( RP, RP16INTF, "RocketPort 16 Intf"), - DEVICE( RP, RP32INTF, "RocketPort 32 Intf"), - DEVICE( CYCLADES, CYCLADES_Y, "Cyclome-Y"), - DEVICE( SYMPHONY, SYMPHONY_101, "82C101"), - DEVICE( TEKRAM, TEKRAM_DC290, "DC-290"), - DEVICE( AVANCE, AVANCE_2302, "ALG-2302"), - DEVICE( S3, S3_811, "Trio32/Trio64"), - DEVICE( S3, S3_868, "Vision 868"), - DEVICE( S3, S3_928, "Vision 928-P"), - DEVICE( S3, S3_864_1, "Vision 864-P"), - DEVICE( S3, S3_864_2, "Vision 864-P"), - DEVICE( S3, S3_964_1, "Vision 964-P"), - DEVICE( S3, S3_964_2, "Vision 964-P"), - DEVICE( S3, S3_968, "Vision 968"), - DEVICE( INTEL, INTEL_82375, "82375EB"), - BRIDGE( INTEL, INTEL_82424, "82424ZX Saturn", 0x00), - DEVICE( INTEL, INTEL_82378, "82378IB"), - DEVICE( INTEL, INTEL_82430, "82430ZX Aries"), - BRIDGE( INTEL, INTEL_82434, "82434LX Mercury/Neptune", 0x00), - DEVICE( INTEL, INTEL_7116, "SAA7116"), - DEVICE( INTEL, INTEL_82596, "82596"), - DEVICE( INTEL, INTEL_82865, "82865"), - DEVICE( INTEL, INTEL_82557, "82557"), - DEVICE( INTEL, INTEL_82437, "82437"), - DEVICE( INTEL, INTEL_82371_0, "82371 Triton PIIX"), - DEVICE( INTEL, INTEL_82371_1, "82371 Triton PIIX"), - DEVICE( INTEL, INTEL_P6, "Orion P6"), - DEVICE( ADAPTEC, ADAPTEC_7850, "AIC-7850"), - DEVICE( ADAPTEC, ADAPTEC_7870, "AIC-7870"), - DEVICE( ADAPTEC, ADAPTEC_7871, "AIC-7871"), - DEVICE( ADAPTEC, ADAPTEC_7872, "AIC-7872"), - DEVICE( ADAPTEC, ADAPTEC_7873, "AIC-7873"), - DEVICE( ADAPTEC, ADAPTEC_7874, "AIC-7874"), - DEVICE( ADAPTEC, ADAPTEC_7880, "AIC-7880U"), - DEVICE( ADAPTEC, ADAPTEC_7881, "AIC-7881U"), - DEVICE( ADAPTEC, ADAPTEC_7882, "AIC-7882U"), - DEVICE( ADAPTEC, ADAPTEC_7883, "AIC-7883U"), - DEVICE( ADAPTEC, ADAPTEC_7884, "AIC-7884U"), - DEVICE( ATRONICS, ATRONICS_2015, "IDE-2015PL"), - DEVICE( HER, HER_STING, "Stingray"), - DEVICE( HER, HER_STINGARK, "Stingray ARK 2000PV") -}; - - -#ifdef CONFIG_PCI_OPTIMIZE - -/* - * An item of this structure has the following meaning: - * for each optimization, the register address, the mask - * and value to write to turn it on. - * There are 5 optimizations for the moment: - * Cache L2 write back best than write through - * Posted Write for CPU to PCI enable - * Posted Write for CPU to MEMORY enable - * Posted Write for PCI to MEMORY enable - * PCI Burst enable - * - * Half of the bios I've meet don't allow you to turn that on, and you - * can gain more than 15% on graphic accesses using those - * optimizations... - */ -struct optimization_type { - const char *type; - const char *off; - const char *on; -} bridge_optimization[] = { - {"Cache L2", "write through", "write back"}, - {"CPU-PCI posted write", "off", "on"}, - {"CPU-Memory posted write", "off", "on"}, - {"PCI-Memory posted write", "off", "on"}, - {"PCI burst", "off", "on"} -}; - -#define NUM_OPTIMIZATIONS \ - (sizeof(bridge_optimization) / sizeof(bridge_optimization[0])) - -struct bridge_mapping_type { - unsigned char addr; /* config space address */ - unsigned char mask; - unsigned char value; -} bridge_mapping[] = { - /* - * Intel Neptune/Mercury/Saturn: - * If the internal cache is write back, - * the L2 cache must be write through! - * I've to check out how to control that - * for the moment, we won't touch the cache - */ - {0x0 ,0x02 ,0x02 }, - {0x53 ,0x02 ,0x02 }, - {0x53 ,0x01 ,0x01 }, - {0x54 ,0x01 ,0x01 }, - {0x54 ,0x02 ,0x02 }, - - /* - * UMC 8891A Pentium chipset: - * Why did you think UMC was cheaper ?? - */ - {0x50 ,0x10 ,0x00 }, - {0x51 ,0x40 ,0x40 }, - {0x0 ,0x0 ,0x0 }, - {0x0 ,0x0 ,0x0 }, - {0x0 ,0x0 ,0x0 }, - - /* - * UMC UM8881F - * This is a dummy entry for my tests. - * I have this chipset and no docs.... - */ - {0x0 ,0x1 ,0x1 }, - {0x0 ,0x2 ,0x0 }, - {0x0 ,0x0 ,0x0 }, - {0x0 ,0x0 ,0x0 }, - {0x0 ,0x0 ,0x0 } -}; - -#endif /* CONFIG_PCI_OPTIMIZE */ - - -/* - * device_info[] is sorted so we can use binary search - */ -struct pci_dev_info *pci_lookup_dev(unsigned int vendor, unsigned int dev) -{ - int min = 0, - max = sizeof(dev_info)/sizeof(dev_info[0]) - 1; - - for ( ; ; ) - { - int i = (min + max) >> 1; - long order; - - order = dev_info[i].vendor - (long) vendor; - if (!order) - order = dev_info[i].device - (long) dev; - - if (order < 0) - { - min = i + 1; - if ( min > max ) - return 0; - continue; - } - - if (order > 0) - { - max = i - 1; - if ( min > max ) - return 0; - continue; - } - - return & dev_info[ i ]; - } -} - -const char *pci_strclass (unsigned int class) -{ - switch (class >> 8) { - case PCI_CLASS_NOT_DEFINED: return "Non-VGA device"; - case PCI_CLASS_NOT_DEFINED_VGA: return "VGA compatible device"; - - case PCI_CLASS_STORAGE_SCSI: return "SCSI storage controller"; - case PCI_CLASS_STORAGE_IDE: return "IDE interface"; - case PCI_CLASS_STORAGE_FLOPPY: return "Floppy disk controller"; - case PCI_CLASS_STORAGE_IPI: return "IPI bus controller"; - case PCI_CLASS_STORAGE_RAID: return "RAID bus controller"; - case PCI_CLASS_STORAGE_OTHER: return "Unknown mass storage controller"; - - case PCI_CLASS_NETWORK_ETHERNET: return "Ethernet controller"; - case PCI_CLASS_NETWORK_TOKEN_RING: return "Token ring network controller"; - case PCI_CLASS_NETWORK_FDDI: return "FDDI network controller"; - case PCI_CLASS_NETWORK_ATM: return "ATM network controller"; - case PCI_CLASS_NETWORK_OTHER: return "Network controller"; - - case PCI_CLASS_DISPLAY_VGA: return "VGA compatible controller"; - case PCI_CLASS_DISPLAY_XGA: return "XGA compatible controller"; - case PCI_CLASS_DISPLAY_OTHER: return "Display controller"; - - case PCI_CLASS_MULTIMEDIA_VIDEO: return "Multimedia video controller"; - case PCI_CLASS_MULTIMEDIA_AUDIO: return "Multimedia audio controller"; - case PCI_CLASS_MULTIMEDIA_OTHER: return "Multimedia controller"; - - case PCI_CLASS_MEMORY_RAM: return "RAM memory"; - case PCI_CLASS_MEMORY_FLASH: return "FLASH memory"; - case PCI_CLASS_MEMORY_OTHER: return "Memory"; - - case PCI_CLASS_BRIDGE_HOST: return "Host bridge"; - case PCI_CLASS_BRIDGE_ISA: return "ISA bridge"; - case PCI_CLASS_BRIDGE_EISA: return "EISA bridge"; - case PCI_CLASS_BRIDGE_MC: return "MicroChannel bridge"; - case PCI_CLASS_BRIDGE_PCI: return "PCI bridge"; - case PCI_CLASS_BRIDGE_PCMCIA: return "PCMCIA bridge"; - case PCI_CLASS_BRIDGE_NUBUS: return "NuBus bridge"; - case PCI_CLASS_BRIDGE_CARDBUS: return "CardBus bridge"; - case PCI_CLASS_BRIDGE_OTHER: return "Bridge"; - - case PCI_CLASS_COMMUNICATION_SERIAL: return "Serial controller"; - case PCI_CLASS_COMMUNICATION_PARALLEL: return "Parallel controller"; - case PCI_CLASS_COMMUNICATION_OTHER: return "Communication controller"; - - case PCI_CLASS_SYSTEM_PIC: return "PIC"; - case PCI_CLASS_SYSTEM_DMA: return "DMA controller"; - case PCI_CLASS_SYSTEM_TIMER: return "Timer"; - case PCI_CLASS_SYSTEM_RTC: return "RTC"; - case PCI_CLASS_SYSTEM_OTHER: return "System peripheral"; - - case PCI_CLASS_INPUT_KEYBOARD: return "Keyboard controller"; - case PCI_CLASS_INPUT_PEN: return "Digitizer Pen"; - case PCI_CLASS_INPUT_MOUSE: return "Mouse controller"; - case PCI_CLASS_INPUT_OTHER: return "Input device controller"; - - case PCI_CLASS_DOCKING_GENERIC: return "Generic Docking Station"; - case PCI_CLASS_DOCKING_OTHER: return "Docking Station"; - - case PCI_CLASS_PROCESSOR_386: return "386"; - case PCI_CLASS_PROCESSOR_486: return "486"; - case PCI_CLASS_PROCESSOR_PENTIUM: return "Pentium"; - case PCI_CLASS_PROCESSOR_ALPHA: return "Alpha"; - case PCI_CLASS_PROCESSOR_POWERPC: return "Power PC"; - case PCI_CLASS_PROCESSOR_CO: return "Co-processor"; - - case PCI_CLASS_SERIAL_FIREWIRE: return "FireWire (IEEE 1394)"; - case PCI_CLASS_SERIAL_ACCESS: return "ACCESS Bus"; - case PCI_CLASS_SERIAL_SSA: return "SSA"; - case PCI_CLASS_SERIAL_FIBER: return "Fiber Channel"; - - default: return "Unknown class"; - } -} - - -const char *pci_strvendor(unsigned int vendor) -{ - switch (vendor) { - case PCI_VENDOR_ID_COMPAQ: return "Compaq"; - case PCI_VENDOR_ID_NCR: return "NCR"; - case PCI_VENDOR_ID_ATI: return "ATI"; - case PCI_VENDOR_ID_VLSI: return "VLSI"; - case PCI_VENDOR_ID_ADL: return "Advance Logic"; - case PCI_VENDOR_ID_NS: return "NS"; - case PCI_VENDOR_ID_TSENG: return "Tseng'Lab"; - case PCI_VENDOR_ID_WEITEK: return "Weitek"; - case PCI_VENDOR_ID_DEC: return "DEC"; - case PCI_VENDOR_ID_CIRRUS: return "Cirrus Logic"; - case PCI_VENDOR_ID_IBM: return "IBM"; - case PCI_VENDOR_ID_WD: return "Western Digital"; - case PCI_VENDOR_ID_AMD: return "AMD"; - case PCI_VENDOR_ID_TRIDENT: return "Trident"; - case PCI_VENDOR_ID_AI: return "Acer Incorporated"; - case PCI_VENDOR_ID_MATROX: return "Matrox"; - case PCI_VENDOR_ID_CT: return "Chips & Technologies"; - case PCI_VENDOR_ID_FD: return "Future Domain"; - case PCI_VENDOR_ID_SI: return "Silicon Integrated Systems"; - case PCI_VENDOR_ID_HP: return "Hewlett Packard"; - case PCI_VENDOR_ID_PCTECH: return "PCTECH"; - case PCI_VENDOR_ID_DPT: return "DPT"; - case PCI_VENDOR_ID_OPTI: return "OPTI"; - case PCI_VENDOR_ID_SGS: return "SGS Thomson"; - case PCI_VENDOR_ID_BUSLOGIC: return "BusLogic"; - case PCI_VENDOR_ID_OAK: return "OAK"; - case PCI_VENDOR_ID_PROMISE: return "Promise Technology"; - case PCI_VENDOR_ID_N9: return "Number Nine"; - case PCI_VENDOR_ID_UMC: return "UMC"; - case PCI_VENDOR_ID_X: return "X TECHNOLOGY"; - case PCI_VENDOR_ID_NEXGEN: return "Nexgen"; - case PCI_VENDOR_ID_QLOGIC: return "Q Logic"; - case PCI_VENDOR_ID_LEADTEK: return "Leadtek Research"; - case PCI_VENDOR_ID_CONTAQ: return "Contaq"; - case PCI_VENDOR_ID_FOREX: return "Forex"; - case PCI_VENDOR_ID_OLICOM: return "Olicom"; - case PCI_VENDOR_ID_CMD: return "CMD"; - case PCI_VENDOR_ID_VISION: return "Vision"; - case PCI_VENDOR_ID_SIERRA: return "Sierra"; - case PCI_VENDOR_ID_ACC: return "ACC MICROELECTRONICS"; - case PCI_VENDOR_ID_WINBOND: return "Winbond"; - case PCI_VENDOR_ID_3COM: return "3Com"; - case PCI_VENDOR_ID_AL: return "Acer Labs"; - case PCI_VENDOR_ID_ASP: return "Advanced System Products"; - case PCI_VENDOR_ID_IMS: return "IMS"; - case PCI_VENDOR_ID_TEKRAM2: return "Tekram"; - case PCI_VENDOR_ID_AMCC: return "AMCC"; - case PCI_VENDOR_ID_INTERG: return "Intergraphics"; - case PCI_VENDOR_ID_REALTEK: return "Realtek"; - case PCI_VENDOR_ID_INIT: return "Initio Corp"; - case PCI_VENDOR_ID_VIA: return "VIA Technologies"; - case PCI_VENDOR_ID_VORTEX: return "VORTEX"; - case PCI_VENDOR_ID_EF: return "Efficient Networks"; - case PCI_VENDOR_ID_FORE: return "Fore Systems"; - case PCI_VENDOR_ID_IMAGINGTECH: return "Imaging Technology"; - case PCI_VENDOR_ID_PLX: return "PLX"; - case PCI_VENDOR_ID_ALLIANCE: return "Alliance"; - case PCI_VENDOR_ID_MUTECH: return "Mutech"; - case PCI_VENDOR_ID_ZEITNET: return "ZeitNet"; - case PCI_VENDOR_ID_SPECIALIX: return "Specialix"; - case PCI_VENDOR_ID_RP: return "Comtrol"; - case PCI_VENDOR_ID_CYCLADES: return "Cyclades"; - case PCI_VENDOR_ID_SYMPHONY: return "Symphony"; - case PCI_VENDOR_ID_TEKRAM: return "Tekram"; - case PCI_VENDOR_ID_AVANCE: return "Avance"; - case PCI_VENDOR_ID_S3: return "S3 Inc."; - case PCI_VENDOR_ID_INTEL: return "Intel"; - case PCI_VENDOR_ID_ADAPTEC: return "Adaptec"; - case PCI_VENDOR_ID_ATRONICS: return "Atronics"; - case PCI_VENDOR_ID_HER: return "Hercules"; - default: return "Unknown vendor"; - } -} - - -const char *pci_strdev(unsigned int vendor, unsigned int device) -{ - struct pci_dev_info *info; - - info = pci_lookup_dev(vendor, device); - return info ? info->name : "Unknown device"; -} - - - -/* - * Turn on/off PCI bridge optimization. This should allow benchmarking. - */ -static void burst_bridge(unsigned char bus, unsigned char devfn, - unsigned char pos, int turn_on) -{ -#ifdef CONFIG_PCI_OPTIMIZE - struct bridge_mapping_type *bmap; - unsigned char val; - int i; - - pos *= NUM_OPTIMIZATIONS; - printk("PCI bridge optimization.\n"); - for (i = 0; i < NUM_OPTIMIZATIONS; i++) { - printk(" %s: ", bridge_optimization[i].type); - bmap = &bridge_mapping[pos + i]; - if (!bmap->addr) { - printk("Not supported."); - } else { - pcibios_read_config_byte(bus, devfn, bmap->addr, &val); - if ((val & bmap->mask) == bmap->value) { - printk("%s.", bridge_optimization[i].on); - if (!turn_on) { - pcibios_write_config_byte(bus, devfn, - bmap->addr, - (val | bmap->mask) - - bmap->value); - printk("Changed! Now %s.", bridge_optimization[i].off); - } - } else { - printk("%s.", bridge_optimization[i].off); - if (turn_on) { - pcibios_write_config_byte(bus, devfn, - bmap->addr, - (val & (0xff - bmap->mask)) - + bmap->value); - printk("Changed! Now %s.", bridge_optimization[i].on); - } - } - } - printk("\n"); - } -#endif /* CONFIG_PCI_OPTIMIZE */ -} - - -/* - * Convert some of the configuration space registers of the device at - * address (bus,devfn) into a string (possibly several lines each). - * The configuration string is stored starting at buf[len]. If the - * string would exceed the size of the buffer (SIZE), 0 is returned. - */ -static int sprint_dev_config(struct pci_dev *dev, char *buf, int size) -{ - unsigned long base; - unsigned int l, class_rev, bus, devfn; - unsigned short vendor, device, status; - unsigned char bist, latency, min_gnt, max_lat; - int reg, len = 0; - const char *str; - - bus = dev->bus->number; - devfn = dev->devfn; - - pcibios_read_config_dword(bus, devfn, PCI_CLASS_REVISION, &class_rev); - pcibios_read_config_word (bus, devfn, PCI_VENDOR_ID, &vendor); - pcibios_read_config_word (bus, devfn, PCI_DEVICE_ID, &device); - pcibios_read_config_word (bus, devfn, PCI_STATUS, &status); - pcibios_read_config_byte (bus, devfn, PCI_BIST, &bist); - pcibios_read_config_byte (bus, devfn, PCI_LATENCY_TIMER, &latency); - pcibios_read_config_byte (bus, devfn, PCI_MIN_GNT, &min_gnt); - pcibios_read_config_byte (bus, devfn, PCI_MAX_LAT, &max_lat); - if (len + 80 > size) { - return -1; - } - len += sprintf(buf + len, " Bus %2d, device %3d, function %2d:\n", - bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); - - if (len + 80 > size) { - return -1; - } - len += sprintf(buf + len, " %s: %s %s (rev %d).\n ", - pci_strclass(class_rev >> 8), pci_strvendor(vendor), - pci_strdev(vendor, device), class_rev & 0xff); - - if (!pci_lookup_dev(vendor, device)) { - len += sprintf(buf + len, - "Vendor id=%x. Device id=%x.\n ", - vendor, device); - } - - str = 0; /* to keep gcc shut... */ - switch (status & PCI_STATUS_DEVSEL_MASK) { - case PCI_STATUS_DEVSEL_FAST: str = "Fast devsel. "; break; - case PCI_STATUS_DEVSEL_MEDIUM: str = "Medium devsel. "; break; - case PCI_STATUS_DEVSEL_SLOW: str = "Slow devsel. "; break; - } - if (len + strlen(str) > size) { - return -1; - } - len += sprintf(buf + len, str); - - if (status & PCI_STATUS_FAST_BACK) { -# define fast_b2b_capable "Fast back-to-back capable. " - if (len + strlen(fast_b2b_capable) > size) { - return -1; - } - len += sprintf(buf + len, fast_b2b_capable); -# undef fast_b2b_capable - } - - if (bist & PCI_BIST_CAPABLE) { -# define BIST_capable "BIST capable. " - if (len + strlen(BIST_capable) > size) { - return -1; - } - len += sprintf(buf + len, BIST_capable); -# undef BIST_capable - } - - if (dev->irq) { - if (len + 40 > size) { - return -1; - } - len += sprintf(buf + len, "IRQ %d. ", dev->irq); - } - - if (dev->master) { - if (len + 80 > size) { - return -1; - } - len += sprintf(buf + len, "Master Capable. "); - if (latency) - len += sprintf(buf + len, "Latency=%d. ", latency); - else - len += sprintf(buf + len, "No bursts. "); - if (min_gnt) - len += sprintf(buf + len, "Min Gnt=%d.", min_gnt); - if (max_lat) - len += sprintf(buf + len, "Max Lat=%d.", max_lat); - } - - for (reg = PCI_BASE_ADDRESS_0; reg <= PCI_BASE_ADDRESS_5; reg += 4) { - if (len + 40 > size) { - return -1; - } - pcibios_read_config_dword(bus, devfn, reg, &l); - base = l; - if (!base) { - continue; - } - - if (base & PCI_BASE_ADDRESS_SPACE_IO) { - len += sprintf(buf + len, - "\n I/O at 0x%lx.", - base & PCI_BASE_ADDRESS_IO_MASK); - } else { - const char *pref, *type = "unknown"; - - if (base & PCI_BASE_ADDRESS_MEM_PREFETCH) { - pref = "P"; - } else { - pref = "Non-p"; - } - switch (base & PCI_BASE_ADDRESS_MEM_TYPE_MASK) { - case PCI_BASE_ADDRESS_MEM_TYPE_32: - type = "32 bit"; break; - case PCI_BASE_ADDRESS_MEM_TYPE_1M: - type = "20 bit"; break; - case PCI_BASE_ADDRESS_MEM_TYPE_64: - type = "64 bit"; - /* read top 32 bit address of base addr: */ - reg += 4; - pcibios_read_config_dword(bus, devfn, reg, &l); - base |= ((u64) l) << 32; - break; - } - len += sprintf(buf + len, - "\n %srefetchable %s memory at " - "0x%lx.", pref, type, - base & PCI_BASE_ADDRESS_MEM_MASK); - } - } - - len += sprintf(buf + len, "\n"); - return len; -} - - -/* - * Return list of PCI devices as a character string for /proc/pci. - * BUF is a buffer that is PAGE_SIZE bytes long. - */ -int get_pci_list(char *buf) -{ - int nprinted, len, size; - struct pci_dev *dev; -# define MSG "\nwarning: page-size limit reached!\n" - - /* reserve same for truncation warning message: */ - size = PAGE_SIZE - (strlen(MSG) + 1); - len = sprintf(buf, "PCI devices found:\n"); - - for (dev = pci_devices; dev; dev = dev->next) { - nprinted = sprint_dev_config(dev, buf + len, size - len); - if (nprinted < 0) { - return len + sprintf(buf + len, MSG); - } - len += nprinted; - } - return len; -} - - -/* - * pci_malloc() returns initialized memory of size SIZE. Can be - * used only while pci_init() is active. - */ -static void *pci_malloc(long size, unsigned long *mem_startp) -{ - void *mem; - -#ifdef DEBUG - printk("...pci_malloc(size=%ld,mem=%p)", size, *mem_startp); -#endif - mem = (void*) *mem_startp; - *mem_startp += (size + sizeof(void*) - 1) & ~(sizeof(void*) - 1); - memset(mem, 0, size); - return mem; -} - - -static unsigned int scan_bus(struct pci_bus *bus, unsigned long *mem_startp) -{ - unsigned int devfn, l, max; - unsigned char cmd, tmp, hdr_type = 0; - struct pci_dev_info *info; - struct pci_dev *dev; - struct pci_bus *child; - -#ifdef DEBUG - printk("...scan_bus(busno=%d,mem=%p)\n", bus->number, *mem_startp); -#endif - - max = bus->secondary; - for (devfn = 0; devfn < 0xff; ++devfn) { - if (PCI_FUNC(devfn) == 0) { - pcibios_read_config_byte(bus->number, devfn, - PCI_HEADER_TYPE, &hdr_type); - } else if (!(hdr_type & 0x80)) { - /* not a multi-function device */ - continue; - } - - pcibios_read_config_dword(bus->number, devfn, PCI_VENDOR_ID, - &l); - /* some broken boards return 0 if a slot is empty: */ - if (l == 0xffffffff || l == 0x00000000) { - hdr_type = 0; - continue; - } - - dev = pci_malloc(sizeof(*dev), mem_startp); - dev->bus = bus; - /* - * Put it into the simple chain of devices on this - * bus. It is used to find devices once everything is - * set up. - */ - dev->next = pci_devices; - pci_devices = dev; - - dev->devfn = devfn; - dev->vendor = l & 0xffff; - dev->device = (l >> 16) & 0xffff; - - /* - * Check to see if we know about this device and report - * a message at boot time. This is the only way to - * learn about new hardware... - */ - info = pci_lookup_dev(dev->vendor, dev->device); - if (!info) { - printk("Warning : Unknown PCI device (%x:%x). Please read include/linux/pci.h \n", - dev->vendor, dev->device); - } else { - /* Some BIOS' are lazy. Let's do their job: */ - if (info->bridge_type != 0xff) { - burst_bridge(bus->number, devfn, - info->bridge_type, 1); - } - } - - /* non-destructively determine if device can be a master: */ - pcibios_read_config_byte(bus->number, devfn, PCI_COMMAND, - &cmd); - pcibios_write_config_byte(bus->number, devfn, PCI_COMMAND, - cmd | PCI_COMMAND_MASTER); - pcibios_read_config_byte(bus->number, devfn, PCI_COMMAND, - &tmp); - dev->master = ((tmp & PCI_COMMAND_MASTER) != 0); - pcibios_write_config_byte(bus->number, devfn, PCI_COMMAND, - cmd); - - /* read irq level (may be changed during pcibios_fixup()): */ - pcibios_read_config_byte(bus->number, devfn, - PCI_INTERRUPT_LINE, &dev->irq); - - /* check to see if this device is a PCI-PCI bridge: */ - pcibios_read_config_dword(bus->number, devfn, - PCI_CLASS_REVISION, &l); - l = l >> 8; /* upper 3 bytes */ - dev->class = l; - /* - * Now insert it into the list of devices held - * by the parent bus. - */ - dev->sibling = bus->devices; - bus->devices = dev; - - if (dev->class >> 8 == PCI_CLASS_BRIDGE_PCI) { - unsigned int buses; - unsigned short cr; - - /* - * Insert it into the tree of buses. - */ - child = pci_malloc(sizeof(*child), mem_startp); - child->next = bus->children; - bus->children = child; - child->self = dev; - child->parent = bus; - - /* - * Set up the primary, secondary and subordinate - * bus numbers. - */ - child->number = child->secondary = ++max; - child->primary = bus->secondary; - child->subordinate = 0xff; - /* - * Clear all status bits and turn off memory, - * I/O and master enables. - */ - pcibios_read_config_word(bus->number, devfn, - PCI_COMMAND, &cr); - pcibios_write_config_word(bus->number, devfn, - PCI_COMMAND, 0x0000); - pcibios_write_config_word(bus->number, devfn, - PCI_STATUS, 0xffff); - /* - * Configure the bus numbers for this bridge: - */ - pcibios_read_config_dword(bus->number, devfn, 0x18, - &buses); - buses &= 0xff000000; - buses |= (((unsigned int)(child->primary) << 0) | - ((unsigned int)(child->secondary) << 8) | - ((unsigned int)(child->subordinate) << 16)); - pcibios_write_config_dword(bus->number, devfn, 0x18, - buses); - /* - * Now we can scan all subordinate buses: - */ - max = scan_bus(child, mem_startp); - /* - * Set the subordinate bus number to its real - * value: - */ - child->subordinate = max; - buses = (buses & 0xff00ffff) - | ((unsigned int)(child->subordinate) << 16); - pcibios_write_config_dword(bus->number, devfn, 0x18, - buses); - pcibios_write_config_word(bus->number, devfn, - PCI_COMMAND, cr); - } - } - /* - * We've scanned the bus and so we know all about what's on - * the other side of any bridges that may be on this bus plus - * any devices. - * - * Return how far we've got finding sub-buses. - */ - return max; -} - - -unsigned long pci_init (unsigned long mem_start, unsigned long mem_end) -{ - mem_start = pcibios_init(mem_start, mem_end); - - if (!pcibios_present()) { - printk("pci_init: no BIOS32 detected\n"); - return mem_start; - } - -#if 0 - printk("Probing PCI hardware.\n"); -#endif - - memset(&pci_root, 0, sizeof(pci_root)); - pci_root.subordinate = scan_bus(&pci_root, &mem_start); - - /* give BIOS a chance to apply platform specific fixes: */ - mem_start = pcibios_fixup(mem_start, mem_end); - -#ifdef DEBUG - { - int len = get_pci_list((char*)mem_start); - if (len) { - ((char *) mem_start)[len] = '\0'; - printk("%s\n", (char *) mem_start); - } - } -#endif - return mem_start; -} diff --git a/i386/i386at/gpl/linux/scsi/53c7,8xx.h b/i386/i386at/gpl/linux/scsi/53c7,8xx.h deleted file mode 100644 index f1dfc4de..00000000 --- a/i386/i386at/gpl/linux/scsi/53c7,8xx.h +++ /dev/null @@ -1,1584 +0,0 @@ -/* - * NCR 53c{7,8}0x0 driver, header file - * - * Sponsored by - * iX Multiuser Multitasking Magazine - * Hannover, Germany - * hm@ix.de - * - * Copyright 1993, 1994, 1995 Drew Eckhardt - * Visionary Computing - * (Unix and Linux consulting and custom programming) - * drew@PoohSticks.ORG - * +1 (303) 786-7975 - * - * TolerANT and SCSI SCRIPTS are registered trademarks of NCR Corporation. - * - * PRE-ALPHA - * - * For more information, please consult - * - * NCR 53C700/53C700-66 - * SCSI I/O Processor - * Data Manual - * - * NCR 53C810 - * PCI-SCSI I/O Processor - * Data Manual - * - * NCR Microelectronics - * 1635 Aeroplaza Drive - * Colorado Springs, CO 80916 - * +1 (719) 578-3400 - * - * Toll free literature number - * +1 (800) 334-5454 - * - */ - -#ifndef NCR53c7x0_H -#define NCR53c7x0_H -#if !defined(LINUX_1_2) && !defined(LINUX_1_3) -#include <linux/version.h> -#if LINUX_VERSION_CODE > 65536 + 3 * 256 -#define LINUX_1_3 -#else -#define LINUX_1_2 -#endif -#endif - -/* - * Prevent name space pollution in hosts.c, and only provide the - * define we need to get the NCR53c7x0 driver into the host template - * array. - */ - -#if defined(HOSTS_C) || defined(MODULE) -#include <linux/scsicam.h> - -extern int NCR53c7xx_abort(Scsi_Cmnd *); -extern int NCR53c7xx_detect(Scsi_Host_Template *tpnt); -extern int NCR53c7xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); -extern int NCR53c7xx_reset(Scsi_Cmnd *); -#ifdef MODULE -extern int NCR53c7xx_release(struct Scsi_Host *); -#else -#define NCR53c7xx_release NULL -#endif - -#ifdef LINUX_1_2 -#define NCR53c7xx {NULL, NULL, "NCR53c{7,8}xx (rel 17)", NCR53c7xx_detect,\ - NULL, /* info */ NULL, /* command, deprecated */ NULL, \ - NCR53c7xx_queue_command, NCR53c7xx_abort, NCR53c7xx_reset, \ - NULL /* slave attach */, scsicam_bios_param, /* can queue */ 24, \ - /* id */ 7, 127 /* old SG_ALL */, /* cmd per lun */ 3, \ - /* present */ 0, /* unchecked isa dma */ 0, DISABLE_CLUSTERING} -#else -#define NCR53c7xx {NULL, NULL, NULL, NULL, \ - "NCR53c{7,8}xx (rel 17)", NCR53c7xx_detect,\ - NULL, /* info */ NULL, /* command, deprecated */ NULL, \ - NCR53c7xx_queue_command, NCR53c7xx_abort, NCR53c7xx_reset, \ - NULL /* slave attach */, scsicam_bios_param, /* can queue */ 24, \ - /* id */ 7, 127 /* old SG_ALL */, /* cmd per lun */ 3, \ - /* present */ 0, /* unchecked isa dma */ 0, DISABLE_CLUSTERING} -#endif - -#endif /* defined(HOSTS_C) || defined(MODULE) */ - -#ifndef HOSTS_C -#ifdef LINUX_1_2 -/* - * Change virtual addresses to physical addresses and vv. - * These are trivial on the 1:1 Linux/i386 mapping (but if we ever - * make the kernel segment mapped at 0, we need to do translation - * on the i386 as well) - */ -extern inline unsigned long virt_to_phys(volatile void * address) -{ - return (unsigned long) address; -} - -extern inline void * phys_to_virt(unsigned long address) -{ - return (void *) address; -} - -/* - * IO bus memory addresses are also 1:1 with the physical address - */ -#define virt_to_bus virt_to_phys -#define bus_to_virt phys_to_virt - -/* - * readX/writeX() are used to access memory mapped devices. On some - * architectures the memory mapped IO stuff needs to be accessed - * differently. On the x86 architecture, we just read/write the - * memory location directly. - */ -#define readb(addr) (*(volatile unsigned char *) (addr)) -#define readw(addr) (*(volatile unsigned short *) (addr)) -#define readl(addr) (*(volatile unsigned int *) (addr)) - -#define writeb(b,addr) ((*(volatile unsigned char *) (addr)) = (b)) -#define writew(b,addr) ((*(volatile unsigned short *) (addr)) = (b)) -#define writel(b,addr) ((*(volatile unsigned int *) (addr)) = (b)) - -#define mb() - -#endif /* def LINUX_1_2 */ - -/* Register addresses, ordered numerically */ - -/* SCSI control 0 rw, default = 0xc0 */ -#define SCNTL0_REG 0x00 -#define SCNTL0_ARB1 0x80 /* 0 0 = simple arbitration */ -#define SCNTL0_ARB2 0x40 /* 1 1 = full arbitration */ -#define SCNTL0_STRT 0x20 /* Start Sequence */ -#define SCNTL0_WATN 0x10 /* Select with ATN */ -#define SCNTL0_EPC 0x08 /* Enable parity checking */ -/* Bit 2 is reserved on 800 series chips */ -#define SCNTL0_EPG_700 0x04 /* Enable parity generation */ -#define SCNTL0_AAP 0x02 /* ATN/ on parity error */ -#define SCNTL0_TRG 0x01 /* Target mode */ - -/* SCSI control 1 rw, default = 0x00 */ - -#define SCNTL1_REG 0x01 -#define SCNTL1_EXC 0x80 /* Extra Clock Cycle of Data setup */ -#define SCNTL1_ADB 0x40 /* contents of SODL on bus */ -#define SCNTL1_ESR_700 0x20 /* Enable SIOP response to selection - and reselection */ -#define SCNTL1_DHP_800 0x20 /* Disable halt on parity error or ATN - target mode only */ -#define SCNTL1_CON 0x10 /* Connected */ -#define SCNTL1_RST 0x08 /* SCSI RST/ */ -#define SCNTL1_AESP 0x04 /* Force bad parity */ -#define SCNTL1_SND_700 0x02 /* Start SCSI send */ -#define SCNTL1_IARB_800 0x02 /* Immediate Arbitration, start - arbitration immediately after - busfree is detected */ -#define SCNTL1_RCV_700 0x01 /* Start SCSI receive */ -#define SCNTL1_SST_800 0x01 /* Start SCSI transfer */ - -/* SCSI control 2 rw, */ - -#define SCNTL2_REG_800 0x02 -#define SCNTL2_800_SDU 0x80 /* SCSI disconnect unexpected */ - -/* SCSI control 3 rw */ - -#define SCNTL3_REG_800 0x03 -#define SCNTL3_800_SCF_SHIFT 4 -#define SCNTL3_800_SCF_MASK 0x70 -#define SCNTL3_800_SCF2 0x40 /* Synchronous divisor */ -#define SCNTL3_800_SCF1 0x20 /* 0x00 = SCLK/3 */ -#define SCNTL3_800_SCF0 0x10 /* 0x10 = SCLK/1 */ - /* 0x20 = SCLK/1.5 - 0x30 = SCLK/2 - 0x40 = SCLK/3 */ - -#define SCNTL3_800_CCF_SHIFT 0 -#define SCNTL3_800_CCF_MASK 0x07 -#define SCNTL3_800_CCF2 0x04 /* 0x00 50.01 to 66 */ -#define SCNTL3_800_CCF1 0x02 /* 0x01 16.67 to 25 */ -#define SCNTL3_800_CCF0 0x01 /* 0x02 25.01 - 37.5 - 0x03 37.51 - 50 - 0x04 50.01 - 66 */ - -/* - * SCSI destination ID rw - the appropriate bit is set for the selected - * target ID. This is written by the SCSI SCRIPTS processor. - * default = 0x00 - */ -#define SDID_REG_700 0x02 -#define SDID_REG_800 0x06 - -#define GP_REG_800 0x07 /* General purpose IO */ -#define GP_800_IO1 0x02 -#define GP_800_IO2 0x01 - - -/* SCSI interrupt enable rw, default = 0x00 */ -#define SIEN_REG_700 0x03 -#define SIEN0_REG_800 0x40 -#define SIEN_MA 0x80 /* Phase mismatch (ini) or ATN (tgt) */ -#define SIEN_FC 0x40 /* Function complete */ -#define SIEN_700_STO 0x20 /* Selection or reselection timeout */ -#define SIEN_800_SEL 0x20 /* Selected */ -#define SIEN_700_SEL 0x10 /* Selected or reselected */ -#define SIEN_800_RESEL 0x10 /* Reselected */ -#define SIEN_SGE 0x08 /* SCSI gross error */ -#define SIEN_UDC 0x04 /* Unexpected disconnect */ -#define SIEN_RST 0x02 /* SCSI RST/ received */ -#define SIEN_PAR 0x01 /* Parity error */ - -/* - * SCSI chip ID rw - * NCR53c700 : - * When arbitrating, the highest bit is used, when reselection or selection - * occurs, the chip responds to all IDs for which a bit is set. - * default = 0x00 - * NCR53c810 : - * Uses bit mapping - */ -#define SCID_REG 0x04 -/* Bit 7 is reserved on 800 series chips */ -#define SCID_800_RRE 0x40 /* Enable response to reselection */ -#define SCID_800_SRE 0x20 /* Enable response to selection */ -/* Bits four and three are reserved on 800 series chips */ -#define SCID_800_ENC_MASK 0x07 /* Encoded SCSI ID */ - -/* SCSI transfer rw, default = 0x00 */ -#define SXFER_REG 0x05 -#define SXFER_DHP 0x80 /* Disable halt on parity */ - -#define SXFER_TP2 0x40 /* Transfer period msb */ -#define SXFER_TP1 0x20 -#define SXFER_TP0 0x10 /* lsb */ -#define SXFER_TP_MASK 0x70 -/* FIXME : SXFER_TP_SHIFT == 5 is right for '8xx chips */ -#define SXFER_TP_SHIFT 5 -#define SXFER_TP_4 0x00 /* Divisors */ -#define SXFER_TP_5 0x10<<1 -#define SXFER_TP_6 0x20<<1 -#define SXFER_TP_7 0x30<<1 -#define SXFER_TP_8 0x40<<1 -#define SXFER_TP_9 0x50<<1 -#define SXFER_TP_10 0x60<<1 -#define SXFER_TP_11 0x70<<1 - -#define SXFER_MO3 0x08 /* Max offset msb */ -#define SXFER_MO2 0x04 -#define SXFER_MO1 0x02 -#define SXFER_MO0 0x01 /* lsb */ -#define SXFER_MO_MASK 0x0f -#define SXFER_MO_SHIFT 0 - -/* - * SCSI output data latch rw - * The contents of this register are driven onto the SCSI bus when - * the Assert Data Bus bit of the SCNTL1 register is set and - * the CD, IO, and MSG bits of the SOCL register match the SCSI phase - */ -#define SODL_REG_700 0x06 -#define SODL_REG_800 0x54 - - -/* - * SCSI output control latch rw, default = 0 - * Note that when the chip is being manually programmed as an initiator, - * the MSG, CD, and IO bits must be set correctly for the phase the target - * is driving the bus in. Otherwise no data transfer will occur due to - * phase mismatch. - */ - -#define SBCL_REG 0x0b -#define SBCL_REQ 0x80 /* REQ */ -#define SBCL_ACK 0x40 /* ACK */ -#define SBCL_BSY 0x20 /* BSY */ -#define SBCL_SEL 0x10 /* SEL */ -#define SBCL_ATN 0x08 /* ATN */ -#define SBCL_MSG 0x04 /* MSG */ -#define SBCL_CD 0x02 /* C/D */ -#define SBCL_IO 0x01 /* I/O */ -#define SBCL_PHASE_CMDOUT SBCL_CD -#define SBCL_PHASE_DATAIN SBCL_IO -#define SBCL_PHASE_DATAOUT 0 -#define SBCL_PHASE_MSGIN (SBCL_CD|SBCL_IO|SBCL_MSG) -#define SBCL_PHASE_MSGOUT (SBCL_CD|SBCL_MSG) -#define SBCL_PHASE_STATIN (SBCL_CD|SBCL_IO) -#define SBCL_PHASE_MASK (SBCL_CD|SBCL_IO|SBCL_MSG) - -/* - * SCSI first byte received latch ro - * This register contains the first byte received during a block MOVE - * SCSI SCRIPTS instruction, including - * - * Initiator mode Target mode - * Message in Command - * Status Message out - * Data in Data out - * - * It also contains the selecting or reselecting device's ID and our - * ID. - * - * Note that this is the register the various IF conditionals can - * operate on. - */ -#define SFBR_REG 0x08 - -/* - * SCSI input data latch ro - * In initiator mode, data is latched into this register on the rising - * edge of REQ/. In target mode, data is latched on the rising edge of - * ACK/ - */ -#define SIDL_REG_700 0x09 -#define SIDL_REG_800 0x50 - -/* - * SCSI bus data lines ro - * This register reflects the instantaneous status of the SCSI data - * lines. Note that SCNTL0 must be set to disable parity checking, - * otherwise reading this register will latch new parity. - */ -#define SBDL_REG_700 0x0a -#define SBDL_REG_800 0x58 - -#define SSID_REG_800 0x0a -#define SSID_800_VAL 0x80 /* Exactly two bits asserted at sel */ -#define SSID_800_ENCID_MASK 0x07 /* Device which performed operation */ - - -/* - * SCSI bus control lines rw, - * instantaneous readout of control lines - */ -#define SOCL_REG 0x0b -#define SOCL_REQ 0x80 /* REQ ro */ -#define SOCL_ACK 0x40 /* ACK ro */ -#define SOCL_BSY 0x20 /* BSY ro */ -#define SOCL_SEL 0x10 /* SEL ro */ -#define SOCL_ATN 0x08 /* ATN ro */ -#define SOCL_MSG 0x04 /* MSG ro */ -#define SOCL_CD 0x02 /* C/D ro */ -#define SOCL_IO 0x01 /* I/O ro */ -/* - * Synchronous SCSI Clock Control bits - * 0 - set by DCNTL - * 1 - SCLK / 1.0 - * 2 - SCLK / 1.5 - * 3 - SCLK / 2.0 - */ -#define SBCL_SSCF1 0x02 /* wo, -66 only */ -#define SBCL_SSCF0 0x01 /* wo, -66 only */ -#define SBCL_SSCF_MASK 0x03 - -/* - * XXX note : when reading the DSTAT and STAT registers to clear interrupts, - * insure that 10 clocks elapse between the two - */ -/* DMA status ro */ -#define DSTAT_REG 0x0c -#define DSTAT_DFE 0x80 /* DMA FIFO empty */ -#define DSTAT_800_MDPE 0x40 /* Master Data Parity Error */ -#define DSTAT_800_BF 0x20 /* Bus Fault */ -#define DSTAT_ABRT 0x10 /* Aborted - set on error */ -#define DSTAT_SSI 0x08 /* SCRIPTS single step interrupt */ -#define DSTAT_SIR 0x04 /* SCRIPTS interrupt received - - set when INT instruction is - executed */ -#define DSTAT_WTD 0x02 /* Watchdog timeout detected */ -#define DSTAT_OPC 0x01 /* Illegal instruction */ -#define DSTAT_800_IID 0x01 /* Same thing, different name */ - - -/* NCR53c800 moves this stuff into SIST0 */ -#define SSTAT0_REG 0x0d /* SCSI status 0 ro */ -#define SIST0_REG_800 0x42 -#define SSTAT0_MA 0x80 /* ini : phase mismatch, - * tgt : ATN/ asserted - */ -#define SSTAT0_CMP 0x40 /* function complete */ -#define SSTAT0_700_STO 0x20 /* Selection or reselection timeout */ -#define SIST0_800_SEL 0x20 /* Selected */ -#define SSTAT0_700_SEL 0x10 /* Selected or reselected */ -#define SIST0_800_RSL 0x10 /* Reselected */ -#define SSTAT0_SGE 0x08 /* SCSI gross error */ -#define SSTAT0_UDC 0x04 /* Unexpected disconnect */ -#define SSTAT0_RST 0x02 /* SCSI RST/ received */ -#define SSTAT0_PAR 0x01 /* Parity error */ - -/* And uses SSTAT0 for what was SSTAT1 */ - -#define SSTAT1_REG 0x0e /* SCSI status 1 ro */ -#define SSTAT1_ILF 0x80 /* SIDL full */ -#define SSTAT1_ORF 0x40 /* SODR full */ -#define SSTAT1_OLF 0x20 /* SODL full */ -#define SSTAT1_AIP 0x10 /* Arbitration in progress */ -#define SSTAT1_LOA 0x08 /* Lost arbitration */ -#define SSTAT1_WOA 0x04 /* Won arbitration */ -#define SSTAT1_RST 0x02 /* Instant readout of RST/ */ -#define SSTAT1_SDP 0x01 /* Instant readout of SDP/ */ - -#define SSTAT2_REG 0x0f /* SCSI status 2 ro */ -#define SSTAT2_FF3 0x80 /* number of bytes in synchronous */ -#define SSTAT2_FF2 0x40 /* data FIFO */ -#define SSTAT2_FF1 0x20 -#define SSTAT2_FF0 0x10 -#define SSTAT2_FF_MASK 0xf0 -#define SSTAT2_FF_SHIFT 4 - -/* - * Latched signals, latched on the leading edge of REQ/ for initiators, - * ACK/ for targets. - */ -#define SSTAT2_SDP 0x08 /* SDP */ -#define SSTAT2_MSG 0x04 /* MSG */ -#define SSTAT2_CD 0x02 /* C/D */ -#define SSTAT2_IO 0x01 /* I/O */ -#define SSTAT2_PHASE_CMDOUT SSTAT2_CD -#define SSTAT2_PHASE_DATAIN SSTAT2_IO -#define SSTAT2_PHASE_DATAOUT 0 -#define SSTAT2_PHASE_MSGIN (SSTAT2_CD|SSTAT2_IO|SSTAT2_MSG) -#define SSTAT2_PHASE_MSGOUT (SSTAT2_CD|SSTAT2_MSG) -#define SSTAT2_PHASE_STATIN (SSTAT2_CD|SSTAT2_IO) -#define SSTAT2_PHASE_MASK (SSTAT2_CD|SSTAT2_IO|SSTAT2_MSG) - - -/* NCR53c700-66 only */ -#define SCRATCHA_REG_00 0x10 /* through 0x13 Scratch A rw */ -/* NCR53c710 and higher */ -#define DSA_REG 0x10 /* DATA structure address */ - -#define CTEST0_REG_700 0x14 /* Chip test 0 ro */ -#define CTEST0_REG_800 0x18 /* Chip test 0 rw, general purpose */ -/* 0x80 - 0x04 are reserved */ -#define CTEST0_700_RTRG 0x02 /* Real target mode */ -#define CTEST0_700_DDIR 0x01 /* Data direction, 1 = - * SCSI bus to host, 0 = - * host to SCSI. - */ - -#define CTEST1_REG_700 0x15 /* Chip test 1 ro */ -#define CTEST1_REG_800 0x19 /* Chip test 1 ro */ -#define CTEST1_FMT3 0x80 /* Identify which byte lanes are empty */ -#define CTEST1_FMT2 0x40 /* in the DMA FIFO */ -#define CTEST1_FMT1 0x20 -#define CTEST1_FMT0 0x10 - -#define CTEST1_FFL3 0x08 /* Identify which bytes lanes are full */ -#define CTEST1_FFL2 0x04 /* in the DMA FIFO */ -#define CTEST1_FFL1 0x02 -#define CTEST1_FFL0 0x01 - -#define CTEST2_REG_700 0x16 /* Chip test 2 ro */ -#define CTEST2_REG_800 0x1a /* Chip test 2 ro */ - -#define CTEST2_800_DDIR 0x80 /* 1 = SCSI->host */ -#define CTEST2_800_SIGP 0x40 /* A copy of SIGP in ISTAT. - Reading this register clears */ -#define CTEST2_800_CIO 0x20 /* Configured as IO */. -#define CTEST2_800_CM 0x10 /* Configured as memory */ - -/* 0x80 - 0x40 are reserved on 700 series chips */ -#define CTEST2_700_SOFF 0x20 /* SCSI Offset Compare, - * As an initiator, this bit is - * one when the synchronous offset - * is zero, as a target this bit - * is one when the synchronous - * offset is at the maximum - * defined in SXFER - */ -#define CTEST2_700_SFP 0x10 /* SCSI FIFO parity bit, - * reading CTEST3 unloads a byte - * from the FIFO and sets this - */ -#define CTEST2_700_DFP 0x08 /* DMA FIFO parity bit, - * reading CTEST6 unloads a byte - * from the FIFO and sets this - */ -#define CTEST2_TEOP 0x04 /* SCSI true end of process, - * indicates a totally finished - * transfer - */ -#define CTEST2_DREQ 0x02 /* Data request signal */ -/* 0x01 is reserved on 700 series chips */ -#define CTEST2_800_DACK 0x01 - -/* - * Chip test 3 ro - * Unloads the bottom byte of the eight deep SCSI synchronous FIFO, - * check SSTAT2 FIFO full bits to determine size. Note that a GROSS - * error results if a read is attempted on this register. Also note - * that 16 and 32 bit reads of this register will cause corruption. - */ -#define CTEST3_REG_700 0x17 -/* Chip test 3 rw */ -#define CTEST3_REG_800 0x1b -#define CTEST3_800_V3 0x80 /* Chip revision */ -#define CTEST3_800_V2 0x40 -#define CTEST3_800_V1 0x20 -#define CTEST3_800_V0 0x10 -#define CTEST3_800_FLF 0x08 /* Flush DMA FIFO */ -#define CTEST3_800_CLF 0x04 /* Clear DMA FIFO */ -#define CTEST3_800_FM 0x02 /* Fetch mode pin */ -/* bit 0 is reserved on 800 series chips */ - -#define CTEST4_REG_700 0x18 /* Chip test 4 rw */ -#define CTEST4_REG_800 0x21 /* Chip test 4 rw */ -/* 0x80 is reserved on 700 series chips */ -#define CTEST4_800_BDIS 0x80 /* Burst mode disable */ -#define CTEST4_ZMOD 0x40 /* High impedance mode */ -#define CTEST4_SZM 0x20 /* SCSI bus high impedance */ -#define CTEST4_700_SLBE 0x10 /* SCSI loopback enabled */ -#define CTEST4_800_SRTM 0x10 /* Shadow Register Test Mode */ -#define CTEST4_700_SFWR 0x08 /* SCSI FIFO write enable, - * redirects writes from SODL - * to the SCSI FIFO. - */ -#define CTEST4_800_MPEE 0x08 /* Enable parity checking - during master cycles on PCI - bus */ - -/* - * These bits send the contents of the CTEST6 register to the appropriate - * byte lane of the 32 bit DMA FIFO. Normal operation is zero, otherwise - * the high bit means the low two bits select the byte lane. - */ -#define CTEST4_FBL2 0x04 -#define CTEST4_FBL1 0x02 -#define CTEST4_FBL0 0x01 -#define CTEST4_FBL_MASK 0x07 -#define CTEST4_FBL_0 0x04 /* Select DMA FIFO byte lane 0 */ -#define CTEST4_FBL_1 0x05 /* Select DMA FIFO byte lane 1 */ -#define CTEST4_FBL_2 0x06 /* Select DMA FIFO byte lane 2 */ -#define CTEST4_FBL_3 0x07 /* Select DMA FIFO byte lane 3 */ -#define CTEST4_800_SAVE (CTEST4_800_BDIS) - - -#define CTEST5_REG_700 0x19 /* Chip test 5 rw */ -#define CTEST5_REG_800 0x22 /* Chip test 5 rw */ -/* - * Clock Address Incrementor. When set, it increments the - * DNAD register to the next bus size boundary. It automatically - * resets itself when the operation is complete. - */ -#define CTEST5_ADCK 0x80 -/* - * Clock Byte Counter. When set, it decrements the DBC register to - * the next bus size boundary. - */ -#define CTEST5_BBCK 0x40 -/* - * Reset SCSI Offset. Setting this bit to 1 clears the current offset - * pointer in the SCSI synchronous offset counter (SSTAT). This bit - * is set to 1 if a SCSI Gross Error Condition occurs. The offset should - * be cleared when a synchronous transfer fails. When written, it is - * automatically cleared after the SCSI synchronous offset counter is - * reset. - */ -/* Bit 5 is reserved on 800 series chips */ -#define CTEST5_700_ROFF 0x20 -/* - * Master Control for Set or Reset pulses. When 1, causes the low - * four bits of register to set when set, 0 causes the low bits to - * clear when set. - */ -#define CTEST5_MASR 0x10 -#define CTEST5_DDIR 0x08 /* DMA direction */ -/* - * Bits 2-0 are reserved on 800 series chips - */ -#define CTEST5_700_EOP 0x04 /* End of process */ -#define CTEST5_700_DREQ 0x02 /* Data request */ -#define CTEST5_700_DACK 0x01 /* Data acknowledge */ - -/* - * Chip test 6 rw - writing to this register writes to the byte - * lane in the DMA FIFO as determined by the FBL bits in the CTEST4 - * register. - */ -#define CTEST6_REG_700 0x1a -#define CTEST6_REG_800 0x23 - -#define CTEST7_REG 0x1b /* Chip test 7 rw */ -/* 0x80 - 0x40 are reserved on NCR53c700 and NCR53c700-66 chips */ -#define CTEST7_10_CDIS 0x80 /* Cache burst disable */ -#define CTEST7_10_SC1 0x40 /* Snoop control bits */ -#define CTEST7_10_SC0 0x20 -#define CTEST7_10_SC_MASK 0x60 -/* 0x20 is reserved on the NCR53c700 */ -#define CTEST7_0060_FM 0x20 /* Fetch mode */ -#define CTEST7_STD 0x10 /* Selection timeout disable */ -#define CTEST7_DFP 0x08 /* DMA FIFO parity bit for CTEST6 */ -#define CTEST7_EVP 0x04 /* 1 = host bus even parity, 0 = odd */ -#define CTEST7_10_TT1 0x02 /* Transfer type */ -#define CTEST7_00_DC 0x02 /* Set to drive DC low during instruction - fetch */ -#define CTEST7_DIFF 0x01 /* Differential mode */ - -#define CTEST7_SAVE ( CTEST7_EVP | CTEST7_DIFF ) - - -#define TEMP_REG 0x1c /* through 0x1f Temporary stack rw */ - -#define DFIFO_REG 0x20 /* DMA FIFO rw */ -/* - * 0x80 is reserved on the NCR53c710, the CLF and FLF bits have been - * moved into the CTEST8 register. - */ -#define DFIFO_00_FLF 0x80 /* Flush DMA FIFO to memory */ -#define DFIFO_00_CLF 0x40 /* Clear DMA and SCSI FIFOs */ -#define DFIFO_BO6 0x40 -#define DFIFO_BO5 0x20 -#define DFIFO_BO4 0x10 -#define DFIFO_BO3 0x08 -#define DFIFO_BO2 0x04 -#define DFIFO_BO1 0x02 -#define DFIFO_BO0 0x01 -#define DFIFO_10_BO_MASK 0x7f /* 7 bit counter */ -#define DFIFO_00_BO_MASK 0x3f /* 6 bit counter */ - -/* - * Interrupt status rw - * Note that this is the only register which can be read while SCSI - * SCRIPTS are being executed. - */ -#define ISTAT_REG_700 0x21 -#define ISTAT_REG_800 0x14 -#define ISTAT_ABRT 0x80 /* Software abort, write - *1 to abort, wait for interrupt. */ -/* 0x40 and 0x20 are reserved on NCR53c700 and NCR53c700-66 chips */ -#define ISTAT_10_SRST 0x40 /* software reset */ -#define ISTAT_10_SIGP 0x20 /* signal script */ -/* 0x10 is reserved on NCR53c700 series chips */ -#define ISTAT_800_SEM 0x10 /* semaphore */ -#define ISTAT_CON 0x08 /* 1 when connected */ -#define ISTAT_800_INTF 0x04 /* Interrupt on the fly */ -#define ISTAT_700_PRE 0x04 /* Pointer register empty. - * Set to 1 when DSPS and DSP - * registers are empty in pipeline - * mode, always set otherwise. - */ -#define ISTAT_SIP 0x02 /* SCSI interrupt pending from - * SCSI portion of SIOP see - * SSTAT0 - */ -#define ISTAT_DIP 0x01 /* DMA interrupt pending - * see DSTAT - */ - -/* NCR53c700-66 and NCR53c710 only */ -#define CTEST8_REG 0x22 /* Chip test 8 rw */ -#define CTEST8_0066_EAS 0x80 /* Enable alternate SCSI clock, - * ie read from SCLK/ rather than CLK/ - */ -#define CTEST8_0066_EFM 0x40 /* Enable fetch and master outputs */ -#define CTEST8_0066_GRP 0x20 /* Generate Receive Parity for - * pass through. This insures that - * bad parity won't reach the host - * bus. - */ -#define CTEST8_0066_TE 0x10 /* TolerANT enable. Enable - * active negation, should only - * be used for slow SCSI - * non-differential. - */ -#define CTEST8_0066_HSC 0x08 /* Halt SCSI clock */ -#define CTEST8_0066_SRA 0x04 /* Shorten REQ/ACK filtering, - * must be set for fast SCSI-II - * speeds. - */ -#define CTEST8_0066_DAS 0x02 /* Disable automatic target/initiator - * switching. - */ -#define CTEST8_0066_LDE 0x01 /* Last disconnect enable. - * The status of pending - * disconnect is maintained by - * the core, eliminating - * the possibility of missing a - * selection or reselection - * while waiting to fetch a - * WAIT DISCONNECT opcode. - */ - -#define CTEST8_10_V3 0x80 /* Chip revision */ -#define CTEST8_10_V2 0x40 -#define CTEST8_10_V1 0x20 -#define CTEST8_10_V0 0x10 -#define CTEST8_10_V_MASK 0xf0 -#define CTEST8_10_FLF 0x08 /* Flush FIFOs */ -#define CTEST8_10_CLF 0x04 /* Clear FIFOs */ -#define CTEST8_10_FM 0x02 /* Fetch pin mode */ -#define CTEST8_10_SM 0x01 /* Snoop pin mode */ - - -/* - * The CTEST9 register may be used to differentiate between a - * NCR53c700 and a NCR53c710. - * - * Write 0xff to this register. - * Read it. - * If the contents are 0xff, it is a NCR53c700 - * If the contents are 0x00, it is a NCR53c700-66 first revision - * If the contents are some other value, it is some other NCR53c700-66 - */ -#define CTEST9_REG_00 0x23 /* Chip test 9 ro */ -#define LCRC_REG_10 0x23 - -/* - * 0x24 through 0x27 are the DMA byte counter register. Instructions - * write their high 8 bits into the DCMD register, the low 24 bits into - * the DBC register. - * - * Function is dependent on the command type being executed. - */ - - -#define DBC_REG 0x24 -/* - * For Block Move Instructions, DBC is a 24 bit quantity representing - * the number of bytes to transfer. - * For Transfer Control Instructions, DBC is bit fielded as follows : - */ -/* Bits 20 - 23 should be clear */ -#define DBC_TCI_TRUE (1 << 19) /* Jump when true */ -#define DBC_TCI_COMPARE_DATA (1 << 18) /* Compare data */ -#define DBC_TCI_COMPARE_PHASE (1 << 17) /* Compare phase with DCMD field */ -#define DBC_TCI_WAIT_FOR_VALID (1 << 16) /* Wait for REQ */ -/* Bits 8 - 15 are reserved on some implementations ? */ -#define DBC_TCI_MASK_MASK 0xff00 /* Mask for data compare */ -#define DBC_TCI_MASK_SHIFT 8 -#define DBC_TCI_DATA_MASK 0xff /* Data to be compared */ -#define DBC_TCI_DATA_SHIFT 0 - -#define DBC_RWRI_IMMEDIATE_MASK 0xff00 /* Immediate data */ -#define DBC_RWRI_IMMEDIATE_SHIFT 8 /* Amount to shift */ -#define DBC_RWRI_ADDRESS_MASK 0x3f0000 /* Register address */ -#define DBC_RWRI_ADDRESS_SHIFT 16 - - -/* - * DMA command r/w - */ -#define DCMD_REG 0x27 -#define DCMD_TYPE_MASK 0xc0 /* Masks off type */ -#define DCMD_TYPE_BMI 0x00 /* Indicates a Block Move instruction */ -#define DCMD_BMI_IO 0x01 /* I/O, CD, and MSG bits selecting */ -#define DCMD_BMI_CD 0x02 /* the phase for the block MOVE */ -#define DCMD_BMI_MSG 0x04 /* instruction */ - -#define DCMD_BMI_OP_MASK 0x18 /* mask for opcode */ -#define DCMD_BMI_OP_MOVE_T 0x00 /* MOVE */ -#define DCMD_BMI_OP_MOVE_I 0x08 /* MOVE Initiator */ - -#define DCMD_BMI_INDIRECT 0x20 /* Indirect addressing */ - -#define DCMD_TYPE_TCI 0x80 /* Indicates a Transfer Control - instruction */ -#define DCMD_TCI_IO 0x01 /* I/O, CD, and MSG bits selecting */ -#define DCMD_TCI_CD 0x02 /* the phase for the block MOVE */ -#define DCMD_TCI_MSG 0x04 /* instruction */ -#define DCMD_TCI_OP_MASK 0x38 /* mask for opcode */ -#define DCMD_TCI_OP_JUMP 0x00 /* JUMP */ -#define DCMD_TCI_OP_CALL 0x08 /* CALL */ -#define DCMD_TCI_OP_RETURN 0x10 /* RETURN */ -#define DCMD_TCI_OP_INT 0x18 /* INT */ - -#define DCMD_TYPE_RWRI 0x40 /* Indicates I/O or register Read/Write - instruction */ -#define DCMD_RWRI_OPC_MASK 0x38 /* Opcode mask */ -#define DCMD_RWRI_OPC_WRITE 0x28 /* Write SFBR to register */ -#define DCMD_RWRI_OPC_READ 0x30 /* Read register to SFBR */ -#define DCMD_RWRI_OPC_MODIFY 0x38 /* Modify in place */ - -#define DCMD_RWRI_OP_MASK 0x07 -#define DCMD_RWRI_OP_MOVE 0x00 -#define DCMD_RWRI_OP_SHL 0x01 -#define DCMD_RWRI_OP_OR 0x02 -#define DCMD_RWRI_OP_XOR 0x03 -#define DCMD_RWRI_OP_AND 0x04 -#define DCMD_RWRI_OP_SHR 0x05 -#define DCMD_RWRI_OP_ADD 0x06 -#define DCMD_RWRI_OP_ADDC 0x07 - -#define DCMD_TYPE_MMI 0xc0 /* Indicates a Memory Move instruction - (three words) */ - - -#define DNAD_REG 0x28 /* through 0x2b DMA next address for - data */ -#define DSP_REG 0x2c /* through 0x2f DMA SCRIPTS pointer rw */ -#define DSPS_REG 0x30 /* through 0x33 DMA SCRIPTS pointer - save rw */ -#define DMODE_REG_00 0x34 /* DMA mode rw */ -#define DMODE_00_BL1 0x80 /* Burst length bits */ -#define DMODE_00_BL0 0x40 -#define DMODE_BL_MASK 0xc0 -/* Burst lengths (800) */ -#define DMODE_BL_2 0x00 /* 2 transfer */ -#define DMODE_BL_4 0x40 /* 4 transfers */ -#define DMODE_BL_8 0x80 /* 8 transfers */ -#define DMODE_BL_16 0xc0 /* 16 transfers */ - -#define DMODE_700_BW16 0x20 /* Host buswidth = 16 */ -#define DMODE_700_286 0x10 /* 286 mode */ -#define DMODE_700_IOM 0x08 /* Transfer to IO port */ -#define DMODE_700_FAM 0x04 /* Fixed address mode */ -#define DMODE_700_PIPE 0x02 /* Pipeline mode disables - * automatic fetch / exec - */ -#define DMODE_MAN 0x01 /* Manual start mode, - * requires a 1 to be written - * to the start DMA bit in the DCNTL - * register to run scripts - */ - -#define DMODE_700_SAVE ( DMODE_00_BL_MASK | DMODE_00_BW16 | DMODE_00_286 ) - -/* NCR53c800 series only */ -#define SCRATCHA_REG_800 0x34 /* through 0x37 Scratch A rw */ -/* NCR53c710 only */ -#define SCRATCB_REG_10 0x34 /* through 0x37 scratch B rw */ - -#define DMODE_REG_10 0x38 /* DMA mode rw, NCR53c710 and newer */ -#define DMODE_800_SIOM 0x20 /* Source IO = 1 */ -#define DMODE_800_DIOM 0x10 /* Destination IO = 1 */ -#define DMODE_800_ERL 0x08 /* Enable Read Line */ - -/* 35-38 are reserved on 700 and 700-66 series chips */ -#define DIEN_REG 0x39 /* DMA interrupt enable rw */ -/* 0x80, 0x40, and 0x20 are reserved on 700-series chips */ -#define DIEN_800_MDPE 0x40 /* Master data parity error */ -#define DIEN_800_BF 0x20 /* BUS fault */ -#define DIEN_ABRT 0x10 /* Enable aborted interrupt */ -#define DIEN_SSI 0x08 /* Enable single step interrupt */ -#define DIEN_SIR 0x04 /* Enable SCRIPTS INT command - * interrupt - */ -/* 0x02 is reserved on 800 series chips */ -#define DIEN_700_WTD 0x02 /* Enable watchdog timeout interrupt */ -#define DIEN_700_OPC 0x01 /* Enable illegal instruction - * interrupt - */ -#define DIEN_800_IID 0x01 /* Same meaning, different name */ - -/* - * DMA watchdog timer rw - * set in 16 CLK input periods. - */ -#define DWT_REG 0x3a - -/* DMA control rw */ -#define DCNTL_REG 0x3b -#define DCNTL_700_CF1 0x80 /* Clock divisor bits */ -#define DCNTL_700_CF0 0x40 -#define DCNTL_700_CF_MASK 0xc0 -/* Clock divisors Divisor SCLK range (MHZ) */ -#define DCNTL_700_CF_2 0x00 /* 2.0 37.51-50.00 */ -#define DCNTL_700_CF_1_5 0x40 /* 1.5 25.01-37.50 */ -#define DCNTL_700_CF_1 0x80 /* 1.0 16.67-25.00 */ -#define DCNTL_700_CF_3 0xc0 /* 3.0 50.01-66.67 (53c700-66) */ - -#define DCNTL_700_S16 0x20 /* Load scripts 16 bits at a time */ -#define DCNTL_SSM 0x10 /* Single step mode */ -#define DCNTL_700_LLM 0x08 /* Low level mode, can only be set - * after selection */ -#define DCNTL_800_IRQM 0x08 /* Totem pole IRQ pin */ -#define DCNTL_STD 0x04 /* Start DMA / SCRIPTS */ -/* 0x02 is reserved */ -#define DCNTL_00_RST 0x01 /* Software reset, resets everything - * but 286 mode bit in DMODE. On the - * NCR53c710, this bit moved to CTEST8 - */ -#define DCNTL_10_COM 0x01 /* 700 software compatibility mode */ - -#define DCNTL_700_SAVE ( DCNTL_CF_MASK | DCNTL_S16) - - -/* NCR53c700-66 only */ -#define SCRATCHB_REG_00 0x3c /* through 0x3f scratch b rw */ -#define SCRATCHB_REG_800 0x5c /* through 0x5f scratch b rw */ -/* NCR53c710 only */ -#define ADDER_REG_10 0x3c /* Adder, NCR53c710 only */ - -#define SIEN1_REG_800 0x41 -#define SIEN1_800_STO 0x04 /* selection/reselection timeout */ -#define SIEN1_800_GEN 0x02 /* general purpose timer */ -#define SIEN1_800_HTH 0x01 /* handshake to handshake */ - -#define SIST1_REG_800 0x43 -#define SIST1_800_STO 0x04 /* selection/reselection timeout */ -#define SIST1_800_GEN 0x02 /* general purpose timer */ -#define SIST1_800_HTH 0x01 /* handshake to handshake */ - -#define SLPAR_REG_800 0x44 /* Parity */ - -#define MACNTL_REG_800 0x46 /* Memory access control */ -#define MACNTL_800_TYP3 0x80 -#define MACNTL_800_TYP2 0x40 -#define MACNTL_800_TYP1 0x20 -#define MACNTL_800_TYP0 0x10 -#define MACNTL_800_DWR 0x08 -#define MACNTL_800_DRD 0x04 -#define MACNTL_800_PSCPT 0x02 -#define MACNTL_800_SCPTS 0x01 - -#define GPCNTL_REG_800 0x47 /* General Purpose Pin Control */ - -/* Timeouts are expressed such that 0=off, 1=100us, doubling after that */ -#define STIME0_REG_800 0x48 /* SCSI Timer Register 0 */ -#define STIME0_800_HTH_MASK 0xf0 /* Handshake to Handshake timeout */ -#define STIME0_800_HTH_SHIFT 4 -#define STIME0_800_SEL_MASK 0x0f /* Selection timeout */ -#define STIME0_800_SEL_SHIFT 0 - -#define STIME1_REG_800 0x49 -#define STIME1_800_GEN_MASK 0x0f /* General purpose timer */ - -#define RESPID_REG_800 0x4a /* Response ID, bit fielded. 8 - bits on narrow chips, 16 on WIDE */ - -#define STEST0_REG_800 0x4c -#define STEST0_800_SLT 0x08 /* Selection response logic test */ -#define STEST0_800_ART 0x04 /* Arbitration priority encoder test */ -#define STEST0_800_SOZ 0x02 /* Synchronous offset zero */ -#define STEST0_800_SOM 0x01 /* Synchronous offset maximum */ - -#define STEST1_REG_800 0x4d -#define STEST1_800_SCLK 0x80 /* Disable SCSI clock */ - -#define STEST2_REG_800 0x4e -#define STEST2_800_SCE 0x80 /* Enable SOCL/SODL */ -#define STEST2_800_ROF 0x40 /* Reset SCSI sync offset */ -#define STEST2_800_SLB 0x10 /* Enable SCSI loopback mode */ -#define STEST2_800_SZM 0x08 /* SCSI high impedance mode */ -#define STEST2_800_EXT 0x02 /* Extend REQ/ACK filter 30 to 60ns */ -#define STEST2_800_LOW 0x01 /* SCSI low level mode */ - -#define STEST3_REG_800 0x4f -#define STEST3_800_TE 0x80 /* Enable active negation */ -#define STEST3_800_STR 0x40 /* SCSI FIFO test read */ -#define STEST3_800_HSC 0x20 /* Halt SCSI clock */ -#define STEST3_800_DSI 0x10 /* Disable single initiator response */ -#define STEST3_800_TTM 0x04 /* Time test mode */ -#define STEST3_800_CSF 0x02 /* Clear SCSI FIFO */ -#define STEST3_800_STW 0x01 /* SCSI FIFO test write */ - -#define OPTION_PARITY 0x1 /* Enable parity checking */ -#define OPTION_TAGGED_QUEUE 0x2 /* Enable SCSI-II tagged queuing */ -#define OPTION_700 0x8 /* Always run NCR53c700 scripts */ -#define OPTION_INTFLY 0x10 /* Use INTFLY interrupts */ -#define OPTION_DEBUG_INTR 0x20 /* Debug interrupts */ -#define OPTION_DEBUG_INIT_ONLY 0x40 /* Run initialization code and - simple test code, return - DID_NO_CONNECT if any SCSI - commands are attempted. */ -#define OPTION_DEBUG_READ_ONLY 0x80 /* Return DID_ERROR if any - SCSI write is attempted */ -#define OPTION_DEBUG_TRACE 0x100 /* Animated trace mode, print - each address and instruction - executed to debug buffer. */ -#define OPTION_DEBUG_SINGLE 0x200 /* stop after executing one - instruction */ -#define OPTION_SYNCHRONOUS 0x400 /* Enable sync SCSI. */ -#define OPTION_MEMORY_MAPPED 0x800 /* NCR registers have valid - memory mapping */ -#define OPTION_IO_MAPPED 0x1000 /* NCR registers have valid - I/O mapping */ -#define OPTION_DEBUG_PROBE_ONLY 0x2000 /* Probe only, don't even init */ -#define OPTION_DEBUG_TESTS_ONLY 0x4000 /* Probe, init, run selected tests */ -#define OPTION_DEBUG_TEST0 0x08000 /* Run test 0 */ -#define OPTION_DEBUG_TEST1 0x10000 /* Run test 1 */ -#define OPTION_DEBUG_TEST2 0x20000 /* Run test 2 */ -#define OPTION_DEBUG_DUMP 0x40000 /* Dump commands */ -#define OPTION_DEBUG_TARGET_LIMIT 0x80000 /* Only talk to target+luns specified */ -#define OPTION_DEBUG_NCOMMANDS_LIMIT 0x100000 /* Limit the number of commands */ -#define OPTION_DEBUG_SCRIPT 0x200000 /* Print when checkpoints are passed */ -#define OPTION_DEBUG_FIXUP 0x400000 /* print fixup values */ -#define OPTION_DEBUG_DSA 0x800000 -#define OPTION_DEBUG_CORRUPTION 0x1000000 /* Detect script corruption */ -#define OPTION_DEBUG_SDTR 0x2000000 /* Debug SDTR problem */ -#define OPTION_DEBUG_MISMATCH 0x4000000 /* Debug phase mismatches */ -#define OPTION_DISCONNECT 0x8000000 /* Allow disconect */ -#define OPTION_DEBUG_DISCONNECT 0x10000000 -#define OPTION_ALWAYS_SYNCHRONOUS 0x20000000 /* Negotiate sync. transfers - on power up */ -#define OPTION_DEBUG_QUEUES 0x80000000 -#define OPTION_DEBUG_ALLOCATION 0x100000000LL -#define OPTION_DEBUG_SYNCHRONOUS 0x200000000LL /* Sanity check SXFER and - SCNTL3 registers */ -#define OPTION_NO_ASYNC 0x400000000LL /* Don't automagically send - SDTR for async transfers when - we haven't been told to do - a synchronous transfer. */ -#define OPTION_NO_PRINT_RACE 0x800000000LL /* Don't print message when - the reselect/WAIT DISCONNECT - race condition hits */ -#if !defined(PERM_OPTIONS) -#define PERM_OPTIONS 0 -#endif - -struct NCR53c7x0_synchronous { - u32 select_indirect; /* Value used for indirect selection */ - u32 script[8]; /* Size ?? Script used when target is - reselected */ - unsigned char synchronous_want[5]; /* Per target desired SDTR */ -/* - * Set_synchronous programs these, select_indirect and current settings after - * int_debug_should show a match. - */ - unsigned char sxfer_sanity, scntl3_sanity; -}; - -#define CMD_FLAG_SDTR 1 /* Initiating synchronous - transfer negotiation */ -#define CMD_FLAG_WDTR 2 /* Initiating wide transfer - negotiation */ -#define CMD_FLAG_DID_SDTR 4 /* did SDTR */ -#define CMD_FLAG_DID_WDTR 8 /* did WDTR */ - -struct NCR53c7x0_table_indirect { - u32 count; - void *address; -}; - -enum ncr_event { - EVENT_NONE = 0, -/* - * Order is IMPORTANT, since these must correspond to the event interrupts - * in 53c7,8xx.scr - */ - - EVENT_ISSUE_QUEUE = 0x5000000, /* Command was added to issue queue */ - EVENT_START_QUEUE, /* Command moved to start queue */ - EVENT_SELECT, /* Command completed selection */ - EVENT_DISCONNECT, /* Command disconnected */ - EVENT_RESELECT, /* Command reselected */ - EVENT_COMPLETE, /* Command completed */ - EVENT_IDLE, - EVENT_SELECT_FAILED, - EVENT_BEFORE_SELECT, - EVENT_RESELECT_FAILED -}; - -struct NCR53c7x0_event { - enum ncr_event event; /* What type of event */ - unsigned char target; - unsigned char lun; - struct timeval time; - u32 *dsa; /* What's in the DSA register now (virt) */ -/* - * A few things from that SCSI pid so we know what happened after - * the Scsi_Cmnd structure in question may have disappeared. - */ - unsigned long pid; /* The SCSI PID which caused this - event */ - unsigned char cmnd[12]; -}; - -/* - * Things in the NCR53c7x0_cmd structure are split into two parts : - * - * 1. A fixed portion, for things which are not accessed directly by static NCR - * code (ie, are referenced only by the Linux side of the driver, - * or only by dynamically genreated code). - * - * 2. The DSA portion, for things which are accessed directly by static NCR - * code. - * - * This is a little ugly, but it - * 1. Avoids conflicts between the NCR code's picture of the structure, and - * Linux code's idea of what it looks like. - * - * 2. Minimizes the pain in the Linux side of the code needed - * to calculate real dsa locations for things, etc. - * - */ - -struct NCR53c7x0_cmd { - void *real; /* Real, unaligned address for - free function */ - void (* free)(void *, int); /* Command to deallocate; NULL - for structures allocated with - scsi_register, etc. */ - Scsi_Cmnd *cmd; /* Associated Scsi_Cmnd - structure, Scsi_Cmnd points - at NCR53c7x0_cmd using - host_scribble structure */ - - int size; /* scsi_malloc'd size of this - structure */ - - int flags; /* CMD_* flags */ - -/* - * SDTR and WIDE messages are an either/or affair - * in this message, since we will go into message out and send - * _the whole mess_ without dropping out of message out to - * let the target go into message in after sending the first - * message. - */ - - unsigned char select[11]; /* Select message, includes - IDENTIFY - (optional) QUEUE TAG - (optional) SDTR or WDTR - */ - - - volatile struct NCR53c7x0_cmd *next; /* Linux maintained lists (free, - running, eventually finished */ - - - u32 *data_transfer_start; /* Start of data transfer routines */ - u32 *data_transfer_end; /* Address after end of data transfer o - routines */ -/* - * The following three fields were moved from the DSA propper to here - * since only dynamically generated NCR code refers to them, meaning - * we don't need dsa_* absolutes, and it is simpler to let the - * host code refer to them directly. - */ - -/* - * HARD CODED : residual and saved_residual need to agree with the sizes - * used in NCR53c7,8xx.scr. - * - * FIXME: we want to consider the case where we have odd-length - * scatter/gather buffers and a WIDE transfer, in which case - * we'll need to use the CHAIN MOVE instruction. Ick. - */ - u32 residual[6]; /* Residual data transfer which - allows pointer code to work - right. - - [0-1] : Conditional call to - appropriate other transfer - routine. - [2-3] : Residual block transfer - instruction. - [4-5] : Jump to instruction - after splice. - */ - u32 saved_residual[6]; /* Copy of old residual, so we - can get another partial - transfer and still recover - */ - - u32 saved_data_pointer; /* Saved data pointer */ - - u32 dsa_next_addr; /* _Address_ of dsa_next field - in this dsa for RISCy - style constant. */ - - u32 dsa_addr; /* Address of dsa; RISCy style - constant */ - - u32 dsa[0]; /* Variable length (depending - on host type, number of scatter / - gather buffers, etc). */ -}; - -struct NCR53c7x0_break { - u32 *address, old_instruction[2]; - struct NCR53c7x0_break *next; - unsigned char old_size; /* Size of old instruction */ -}; - -/* Indicates that the NCR is not executing code */ -#define STATE_HALTED 0 -/* - * Indicates that the NCR is executing the wait for select / reselect - * script. Only used when running NCR53c700 compatible scripts, only - * state during which an ABORT is _not_ considered an error condition. - */ -#define STATE_WAITING 1 -/* Indicates that the NCR is executing other code. */ -#define STATE_RUNNING 2 -/* - * Indicates that the NCR was being aborted. - */ -#define STATE_ABORTING 3 -/* Indicates that the NCR was successfully aborted. */ -#define STATE_ABORTED 4 -/* Indicates that the NCR has been disabled due to a fatal error */ -#define STATE_DISABLED 5 - -/* - * Where knowledge of SCSI SCRIPT(tm) specified values are needed - * in an interrupt handler, an interrupt handler exists for each - * different SCSI script so we don't have name space problems. - * - * Return values of these handlers are as follows : - */ -#define SPECIFIC_INT_NOTHING 0 /* don't even restart */ -#define SPECIFIC_INT_RESTART 1 /* restart at the next instruction */ -#define SPECIFIC_INT_ABORT 2 /* recoverable error, abort cmd */ -#define SPECIFIC_INT_PANIC 3 /* unrecoverable error, panic */ -#define SPECIFIC_INT_DONE 4 /* normal command completion */ -#define SPECIFIC_INT_BREAK 5 /* break point encountered */ - -struct NCR53c7x0_hostdata { - int size; /* Size of entire Scsi_Host - structure */ - int board; /* set to board type, useful if - we have host specific things, - ie, a general purpose I/O - bit is being used to enable - termination, etc. */ - - int chip; /* set to chip type; 700-66 is - 700-66, rest are last three - digits of part number */ - /* - * PCI bus, device, function, only for NCR53c8x0 chips. - * pci_valid indicates that the PCI configuration information - * is valid, and we can twiddle MAX_LAT, etc. as recommended - * for maximum performance in the NCR documentation. - */ - unsigned char pci_bus, pci_device_fn; - unsigned pci_valid:1; - - u32 *dsp; /* dsp to restart with after - all stacked interrupts are - handled. */ - - unsigned dsp_changed:1; /* Has dsp changed within this - set of stacked interrupts ? */ - - unsigned char dstat; /* Most recent value of dstat */ - unsigned dstat_valid:1; - - unsigned expecting_iid:1; /* Expect IID interrupt */ - unsigned expecting_sto:1; /* Expect STO interrupt */ - - /* - * The code stays cleaner if we use variables with function - * pointers and offsets that are unique for the different - * scripts rather than having a slew of switch(hostdata->chip) - * statements. - * - * It also means that the #defines from the SCSI SCRIPTS(tm) - * don't have to be visible outside of the script-specific - * instructions, preventing name space pollution. - */ - - void (* init_fixup)(struct Scsi_Host *host); - void (* init_save_regs)(struct Scsi_Host *host); - void (* dsa_fixup)(struct NCR53c7x0_cmd *cmd); - void (* soft_reset)(struct Scsi_Host *host); - int (* run_tests)(struct Scsi_Host *host); - - /* - * Called when DSTAT_SIR is set, indicating an interrupt generated - * by the INT instruction, where values are unique for each SCSI - * script. Should return one of the SPEC_* values. - */ - - int (* dstat_sir_intr)(struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd); - - int dsa_len; /* Size of DSA structure */ - - /* - * Location of DSA fields for the SCSI SCRIPT corresponding to this - * chip. - */ - - s32 dsa_start; - s32 dsa_end; - s32 dsa_next; - s32 dsa_prev; - s32 dsa_cmnd; - s32 dsa_select; - s32 dsa_msgout; - s32 dsa_cmdout; - s32 dsa_dataout; - s32 dsa_datain; - s32 dsa_msgin; - s32 dsa_msgout_other; - s32 dsa_write_sync; - s32 dsa_write_resume; - s32 dsa_check_reselect; - s32 dsa_status; - s32 dsa_saved_pointer; - s32 dsa_jump_dest; - - /* - * Important entry points that generic fixup code needs - * to know about, fixed up. - */ - - s32 E_accept_message; - s32 E_command_complete; - s32 E_data_transfer; - s32 E_dsa_code_template; - s32 E_dsa_code_template_end; - s32 E_end_data_transfer; - s32 E_msg_in; - s32 E_initiator_abort; - s32 E_other_transfer; - s32 E_other_in; - s32 E_other_out; - s32 E_target_abort; - s32 E_debug_break; - s32 E_reject_message; - s32 E_respond_message; - s32 E_select; - s32 E_select_msgout; - s32 E_test_0; - s32 E_test_1; - s32 E_test_2; - s32 E_test_3; - s32 E_dsa_zero; - s32 E_cmdout_cmdout; - s32 E_wait_reselect; - s32 E_dsa_code_begin; - - long long options; /* Bitfielded set of options enabled */ - volatile u32 test_completed; /* Test completed */ - int test_running; /* Test currently running */ - s32 test_source; - volatile s32 test_dest; - - volatile int state; /* state of driver, only used for - OPTION_700 */ - - unsigned char dmode; /* - * set to the address of the DMODE - * register for this chip. - */ - unsigned char istat; /* - * set to the address of the ISTAT - * register for this chip. - */ - - int scsi_clock; /* - * SCSI clock in HZ. 0 may be used - * for unknown, although this will - * disable synchronous negotiation. - */ - - volatile int intrs; /* Number of interrupts */ - volatile int resets; /* Number of SCSI resets */ - unsigned char saved_dmode; - unsigned char saved_ctest4; - unsigned char saved_ctest7; - unsigned char saved_dcntl; - unsigned char saved_scntl3; - - unsigned char this_id_mask; - - /* Debugger information */ - struct NCR53c7x0_break *breakpoints, /* Linked list of all break points */ - *breakpoint_current; /* Current breakpoint being stepped - through, NULL if we are running - normally. */ -#ifdef NCR_DEBUG - int debug_size; /* Size of debug buffer */ - volatile int debug_count; /* Current data count */ - volatile char *debug_buf; /* Output ring buffer */ - volatile char *debug_write; /* Current write pointer */ - volatile char *debug_read; /* Current read pointer */ -#endif /* def NCR_DEBUG */ - - /* XXX - primitive debugging junk, remove when working ? */ - int debug_print_limit; /* Number of commands to print - out exhaustive debugging - information for if - OPTION_DEBUG_DUMP is set */ - - unsigned char debug_lun_limit[16]; /* If OPTION_DEBUG_TARGET_LIMIT - set, puke if commands are sent - to other target/lun combinations */ - - int debug_count_limit; /* Number of commands to execute - before puking to limit debugging - output */ - - - volatile unsigned idle:1; /* set to 1 if idle */ - - /* - * Table of synchronous+wide transfer parameters set on a per-target - * basis. - */ - - volatile struct NCR53c7x0_synchronous sync[16]; - - volatile Scsi_Cmnd *issue_queue; - /* waiting to be issued by - Linux driver */ - volatile struct NCR53c7x0_cmd *running_list; - /* commands running, maintained - by Linux driver */ - - volatile struct NCR53c7x0_cmd *current; /* currently connected - nexus, ONLY valid for - NCR53c700/NCR53c700-66 - */ - - volatile struct NCR53c7x0_cmd *spare; /* pointer to spare, - allocated at probe time, - which we can use for - initialization */ - volatile struct NCR53c7x0_cmd *free; - int max_cmd_size; /* Maximum size of NCR53c7x0_cmd - based on number of - scatter/gather segments, etc. - */ - volatile int num_cmds; /* Number of commands - allocated */ - volatile int extra_allocate; - volatile unsigned char cmd_allocated[16]; /* Have we allocated commands - for this target yet? If not, - do so ASAP */ - volatile unsigned char busy[16][8]; /* number of commands - executing on each target - */ - /* - * Eventually, I'll switch to a coroutine for calling - * cmd->done(cmd), etc. so that we can overlap interrupt - * processing with this code for maximum performance. - */ - - volatile struct NCR53c7x0_cmd *finished_queue; - - - /* Shared variables between SCRIPT and host driver */ - volatile u32 *schedule; /* Array of JUMPs to dsa_begin - routines of various DSAs. - When not in use, replace - with jump to next slot */ - - - volatile unsigned char msg_buf[16]; /* buffer for messages - other than the command - complete message */ - - /* Per-target default synchronous and WIDE messages */ - volatile unsigned char synchronous_want[16][5]; - volatile unsigned char wide_want[16][4]; - - /* Bit fielded set of targets we want to speak synchronously with */ - volatile u16 initiate_sdtr; - /* Bit fielded set of targets we want to speak wide with */ - volatile u16 initiate_wdtr; - /* Bit fielded list of targets we've talked to. */ - volatile u16 talked_to; - - /* Array of bit-fielded lun lists that we need to request_sense */ - volatile unsigned char request_sense[16]; - - u32 addr_reconnect_dsa_head; /* RISCy style constant, - address of following */ - volatile u32 reconnect_dsa_head; - /* Data identifying nexus we are trying to match during reselection */ - volatile unsigned char reselected_identify; /* IDENTIFY message */ - volatile unsigned char reselected_tag; /* second byte of queue tag - message or 0 */ - /* These were static variables before we moved them */ - - s32 NCR53c7xx_zero; - s32 NCR53c7xx_sink; - u32 NOP_insn; - char NCR53c7xx_msg_reject; - char NCR53c7xx_msg_abort; - char NCR53c7xx_msg_nop; - - volatile int event_size, event_index; - volatile struct NCR53c7x0_event *events; - - /* If we need to generate code to kill off the currently connected - command, this is where we do it. Should have a BMI instruction - to source or sink the current data, followed by a JUMP - to abort_connected */ - - u32 *abort_script; - - int script_count; /* Size of script in words */ - u32 script[0]; /* Relocated SCSI script */ - -}; - -#define IRQ_NONE 255 -#define DMA_NONE 255 -#define IRQ_AUTO 254 -#define DMA_AUTO 254 - -#define BOARD_GENERIC 0 - -#define NCR53c7x0_insn_size(insn) \ - (((insn) & DCMD_TYPE_MASK) == DCMD_TYPE_MMI ? 3 : 2) - - -#define NCR53c7x0_local_declare() \ - volatile unsigned char *NCR53c7x0_address_memory; \ - unsigned int NCR53c7x0_address_io; \ - int NCR53c7x0_memory_mapped - -#define NCR53c7x0_local_setup(host) \ - NCR53c7x0_address_memory = (void *) (host)->base; \ - NCR53c7x0_address_io = (unsigned int) (host)->io_port; \ - NCR53c7x0_memory_mapped = ((struct NCR53c7x0_hostdata *) \ - host->hostdata)-> options & OPTION_MEMORY_MAPPED - -#define NCR53c7x0_read8(address) \ - (NCR53c7x0_memory_mapped ? \ - (unsigned int)readb(NCR53c7x0_address_memory + (address)) : \ - inb(NCR53c7x0_address_io + (address))) - -#define NCR53c7x0_read16(address) \ - (NCR53c7x0_memory_mapped ? \ - (unsigned int)readw(NCR53c7x0_address_memory + (address)) : \ - inw(NCR53c7x0_address_io + (address))) - -#define NCR53c7x0_read32(address) \ - (NCR53c7x0_memory_mapped ? \ - (unsigned int) readl(NCR53c7x0_address_memory + (address)) : \ - inl(NCR53c7x0_address_io + (address))) - -#define NCR53c7x0_write8(address,value) \ - (NCR53c7x0_memory_mapped ? \ - ({writeb((value), NCR53c7x0_address_memory + (address)); mb();}) : \ - outb((value), NCR53c7x0_address_io + (address))) - -#define NCR53c7x0_write16(address,value) \ - (NCR53c7x0_memory_mapped ? \ - ({writew((value), NCR53c7x0_address_memory + (address)); mb();}) : \ - outw((value), NCR53c7x0_address_io + (address))) - -#define NCR53c7x0_write32(address,value) \ - (NCR53c7x0_memory_mapped ? \ - ({writel((value), NCR53c7x0_address_memory + (address)); mb();}) : \ - outl((value), NCR53c7x0_address_io + (address))) - -/* Patch arbitrary 32 bit words in the script */ -#define patch_abs_32(script, offset, symbol, value) \ - for (i = 0; i < (sizeof (A_##symbol##_used) / sizeof \ - (u32)); ++i) { \ - (script)[A_##symbol##_used[i] - (offset)] += (value); \ - if (hostdata->options & OPTION_DEBUG_FIXUP) \ - printk("scsi%d : %s reference %d at 0x%x in %s is now 0x%x\n",\ - host->host_no, #symbol, i, A_##symbol##_used[i] - \ - (int)(offset), #script, (script)[A_##symbol##_used[i] - \ - (offset)]); \ - } - -/* Patch read/write instruction immediate field */ -#define patch_abs_rwri_data(script, offset, symbol, value) \ - for (i = 0; i < (sizeof (A_##symbol##_used) / sizeof \ - (u32)); ++i) \ - (script)[A_##symbol##_used[i] - (offset)] = \ - ((script)[A_##symbol##_used[i] - (offset)] & \ - ~DBC_RWRI_IMMEDIATE_MASK) | \ - (((value) << DBC_RWRI_IMMEDIATE_SHIFT) & \ - DBC_RWRI_IMMEDIATE_MASK) - -/* Patch transfer control instruction data field */ -#define patch_abs_tci_data(script, offset, symbol, value) \ - for (i = 0; i < (sizeof (A_##symbol##_used) / sizeof \ - (u32)); ++i) \ - (script)[A_##symbol##_used[i] - (offset)] = \ - ((script)[A_##symbol##_used[i] - (offset)] & \ - ~DBC_TCI_DATA_MASK) | \ - (((value) << DBC_TCI_DATA_SHIFT) & \ - DBC_TCI_DATA_MASK) - -/* Patch field in dsa structure (assignment should be +=?) */ -#define patch_dsa_32(dsa, symbol, word, value) \ - { \ - (dsa)[(hostdata->##symbol - hostdata->dsa_start) / sizeof(u32) \ - + (word)] = (value); \ - if (hostdata->options & OPTION_DEBUG_DSA) \ - printk("scsi : dsa %s symbol %s(%d) word %d now 0x%x\n", \ - #dsa, #symbol, hostdata->##symbol, \ - (word), (u32) (value)); \ - } - -/* Paranoid people could use panic() here. */ -#define FATAL(host) shutdown((host)); - -#endif /* NCR53c7x0_C */ -#endif /* NCR53c7x0_H */ diff --git a/i386/i386at/gpl/linux/scsi/53c78xx.c b/i386/i386at/gpl/linux/scsi/53c78xx.c deleted file mode 100644 index 74350b08..00000000 --- a/i386/i386at/gpl/linux/scsi/53c78xx.c +++ /dev/null @@ -1,6381 +0,0 @@ -/* - * PERM_OPTIONS are driver options which will be enabled for all NCR boards - * in the system at driver initialization time. - * - * Don't THINK about touching these in PERM_OPTIONS : - * OPTION_IO_MAPPED - * Memory mapped IO does not work under i86 Linux. - * - * OPTION_DEBUG_TEST1 - * Test 1 does bus mastering and interrupt tests, which will help weed - * out brain damaged main boards. - * - * These are development kernel changes. Code for them included in this - * driver release may or may not work. If you turn them on, you should be - * running the latest copy of the development sources from - * - * ftp://tsx-11.mit.edu/pub/linux/ALPHA/scsi/53c7,8xx - * - * and be subscribed to the ncr53c810@colorado.edu mailing list. To - * subscribe, send mail to majordomo@colorado.edu with - * - * subscribe ncr53c810 - * - * in the text. - * - * - * OPTION_NOASYNC - * Don't negotiate for asynchronous transfers on the first command - * when OPTION_ALWAYS_SYNCHRONOUS is set. Useful for dain bramaged - * devices which do something bad rather than sending a MESSAGE - * REJECT back to us like they should if they can't cope. - * - * OPTION_SYNCHRONOUS - * Enable support for synchronous transfers. Target negotiated - * synchronous transfers will be responded to. To initiate - * a synchronous transfer request, call - * - * request_synchronous (hostno, target) - * - * from within KGDB. - * - * OPTION_ALWAYS_SYNCHRONOUS - * Negotiate for synchronous transfers with every target after - * driver initialization or a SCSI bus reset. This is a bit dangerous, - * since there are some dain bramaged SCSI devices which will accept - * SDTR messages but keep talking asynchronously. - * - * OPTION_DISCONNECT - * Enable support for disconnect/reconnect. To change the - * default setting on a given host adapter, call - * - * request_disconnect (hostno, allow) - * - * where allow is non-zero to allow, 0 to disallow. - * - * If you really want to run 10MHz FAST SCSI-II transfers, you should - * know that the NCR driver currently ignores parity information. Most - * systems do 5MHz SCSI fine. I've seen a lot that have problems faster - * than 8MHz. To play it safe, we only request 5MHz transfers. - * - * If you'd rather get 10MHz transfers, edit sdtr_message and change - * the fourth byte from 50 to 25. - */ - -#define PERM_OPTIONS (OPTION_IO_MAPPED|OPTION_DEBUG_TEST1|OPTION_DISCONNECT|\ - OPTION_SYNCHRONOUS) - -/* - * Sponsored by - * iX Multiuser Multitasking Magazine - * Hannover, Germany - * hm@ix.de - * - * Copyright 1993, 1994, 1995 Drew Eckhardt - * Visionary Computing - * (Unix and Linux consulting and custom programming) - * drew@PoohSticks.ORG - * +1 (303) 786-7975 - * - * TolerANT and SCSI SCRIPTS are registered trademarks of NCR Corporation. - * - * For more information, please consult - * - * NCR53C810 - * SCSI I/O Processor - * Programmer's Guide - * - * NCR 53C810 - * PCI-SCSI I/O Processor - * Data Manual - * - * NCR 53C810/53C820 - * PCI-SCSI I/O Processor Design In Guide - * - * For literature on Symbios Logic Inc. formerly NCR, SCSI, - * and Communication products please call (800) 334-5454 or - * (719) 536-3300. - * - * PCI BIOS Specification Revision - * PCI Local Bus Specification - * PCI System Design Guide - * - * PCI Special Interest Group - * M/S HF3-15A - * 5200 N.E. Elam Young Parkway - * Hillsboro, Oregon 97124-6497 - * +1 (503) 696-2000 - * +1 (800) 433-5177 - */ - -/* - * Design issues : - * The cumulative latency needed to propagate a read/write request - * through the file system, buffer cache, driver stacks, SCSI host, and - * SCSI device is ultimately the limiting factor in throughput once we - * have a sufficiently fast host adapter. - * - * So, to maximize performance we want to keep the ratio of latency to data - * transfer time to a minimum by - * 1. Minimizing the total number of commands sent (typical command latency - * including drive and bus mastering host overhead is as high as 4.5ms) - * to transfer a given amount of data. - * - * This is accomplished by placing no arbitrary limit on the number - * of scatter/gather buffers supported, since we can transfer 1K - * per scatter/gather buffer without Eric's cluster patches, - * 4K with. - * - * 2. Minimizing the number of fatal interrupts serviced, since - * fatal interrupts halt the SCSI I/O processor. Basically, - * this means offloading the practical maximum amount of processing - * to the SCSI chip. - * - * On the NCR53c810/820/720, this is accomplished by using - * interrupt-on-the-fly signals when commands complete, - * and only handling fatal errors and SDTR / WDTR messages - * in the host code. - * - * On the NCR53c710, interrupts are generated as on the NCR53c8x0, - * only the lack of a interrupt-on-the-fly facility complicates - * things. Also, SCSI ID registers and commands are - * bit fielded rather than binary encoded. - * - * On the NCR53c700 and NCR53c700-66, operations that are done via - * indirect, table mode on the more advanced chips must be - * replaced by calls through a jump table which - * acts as a surrogate for the DSA. Unfortunately, this - * will mean that we must service an interrupt for each - * disconnect/reconnect. - * - * 3. Eliminating latency by pipelining operations at the different levels. - * - * This driver allows a configurable number of commands to be enqueued - * for each target/lun combination (experimentally, I have discovered - * that two seems to work best) and will ultimately allow for - * SCSI-II tagged queuing. - * - * - * Architecture : - * This driver is built around a Linux queue of commands waiting to - * be executed, and a shared Linux/NCR array of commands to start. Commands - * are transfered to the array by the run_process_issue_queue() function - * which is called whenever a command completes. - * - * As commands are completed, the interrupt routine is triggered, - * looks for commands in the linked list of completed commands with - * valid status, removes these commands from a list of running commands, - * calls the done routine, and flags their target/luns as not busy. - * - * Due to limitations in the intelligence of the NCR chips, certain - * concessions are made. In many cases, it is easier to dynamically - * generate/fix-up code rather than calculate on the NCR at run time. - * So, code is generated or fixed up for - * - * - Handling data transfers, using a variable number of MOVE instructions - * interspersed with CALL MSG_IN, WHEN MSGIN instructions. - * - * The DATAIN and DATAOUT routines are separate, so that an incorrect - * direction can be trapped, and space isn't wasted. - * - * It may turn out that we're better off using some sort - * of table indirect instruction in a loop with a variable - * sized table on the NCR53c710 and newer chips. - * - * - Checking for reselection (NCR53c710 and better) - * - * - Handling the details of SCSI context switches (NCR53c710 and better), - * such as reprogramming appropriate synchronous parameters, - * removing the dsa structure from the NCR's queue of outstanding - * commands, etc. - * - */ - -/* - * Accommodate differences between stock 1.2.x and 1.3.x asm-i386/types.h - * so lusers can drop in 53c7,8xx.* and get something which compiles - * without warnings. - */ - -#if !defined(LINUX_1_2) && !defined(LINUX_1_3) -#include <linux/version.h> -#if LINUX_VERSION_CODE > 65536 + 3 * 256 -#define LINUX_1_3 -#else -#define LINUX_1_2 -#endif -#endif - -#ifdef LINUX_1_2 -#define u32 bogus_u32 -#define s32 bogus_s32 -#include <asm/types.h> -#undef u32 -#undef s32 -typedef __signed__ int s32; -typedef unsigned int u32; -#endif /* def LINUX_1_2 */ - -#ifdef MODULE -#include <linux/module.h> -#endif - -#include <asm/dma.h> -#include <asm/io.h> -#include <asm/system.h> -#include <linux/delay.h> -#include <linux/signal.h> -#include <linux/sched.h> -#include <linux/errno.h> -#include <linux/bios32.h> -#include <linux/pci.h> -#include <linux/proc_fs.h> -#include <linux/string.h> -#include <linux/malloc.h> -#include <linux/mm.h> -#include <linux/ioport.h> -#include <linux/time.h> -#ifdef LINUX_1_2 -#include "../block/blk.h" -#else -#include <linux/blk.h> -#endif -#undef current - -#include "scsi.h" -#include "hosts.h" -#include "53c7,8xx.h" -#include "constants.h" -#include "sd.h" -#include <linux/stat.h> -#include <linux/stddef.h> - -#ifndef LINUX_1_2 -struct proc_dir_entry proc_scsi_ncr53c7xx = { - PROC_SCSI_NCR53C7xx, 9, "ncr53c7xx", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; -#endif - -static int check_address (unsigned long addr, int size); -static void dump_events (struct Scsi_Host *host, int count); -static Scsi_Cmnd * return_outstanding_commands (struct Scsi_Host *host, - int free, int issue); -static void hard_reset (struct Scsi_Host *host); -static void ncr_scsi_reset (struct Scsi_Host *host); -static void print_lots (struct Scsi_Host *host); -static void set_synchronous (struct Scsi_Host *host, int target, int sxfer, - int scntl3, int now_connected); -static int datapath_residual (struct Scsi_Host *host); -static const char * sbcl_to_phase (int sbcl); -static void print_progress (Scsi_Cmnd *cmd); -static void print_queues (struct Scsi_Host *host); -static void process_issue_queue (unsigned long flags); -static int shutdown (struct Scsi_Host *host); -static void abnormal_finished (struct NCR53c7x0_cmd *cmd, int result); -static int disable (struct Scsi_Host *host); -static int NCR53c8xx_run_tests (struct Scsi_Host *host); -static int NCR53c8xx_script_len; -static int NCR53c8xx_dsa_len; -static void NCR53c7x0_intr(int irq, struct pt_regs * regs); -static int ncr_halt (struct Scsi_Host *host); -static void intr_phase_mismatch (struct Scsi_Host *host, struct NCR53c7x0_cmd - *cmd); -static void intr_dma (struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd); -static void print_dsa (struct Scsi_Host *host, u32 *dsa, - const char *prefix); -static int print_insn (struct Scsi_Host *host, const u32 *insn, - const char *prefix, int kernel); - -static void NCR53c8xx_dsa_fixup (struct NCR53c7x0_cmd *cmd); -static void NCR53c8x0_init_fixup (struct Scsi_Host *host); -static int NCR53c8x0_dstat_sir_intr (struct Scsi_Host *host, struct - NCR53c7x0_cmd *cmd); -static void NCR53c8x0_soft_reset (struct Scsi_Host *host); - -/* INSMOD variables */ -static long long perm_options = PERM_OPTIONS; -/* 14 = .5s; 15 is max; decreasing divides by two. */ -static int selection_timeout = 14; -/* Size of event list (per host adapter) */ -static int track_events = 0; - -static struct Scsi_Host *first_host = NULL; /* Head of list of NCR boards */ -static Scsi_Host_Template *the_template = NULL; - -/* - * KNOWN BUGS : - * - There is some sort of conflict when the PPP driver is compiled with - * support for 16 channels? - * - * - On systems which predate the 1.3.x initialization order change, - * the NCR driver will cause Cannot get free page messages to appear. - * These are harmless, but I don't know of an easy way to avoid them. - * - * - With OPTION_DISCONNECT, on two systems under unknown circumstances, - * we get a PHASE MISMATCH with DSA set to zero (suggests that we - * are occurring somewhere in the reselection code) where - * DSP=some value DCMD|DBC=same value. - * - * Closer inspection suggests that we may be trying to execute - * some portion of the DSA? - * scsi0 : handling residual transfer (+ 0 bytes from DMA FIFO) - * scsi0 : handling residual transfer (+ 0 bytes from DMA FIFO) - * scsi0 : no current command : unexpected phase MSGIN. - * DSP=0x1c46cc, DCMD|DBC=0x1c46ac, DSA=0x0 - * DSPS=0x0, TEMP=0x1c3e70, DMODE=0x80 - * scsi0 : DSP-> - * 001c46cc : 0x001c46cc 0x00000000 - * 001c46d4 : 0x001c5ea0 0x000011f8 - * - * Changed the print code in the phase_mismatch handler so - * that we call print_lots to try and diagnose this. - * - */ - -/* - * Possible future direction of architecture for max performance : - * - * We're using a single start array for the NCR chip. This is - * sub-optimal, because we cannot add a command which would conflict with - * an executing command to this start queue, and therefore must insert the - * next command for a given I/T/L combination after the first has completed; - * incurring our interrupt latency between SCSI commands. - * - * To allow furthur pipelining of the NCR and host CPU operation, we want - * to set things up so that immediately on termination of a command destined - * for a given LUN, we get that LUN busy again. - * - * To do this, we need to add a 32 bit pointer to which is jumped to - * on completion of a command. If no new command is available, this - * would point to the usual DSA issue queue select routine. - * - * If one were, it would point to a per-NCR53c7x0_cmd select routine - * which starts execution immediately, inserting the command at the head - * of the start queue if the NCR chip is selected or reselected. - * - * We would chanage so that we keep a list of outstanding commands - * for each unit, rather than a single running_list. We'd insert - * a new command into the right running list; if the NCR didn't - * have something running for that yet, we'd put it in the - * start queue as well. Some magic needs to happen to handle the - * race condition between the first command terminating before the - * new one is written. - * - * Potential for profiling : - * Call do_gettimeofday(struct timeval *tv) to get 800ns resolution. - */ - - -/* - * TODO : - * 1. To support WIDE transfers, not much needs to happen. We - * should do CHMOVE instructions instead of MOVEs when - * we have scatter/gather segments of uneven length. When - * we do this, we need to handle the case where we disconnect - * between segments. - * - * 2. Currently, when Icky things happen we do a FATAL(). Instead, - * we want to do an integrity check on the parts of the NCR hostdata - * structure which were initialized at boot time; FATAL() if that - * fails, and otherwise try to recover. Keep track of how many - * times this has happened within a single SCSI command; if it - * gets excessive, then FATAL(). - * - * 3. Parity checking is currently disabled, and a few things should - * happen here now that we support synchronous SCSI transfers : - * 1. On soft-reset, we shuld set the EPC (Enable Parity Checking) - * and AAP (Assert SATN/ on parity error) bits in SCNTL0. - * - * 2. We should enable the parity interrupt in the SIEN0 register. - * - * 3. intr_phase_mismatch() needs to believe that message out is - * allways an "acceptable" phase to have a mismatch in. If - * the old phase was MSG_IN, we should send a MESSAGE PARITY - * error. If the old phase was something else, we should send - * a INITIATOR_DETECTED_ERROR message. Note that this could - * cause a RESTORE POINTERS message; so we should handle that - * correctly first. Instead, we should probably do an - * initiator_abort. - * - * 4. MPEE bit of CTEST4 should be set so we get interrupted if - * we detect an error. - * - * - * 5. The initial code has been tested on the NCR53c810. I don't - * have access to NCR53c700, 700-66 (Forex boards), NCR53c710 - * (NCR Pentium systems), NCR53c720, NCR53c820, or NCR53c825 boards to - * finish development on those platforms. - * - * NCR53c820/825/720 - need to add wide transfer support, including WDTR - * negotiation, programming of wide transfer capabilities - * on reselection and table indirect selection. - * - * NCR53c710 - need to add fatal interrupt or GEN code for - * command completion signaling. Need to modify all - * SDID, SCID, etc. registers, and table indirect select code - * since these use bit fielded (ie 1<<target) instead of - * binary encoded target ids. Need to accomodate - * different register mappings, probably scan through - * the SCRIPT code and change the non SFBR register operand - * of all MOVE instructions. - * - * NCR53c700/700-66 - need to add code to refix addresses on - * every nexus change, eliminate all table indirect code, - * very messy. - * - * 6. The NCR53c7x0 series is very popular on other platforms that - * could be running Linux - ie, some high performance AMIGA SCSI - * boards use it. - * - * So, I should include #ifdef'd code so that it is - * compatible with these systems. - * - * Specifically, the little Endian assumptions I made in my - * bit fields need to change, and if the NCR doesn't see memory - * the right way, we need to provide options to reverse words - * when the scripts are relocated. - * - * 7. Use vremap() to access memory mapped boards. - */ - -/* - * Allow for simultaneous existence of multiple SCSI scripts so we - * can have a single driver binary for all of the family. - * - * - one for NCR53c700 and NCR53c700-66 chips (not yet supported) - * - one for rest (only the NCR53c810, 815, 820, and 825 are currently - * supported) - * - * So that we only need two SCSI scripts, we need to modify things so - * that we fixup register accesses in READ/WRITE instructions, and - * we'll also have to accomodate the bit vs. binary encoding of IDs - * with the 7xx chips. - */ - -/* - * Use pci_chips_ids to translate in both directions between PCI device ID - * and chip numbers. - */ - -static struct { - unsigned short pci_device_id; - int chip; -/* - * The revision field of the PCI_CLASS_REVISION register is compared - * against each of these fields if the field is not -1. If it - * is less than min_revision or larger than max_revision, a warning - * message is printed. - */ - int max_revision; - int min_revision; -} pci_chip_ids[] = { - {PCI_DEVICE_ID_NCR_53C810, 810, 2, 1}, - {PCI_DEVICE_ID_NCR_53C815, 815, 3, 2}, - {PCI_DEVICE_ID_NCR_53C820, 820, -1, -1}, - {PCI_DEVICE_ID_NCR_53C825, 825, -1, -1} -}; - -#define NPCI_CHIP_IDS (sizeof (pci_chip_ids) / sizeof(pci_chip_ids[0])) - -#define ROUNDUP(adr,type) \ - ((void *) (((long) (adr) + sizeof(type) - 1) & ~(sizeof(type) - 1))) - -/* - * Forced detection and autoprobe code for various hardware. Currently, - * entry points for these are not included in init/main.c because if the - * PCI BIOS code isn't working right, you're not going to be able to use - * the hardware anyways; this way we force users to solve their - * problems rather than forcing detection and blaming us when it - * does not work. - */ - -static struct override { - int chip; /* 700, 70066, 710, 720, 810, 820 */ - int board; /* Any special board level gunk */ - unsigned pci:1; - union { - struct { - int base; /* Memory address - indicates memory mapped regs */ - int io_port;/* I/O port address - indicates I/O mapped regs */ - int irq; /* IRQ line */ - int dma; /* DMA channel - often none */ - } normal; - struct { - int bus; - int device; - int function; - } pci; - } data; - long long options; -} overrides [4] = {{0,},}; -static int commandline_current = 0; -static int no_overrides = 0; - -#if 0 -#define OVERRIDE_LIMIT (sizeof(overrides) / sizeof(struct override)) -#else -#define OVERRIDE_LIMIT commandline_current -#endif - -/* - * Function: issue_to_cmd - * - * Purpose: convert jump instruction in issue array to NCR53c7x0_cmd - * structure pointer. - * - * Inputs; issue - pointer to start of NOP or JUMP instruction - * in issue array. - * - * Returns: pointer to command on success; 0 if opcode is NOP. - */ - -static inline struct NCR53c7x0_cmd * -issue_to_cmd (struct Scsi_Host *host, struct NCR53c7x0_hostdata *hostdata, - u32 *issue) -{ - return (issue[0] != hostdata->NOP_insn) ? - /* - * If the IF TRUE bit is set, it's a JUMP instruction. The - * operand is a bus pointer to the dsa_begin routine for this DSA. The - * dsa field of the NCR53c7x0_cmd structure starts with the - * DSA code template. By converting to a virtual address, - * subtracting the code template size, and offset of the - * dsa field, we end up with a pointer to the start of the - * structure (alternatively, we could use the - * dsa_cmnd field, an anachronism from when we weren't - * sure what the relationship between the NCR structures - * and host structures were going to be. - */ - (struct NCR53c7x0_cmd *) ((char *) bus_to_virt (issue[1]) - - (hostdata->E_dsa_code_begin - hostdata->E_dsa_code_template) - - offsetof(struct NCR53c7x0_cmd, dsa)) - /* If the IF TRUE bit is not set, it's a NOP */ - : NULL; -} - - -/* - * Function : static internal_setup(int board, int chip, char *str, int *ints) - * - * Purpose : LILO command line initialization of the overrides array, - * - * Inputs : board - currently, unsupported. chip - 700, 70066, 710, 720 - * 810, 815, 820, 825, although currently only the NCR53c810 is - * supported. - * - */ - -static void -internal_setup(int board, int chip, char *str, int *ints) { - unsigned char pci; /* Specifies a PCI override, with bus, device, - function */ - - pci = (str && !strcmp (str, "pci")) ? 1 : 0; - -/* - * Override syntaxes are as follows : - * ncr53c700,ncr53c700-66,ncr53c710,ncr53c720=mem,io,irq,dma - * ncr53c810,ncr53c820,ncr53c825=mem,io,irq or pci,bus,device,function - */ - - if (commandline_current < OVERRIDE_LIMIT) { - overrides[commandline_current].pci = pci ? 1 : 0; - if (!pci) { - overrides[commandline_current].data.normal.base = ints[1]; - overrides[commandline_current].data.normal.io_port = ints[2]; - overrides[commandline_current].data.normal.irq = ints[3]; - overrides[commandline_current].data.normal.dma = (ints[0] >= 4) ? - ints[4] : DMA_NONE; - /* FIXME: options is now a long long */ - overrides[commandline_current].options = (ints[0] >= 5) ? - ints[5] : 0; - } else { - overrides[commandline_current].data.pci.bus = ints[1]; - overrides[commandline_current].data.pci.device = ints[2]; - overrides[commandline_current].data.pci.function = ints[3]; - /* FIXME: options is now a long long */ - overrides[commandline_current].options = (ints[0] >= 4) ? - ints[4] : 0; - } - overrides[commandline_current].board = board; - overrides[commandline_current].chip = chip; - ++commandline_current; - ++no_overrides; - } else { - printk ("53c7,7x0.c:internal_setup() : too many overrides\n"); - } -} - -/* - * XXX - we might want to implement a single override function - * with a chip type field, revamp the command line configuration, - * etc. - */ - -#define setup_wrapper(x) \ -void ncr53c##x##_setup (char *str, int *ints) { \ - internal_setup (BOARD_GENERIC, x, str, ints); \ -} - -setup_wrapper(700) -setup_wrapper(70066) -setup_wrapper(710) -setup_wrapper(720) -setup_wrapper(810) -setup_wrapper(815) -setup_wrapper(820) -setup_wrapper(825) - -/* - * FIXME: we should junk these, in favor of synchronous_want and - * wide_want in the NCR53c7x0_hostdata structure. - */ - -/* Template for "preferred" synchronous transfer parameters. */ - -static const unsigned char sdtr_message[] = { - EXTENDED_MESSAGE, 3 /* length */, EXTENDED_SDTR, 50 /* *4ns */, 8 /* off */ -}; - -/* Template to request asynchronous transfers */ - -static const unsigned char async_message[] = { - EXTENDED_MESSAGE, 3 /* length */, EXTENDED_SDTR, 0, 0 /* asynchronous */ -}; - -/* Template for "preferred" WIDE transfer parameters */ - -static const unsigned char wdtr_message[] = { - EXTENDED_MESSAGE, 2 /* length */, EXTENDED_WDTR, 1 /* 2^1 bytes */ -}; - -/* - * Function : struct Scsi_Host *find_host (int host) - * - * Purpose : KGDB support function which translates a host number - * to a host structure. - * - * Inputs : host - number of SCSI host - * - * Returns : NULL on failure, pointer to host structure on success. - */ - -static struct Scsi_Host * -find_host (int host) { - struct Scsi_Host *h; - for (h = first_host; h && h->host_no != host; h = h->next); - if (!h) { - printk (KERN_ALERT "scsi%d not found\n", host); - return NULL; - } else if (h->hostt != the_template) { - printk (KERN_ALERT "scsi%d is not a NCR board\n", host); - return NULL; - } - return h; -} - -/* - * Function : request_synchronous (int host, int target) - * - * Purpose : KGDB interface which will allow us to negotiate for - * synchronous transfers. This ill be replaced with a more - * integrated function; perhaps a new entry in the scsi_host - * structure, accessable via an ioctl() or perhaps /proc/scsi. - * - * Inputs : host - number of SCSI host; target - number of target. - * - * Returns : 0 when negotiation has been setup for next SCSI command, - * -1 on failure. - */ - -static int -request_synchronous (int host, int target) { - struct Scsi_Host *h; - struct NCR53c7x0_hostdata *hostdata; - unsigned long flags; - if (target < 0) { - printk (KERN_ALERT "target %d is bogus\n", target); - return -1; - } - if (!(h = find_host (host))) - return -1; - else if (h->this_id == target) { - printk (KERN_ALERT "target %d is host ID\n", target); - return -1; - } -#ifndef LINUX_1_2 - else if (target > h->max_id) { - printk (KERN_ALERT "target %d exceeds maximum of %d\n", target, - h->max_id); - return -1; - } -#endif - hostdata = (struct NCR53c7x0_hostdata *)h->hostdata; - - save_flags(flags); - cli(); - if (hostdata->initiate_sdtr & (1 << target)) { - restore_flags(flags); - printk (KERN_ALERT "target %d allready doing SDTR\n", target); - return -1; - } - hostdata->initiate_sdtr |= (1 << target); - restore_flags(flags); - return 0; -} - -/* - * Function : request_disconnect (int host, int on_or_off) - * - * Purpose : KGDB support function, tells us to allow or disallow - * disconnections. - * - * Inputs : host - number of SCSI host; on_or_off - non-zero to allow, - * zero to disallow. - * - * Returns : 0 on success, * -1 on failure. - */ - -static int -request_disconnect (int host, int on_or_off) { - struct Scsi_Host *h; - struct NCR53c7x0_hostdata *hostdata; - if (!(h = find_host (host))) - return -1; - hostdata = (struct NCR53c7x0_hostdata *) h->hostdata; - if (on_or_off) - hostdata->options |= OPTION_DISCONNECT; - else - hostdata->options &= ~OPTION_DISCONNECT; - return 0; -} - -/* - * Function : static void NCR53c7x0_driver_init (struct Scsi_Host *host) - * - * Purpose : Initialize internal structures, as required on startup, or - * after a SCSI bus reset. - * - * Inputs : host - pointer to this host adapter's structure - */ - -static void -NCR53c7x0_driver_init (struct Scsi_Host *host) { - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - host->hostdata; - int i, j; - u32 *current; - for (i = 0; i < 16; ++i) { - hostdata->request_sense[i] = 0; - for (j = 0; j < 8; ++j) - hostdata->busy[i][j] = 0; - set_synchronous (host, i, /* sxfer */ 0, hostdata->saved_scntl3, 0); - } - hostdata->issue_queue = NULL; - hostdata->running_list = hostdata->finished_queue = - hostdata->current = NULL; - for (i = 0, current = (u32 *) hostdata->schedule; - i < host->can_queue; ++i, current += 2) { - current[0] = hostdata->NOP_insn; - current[1] = 0xdeadbeef; - } - current[0] = ((DCMD_TYPE_TCI|DCMD_TCI_OP_JUMP) << 24) | DBC_TCI_TRUE; - current[1] = (u32) virt_to_bus (hostdata->script) + - hostdata->E_wait_reselect; - hostdata->reconnect_dsa_head = 0; - hostdata->addr_reconnect_dsa_head = (u32) - virt_to_bus((void *) &(hostdata->reconnect_dsa_head)); - hostdata->expecting_iid = 0; - hostdata->expecting_sto = 0; - if (hostdata->options & OPTION_ALWAYS_SYNCHRONOUS) - hostdata->initiate_sdtr = 0xffff; - else - hostdata->initiate_sdtr = 0; - hostdata->talked_to = 0; - hostdata->idle = 1; -} - -/* - * Function : static int ccf_to_clock (int ccf) - * - * Purpose : Return the largest SCSI clock allowable for a given - * clock conversion factor, allowing us to do synchronous periods - * when we don't know what the SCSI clock is by taking at least - * as long as the device says we can. - * - * Inputs : ccf - * - * Returns : clock on success, -1 on failure. - */ - -static int -ccf_to_clock (int ccf) { - switch (ccf) { - case 1: return 25000000; /* Divide by 1.0 */ - case 2: return 37500000; /* Divide by 1.5 */ - case 3: return 50000000; /* Divide by 2.0 */ - case 0: /* Divide by 3.0 */ - case 4: return 66000000; - default: return -1; - } -} - -/* - * Function : static int clock_to_ccf (int clock) - * - * Purpose : Return the clock conversion factor for a given SCSI clock. - * - * Inputs : clock - SCSI clock expressed in Hz. - * - * Returns : ccf on success, -1 on failure. - */ - -static int -clock_to_ccf (int clock) { - if (clock < 16666666) - return -1; - if (clock < 25000000) - return 1; /* Divide by 1.0 */ - else if (clock < 37500000) - return 2; /* Divide by 1.5 */ - else if (clock < 50000000) - return 3; /* Divide by 2.0 */ - else if (clock < 66000000) - return 4; /* Divide by 3.0 */ - else - return -1; -} - -/* - * Function : static int NCR53c7x0_init (struct Scsi_Host *host) - * - * Purpose : initialize the internal structures for a given SCSI host - * - * Inputs : host - pointer to this host adapter's structure - * - * Preconditions : when this function is called, the chip_type - * field of the hostdata structure MUST have been set. - * - * Returns : 0 on success, -1 on failure. - */ - -static int -NCR53c7x0_init (struct Scsi_Host *host) { - NCR53c7x0_local_declare(); - int i, ccf, expected_ccf; - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - host->hostdata; - struct Scsi_Host *search; - /* - * There are some things which we need to know about in order to provide - * a semblance of support. Print 'em if they aren't what we expect, - * otherwise don't add to the noise. - * - * -1 means we don't know what to expect. - */ - int expected_id = -1; - int expected_clock = -1; - int uninitialized = 0; - /* - * FIXME : this is only on Intel boxes. On other platforms, this - * will differ. - */ - int expected_mapping = OPTION_IO_MAPPED; - NCR53c7x0_local_setup(host); - - switch (hostdata->chip) { - case 820: - case 825: -#ifdef notyet - host->max_id = 15; -#endif - /* Fall through */ - case 810: - case 815: - hostdata->dstat_sir_intr = NCR53c8x0_dstat_sir_intr; - hostdata->init_save_regs = NULL; - hostdata->dsa_fixup = NCR53c8xx_dsa_fixup; - hostdata->init_fixup = NCR53c8x0_init_fixup; - hostdata->soft_reset = NCR53c8x0_soft_reset; - hostdata->run_tests = NCR53c8xx_run_tests; -/* Is the SCSI clock ever anything else on these chips? */ - expected_clock = hostdata->scsi_clock = 40000000; - expected_id = 7; - break; - default: - printk ("scsi%d : chip type of %d is not supported yet, detaching.\n", - host->host_no, hostdata->chip); - scsi_unregister (host); - return -1; - } - - /* Assign constants accessed by NCR */ - hostdata->NCR53c7xx_zero = 0; - hostdata->NCR53c7xx_msg_reject = MESSAGE_REJECT; - hostdata->NCR53c7xx_msg_abort = ABORT; - hostdata->NCR53c7xx_msg_nop = NOP; - hostdata->NOP_insn = (DCMD_TYPE_TCI|DCMD_TCI_OP_JUMP) << 24; - - if (expected_mapping == -1 || - (hostdata->options & (OPTION_MEMORY_MAPPED)) != - (expected_mapping & OPTION_MEMORY_MAPPED)) - printk ("scsi%d : using %s mapped access\n", host->host_no, - (hostdata->options & OPTION_MEMORY_MAPPED) ? "memory" : - "io"); - - hostdata->dmode = (hostdata->chip == 700 || hostdata->chip == 70066) ? - DMODE_REG_00 : DMODE_REG_10; - hostdata->istat = ((hostdata->chip / 100) == 8) ? - ISTAT_REG_800 : ISTAT_REG_700; - -/* Only the ISTAT register is readable when the NCR is running, so make - sure it's halted. */ - ncr_halt(host); - -/* - * XXX - the NCR53c700 uses bitfielded registers for SCID, SDID, etc, - * as does the 710 with one bit per SCSI ID. Conversely, the NCR - * uses a normal, 3 bit binary representation of these values. - * - * Get the rest of the NCR documentation, and FIND OUT where the change - * was. - */ -#if 0 - tmp = hostdata->this_id_mask = NCR53c7x0_read8(SCID_REG); - for (host->this_id = 0; tmp != 1; tmp >>=1, ++host->this_id); -#else - host->this_id = NCR53c7x0_read8(SCID_REG) & 15; - if (host->this_id == 0) - host->this_id = 7; /* sanitize hostid---0 doesn't make sense */ - hostdata->this_id_mask = 1 << host->this_id; -#endif - -/* - * Note : we should never encounter a board setup for ID0. So, - * if we see ID0, assume that it was uninitialized and set it - * to the industry standard 7. - */ - if (!host->this_id) { - printk("scsi%d : initiator ID was %d, changing to 7\n", - host->host_no, host->this_id); - host->this_id = 7; - hostdata->this_id_mask = 1 << 7; - uninitialized = 1; - }; - - if (expected_id == -1 || host->this_id != expected_id) - printk("scsi%d : using initiator ID %d\n", host->host_no, - host->this_id); - - /* - * Save important registers to allow a soft reset. - */ - - if ((hostdata->chip / 100) == 8) { - /* - * CTEST4 controls burst mode disable. - */ - hostdata->saved_ctest4 = NCR53c7x0_read8(CTEST4_REG_800) & - CTEST4_800_SAVE; - } else { - /* - * CTEST7 controls cache snooping, burst mode, and support for - * external differential drivers. - */ - hostdata->saved_ctest7 = NCR53c7x0_read8(CTEST7_REG) & CTEST7_SAVE; - } - - /* - * On NCR53c700 series chips, DCNTL controls the SCSI clock divisor, - * on 800 series chips, it allows for a totem-pole IRQ driver. - */ - - hostdata->saved_dcntl = NCR53c7x0_read8(DCNTL_REG); - - /* - * DCNTL_800_IRQM controls weather we are using an open drain - * driver (reset) or totem pole driver (set). In all cases, - * it's level active. I suppose this is an issue when we're trying to - * wire-or the same PCI INTx line? - */ - if ((hostdata->chip / 100) == 8) - hostdata->saved_dcntl &= ~DCNTL_800_IRQM; - - /* - * DMODE controls DMA burst length, and on 700 series chips, - * 286 mode and bus width - */ - hostdata->saved_dmode = NCR53c7x0_read8(hostdata->dmode); - - /* - * Now that burst length and enabled/disabled status is known, - * clue the user in on it. - */ - - if ((hostdata->chip / 100) == 8) { - if (hostdata->saved_ctest4 & CTEST4_800_BDIS) { - printk ("scsi%d : burst mode disabled\n", host->host_no); - } else { - switch (hostdata->saved_dmode & DMODE_BL_MASK) { - case DMODE_BL_2: i = 2; break; - case DMODE_BL_4: i = 4; break; - case DMODE_BL_8: i = 8; break; - case DMODE_BL_16: i = 16; break; - default: i = 0; - } - printk ("scsi%d : burst length %d\n", host->host_no, i); - } - } - - /* - * On NCR53c810 and NCR53c820 chips, SCNTL3 contails the synchronous - * and normal clock conversion factors. - */ - if (hostdata->chip / 100 == 8) { - expected_ccf = clock_to_ccf (expected_clock); - hostdata->saved_scntl3 = NCR53c7x0_read8(SCNTL3_REG_800); - ccf = hostdata->saved_scntl3 & SCNTL3_800_CCF_MASK; - if (expected_ccf != -1 && ccf != expected_ccf && !ccf) { - hostdata->saved_scntl3 = (hostdata->saved_scntl3 & - ~SCNTL3_800_CCF_MASK) | expected_ccf; - if (!uninitialized) { - printk ("scsi%d : reset ccf to %d from %d\n", - host->host_no, expected_ccf, ccf); - uninitialized = 1; - } - } - } else - ccf = 0; - - /* - * If we don't have a SCSI clock programmed, pick one on the upper - * bound of that allowed by NCR so that our transfers err on the - * slow side, since transfer period must be >= the agreed - * upon period. - */ - - if ((!hostdata->scsi_clock) && (hostdata->scsi_clock = ccf_to_clock (ccf)) - == -1) { - printk ("scsi%d : clock conversion factor %d unknown.\n" - " synchronous transfers disabled\n", - host->host_no, ccf); - hostdata->options &= ~OPTION_SYNCHRONOUS; - hostdata->scsi_clock = 0; - } - - if (expected_clock == -1 || hostdata->scsi_clock != expected_clock) - printk ("scsi%d : using %dMHz SCSI clock\n", host->host_no, - hostdata->scsi_clock / 1000000); - - for (i = 0; i < 16; ++i) - hostdata->cmd_allocated[i] = 0; - - if (hostdata->init_save_regs) - hostdata->init_save_regs (host); - if (hostdata->init_fixup) - hostdata->init_fixup (host); - - if (!the_template) { - the_template = host->hostt; - first_host = host; - } - - /* - * Linux SCSI drivers have always been plagued with initialization - * problems - some didn't work with the BIOS disabled since they expected - * initialization from it, some didn't work when the networking code - * was enabled and registers got scrambled, etc. - * - * To avoid problems like this, in the future, we will do a soft - * reset on the SCSI chip, taking it back to a sane state. - */ - - hostdata->soft_reset (host); - -#if 1 - hostdata->debug_count_limit = -1; -#else - hostdata->debug_count_limit = 1; -#endif - hostdata->intrs = -1; - hostdata->resets = -1; - memcpy ((void *) hostdata->synchronous_want, (void *) sdtr_message, - sizeof (hostdata->synchronous_want)); - - NCR53c7x0_driver_init (host); - - /* - * Set up an interrupt handler if we aren't already sharing an IRQ - * with another board. - */ - - for (search = first_host; search && !(search->hostt == the_template && - search->irq == host->irq && search != host); search=search->next); - - if (!search) { - if (request_irq(host->irq, NCR53c7x0_intr, SA_INTERRUPT, "53c7,8xx")) { - printk("scsi%d : IRQ%d not free, detaching\n" - " You have either a configuration problem, or a\n" - " broken BIOS. You may wish to manually assign\n" - " an interrupt to the NCR board rather than using\n" - " an automatic setting.\n", - host->host_no, host->irq); - scsi_unregister (host); - return -1; - } - } else { - printk("scsi%d : using interrupt handler previously installed for scsi%d\n", - host->host_no, search->host_no); - } - - - if ((hostdata->run_tests && hostdata->run_tests(host) == -1) || - (hostdata->options & OPTION_DEBUG_TESTS_ONLY)) { - /* XXX Should disable interrupts, etc. here */ - scsi_unregister (host); - return -1; - } else { - if (host->io_port) { - host->n_io_port = 128; - request_region (host->io_port, host->n_io_port, "ncr53c7,8xx"); - } - } - - if (NCR53c7x0_read8 (SBCL_REG) & SBCL_BSY) { - printk ("scsi%d : bus wedge, doing SCSI reset\n", host->host_no); - hard_reset (host); - } - return 0; -} - -/* - * Function : static int normal_init(Scsi_Host_Template *tpnt, int board, - * int chip, u32 base, int io_port, int irq, int dma, int pcivalid, - * unsigned char pci_bus, unsigned char pci_device_fn, - * long long options); - * - * Purpose : initializes a NCR53c7,8x0 based on base addresses, - * IRQ, and DMA channel. - * - * Useful where a new NCR chip is backwards compatible with - * a supported chip, but the DEVICE ID has changed so it - * doesn't show up when the autoprobe does a pcibios_find_device. - * - * Inputs : tpnt - Template for this SCSI adapter, board - board level - * product, chip - 810, 820, or 825, bus - PCI bus, device_fn - - * device and function encoding as used by PCI BIOS calls. - * - * Returns : 0 on success, -1 on failure. - * - */ - -static int -normal_init (Scsi_Host_Template *tpnt, int board, int chip, - u32 base, int io_port, int irq, int dma, int pci_valid, - unsigned char pci_bus, unsigned char pci_device_fn, long long options) { - struct Scsi_Host *instance; - struct NCR53c7x0_hostdata *hostdata; - char chip_str[80]; - int script_len = 0, dsa_len = 0, size = 0, max_cmd_size = 0, - schedule_size = 0, ok = 0; - void *tmp; - - options |= perm_options; - - switch (chip) { - case 825: - case 820: - case 815: - case 810: - schedule_size = (tpnt->can_queue + 1) * 8 /* JUMP instruction size */; - script_len = NCR53c8xx_script_len; - dsa_len = NCR53c8xx_dsa_len; - options |= OPTION_INTFLY; - sprintf (chip_str, "NCR53c%d", chip); - break; - default: - printk("scsi-ncr53c7,8xx : unsupported SCSI chip %d\n", chip); - return -1; - } - - printk("scsi-ncr53c7,8xx : %s at memory 0x%x, io 0x%x, irq %d", - chip_str, (unsigned) base, io_port, irq); - if (dma == DMA_NONE) - printk("\n"); - else - printk(", dma %d\n", dma); - - if ((chip / 100 == 8) && !pci_valid) - printk ("scsi-ncr53c7,8xx : for better reliability and performance, please use the\n" - " PCI override instead.\n" - " Syntax : ncr53c8{10,15,20,25}=pci,<bus>,<device>,<function>\n" - " <bus> and <device> are usually 0.\n"); - - if (options & OPTION_DEBUG_PROBE_ONLY) { - printk ("scsi-ncr53c7,8xx : probe only enabled, aborting initialization\n"); - return -1; - } - - max_cmd_size = sizeof(struct NCR53c7x0_cmd) + dsa_len + - /* Size of dynamic part of command structure : */ - 2 * /* Worst case : we don't know if we need DATA IN or DATA out */ - ( 2 * /* Current instructions per scatter/gather segment */ - tpnt->sg_tablesize + - 3 /* Current startup / termination required per phase */ - ) * - 8 /* Each instruction is eight bytes */; - - /* Allocate fixed part of hostdata, dynamic part to hold appropriate - SCSI SCRIPT(tm) plus a single, maximum-sized NCR53c7x0_cmd structure. - - We need a NCR53c7x0_cmd structure for scan_scsis() when we are - not loaded as a module, and when we're loaded as a module, we - can't use a non-dynamically allocated structure because modules - are vmalloc()'d, which can allow structures to cross page - boundaries and breaks our physical/virtual address assumptions - for DMA. - - So, we stick it past the end of our hostdata structure. - - ASSUMPTION : - Regardless of how many simultaneous SCSI commands we allow, - the probe code only executes a _single_ instruction at a time, - so we only need one here, and don't need to allocate NCR53c7x0_cmd - structures for each target until we are no longer in scan_scsis - and kmalloc() has become functional (memory_init() happens - after all device driver initialization). - */ - - size = sizeof(struct NCR53c7x0_hostdata) + script_len + - /* Note that alignment will be guaranteed, since we put the command - allocated at probe time after the fixed-up SCSI script, which - consists of 32 bit words, aligned on a 32 bit boundary. But - on a 64bit machine we need 8 byte alignment for hostdata->free, so - we add in another 4 bytes to take care of potential misalignment - */ - (sizeof(void *) - sizeof(u32)) + max_cmd_size + schedule_size; - - instance = scsi_register (tpnt, size); - if (!instance) - return -1; - - /* FIXME : if we ever support an ISA NCR53c7xx based board, we - need to check if the chip is running in a 16 bit mode, and if so - unregister it if it is past the 16M (0x1000000) mark */ - - hostdata = (struct NCR53c7x0_hostdata *) - instance->hostdata; - hostdata->size = size; - hostdata->script_count = script_len / sizeof(u32); - hostdata = (struct NCR53c7x0_hostdata *) instance->hostdata; - hostdata->board = board; - hostdata->chip = chip; - if ((hostdata->pci_valid = pci_valid)) { - hostdata->pci_bus = pci_bus; - hostdata->pci_device_fn = pci_device_fn; - } - - /* - * Being memory mapped is more desirable, since - * - * - Memory accesses may be faster. - * - * - The destination and source address spaces are the same for - * all instructions, meaning we don't have to twiddle dmode or - * any other registers. - * - * So, we try for memory mapped, and if we don't get it, - * we go for port mapped, and that failing we tell the user - * it can't work. - */ - - if (base) { - instance->base = (unsigned char *) (unsigned long) base; - /* Check for forced I/O mapping */ - if (!(options & OPTION_IO_MAPPED)) { - options |= OPTION_MEMORY_MAPPED; - ok = 1; - } - } else { - options &= ~OPTION_MEMORY_MAPPED; - } - - if (io_port) { - instance->io_port = io_port; - options |= OPTION_IO_MAPPED; - ok = 1; - } else { - options &= ~OPTION_IO_MAPPED; - } - - if (!ok) { - printk ("scsi%d : not initializing, no I/O or memory mapping known \n", - instance->host_no); - scsi_unregister (instance); - return -1; - } - instance->irq = irq; - instance->dma_channel = dma; - - hostdata->options = options; - hostdata->dsa_len = dsa_len; - hostdata->max_cmd_size = max_cmd_size; - hostdata->num_cmds = 1; - /* Initialize single command */ - tmp = (hostdata->script + hostdata->script_count); - hostdata->free = ROUNDUP(tmp, void *); - hostdata->free->real = tmp; - hostdata->free->size = max_cmd_size; - hostdata->free->free = NULL; - hostdata->free->next = NULL; - hostdata->extra_allocate = 0; - - /* Allocate command start code space */ - hostdata->schedule = (chip == 700 || chip == 70066) ? - NULL : (u32 *) ((char *)hostdata->free + max_cmd_size); - -/* - * For diagnostic purposes, we don't really care how fast things blaze. - * For profiling, we want to access the 800ns resolution system clock, - * using a 'C' call on the host processor. - * - * Therefore, there's no need for the NCR chip to directly manipulate - * this data, and we should put it wherever is most convienient for - * Linux. - */ - if (track_events) - hostdata->events = (struct NCR53c7x0_event *) (track_events ? - vmalloc (sizeof (struct NCR53c7x0_event) * track_events) : NULL); - else - hostdata->events = NULL; - - if (hostdata->events) { - memset ((void *) hostdata->events, 0, sizeof(struct NCR53c7x0_event) * - track_events); - hostdata->event_size = track_events; - hostdata->event_index = 0; - } else - hostdata->event_size = 0; - - return NCR53c7x0_init(instance); -} - - -/* - * Function : static int ncr_pci_init(Scsi_Host_Template *tpnt, int board, - * int chip, int bus, int device_fn, long long options) - * - * Purpose : initializes a NCR53c800 family based on the PCI - * bus, device, and function location of it. Allows - * reprogramming of latency timer and determining addresses - * and whether bus mastering, etc. are OK. - * - * Useful where a new NCR chip is backwards compatible with - * a supported chip, but the DEVICE ID has changed so it - * doesn't show up when the autoprobe does a pcibios_find_device. - * - * Inputs : tpnt - Template for this SCSI adapter, board - board level - * product, chip - 810, 820, or 825, bus - PCI bus, device_fn - - * device and function encoding as used by PCI BIOS calls. - * - * Returns : 0 on success, -1 on failure. - * - */ - -static int -ncr_pci_init (Scsi_Host_Template *tpnt, int board, int chip, - unsigned char bus, unsigned char device_fn, long long options) { - unsigned short vendor_id, device_id, command; -#ifdef LINUX_1_2 - unsigned long -#else - unsigned int -#endif - base, io_port; - unsigned char irq, revision; - int error, expected_chip; - int expected_id = -1, max_revision = -1, min_revision = -1; - int i; - - printk("scsi-ncr53c7,8xx : at PCI bus %d, device %d, function %d\n", - bus, (int) (device_fn & 0xf8) >> 3, - (int) device_fn & 7); - - if (!pcibios_present()) { - printk("scsi-ncr53c7,8xx : not initializing due to lack of PCI BIOS,\n" - " try using memory, port, irq override instead.\n"); - return -1; - } - - if ((error = pcibios_read_config_word (bus, device_fn, PCI_VENDOR_ID, - &vendor_id)) || - (error = pcibios_read_config_word (bus, device_fn, PCI_DEVICE_ID, - &device_id)) || - (error = pcibios_read_config_word (bus, device_fn, PCI_COMMAND, - &command)) || - (error = pcibios_read_config_dword (bus, device_fn, - PCI_BASE_ADDRESS_0, &io_port)) || - (error = pcibios_read_config_dword (bus, device_fn, - PCI_BASE_ADDRESS_1, &base)) || - (error = pcibios_read_config_byte (bus, device_fn, PCI_CLASS_REVISION, - &revision)) || - (error = pcibios_read_config_byte (bus, device_fn, PCI_INTERRUPT_LINE, - &irq))) { - printk ("scsi-ncr53c7,8xx : error %s not initializing due to error reading configuration space\n" - " perhaps you specified an incorrect PCI bus, device, or function.\n" - , pcibios_strerror(error)); - return -1; - } - - /* If any one ever clones the NCR chips, this will have to change */ - - if (vendor_id != PCI_VENDOR_ID_NCR) { - printk ("scsi-ncr53c7,8xx : not initializing, 0x%04x is not NCR vendor ID\n", - (int) vendor_id); - return -1; - } - - - /* - * Bit 0 is the address space indicator and must be one for I/O - * space mappings, bit 1 is reserved, discard them after checking - * that they have the correct value of 1. - */ - - if (command & PCI_COMMAND_IO) { - if ((io_port & 3) != 1) { - printk ("scsi-ncr53c7,8xx : disabling I/O mapping since base address 0 (0x%x)\n" - " bits 0..1 indicate a non-IO mapping\n", - (unsigned) io_port); - io_port = 0; - } else - io_port &= PCI_BASE_ADDRESS_IO_MASK; - } else { - io_port = 0; - } - - if (command & PCI_COMMAND_MEMORY) { - if ((base & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_MEMORY) { - printk("scsi-ncr53c7,8xx : disabling memory mapping since base address 1\n" - " contains a non-memory mapping\n"); - base = 0; - } else - base &= PCI_BASE_ADDRESS_MEM_MASK; - } else { - base = 0; - } - - if (!io_port && !base) { - printk ("scsi-ncr53c7,8xx : not initializing, both I/O and memory mappings disabled\n"); - return -1; - } - - if (!(command & PCI_COMMAND_MASTER)) { - printk ("scsi-ncr53c7,8xx : not initializing, BUS MASTERING was disabled\n"); - return -1; - } - - for (i = 0; i < NPCI_CHIP_IDS; ++i) { - if (device_id == pci_chip_ids[i].pci_device_id) { - max_revision = pci_chip_ids[i].max_revision; - min_revision = pci_chip_ids[i].min_revision; - expected_chip = pci_chip_ids[i].chip; - } - if (chip == pci_chip_ids[i].chip) - expected_id = pci_chip_ids[i].pci_device_id; - } - - if (chip && device_id != expected_id) - printk ("scsi-ncr53c7,8xx : warning : device id of 0x%04x doesn't\n" - " match expected 0x%04x\n", - (unsigned int) device_id, (unsigned int) expected_id ); - - if (max_revision != -1 && revision > max_revision) - printk ("scsi-ncr53c7,8xx : warning : revision of %d is greater than %d.\n", - (int) revision, max_revision); - else if (min_revision != -1 && revision < min_revision) - printk ("scsi-ncr53c7,8xx : warning : revision of %d is less than %d.\n", - (int) revision, min_revision); - - if (io_port && check_region (io_port, 128)) { - printk ("scsi-ncr53c7,8xx : IO region 0x%x to 0x%x is in use\n", - (unsigned) io_port, (unsigned) io_port + 127); - return -1; - } - - return normal_init (tpnt, board, chip, (int) base, io_port, - (int) irq, DMA_NONE, 1, bus, device_fn, options); -} - - -/* - * Function : int NCR53c7xx_detect(Scsi_Host_Template *tpnt) - * - * Purpose : detects and initializes NCR53c7,8x0 SCSI chips - * that were autoprobed, overridden on the LILO command line, - * or specified at compile time. - * - * Inputs : tpnt - template for this SCSI adapter - * - * Returns : number of host adapters detected - * - */ - -int -NCR53c7xx_detect(Scsi_Host_Template *tpnt) { - int i; - int current_override; - int count; /* Number of boards detected */ - unsigned char pci_bus, pci_device_fn; - static short pci_index=0; /* Device index to PCI BIOS calls */ - -#ifndef LINUX_1_2 - tpnt->proc_dir = &proc_scsi_ncr53c7xx; -#endif - - for (current_override = count = 0; current_override < OVERRIDE_LIMIT; - ++current_override) { - if (overrides[current_override].pci ? - !ncr_pci_init (tpnt, overrides[current_override].board, - overrides[current_override].chip, - (unsigned char) overrides[current_override].data.pci.bus, - (((overrides[current_override].data.pci.device - << 3) & 0xf8)|(overrides[current_override].data.pci.function & - 7)), overrides[current_override].options): - !normal_init (tpnt, overrides[current_override].board, - overrides[current_override].chip, - overrides[current_override].data.normal.base, - overrides[current_override].data.normal.io_port, - overrides[current_override].data.normal.irq, - overrides[current_override].data.normal.dma, - 0 /* PCI data invalid */, 0 /* PCI bus place holder */, - 0 /* PCI device_function place holder */, - overrides[current_override].options)) { - ++count; - } - } - - if (pcibios_present()) { - for (i = 0; i < NPCI_CHIP_IDS; ++i) - for (pci_index = 0; - !pcibios_find_device (PCI_VENDOR_ID_NCR, - pci_chip_ids[i].pci_device_id, pci_index, &pci_bus, - &pci_device_fn); - ++pci_index) - if (!ncr_pci_init (tpnt, BOARD_GENERIC, pci_chip_ids[i].chip, - pci_bus, pci_device_fn, /* no options */ 0)) - ++count; - } - return count; -} - -/* NCR53c810 and NCR53c820 script handling code */ - -#include "53c8xx_d.h" -#ifdef A_int_debug_sync -#define DEBUG_SYNC_INTR A_int_debug_sync -#endif -static int NCR53c8xx_script_len = sizeof (SCRIPT); -static int NCR53c8xx_dsa_len = A_dsa_end + Ent_dsa_zero - Ent_dsa_code_template; - -/* - * Function : static void NCR53c8x0_init_fixup (struct Scsi_Host *host) - * - * Purpose : copy and fixup the SCSI SCRIPTS(tm) code for this device. - * - * Inputs : host - pointer to this host adapter's structure - * - */ - -static void -NCR53c8x0_init_fixup (struct Scsi_Host *host) { - NCR53c7x0_local_declare(); - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - host->hostdata; - unsigned char tmp; - int i, ncr_to_memory, memory_to_ncr; - u32 base; - NCR53c7x0_local_setup(host); - - - /* XXX - NOTE : this code MUST be made endian aware */ - /* Copy code into buffer that was allocated at detection time. */ - memcpy ((void *) hostdata->script, (void *) SCRIPT, - sizeof(SCRIPT)); - /* Fixup labels */ - for (i = 0; i < PATCHES; ++i) - hostdata->script[LABELPATCHES[i]] += - virt_to_bus(hostdata->script); - /* Fixup addresses of constants that used to be EXTERNAL */ - - patch_abs_32 (hostdata->script, 0, NCR53c7xx_msg_abort, - virt_to_bus(&(hostdata->NCR53c7xx_msg_abort))); - patch_abs_32 (hostdata->script, 0, NCR53c7xx_msg_reject, - virt_to_bus(&(hostdata->NCR53c7xx_msg_reject))); - patch_abs_32 (hostdata->script, 0, NCR53c7xx_zero, - virt_to_bus(&(hostdata->NCR53c7xx_zero))); - patch_abs_32 (hostdata->script, 0, NCR53c7xx_sink, - virt_to_bus(&(hostdata->NCR53c7xx_sink))); - patch_abs_32 (hostdata->script, 0, NOP_insn, - virt_to_bus(&(hostdata->NOP_insn))); - patch_abs_32 (hostdata->script, 0, schedule, - virt_to_bus((void *) hostdata->schedule)); - - /* Fixup references to external variables: */ - for (i = 0; i < EXTERNAL_PATCHES_LEN; ++i) - hostdata->script[EXTERNAL_PATCHES[i].offset] += - virt_to_bus(EXTERNAL_PATCHES[i].address); - - /* - * Fixup absolutes set at boot-time. - * - * All non-code absolute variables suffixed with "dsa_" and "int_" - * are constants, and need no fixup provided the assembler has done - * it for us (I don't know what the "real" NCR assembler does in - * this case, my assembler does the right magic). - */ - - patch_abs_rwri_data (hostdata->script, 0, dsa_save_data_pointer, - Ent_dsa_code_save_data_pointer - Ent_dsa_zero); - patch_abs_rwri_data (hostdata->script, 0, dsa_restore_pointers, - Ent_dsa_code_restore_pointers - Ent_dsa_zero); - patch_abs_rwri_data (hostdata->script, 0, dsa_check_reselect, - Ent_dsa_code_check_reselect - Ent_dsa_zero); - - /* - * Just for the hell of it, preserve the settings of - * Burst Length and Enable Read Line bits from the DMODE - * register. Make sure SCRIPTS start automagically. - */ - - tmp = NCR53c7x0_read8(DMODE_REG_10); - tmp &= (DMODE_800_ERL | DMODE_BL_MASK); - - if (!(hostdata->options & OPTION_MEMORY_MAPPED)) { - base = (u32) host->io_port; - memory_to_ncr = tmp|DMODE_800_DIOM; - ncr_to_memory = tmp|DMODE_800_SIOM; - } else { - base = virt_to_bus(host->base); - memory_to_ncr = ncr_to_memory = tmp; - } - - patch_abs_32 (hostdata->script, 0, addr_scratch, base + SCRATCHA_REG_800); - patch_abs_32 (hostdata->script, 0, addr_temp, base + TEMP_REG); - - /* - * I needed some variables in the script to be accessible to - * both the NCR chip and the host processor. For these variables, - * I made the arbitrary decision to store them directly in the - * hostdata structure rather than in the RELATIVE area of the - * SCRIPTS. - */ - - - patch_abs_rwri_data (hostdata->script, 0, dmode_memory_to_memory, tmp); - patch_abs_rwri_data (hostdata->script, 0, dmode_memory_to_ncr, memory_to_ncr); - patch_abs_rwri_data (hostdata->script, 0, dmode_ncr_to_memory, ncr_to_memory); - - patch_abs_32 (hostdata->script, 0, msg_buf, - virt_to_bus((void *)&(hostdata->msg_buf))); - patch_abs_32 (hostdata->script, 0, reconnect_dsa_head, - virt_to_bus((void *)&(hostdata->reconnect_dsa_head))); - patch_abs_32 (hostdata->script, 0, addr_reconnect_dsa_head, - virt_to_bus((void *)&(hostdata->addr_reconnect_dsa_head))); - patch_abs_32 (hostdata->script, 0, reselected_identify, - virt_to_bus((void *)&(hostdata->reselected_identify))); -/* reselected_tag is currently unused */ -#if 0 - patch_abs_32 (hostdata->script, 0, reselected_tag, - virt_to_bus((void *)&(hostdata->reselected_tag))); -#endif - - patch_abs_32 (hostdata->script, 0, test_dest, - virt_to_bus((void*)&hostdata->test_dest)); - patch_abs_32 (hostdata->script, 0, test_src, - virt_to_bus(&hostdata->test_source)); - - patch_abs_rwri_data (hostdata->script, 0, dsa_check_reselect, - (unsigned char)(Ent_dsa_code_check_reselect - Ent_dsa_zero)); - -/* These are for event logging; the ncr_event enum contains the - actual interrupt numbers. */ -#ifdef A_int_EVENT_SELECT - patch_abs_32 (hostdata->script, 0, int_EVENT_SELECT, (u32) EVENT_SELECT); -#endif -#ifdef A_int_EVENT_DISCONNECT - patch_abs_32 (hostdata->script, 0, int_EVENT_DISCONNECT, (u32) EVENT_DISCONNECT); -#endif -#ifdef A_int_EVENT_RESELECT - patch_abs_32 (hostdata->script, 0, int_EVENT_RESELECT, (u32) EVENT_RESELECT); -#endif -#ifdef A_int_EVENT_COMPLETE - patch_abs_32 (hostdata->script, 0, int_EVENT_COMPLETE, (u32) EVENT_COMPLETE); -#endif -#ifdef A_int_EVENT_IDLE - patch_abs_32 (hostdata->script, 0, int_EVENT_IDLE, (u32) EVENT_IDLE); -#endif -#ifdef A_int_EVENT_SELECT_FAILED - patch_abs_32 (hostdata->script, 0, int_EVENT_SELECT_FAILED, - (u32) EVENT_SELECT_FAILED); -#endif -#ifdef A_int_EVENT_BEFORE_SELECT - patch_abs_32 (hostdata->script, 0, int_EVENT_BEFORE_SELECT, - (u32) EVENT_BEFORE_SELECT); -#endif -#ifdef A_int_EVENT_RESELECT_FAILED - patch_abs_32 (hostdata->script, 0, int_EVENT_RESELECT_FAILED, - (u32) EVENT_RESELECT_FAILED); -#endif - - /* - * Make sure the NCR and Linux code agree on the location of - * certain fields. - */ - - hostdata->E_accept_message = Ent_accept_message; - hostdata->E_command_complete = Ent_command_complete; - hostdata->E_cmdout_cmdout = Ent_cmdout_cmdout; - hostdata->E_data_transfer = Ent_data_transfer; - hostdata->E_debug_break = Ent_debug_break; - hostdata->E_dsa_code_template = Ent_dsa_code_template; - hostdata->E_dsa_code_template_end = Ent_dsa_code_template_end; - hostdata->E_end_data_transfer = Ent_end_data_transfer; - hostdata->E_initiator_abort = Ent_initiator_abort; - hostdata->E_msg_in = Ent_msg_in; - hostdata->E_other_transfer = Ent_other_transfer; - hostdata->E_other_in = Ent_other_in; - hostdata->E_other_out = Ent_other_out; - hostdata->E_reject_message = Ent_reject_message; - hostdata->E_respond_message = Ent_respond_message; - hostdata->E_select = Ent_select; - hostdata->E_select_msgout = Ent_select_msgout; - hostdata->E_target_abort = Ent_target_abort; -#ifdef Ent_test_0 - hostdata->E_test_0 = Ent_test_0; -#endif - hostdata->E_test_1 = Ent_test_1; - hostdata->E_test_2 = Ent_test_2; -#ifdef Ent_test_3 - hostdata->E_test_3 = Ent_test_3; -#endif - hostdata->E_wait_reselect = Ent_wait_reselect; - hostdata->E_dsa_code_begin = Ent_dsa_code_begin; - - hostdata->dsa_cmdout = A_dsa_cmdout; - hostdata->dsa_cmnd = A_dsa_cmnd; - hostdata->dsa_datain = A_dsa_datain; - hostdata->dsa_dataout = A_dsa_dataout; - hostdata->dsa_end = A_dsa_end; - hostdata->dsa_msgin = A_dsa_msgin; - hostdata->dsa_msgout = A_dsa_msgout; - hostdata->dsa_msgout_other = A_dsa_msgout_other; - hostdata->dsa_next = A_dsa_next; - hostdata->dsa_select = A_dsa_select; - hostdata->dsa_start = Ent_dsa_code_template - Ent_dsa_zero; - hostdata->dsa_status = A_dsa_status; - hostdata->dsa_jump_dest = Ent_dsa_code_fix_jump - Ent_dsa_zero + - 8 /* destination operand */; - - /* sanity check */ - if (A_dsa_fields_start != Ent_dsa_code_template_end - - Ent_dsa_zero) - printk("scsi%d : NCR dsa_fields start is %d not %d\n", - host->host_no, A_dsa_fields_start, Ent_dsa_code_template_end - - Ent_dsa_zero); - - printk("scsi%d : NCR code relocated to 0x%lx (virt 0x%p)\n", host->host_no, - virt_to_bus(hostdata->script), hostdata->script); -} - -/* - * Function : static int NCR53c8xx_run_tests (struct Scsi_Host *host) - * - * Purpose : run various verification tests on the NCR chip, - * including interrupt generation, and proper bus mastering - * operation. - * - * Inputs : host - a properly initialized Scsi_Host structure - * - * Preconditions : the NCR chip must be in a halted state. - * - * Returns : 0 if all tests were successful, -1 on error. - * - */ - -static int -NCR53c8xx_run_tests (struct Scsi_Host *host) { - NCR53c7x0_local_declare(); - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - host->hostdata; - unsigned long timeout; - u32 start; - int failed, i; - unsigned long flags; - NCR53c7x0_local_setup(host); - - /* The NCR chip _must_ be idle to run the test scripts */ - - save_flags(flags); - cli(); - if (!hostdata->idle) { - printk ("scsi%d : chip not idle, aborting tests\n", host->host_no); - restore_flags(flags); - return -1; - } - - /* - * Check for functional interrupts, this could work as an - * autoprobe routine. - */ - - if ((hostdata->options & OPTION_DEBUG_TEST1) && - hostdata->state != STATE_DISABLED) { - hostdata->idle = 0; - hostdata->test_running = 1; - hostdata->test_completed = -1; - hostdata->test_dest = 0; - hostdata->test_source = 0xdeadbeef; - start = virt_to_bus (hostdata->script) + hostdata->E_test_1; - hostdata->state = STATE_RUNNING; - printk ("scsi%d : test 1", host->host_no); - NCR53c7x0_write32 (DSP_REG, start); - printk (" started\n"); - sti(); - - /* - * This is currently a .5 second timeout, since (in theory) no slow - * board will take that long. In practice, we've seen one - * pentium which ocassionally fails with this, but works with - * 10 times as much? - */ - - timeout = jiffies + 5 * HZ / 10; - while ((hostdata->test_completed == -1) && jiffies < timeout) - barrier(); - - failed = 1; - if (hostdata->test_completed == -1) - printk ("scsi%d : driver test 1 timed out%s\n",host->host_no , - (hostdata->test_dest == 0xdeadbeef) ? - " due to lost interrupt.\n" - " Please verify that the correct IRQ is being used for your board,\n" - " and that the motherboard IRQ jumpering matches the PCI setup on\n" - " PCI systems.\n" - " If you are using a NCR53c810 board in a PCI system, you should\n" - " also verify that the board is jumpered to use PCI INTA, since\n" - " most PCI motherboards lack support for INTB, INTC, and INTD.\n" - : ""); - else if (hostdata->test_completed != 1) - printk ("scsi%d : test 1 bad interrupt value (%d)\n", - host->host_no, hostdata->test_completed); - else - failed = (hostdata->test_dest != 0xdeadbeef); - - if (hostdata->test_dest != 0xdeadbeef) { - printk ("scsi%d : driver test 1 read 0x%x instead of 0xdeadbeef indicating a\n" - " probable cache invalidation problem. Please configure caching\n" - " as write-through or disabled\n", - host->host_no, hostdata->test_dest); - } - - if (failed) { - printk ("scsi%d : DSP = 0x%p (script at 0x%p, start at 0x%x)\n", - host->host_no, bus_to_virt(NCR53c7x0_read32(DSP_REG)), - hostdata->script, start); - printk ("scsi%d : DSPS = 0x%x\n", host->host_no, - NCR53c7x0_read32(DSPS_REG)); - restore_flags(flags); - return -1; - } - hostdata->test_running = 0; - } - - if ((hostdata->options & OPTION_DEBUG_TEST2) && - hostdata->state != STATE_DISABLED) { - u32 dsa[48]; - unsigned char identify = IDENTIFY(0, 0); - unsigned char cmd[6]; - unsigned char data[36]; - unsigned char status = 0xff; - unsigned char msg = 0xff; - - cmd[0] = INQUIRY; - cmd[1] = cmd[2] = cmd[3] = cmd[5] = 0; - cmd[4] = sizeof(data); - - dsa[2] = 1; - dsa[3] = virt_to_bus(&identify); - dsa[4] = 6; - dsa[5] = virt_to_bus(&cmd); - dsa[6] = sizeof(data); - dsa[7] = virt_to_bus(&data); - dsa[8] = 1; - dsa[9] = virt_to_bus(&status); - dsa[10] = 1; - dsa[11] = virt_to_bus(&msg); - - for (i = 0; i < 3; ++i) { - cli(); - if (!hostdata->idle) { - printk ("scsi%d : chip not idle, aborting tests\n", host->host_no); - restore_flags(flags); - return -1; - } - - /* SCNTL3 SDID */ - dsa[0] = (0x33 << 24) | (i << 16) ; - hostdata->idle = 0; - hostdata->test_running = 2; - hostdata->test_completed = -1; - start = virt_to_bus(hostdata->script) + hostdata->E_test_2; - hostdata->state = STATE_RUNNING; - NCR53c7x0_write32 (DSA_REG, virt_to_bus(dsa)); - NCR53c7x0_write32 (DSP_REG, start); - sti(); - - timeout = jiffies + 5 * HZ; /* arbitrary */ - while ((hostdata->test_completed == -1) && jiffies < timeout) - barrier(); - NCR53c7x0_write32 (DSA_REG, 0); - - if (hostdata->test_completed == 2) { - data[35] = 0; - printk ("scsi%d : test 2 INQUIRY to target %d, lun 0 : %s\n", - host->host_no, i, data + 8); - printk ("scsi%d : status ", host->host_no); - print_status (status); - printk ("\nscsi%d : message ", host->host_no); - print_msg (&msg); - printk ("\n"); - } else if (hostdata->test_completed == 3) { - printk("scsi%d : test 2 no connection with target %d\n", - host->host_no, i); - if (!hostdata->idle) { - printk("scsi%d : not idle\n", host->host_no); - restore_flags(flags); - return -1; - } - } else if (hostdata->test_completed == -1) { - printk ("scsi%d : test 2 timed out\n", host->host_no); - restore_flags(flags); - return -1; - } - hostdata->test_running = 0; - } - } - - restore_flags(flags); - return 0; -} - -/* - * Function : static void NCR53c8xx_dsa_fixup (struct NCR53c7x0_cmd *cmd) - * - * Purpose : copy the NCR53c8xx dsa structure into cmd's dsa buffer, - * performing all necessary relocation. - * - * Inputs : cmd, a NCR53c7x0_cmd structure with a dsa area large - * enough to hold the NCR53c8xx dsa. - */ - -static void -NCR53c8xx_dsa_fixup (struct NCR53c7x0_cmd *cmd) { - Scsi_Cmnd *c = cmd->cmd; - struct Scsi_Host *host = c->host; - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - host->hostdata; - int i; - - memcpy (cmd->dsa, hostdata->script + (hostdata->E_dsa_code_template / 4), - hostdata->E_dsa_code_template_end - hostdata->E_dsa_code_template); - - /* - * Note : within the NCR 'C' code, dsa points to the _start_ - * of the DSA structure, and _not_ the offset of dsa_zero within - * that structure used to facilitate shorter signed offsets - * for the 8 bit ALU. - * - * The implications of this are that - * - * - 32 bit A_dsa_* absolute values require an additional - * dsa_zero added to their value to be correct, since they are - * relative to dsa_zero which is in essentially a separate - * space from the code symbols. - * - * - All other symbols require no special treatment. - */ - - patch_abs_tci_data (cmd->dsa, Ent_dsa_code_template / sizeof(u32), - dsa_temp_lun, c->lun); - patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32), - dsa_temp_addr_next, virt_to_bus(&cmd->dsa_next_addr)); - patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32), - dsa_temp_next, virt_to_bus(cmd->dsa) + Ent_dsa_zero - - Ent_dsa_code_template + A_dsa_next); - patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32), - dsa_temp_sync, virt_to_bus((void *)hostdata->sync[c->target].script)); - patch_abs_tci_data (cmd->dsa, Ent_dsa_code_template / sizeof(u32), - dsa_temp_target, c->target); - /* XXX - new pointer stuff */ - patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32), - dsa_temp_addr_saved_pointer, virt_to_bus(&cmd->saved_data_pointer)); - patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32), - dsa_temp_addr_saved_residual, virt_to_bus(&cmd->saved_residual)); - patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32), - dsa_temp_addr_residual, virt_to_bus(&cmd->residual)); - - /* XXX - new start stuff */ - patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32), - dsa_temp_addr_dsa_value, virt_to_bus(&cmd->dsa_addr)); - -} - -/* - * Function : run_process_issue_queue (void) - * - * Purpose : insure that the coroutine is running and will process our - * request. process_issue_queue_running is checked/set here (in an - * inline function) rather than in process_issue_queue itself to reduce - * the chances of stack overflow. - * - */ - -static volatile int process_issue_queue_running = 0; - -static __inline__ void -run_process_issue_queue(void) { - unsigned long flags; - save_flags (flags); - cli(); - if (!process_issue_queue_running) { - process_issue_queue_running = 1; - process_issue_queue(flags); - /* - * process_issue_queue_running is cleared in process_issue_queue - * once it can't do more work, and process_issue_queue exits with - * interrupts disabled. - */ - } - restore_flags (flags); -} - -/* - * Function : static void abnormal_finished (struct NCR53c7x0_cmd *cmd, int - * result) - * - * Purpose : mark SCSI command as finished, OR'ing the host portion - * of the result word into the result field of the corresponding - * Scsi_Cmnd structure, and removing it from the internal queues. - * - * Inputs : cmd - command, result - entire result field - * - * Preconditions : the NCR chip should be in a halted state when - * abnormal_finished is run, since it modifies structures which - * the NCR expects to have exclusive access to. - */ - -static void -abnormal_finished (struct NCR53c7x0_cmd *cmd, int result) { - Scsi_Cmnd *c = cmd->cmd; - struct Scsi_Host *host = c->host; - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - host->hostdata; - unsigned long flags; - int left, found; - volatile struct NCR53c7x0_cmd * linux_search; - volatile struct NCR53c7x0_cmd * volatile *linux_prev; - volatile u32 *ncr_prev, *current, ncr_search; - -#if 0 - printk ("scsi%d: abnormal finished\n", host->host_no); -#endif - - save_flags(flags); - cli(); - found = 0; - /* - * Traverse the NCR issue array until we find a match or run out - * of instructions. Instructions in the NCR issue array are - * either JUMP or NOP instructions, which are 2 words in length. - */ - - - for (found = 0, left = host->can_queue, current = hostdata->schedule; - left > 0; --left, current += 2) - { - if (issue_to_cmd (host, hostdata, (u32 *) current) == cmd) - { - current[0] = hostdata->NOP_insn; - current[1] = 0xdeadbeef; - ++found; - break; - } - } - - /* - * Traverse the NCR reconnect list of DSA structures until we find - * a pointer to this dsa or have found too many command structures. - * We let prev point at the next field of the previous element or - * head of the list, so we don't do anything different for removing - * the head element. - */ - - for (left = host->can_queue, - ncr_search = hostdata->reconnect_dsa_head, - ncr_prev = &hostdata->reconnect_dsa_head; - left >= 0 && ncr_search && - ((char*)bus_to_virt(ncr_search) + hostdata->dsa_start) - != (char *) cmd->dsa; - ncr_prev = (u32*) ((char*)bus_to_virt(ncr_search) + - hostdata->dsa_next), ncr_search = *ncr_prev, --left); - - if (left < 0) - printk("scsi%d: loop detected in ncr reonncect list\n", - host->host_no); - else if (ncr_search) - if (found) - printk("scsi%d: scsi %ld in ncr issue array and reconnect lists\n", - host->host_no, c->pid); - else { - volatile u32 * next = (u32 *) - ((char *)bus_to_virt(ncr_search) + hostdata->dsa_next); - *ncr_prev = *next; -/* If we're at the tail end of the issue queue, update that pointer too. */ - found = 1; - } - - /* - * Traverse the host running list until we find this command or discover - * we have too many elements, pointing linux_prev at the next field of the - * linux_previous element or head of the list, search at this element. - */ - - for (left = host->can_queue, linux_search = hostdata->running_list, - linux_prev = &hostdata->running_list; - left >= 0 && linux_search && linux_search != cmd; - linux_prev = &(linux_search->next), - linux_search = linux_search->next, --left); - - if (left < 0) - printk ("scsi%d: loop detected in host running list for scsi pid %ld\n", - host->host_no, c->pid); - else if (linux_search) { - *linux_prev = linux_search->next; - --hostdata->busy[c->target][c->lun]; - } - - /* Return the NCR command structure to the free list */ - cmd->next = hostdata->free; - hostdata->free = cmd; - c->host_scribble = NULL; - - /* And return */ - c->result = result; - c->scsi_done(c); - - restore_flags(flags); - run_process_issue_queue(); -} - -/* - * Function : static void intr_break (struct Scsi_Host *host, - * struct NCR53c7x0_cmd *cmd) - * - * Purpose : Handler for breakpoint interrupts from a SCSI script - * - * Inputs : host - pointer to this host adapter's structure, - * cmd - pointer to the command (if any) dsa was pointing - * to. - * - */ - -static void -intr_break (struct Scsi_Host *host, struct - NCR53c7x0_cmd *cmd) { - NCR53c7x0_local_declare(); - struct NCR53c7x0_break *bp; -#if 0 - Scsi_Cmnd *c = cmd ? cmd->cmd : NULL; -#endif - u32 *dsp; - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - host->hostdata; - unsigned long flags; - NCR53c7x0_local_setup(host); - - /* - * Find the break point corresponding to this address, and - * dump the appropriate debugging information to standard - * output. - */ - save_flags(flags); - cli(); - dsp = (u32 *) bus_to_virt(NCR53c7x0_read32(DSP_REG)); - for (bp = hostdata->breakpoints; bp && bp->address != dsp; - bp = bp->next); - if (!bp) - panic("scsi%d : break point interrupt from %p with no breakpoint!", - host->host_no, dsp); - - /* - * Configure the NCR chip for manual start mode, so that we can - * point the DSP register at the instruction that follows the - * INT int_debug_break instruction. - */ - - NCR53c7x0_write8 (hostdata->dmode, - NCR53c7x0_read8(hostdata->dmode)|DMODE_MAN); - - /* - * And update the DSP register, using the size of the old - * instruction in bytes. - */ - - restore_flags(flags); -} -/* - * Function : static void print_synchronous (const char *prefix, - * const unsigned char *msg) - * - * Purpose : print a pretty, user and machine parsable representation - * of a SDTR message, including the "real" parameters, data - * clock so we can tell transfer rate at a glance. - * - * Inputs ; prefix - text to prepend, msg - SDTR message (5 bytes) - */ - -static void -print_synchronous (const char *prefix, const unsigned char *msg) { - if (msg[4]) { - int Hz = 1000000000 / (msg[3] * 4); - int integer = Hz / 1000000; - int fraction = (Hz - (integer * 1000000)) / 10000; - printk ("%speriod %dns offset %d %d.%02dMHz %s SCSI%s\n", - prefix, (int) msg[3] * 4, (int) msg[4], integer, fraction, - (((msg[3] * 4) < 200) ? "FAST" : "synchronous"), - (((msg[3] * 4) < 200) ? "-II" : "")); - } else - printk ("%sasynchronous SCSI\n", prefix); -} - -/* - * Function : static void set_synchronous (struct Scsi_Host *host, - * int target, int sxfer, int scntl3, int now_connected) - * - * Purpose : reprogram transfers between the selected SCSI initiator and - * target with the given register values; in the indirect - * select operand, reselection script, and chip registers. - * - * Inputs : host - NCR53c7,8xx SCSI host, target - number SCSI target id, - * sxfer and scntl3 - NCR registers. now_connected - if non-zero, - * we should reprogram the registers now too. - */ - -static void -set_synchronous (struct Scsi_Host *host, int target, int sxfer, int scntl3, - int now_connected) { - NCR53c7x0_local_declare(); - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - host->hostdata; - u32 *script; - NCR53c7x0_local_setup(host); - - /* These are eight bit registers */ - sxfer &= 0xff; - scntl3 &= 0xff; - - hostdata->sync[target].sxfer_sanity = sxfer; - hostdata->sync[target].scntl3_sanity = scntl3; - -/* - * HARD CODED : synchronous script is EIGHT words long. This - * must agree with 53c7.8xx.h - */ - - if ((hostdata->chip != 700) && (hostdata->chip != 70066)) { - hostdata->sync[target].select_indirect = (scntl3 << 24) | - (target << 16) | (sxfer << 8); - - script = (u32 *) hostdata->sync[target].script; - - /* XXX - add NCR53c7x0 code to reprogram SCF bits if we want to */ - if ((hostdata->chip / 100) == 8) { - script[0] = ((DCMD_TYPE_RWRI | DCMD_RWRI_OPC_MODIFY | - DCMD_RWRI_OP_MOVE) << 24) | - (SCNTL3_REG_800 << 16) | (scntl3 << 8); - script[1] = 0; - script += 2; - } - - script[0] = ((DCMD_TYPE_RWRI | DCMD_RWRI_OPC_MODIFY | - DCMD_RWRI_OP_MOVE) << 24) | - (SXFER_REG << 16) | (sxfer << 8); - script[1] = 0; - script += 2; - -#ifdef DEBUG_SYNC_INTR - if (hostdata->options & OPTION_DEBUG_DISCONNECT) { - script[0] = ((DCMD_TYPE_TCI|DCMD_TCI_OP_INT) << 24) | DBC_TCI_TRUE; - script[1] = DEBUG_SYNC_INTR; - script += 2; - } -#endif - - script[0] = ((DCMD_TYPE_TCI|DCMD_TCI_OP_RETURN) << 24) | DBC_TCI_TRUE; - script[1] = 0; - script += 2; - } - - if (hostdata->options & OPTION_DEBUG_SYNCHRONOUS) - printk ("scsi%d : target %d sync parameters are sxfer=0x%x, scntl3=0x%x\n", - host->host_no, target, sxfer, scntl3); - - if (now_connected) { - if ((hostdata->chip / 100) == 8) - NCR53c7x0_write8(SCNTL3_REG_800, scntl3); - NCR53c7x0_write8(SXFER_REG, sxfer); - } -} - - -/* - * Function : static int asynchronous (struct Scsi_Host *host, int target) - * - * Purpose : reprogram between the selected SCSI Host adapter and target - * (assumed to be currently connected) for asynchronous transfers. - * - * Inputs : host - SCSI host structure, target - numeric target ID. - * - * Preconditions : the NCR chip should be in one of the halted states - */ - -static void -asynchronous (struct Scsi_Host *host, int target) { - NCR53c7x0_local_declare(); - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - host->hostdata; - NCR53c7x0_local_setup(host); - set_synchronous (host, target, /* no offset */ 0, hostdata->saved_scntl3, - 1); - printk ("scsi%d : setting target %d to asynchronous SCSI\n", - host->host_no, target); -} - -/* - * XXX - do we want to go out of our way (ie, add extra code to selection - * in the NCR53c710/NCR53c720 script) to reprogram the synchronous - * conversion bits, or can we be content in just setting the - * sxfer bits? - */ - -/* Table for NCR53c8xx synchronous values */ -static const struct { - int div; /* Total clock divisor * 10 */ - unsigned char scf; /* */ - unsigned char tp; /* 4 + tp = xferp divisor */ -} syncs[] = { -/* div scf tp div scf tp div scf tp */ - { 40, 1, 0}, { 50, 1, 1}, { 60, 1, 2}, - { 70, 1, 3}, { 75, 2, 1}, { 80, 1, 4}, - { 90, 1, 5}, { 100, 1, 6}, { 105, 2, 3}, - { 110, 1, 7}, { 120, 2, 4}, { 135, 2, 5}, - { 140, 3, 3}, { 150, 2, 6}, { 160, 3, 4}, - { 165, 2, 7}, { 180, 3, 5}, { 200, 3, 6}, - { 210, 4, 3}, { 220, 3, 7}, { 240, 4, 4}, - { 270, 4, 5}, { 300, 4, 6}, { 330, 4, 7} -}; - -/* - * Function : static void synchronous (struct Scsi_Host *host, int target, - * char *msg) - * - * Purpose : reprogram transfers between the selected SCSI initiator and - * target for synchronous SCSI transfers such that the synchronous - * offset is less than that requested and period at least as long - * as that requested. Also modify *msg such that it contains - * an appropriate response. - * - * Inputs : host - NCR53c7,8xx SCSI host, target - number SCSI target id, - * msg - synchronous transfer request. - */ - - -static void -synchronous (struct Scsi_Host *host, int target, char *msg) { - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - host->hostdata; - int desire, divisor, i, limit; - unsigned char scntl3, sxfer; -/* The diagnostic message fits on one line, even with max. width integers */ - char buf[80]; - -/* Desired transfer clock in Hz */ - desire = 1000000000L / (msg[3] * 4); -/* Scale the available SCSI clock by 10 so we get tenths */ - divisor = (hostdata->scsi_clock * 10) / desire; - -/* NCR chips can handle at most an offset of 8 */ - if (msg[4] > 8) - msg[4] = 8; - - if (hostdata->options & OPTION_DEBUG_SDTR) - printk("scsi%d : optimal synchronous divisor of %d.%01d\n", - host->host_no, divisor / 10, divisor % 10); - - limit = (sizeof(syncs) / sizeof(syncs[0]) -1); - for (i = 0; (i < limit) && (divisor > syncs[i].div); ++i); - - if (hostdata->options & OPTION_DEBUG_SDTR) - printk("scsi%d : selected synchronous divisor of %d.%01d\n", - host->host_no, syncs[i].div / 10, syncs[i].div % 10); - - msg[3] = ((1000000000L / hostdata->scsi_clock) * syncs[i].div / 10 / 4); - - if (hostdata->options & OPTION_DEBUG_SDTR) - printk("scsi%d : selected synchronous period of %dns\n", host->host_no, - msg[3] * 4); - - scntl3 = (hostdata->chip / 100 == 8) ? ((hostdata->saved_scntl3 & - ~SCNTL3_800_SCF_MASK) | (syncs[i].scf << SCNTL3_800_SCF_SHIFT)) : 0; - sxfer = (msg[4] << SXFER_MO_SHIFT) | ((syncs[i].tp) << SXFER_TP_SHIFT); - if (hostdata->options & OPTION_DEBUG_SDTR) - printk ("scsi%d : sxfer=0x%x scntl3=0x%x\n", - host->host_no, (int) sxfer, (int) scntl3); - set_synchronous (host, target, sxfer, scntl3, 1); - sprintf (buf, "scsi%d : setting target %d to ", host->host_no, target); - print_synchronous (buf, msg); -} - -/* - * Function : static int NCR53c8x0_dstat_sir_intr (struct Scsi_Host *host, - * struct NCR53c7x0_cmd *cmd) - * - * Purpose : Handler for INT generated instructions for the - * NCR53c810/820 SCSI SCRIPT - * - * Inputs : host - pointer to this host adapter's structure, - * cmd - pointer to the command (if any) dsa was pointing - * to. - * - */ - -static int -NCR53c8x0_dstat_sir_intr (struct Scsi_Host *host, struct - NCR53c7x0_cmd *cmd) { - NCR53c7x0_local_declare(); - int print; - Scsi_Cmnd *c = cmd ? cmd->cmd : NULL; - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - host->hostdata; - u32 dsps,*dsp; /* Argument of the INT instruction */ - NCR53c7x0_local_setup(host); - dsps = NCR53c7x0_read32(DSPS_REG); - dsp = (u32 *) bus_to_virt(NCR53c7x0_read32(DSP_REG)); - - if (hostdata->options & OPTION_DEBUG_INTR) - printk ("scsi%d : DSPS = 0x%x\n", host->host_no, dsps); - - switch (dsps) { - case A_int_msg_1: - print = 1; - switch (hostdata->msg_buf[0]) { - /* - * Unless we've initiated synchronous negotiation, I don't - * think that this should happen. - */ - case MESSAGE_REJECT: - hostdata->dsp = hostdata->script + hostdata->E_accept_message / - sizeof(u32); - hostdata->dsp_changed = 1; - if (cmd && (cmd->flags & CMD_FLAG_SDTR)) { - printk ("scsi%d : target %d rejected SDTR\n", host->host_no, - c->target); - cmd->flags &= ~CMD_FLAG_SDTR; - asynchronous (host, c->target); - print = 0; - } - break; - case INITIATE_RECOVERY: - printk ("scsi%d : extended contingent allegiance not supported yet, rejecting\n", - host->host_no); - /* Fall through to default */ - hostdata->dsp = hostdata->script + hostdata->E_reject_message / - sizeof(u32); - hostdata->dsp_changed = 1; - break; - default: - printk ("scsi%d : unsupported message, resjecting\n", - host->host_no); - hostdata->dsp = hostdata->script + hostdata->E_reject_message / - sizeof(u32); - hostdata->dsp_changed = 1; - } - if (print) { - printk ("scsi%d : received message", host->host_no); - if (c) - printk (" from target %d lun %d ", c->target, c->lun); - print_msg ((unsigned char *) hostdata->msg_buf); - printk("\n"); - } - - return SPECIFIC_INT_NOTHING; - - - case A_int_msg_sdtr: -/* - * At this point, hostdata->msg_buf contains - * 0 EXTENDED MESSAGE - * 1 length - * 2 SDTR - * 3 period * 4ns - * 4 offset - */ - - if (cmd) { - char buf[80]; - sprintf (buf, "scsi%d : target %d %s ", host->host_no, c->target, - (cmd->flags & CMD_FLAG_SDTR) ? "accepting" : "requesting"); - print_synchronous (buf, (unsigned char *) hostdata->msg_buf); - - /* - * Initiator initiated, won't happen unless synchronous - * transfers are enabled. If we get a SDTR message in - * response to our SDTR, we should program our parameters - * such that - * offset <= requested offset - * period >= requested period - */ - if (cmd->flags & CMD_FLAG_SDTR) { - cmd->flags &= ~CMD_FLAG_SDTR; - if (hostdata->msg_buf[4]) - synchronous (host, c->target, (unsigned char *) - hostdata->msg_buf); - else - asynchronous (host, c->target); - hostdata->dsp = hostdata->script + hostdata->E_accept_message / - sizeof(u32); - hostdata->dsp_changed = 1; - return SPECIFIC_INT_NOTHING; - } else { - if (hostdata->options & OPTION_SYNCHRONOUS) { - cmd->flags |= CMD_FLAG_DID_SDTR; - synchronous (host, c->target, (unsigned char *) - hostdata->msg_buf); - } else { - hostdata->msg_buf[4] = 0; /* 0 offset = async */ - asynchronous (host, c->target); - } - patch_dsa_32 (cmd->dsa, dsa_msgout_other, 0, 5); - patch_dsa_32 (cmd->dsa, dsa_msgout_other, 1, (u32) - virt_to_bus ((void *)&hostdata->msg_buf)); - hostdata->dsp = hostdata->script + - hostdata->E_respond_message / sizeof(u32); - hostdata->dsp_changed = 1; - } - return SPECIFIC_INT_NOTHING; - } - /* Fall through to abort if we couldn't find a cmd, and - therefore a dsa structure to twiddle */ - case A_int_msg_wdtr: - hostdata->dsp = hostdata->script + hostdata->E_reject_message / - sizeof(u32); - hostdata->dsp_changed = 1; - return SPECIFIC_INT_NOTHING; - case A_int_err_unexpected_phase: - if (hostdata->options & OPTION_DEBUG_INTR) - printk ("scsi%d : unexpected phase\n", host->host_no); - return SPECIFIC_INT_ABORT; - case A_int_err_selected: - printk ("scsi%d : selected by target %d\n", host->host_no, - (int) NCR53c7x0_read8(SDID_REG_800) &7); - hostdata->dsp = hostdata->script + hostdata->E_target_abort / - sizeof(u32); - hostdata->dsp_changed = 1; - return SPECIFIC_INT_NOTHING; - case A_int_err_unexpected_reselect: - printk ("scsi%d : unexpected reselect by target %d lun %d\n", - host->host_no, (int) NCR53c7x0_read8(SDID_REG_800) & 7, - hostdata->reselected_identify & 7); - hostdata->dsp = hostdata->script + hostdata->E_initiator_abort / - sizeof(u32); - hostdata->dsp_changed = 1; - return SPECIFIC_INT_NOTHING; -/* - * Since contingent allegiance conditions are cleared by the next - * command issued to a target, we must issue a REQUEST SENSE - * command after receiving a CHECK CONDITION status, before - * another command is issued. - * - * Since this NCR53c7x0_cmd will be freed after use, we don't - * care if we step on the various fields, so modify a few things. - */ - case A_int_err_check_condition: -#if 0 - if (hostdata->options & OPTION_DEBUG_INTR) -#endif - printk ("scsi%d : CHECK CONDITION\n", host->host_no); - if (!c) { - printk("scsi%d : CHECK CONDITION with no SCSI command\n", - host->host_no); - return SPECIFIC_INT_PANIC; - } - - /* - * FIXME : this uses the normal one-byte selection message. - * We may want to renegotiate for synchronous & WIDE transfers - * since these could be the crux of our problem. - * - hostdata->NOP_insn* FIXME : once SCSI-II tagged queuing is implemented, we'll - * have to set this up so that the rest of the DSA - * agrees with this being an untagged queue'd command. - */ - - patch_dsa_32 (cmd->dsa, dsa_msgout, 0, 1); - - /* - * Modify the table indirect for COMMAND OUT phase, since - * Request Sense is a six byte command. - */ - - patch_dsa_32 (cmd->dsa, dsa_cmdout, 0, 6); - - c->cmnd[0] = REQUEST_SENSE; - c->cmnd[1] &= 0xe0; /* Zero all but LUN */ - c->cmnd[2] = 0; - c->cmnd[3] = 0; - c->cmnd[4] = sizeof(c->sense_buffer); - c->cmnd[5] = 0; - - /* - * Disable dataout phase, and program datain to transfer to the - * sense buffer, and add a jump to other_transfer after the - * command so overflow/underrun conditions are detected. - */ - - patch_dsa_32 (cmd->dsa, dsa_dataout, 0, - virt_to_bus(hostdata->script) + hostdata->E_other_transfer); - patch_dsa_32 (cmd->dsa, dsa_datain, 0, - virt_to_bus(cmd->data_transfer_start)); - cmd->data_transfer_start[0] = (((DCMD_TYPE_BMI | DCMD_BMI_OP_MOVE_I | - DCMD_BMI_IO)) << 24) | sizeof(c->sense_buffer); - cmd->data_transfer_start[1] = (u32) virt_to_bus(c->sense_buffer); - - cmd->data_transfer_start[2] = ((DCMD_TYPE_TCI | DCMD_TCI_OP_JUMP) - << 24) | DBC_TCI_TRUE; - cmd->data_transfer_start[3] = (u32) virt_to_bus(hostdata->script) + - hostdata->E_other_transfer; - - /* - * Currently, this command is flagged as completed, ie - * it has valid status and message data. Reflag it as - * incomplete. Q - need to do something so that original - * status, etc are used. - */ - - cmd->cmd->result = 0xffff; - - /* - * Restart command as a REQUEST SENSE. - */ - hostdata->dsp = (u32 *) hostdata->script + hostdata->E_select / - sizeof(u32); - hostdata->dsp_changed = 1; - return SPECIFIC_INT_NOTHING; - case A_int_debug_break: - return SPECIFIC_INT_BREAK; - case A_int_norm_aborted: - hostdata->dsp = (u32 *) hostdata->schedule; - hostdata->dsp_changed = 1; - if (cmd) - abnormal_finished (cmd, DID_ERROR << 16); - return SPECIFIC_INT_NOTHING; - case A_int_test_1: - case A_int_test_2: - hostdata->idle = 1; - hostdata->test_completed = (dsps - A_int_test_1) / 0x00010000 + 1; - if (hostdata->options & OPTION_DEBUG_INTR) - printk("scsi%d : test%d complete\n", host->host_no, - hostdata->test_completed); - return SPECIFIC_INT_NOTHING; -#ifdef A_int_debug_reselected_ok - case A_int_debug_reselected_ok: - if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR| - OPTION_DEBUG_DISCONNECT)) { - /* - * Note - this dsa is not based on location relative to - * the command structure, but to location relative to the - * DSA register - */ - u32 *dsa; - dsa = (u32 *) bus_to_virt (NCR53c7x0_read32(DSA_REG)); - - printk("scsi%d : reselected_ok (DSA = 0x%x (virt 0x%p)\n", - host->host_no, NCR53c7x0_read32(DSA_REG), dsa); - printk("scsi%d : resume address is 0x%x (virt 0x%p)\n", - host->host_no, cmd->saved_data_pointer, - bus_to_virt(cmd->saved_data_pointer)); - print_insn (host, hostdata->script + Ent_reselected_ok / - sizeof(u32), "", 1); - printk ("scsi%d : sxfer=0x%x, scntl3=0x%x\n", - host->host_no, NCR53c7x0_read8(SXFER_REG), - NCR53c7x0_read8(SCNTL3_REG_800)); - if (c) { - print_insn (host, (u32 *) - hostdata->sync[c->target].script, "", 1); - print_insn (host, (u32 *) - hostdata->sync[c->target].script + 2, "", 1); - } - } - return SPECIFIC_INT_RESTART; -#endif -#ifdef A_int_debug_reselect_check - case A_int_debug_reselect_check: - if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR)) { - u32 *dsa; -#if 0 - u32 *code; -#endif - /* - * Note - this dsa is not based on location relative to - * the command structure, but to location relative to the - * DSA register - */ - dsa = bus_to_virt (NCR53c7x0_read32(DSA_REG)); - printk("scsi%d : reselected_check_next (DSA = 0x%lx (virt 0x%p))\n", - host->host_no, virt_to_bus(dsa), dsa); - if (dsa) { - printk("scsi%d : resume address is 0x%x (virt 0x%p)\n", - host->host_no, cmd->saved_data_pointer, - bus_to_virt (cmd->saved_data_pointer)); -#if 0 - printk("scsi%d : template code :\n", host->host_no); - for (code = dsa + (Ent_dsa_code_check_reselect - Ent_dsa_zero) - / sizeof(u32); code < (dsa + Ent_dsa_zero / sizeof(u32)); - code += print_insn (host, code, "", 1)); -#endif - } - print_insn (host, hostdata->script + Ent_reselected_ok / - sizeof(u32), "", 1); - } - return SPECIFIC_INT_RESTART; -#endif -#ifdef A_int_debug_dsa_schedule - case A_int_debug_dsa_schedule: - if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR)) { - u32 *dsa; - /* - * Note - this dsa is not based on location relative to - * the command structure, but to location relative to the - * DSA register - */ - dsa = (u32 *) bus_to_virt (NCR53c7x0_read32(DSA_REG)); - printk("scsi%d : dsa_schedule (old DSA = 0x%lx (virt 0x%p))\n", - host->host_no, virt_to_bus(dsa), dsa); - if (dsa) - printk("scsi%d : resume address is 0x%x (virt 0x%p)\n" - " (temp was 0x%x (virt 0x%p))\n", - host->host_no, cmd->saved_data_pointer, - bus_to_virt (cmd->saved_data_pointer), - NCR53c7x0_read32 (TEMP_REG), - bus_to_virt (NCR53c7x0_read32(TEMP_REG))); - } - return SPECIFIC_INT_RESTART; -#endif -#ifdef A_int_debug_scheduled - case A_int_debug_scheduled: - if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR)) { - printk("scsi%d : new I/O 0x%x (virt 0x%p) scheduled\n", - host->host_no, NCR53c7x0_read32(DSA_REG), - bus_to_virt(NCR53c7x0_read32(DSA_REG))); - } - return SPECIFIC_INT_RESTART; -#endif -#ifdef A_int_debug_idle - case A_int_debug_idle: - if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR)) { - printk("scsi%d : idle\n", host->host_no); - } - return SPECIFIC_INT_RESTART; -#endif -#ifdef A_int_debug_cmd - case A_int_debug_cmd: - if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR)) { - printk("scsi%d : command sent\n"); - } - return SPECIFIC_INT_RESTART; -#endif -#ifdef A_int_debug_dsa_loaded - case A_int_debug_dsa_loaded: - if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR)) { - printk("scsi%d : DSA loaded with 0x%x (virt 0x%p)\n", host->host_no, - NCR53c7x0_read32(DSA_REG), - bus_to_virt(NCR53c7x0_read32(DSA_REG))); - } - return SPECIFIC_INT_RESTART; -#endif -#ifdef A_int_debug_reselected - case A_int_debug_reselected: - if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR| - OPTION_DEBUG_DISCONNECT)) { - printk("scsi%d : reselected by target %d lun %d\n", - host->host_no, (int) NCR53c7x0_read8(SDID_REG_800) & ~0x80, - (int) hostdata->reselected_identify & 7); - print_queues(host); - } - return SPECIFIC_INT_RESTART; -#endif -#ifdef A_int_debug_disconnect_msg - case A_int_debug_disconnect_msg: - if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR)) { - if (c) - printk("scsi%d : target %d lun %d disconnecting\n", - host->host_no, c->target, c->lun); - else - printk("scsi%d : unknown target disconnecting\n", - host->host_no); - } - return SPECIFIC_INT_RESTART; -#endif -#ifdef A_int_debug_disconnected - case A_int_debug_disconnected: - if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR| - OPTION_DEBUG_DISCONNECT)) { - printk ("scsi%d : disconnected, new queues are\n", - host->host_no); - print_queues(host); -#if 0 - printk ("scsi%d : sxfer=0x%x, scntl3=0x%x\n", - host->host_no, NCR53c7x0_read8(SXFER_REG), - NCR53c7x0_read8(SCNTL3_REG_800)); -#endif - if (c) { - print_insn (host, (u32 *) - hostdata->sync[c->target].script, "", 1); - print_insn (host, (u32 *) - hostdata->sync[c->target].script + 2, "", 1); - } - } - return SPECIFIC_INT_RESTART; -#endif -#ifdef A_int_debug_panic - case A_int_debug_panic: - printk("scsi%d : int_debug_panic received\n", host->host_no); - print_lots (host); - return SPECIFIC_INT_PANIC; -#endif -#ifdef A_int_debug_saved - case A_int_debug_saved: - if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR| - OPTION_DEBUG_DISCONNECT)) { - printk ("scsi%d : saved data pointer 0x%x (virt 0x%p)\n", - host->host_no, cmd->saved_data_pointer, - bus_to_virt (cmd->saved_data_pointer)); - print_progress (c); - } - return SPECIFIC_INT_RESTART; -#endif -#ifdef A_int_debug_restored - case A_int_debug_restored: - if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR| - OPTION_DEBUG_DISCONNECT)) { - if (cmd) { - int size; - printk ("scsi%d : restored data pointer 0x%x (virt 0x%p)\n", - host->host_no, cmd->saved_data_pointer, bus_to_virt ( - cmd->saved_data_pointer)); - size = print_insn (host, (u32 *) - bus_to_virt(cmd->saved_data_pointer), "", 1); - size = print_insn (host, (u32 *) - bus_to_virt(cmd->saved_data_pointer) + size, "", 1); - print_progress (c); - } -#if 0 - printk ("scsi%d : datapath residual %d\n", - host->host_no, datapath_residual (host)) ; -#endif - } - return SPECIFIC_INT_RESTART; -#endif -#ifdef A_int_debug_sync - case A_int_debug_sync: - if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR| - OPTION_DEBUG_DISCONNECT|OPTION_DEBUG_SDTR)) { - unsigned char sxfer = NCR53c7x0_read8 (SXFER_REG), - scntl3 = NCR53c7x0_read8 (SCNTL3_REG_800); - if (c) { - if (sxfer != hostdata->sync[c->target].sxfer_sanity || - scntl3 != hostdata->sync[c->target].scntl3_sanity) { - printk ("scsi%d : sync sanity check failed sxfer=0x%x, scntl3=0x%x", - host->host_no, sxfer, scntl3); - NCR53c7x0_write8 (SXFER_REG, sxfer); - NCR53c7x0_write8 (SCNTL3_REG_800, scntl3); - } - } else - printk ("scsi%d : unknown command sxfer=0x%x, scntl3=0x%x\n", - host->host_no, (int) sxfer, (int) scntl3); - } - return SPECIFIC_INT_RESTART; -#endif -#ifdef A_int_debug_datain - case A_int_debug_datain: - if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR| - OPTION_DEBUG_DISCONNECT|OPTION_DEBUG_SDTR)) { - int size; - printk ("scsi%d : In do_datain (%s) sxfer=0x%x, scntl3=0x%x\n" - " datapath residual=%d\n", - host->host_no, sbcl_to_phase (NCR53c7x0_read8 (SBCL_REG)), - (int) NCR53c7x0_read8(SXFER_REG), - (int) NCR53c7x0_read8(SCNTL3_REG_800), - datapath_residual (host)) ; - print_insn (host, dsp, "", 1); - size = print_insn (host, (u32 *) bus_to_virt(dsp[1]), "", 1); - print_insn (host, (u32 *) bus_to_virt(dsp[1]) + size, "", 1); - } - return SPECIFIC_INT_RESTART; -#endif -/* - * FIXME : for 7xx support, we need to read SDID_REG_700 and handle - * the comparison as bitfielded, not binary. - */ -#ifdef A_int_debug_check_dsa - case A_int_debug_check_dsa: - if (NCR53c7x0_read8 (SCNTL1_REG) & SCNTL1_CON) { - int sdid = NCR53c7x0_read8 (SDID_REG_800) & 15; - char *where = dsp - NCR53c7x0_insn_size(NCR53c7x0_read8 - (DCMD_REG)) == hostdata->script + - Ent_select_check_dsa / sizeof(u32) ? - "selection" : "reselection"; - if (c && sdid != c->target) { - printk ("scsi%d : SDID target %d != DSA target %d at %s\n", - host->host_no, sdid, c->target, where); - print_lots(host); - dump_events (host, 20); - return SPECIFIC_INT_PANIC; - } - } - return SPECIFIC_INT_RESTART; -#endif - default: - if ((dsps & 0xff000000) == 0x03000000) { - printk ("scsi%d : misc debug interrupt 0x%x\n", - host->host_no, dsps); - return SPECIFIC_INT_RESTART; - } else if ((dsps & 0xff000000) == 0x05000000) { - if (hostdata->events) { - struct NCR53c7x0_event *event; - ++hostdata->event_index; - if (hostdata->event_index >= hostdata->event_size) - hostdata->event_index = 0; - event = (struct NCR53c7x0_event *) hostdata->events + - hostdata->event_index; - event->event = (enum ncr_event) dsps; - event->dsa = bus_to_virt(NCR53c7x0_read32(DSA_REG)); - /* FIXME : this needs to change for the '7xx family */ - if (NCR53c7x0_read8 (SCNTL1_REG) & SCNTL1_CON) - event->target = NCR53c7x0_read8(SSID_REG_800); - else - event->target = 255; - - if (event->event == EVENT_RESELECT) - event->lun = hostdata->reselected_identify & 0xf; - else if (c) - event->lun = c->lun; - else - event->lun = 255; - do_gettimeofday(&(event->time)); - if (c) { - event->pid = c->pid; - memcpy ((void *) event->cmnd, (void *) c->cmnd, - sizeof (event->cmnd)); - } else { - event->pid = -1; - } - } - return SPECIFIC_INT_RESTART; - } - - printk ("scsi%d : unknown user interrupt 0x%x\n", - host->host_no, (unsigned) dsps); - return SPECIFIC_INT_PANIC; - } -} - -/* - * XXX - the stock NCR assembler won't output the scriptu.h file, - * which undefine's all #define'd CPP symbols from the script.h - * file, which will create problems if you use multiple scripts - * with the same symbol names. - * - * If you insist on using NCR's assembler, you could generate - * scriptu.h from script.h using something like - * - * grep #define script.h | \ - * sed 's/#define[ ][ ]*\([_a-zA-Z][_a-zA-Z0-9]*\).*$/#undefine \1/' \ - * > scriptu.h - */ - -#include "53c8xx_u.h" - -/* XXX - add alternate script handling code here */ - - -#ifdef NCR_DEBUG -/* - * Debugging without a debugger is no fun. So, I've provided - * a debugging interface in the NCR53c7x0 driver. To avoid - * kernel cruft, there's just enough here to act as an interface - * to a user level debugger (aka, GDB). - * - * - * The following restrictions apply to debugger commands : - * 1. The command must be terminated by a newline. - * 2. Command length must be less than 80 bytes including the - * newline. - * 3. The entire command must be written with one system call. - */ - -static const char debugger_help = -"bc <addr> - clear breakpoint\n" -"bl - list breakpoints\n" -"bs <addr> - set breakpoint\n" -"g - start\n" -"h - halt\n" -"? - this message\n" -"i - info\n" -"mp <addr> <size> - print memory\n" -"ms <addr> <size> <value> - store memory\n" -"rp <num> <size> - print register\n" -"rs <num> <size> <value> - store register\n" -"s - single step\n" -"tb - begin trace \n" -"te - end trace\n"; - -/* - * Whenever we change a break point, we should probably - * set the NCR up so that it is in a single step mode. - */ - -static int debugger_fn_bc (struct Scsi_Host *host, struct debugger_token *token, - u32 args[]) { - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - instance->hostdata; - struct NCR53c7x0_break *bp, **prev; - unsigned long flags; - save_flags(flags); - cli(); - for (bp = (struct NCR53c7x0_break *) instance->breakpoints, - prev = (struct NCR53c7x0_break **) &instance->breakpoints; - bp; prev = (struct NCR53c7x0_break **) &(bp->next), - bp = (struct NCR53c7x0_break *) bp->next); - - if (!bp) { - restore_flags(flags); - return -EIO; - } - - /* - * XXX - we need to insure that the processor is halted - * here in order to prevent a race condition. - */ - - memcpy ((void *) bp->addr, (void *) bp->old, sizeof(bp->old)); - if (prev) - *prev = bp->next; - - restore_flags(flags); - return 0; -} - - -static int -debugger_fn_bl (struct Scsi_Host *host, struct debugger_token *token, - u32 args[]) { - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - host->hostdata; - struct NCR53c7x0_break *bp; - char buf[80]; - size_t len; - unsigned long flags; - /* - * XXX - we need to insure that the processor is halted - * here in order to prevent a race condition. So, if the - * processor isn't halted, print an error message and continue. - */ - - sprintf (buf, "scsi%d : bp : warning : processor not halted\b", - host->host_no); - debugger_kernel_write (host, buf, strlen(buf)); - - save_flags(flags); - cli(); - for (bp = (struct NCR53c7x0_break *) host->breakpoints; - bp; bp = (struct NCR53c7x0_break *) bp->next); { - sprintf (buf, "scsi%d : bp : success : at %08x, replaces %08x %08x", - bp->addr, bp->old[0], bp->old[1]); - len = strlen(buf); - if ((bp->old[0] & (DCMD_TYPE_MASK << 24)) == - (DCMD_TYPE_MMI << 24)) { - sprintf(buf + len, "%08x\n", * (u32 *) bp->addr); - } else { - sprintf(buf + len, "\n"); - } - len = strlen(buf); - debugger_kernel_write (host, buf, len); - } - restore_flags(flags); - return 0; -} - -static int -debugger_fn_bs (struct Scsi_Host *host, struct debugger_token *token, - u32 args[]) { - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - host->hostdata; - struct NCR53c7x0_break *bp; - char buf[80]; - size_t len; - unsigned long flags; - save_flags(flags); - cli(); - - if (hostdata->state != STATE_HALTED) { - sprintf (buf, "scsi%d : bs : failure : NCR not halted\n", host->host_no); - debugger_kernel_write (host, buf, strlen(buf)); - restore_flags(flags); - return -1; - } - - if (!(bp = kmalloc (sizeof (struct NCR53c7x0_break)))) { - printk ("scsi%d : kmalloc(%d) of breakpoint structure failed, try again\n", - host->host_no, sizeof(struct NCR53c7x0_break)); - restore_flags(flags); - return -1; - } - - bp->address = (u32 *) args[0]; - memcpy ((void *) bp->old_instruction, (void *) bp->address, 8); - bp->old_size = (((bp->old_instruction[0] >> 24) & DCMD_TYPE_MASK) == - DCMD_TYPE_MMI ? 3 : 2; - bp->next = hostdata->breakpoints; - hostdata->breakpoints = bp->next; - memcpy ((void *) bp->address, (void *) hostdata->E_debug_break, 8); - - restore_flags(flags); - return 0; -} - -#define TOKEN(name,nargs) {#name, nargs, debugger_fn_##name} -static const struct debugger_token { - char *name; - int numargs; - int (*fn)(struct debugger_token *token, u32 args[]); -} debugger_tokens[] = { - TOKEN(bc,1), TOKEN(bl,0), TOKEN(bs,1), TOKEN(g,0), TOKEN(halt,0), - {DT_help, "?", 0} , TOKEN(h,0), TOKEN(i,0), TOKEN(mp,2), - TOKEN(ms,3), TOKEN(rp,2), TOKEN(rs,2), TOKEN(s,0), TOKEN(tb,0), TOKEN(te,0) -}; - -#define NDT sizeof(debugger_tokens / sizeof(struct debugger_token)) - -static struct Scsi_Host * inode_to_host (struct inode *inode) { - int dev; - struct Scsi_Host *tmp; - for (dev = MINOR(inode->rdev), host = first_host; - (host->hostt == the_template); --dev, host = host->next) - if (!dev) return host; - return NULL; -} - - -static int -debugger_user_write (struct inode *inode,struct file *filp, - char *buf,int count) { - struct Scsi_Host *host; /* This SCSI host */ - struct NCR53c7x0_hostadata *hostdata; - char input_buf[80], /* Kernel space copy of buf */ - *ptr; /* Pointer to argument list */ - u32 args[3]; /* Arguments */ - int i, j, error, len; - - if (!(host = inode_to_host(inode))) - return -ENXIO; - - hostdata = (struct NCR53c7x0_hostdata *) host->hostdata; - - if (error = verify_area(VERIFY_READ,buf,count)) - return error; - - if (count > 80) - return -EIO; - - memcpy_from_fs(input_buf, buf, count); - - if (input_buf[count - 1] != '\n') - return -EIO; - - input_buf[count - 1]=0; - - for (i = 0; i < NDT; ++i) { - len = strlen (debugger_tokens[i].name); - if (!strncmp(input_buf, debugger_tokens[i].name, len)) - break; - }; - - if (i == NDT) - return -EIO; - - for (ptr = input_buf + len, j = 0; j < debugger_tokens[i].nargs && *ptr;) { - if (*ptr == ' ' || *ptr == '\t') { - ++ptr; - } else if (isdigit(*ptr)) { - args[j++] = simple_strtoul (ptr, &ptr, 0); - } else { - return -EIO; - } - } - - if (j != debugger_tokens[i].nargs) - return -EIO; - - return count; -} - -static int -debugger_user_read (struct inode *inode,struct file *filp, - char *buf,int count) { - struct Scsi_Host *instance; - -} - -static int -debugger_kernel_write (struct Scsi_Host *host, char *buf, size_t - buflen) { - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - host->hostdata; - int copy, left; - unsigned long flags; - save_flags(flags); - cli(); - while (buflen) { - left = (hostdata->debug_buf + hostdata->debug_size - 1) - - hostdata->debug_write; - copy = (buflen <= left) ? buflen : left; - memcpy (hostdata->debug_write, buf, copy); - buf += copy; - buflen -= copy; - hostdata->debug_count += copy; - if ((hostdata->debug_write += copy) == - (hostdata->debug_buf + hostdata->debug_size)) - hosdata->debug_write = hostdata->debug_buf; - } - restore_flags(flags); -} - -#endif /* def NCRDEBUG */ - -/* - * Function : static void NCR538xx_soft_reset (struct Scsi_Host *host) - * - * Purpose : perform a soft reset of the NCR53c8xx chip - * - * Inputs : host - pointer to this host adapter's structure - * - * Preconditions : NCR53c7x0_init must have been called for this - * host. - * - */ - -static void -NCR53c8x0_soft_reset (struct Scsi_Host *host) { - NCR53c7x0_local_declare(); - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - host->hostdata; - NCR53c7x0_local_setup(host); - - - /* - * Do a soft reset of the chip so that everything is - * reinitialized to the power-on state. - * - * Basically follow the procedure outlined in the NCR53c700 - * data manual under Chapter Six, How to Use, Steps Necessary to - * Start SCRIPTS, with the exception of actually starting the - * script and setting up the synchronous transfer gunk. - */ - - NCR53c7x0_write8(ISTAT_REG_800, ISTAT_10_SRST); - NCR53c7x0_write8(ISTAT_REG_800, 0); - NCR53c7x0_write8(hostdata->dmode, hostdata->saved_dmode & ~DMODE_MAN); - - - /* - * Respond to reselection by targets and use our _initiator_ SCSI ID - * for arbitration. If notyet, also respond to SCSI selection. - * - * XXX - Note : we must reprogram this when reselecting as - * a target. - */ - -#ifdef notyet - NCR53c7x0_write8(SCID_REG, (host->this_id & 7)|SCID_800_RRE|SCID_800_SRE); -#else - NCR53c7x0_write8(SCID_REG, (host->this_id & 7)|SCID_800_RRE); -#endif - NCR53c7x0_write8(RESPID_REG_800, hostdata->this_id_mask); - - /* - * Use a maximum (1.6) second handshake to handshake timeout, - * and SCSI recommended .5s selection timeout. - */ - - /* - * The new gcc won't recognize preprocessing directives - * within macro args. - */ -#if 0 - NCR53c7x0_write8(STIME0_REG_800, - ((selection_timeout << STIME0_800_SEL_SHIFT) & STIME0_800_SEL_MASK) - | ((15 << STIME0_800_HTH_SHIFT) & STIME0_800_HTH_MASK)); -#else -/* Disable HTH interrupt */ - NCR53c7x0_write8(STIME0_REG_800, - ((selection_timeout << STIME0_800_SEL_SHIFT) & STIME0_800_SEL_MASK)); -#endif - - - /* - * Enable active negation for happy synchronous transfers. - */ - - NCR53c7x0_write8(STEST3_REG_800, STEST3_800_TE); - - /* - * Enable all interrupts, except parity which we only want when - * the user requests it. - */ - - NCR53c7x0_write8(DIEN_REG, DIEN_800_MDPE | DIEN_800_BF | - DIEN_ABRT | DIEN_SSI | DIEN_SIR | DIEN_800_IID); - - - NCR53c7x0_write8(SIEN0_REG_800, ((hostdata->options & OPTION_PARITY) ? - SIEN_PAR : 0) | SIEN_RST | SIEN_UDC | SIEN_SGE | SIEN_MA); - NCR53c7x0_write8(SIEN1_REG_800, SIEN1_800_STO | SIEN1_800_HTH); - - /* - * Use saved clock frequency divisor and scripts loaded in 16 bit - * mode flags from the saved dcntl. - */ - - NCR53c7x0_write8(DCNTL_REG, hostdata->saved_dcntl); - NCR53c7x0_write8(CTEST4_REG_800, hostdata->saved_ctest4); - - /* Enable active negation */ - NCR53c7x0_write8(STEST3_REG_800, STEST3_800_TE); -} - -/* - * Function static struct NCR53c7x0_cmd *allocate_cmd (Scsi_Cmnd *cmd) - * - * Purpose : Return the first free NCR53c7x0_cmd structure (which are - * reused in a LIFO maner to minimize cache thrashing). - * - * Side effects : If we haven't yet scheduled allocation of NCR53c7x0_cmd - * structures for this device, do so. Attempt to complete all scheduled - * allocations using kmalloc(), putting NCR53c7x0_cmd structures on - * the free list. Teach programmers not to drink and hack. - * - * Inputs : cmd - SCSI command - * - * Returns : NCR53c7x0_cmd structure allocated on behalf of cmd; - * NULL on failure. - */ - -static struct NCR53c7x0_cmd * -allocate_cmd (Scsi_Cmnd *cmd) { - struct Scsi_Host *host = cmd->host; - struct NCR53c7x0_hostdata *hostdata = - (struct NCR53c7x0_hostdata *) host->hostdata; - void *real; /* Real address */ - int size; /* Size of *tmp */ - struct NCR53c7x0_cmd *tmp; - unsigned long flags; - - if (hostdata->options & OPTION_DEBUG_ALLOCATION) - printk ("scsi%d : num_cmds = %d, can_queue = %d\n" - " target = %d, lun = %d, %s\n", - host->host_no, hostdata->num_cmds, host->can_queue, - cmd->target, cmd->lun, (hostdata->cmd_allocated[cmd->target] & - (1 << cmd->lun)) ? "allready allocated" : "not allocated"); - -/* - * If we have not yet reserved commands for this I_T_L nexus, and - * the device exists (as indicated by permanant Scsi_Cmnd structures - * being allocated under 1.3.x, or being outside of scan_scsis in - * 1.2.x), do so now. - */ - if (!(hostdata->cmd_allocated[cmd->target] & (1 << cmd->lun)) && -#ifdef LINUX_1_2 - !in_scan_scsis -#else - cmd->device && cmd->device->has_cmdblocks -#endif - ) { - if ((hostdata->extra_allocate + hostdata->num_cmds) < host->can_queue) - hostdata->extra_allocate += host->cmd_per_lun; - hostdata->cmd_allocated[cmd->target] |= (1 << cmd->lun); - } - - for (; hostdata->extra_allocate > 0 ; --hostdata->extra_allocate, - ++hostdata->num_cmds) { - /* historically, kmalloc has returned unaligned addresses; pad so we - have enough room to ROUNDUP */ - size = hostdata->max_cmd_size + sizeof (void *); -/* FIXME: for ISA bus '7xx chips, we need to or GFP_DMA in here */ - real = kmalloc (size, GFP_ATOMIC); - if (!real) { - if (hostdata->options & OPTION_DEBUG_ALLOCATION) - printk ("scsi%d : kmalloc(%d) failed\n", - host->host_no, size); - break; - } - tmp = ROUNDUP(real, void *); - tmp->real = real; - tmp->size = size; -#ifdef LINUX_1_2 - tmp->free = ((void (*)(void *, int)) kfree_s); -#else - tmp->free = ((void (*)(void *, int)) kfree); -#endif - save_flags (flags); - cli(); - tmp->next = hostdata->free; - hostdata->free = tmp; - restore_flags (flags); - } - save_flags(flags); - cli(); - tmp = (struct NCR53c7x0_cmd *) hostdata->free; - if (tmp) { - hostdata->free = tmp->next; - } - restore_flags(flags); - if (!tmp) - printk ("scsi%d : can't allocate command for target %d lun %d\n", - host->host_no, cmd->target, cmd->lun); - return tmp; -} - -/* - * Function static struct NCR53c7x0_cmd *create_cmd (Scsi_Cmnd *cmd) - * - * - * Purpose : allocate a NCR53c7x0_cmd structure, initialize it based on the - * Scsi_Cmnd structure passed in cmd, including dsa and Linux field - * initialization, and dsa code relocation. - * - * Inputs : cmd - SCSI command - * - * Returns : NCR53c7x0_cmd structure corresponding to cmd, - * NULL on failure. - */ - -static struct NCR53c7x0_cmd * -create_cmd (Scsi_Cmnd *cmd) { - NCR53c7x0_local_declare(); - struct Scsi_Host *host = cmd->host; - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - host->hostdata; - struct NCR53c7x0_cmd *tmp; /* NCR53c7x0_cmd structure for this command */ - int datain, /* Number of instructions per phase */ - dataout; - int data_transfer_instructions, /* Count of dynamic instructions */ - i; /* Counter */ - u32 *cmd_datain, /* Address of datain/dataout code */ - *cmd_dataout; /* Incremented as we assemble */ -#ifdef notyet - unsigned char *msgptr; /* Current byte in select message */ - int msglen; /* Length of whole select message */ -#endif - unsigned long flags; - NCR53c7x0_local_setup(cmd->host); - - if (!(tmp = allocate_cmd (cmd))) - return NULL; - - - /* - * Decide whether we need to generate commands for DATA IN, - * DATA OUT, neither, or both based on the SCSI command - */ - - switch (cmd->cmnd[0]) { - /* These commands do DATA IN */ - case INQUIRY: - case MODE_SENSE: - case READ_6: - case READ_10: - case READ_CAPACITY: - case REQUEST_SENSE: - datain = 2 * (cmd->use_sg ? cmd->use_sg : 1) + 3; - dataout = 0; - break; - /* These commands do DATA OUT */ - case MODE_SELECT: - case WRITE_6: - case WRITE_10: -#if 0 - printk("scsi%d : command is ", host->host_no); - print_command(cmd->cmnd); -#endif -#if 0 - printk ("scsi%d : %d scatter/gather segments\n", host->host_no, - cmd->use_sg); -#endif - datain = 0; - dataout = 2 * (cmd->use_sg ? cmd->use_sg : 1) + 3; -#if 0 - hostdata->options |= OPTION_DEBUG_INTR; -#endif - break; - /* - * These commands do no data transfer, we should force an - * interrupt if a data phase is attempted on them. - */ - case START_STOP: - case TEST_UNIT_READY: - datain = dataout = 0; - break; - /* - * We don't know about these commands, so generate code to handle - * both DATA IN and DATA OUT phases. - */ - default: - datain = dataout = 2 * (cmd->use_sg ? cmd->use_sg : 1) + 3; - } - - /* - * New code : so that active pointers work correctly irregardless - * of where the saved data pointer is at, we want to immediately - * enter the dynamic code after selection, and on a non-data - * phase perform a CALL to the non-data phase handler, with - * returns back to this address. - * - * If a phase mismatch is encountered in the middle of a - * Block MOVE instruction, we want to _leave_ that instruction - * unchanged as the current case is, modify a temporary buffer, - * and point the active pointer (TEMP) at that. - * - * Furthermore, we want to implement a saved data pointer, - * set by the SAVE_DATA_POINTERs message. - * - * So, the data transfer segments will change to - * CALL data_transfer, WHEN NOT data phase - * MOVE x, x, WHEN data phase - * ( repeat ) - * JUMP other_transfer - */ - - data_transfer_instructions = datain + dataout; - - /* - * When we perform a request sense, we overwrite various things, - * including the data transfer code. Make sure we have enough - * space to do that. - */ - - if (data_transfer_instructions < 2) - data_transfer_instructions = 2; - - - /* - * The saved data pointer is set up so that a RESTORE POINTERS message - * will start the data transfer over at the beggining. - */ - - tmp->saved_data_pointer = virt_to_bus (hostdata->script) + - hostdata->E_data_transfer; - - /* - * Initialize Linux specific fields. - */ - - tmp->cmd = cmd; - tmp->next = NULL; - tmp->flags = 0; - tmp->dsa_next_addr = virt_to_bus(tmp->dsa) + hostdata->dsa_next - - hostdata->dsa_start; - tmp->dsa_addr = virt_to_bus(tmp->dsa) - hostdata->dsa_start; - - /* - * Calculate addresses of dynamic code to fill in DSA - */ - - tmp->data_transfer_start = tmp->dsa + (hostdata->dsa_end - - hostdata->dsa_start) / sizeof(u32); - tmp->data_transfer_end = tmp->data_transfer_start + - 2 * data_transfer_instructions; - - cmd_datain = datain ? tmp->data_transfer_start : NULL; - cmd_dataout = dataout ? (datain ? cmd_datain + 2 * datain : tmp-> - data_transfer_start) : NULL; - - /* - * Fill in the NCR53c7x0_cmd structure as follows - * dsa, with fixed up DSA code - * datain code - * dataout code - */ - - /* Copy template code into dsa and perform all necessary fixups */ - if (hostdata->dsa_fixup) - hostdata->dsa_fixup(tmp); - - patch_dsa_32(tmp->dsa, dsa_next, 0, 0); - patch_dsa_32(tmp->dsa, dsa_cmnd, 0, virt_to_bus(cmd)); - - if (hostdata->options & OPTION_DEBUG_SYNCHRONOUS) - if (hostdata->sync[cmd->target].select_indirect != - ((hostdata->sync[cmd->target].scntl3_sanity << 24) | - (cmd->target << 16) | - (hostdata->sync[cmd->target].sxfer_sanity << 8))) { - printk ("scsi%d : sanity check failed select_indirect=0x%x\n", - host->host_no, hostdata->sync[cmd->target].select_indirect); - FATAL(host); - - } - - patch_dsa_32(tmp->dsa, dsa_select, 0, hostdata->sync[cmd->target]. - select_indirect); - /* - * Right now, we'll do the WIDE and SYNCHRONOUS negotiations on - * different commands; although it should be trivial to do them - * both at the same time. - */ - if (hostdata->initiate_wdtr & (1 << cmd->target)) { - memcpy ((void *) (tmp->select + 1), (void *) wdtr_message, - sizeof(wdtr_message)); - patch_dsa_32(tmp->dsa, dsa_msgout, 0, 1 + sizeof(wdtr_message)); - save_flags(flags); - cli(); - hostdata->initiate_wdtr &= ~(1 << cmd->target); - restore_flags(flags); - } else if (hostdata->initiate_sdtr & (1 << cmd->target)) { - memcpy ((void *) (tmp->select + 1), (void *) sdtr_message, - sizeof(sdtr_message)); - patch_dsa_32(tmp->dsa, dsa_msgout, 0, 1 + sizeof(sdtr_message)); - tmp->flags |= CMD_FLAG_SDTR; - save_flags(flags); - cli(); - hostdata->initiate_sdtr &= ~(1 << cmd->target); - restore_flags(flags); - - } -#if 1 - else if (!(hostdata->talked_to & (1 << cmd->target)) && - !(hostdata->options & OPTION_NO_ASYNC)) { - memcpy ((void *) (tmp->select + 1), (void *) async_message, - sizeof(async_message)); - patch_dsa_32(tmp->dsa, dsa_msgout, 0, 1 + sizeof(async_message)); - tmp->flags |= CMD_FLAG_SDTR; - } -#endif - else - patch_dsa_32(tmp->dsa, dsa_msgout, 0, 1); - hostdata->talked_to |= (1 << cmd->target); - tmp->select[0] = (hostdata->options & OPTION_DISCONNECT) ? - IDENTIFY (1, cmd->lun) : IDENTIFY (0, cmd->lun); - patch_dsa_32(tmp->dsa, dsa_msgout, 1, virt_to_bus(tmp->select)); - patch_dsa_32(tmp->dsa, dsa_cmdout, 0, cmd->cmd_len); - patch_dsa_32(tmp->dsa, dsa_cmdout, 1, virt_to_bus(cmd->cmnd)); - patch_dsa_32(tmp->dsa, dsa_dataout, 0, cmd_dataout ? - virt_to_bus (cmd_dataout) - : virt_to_bus (hostdata->script) + hostdata->E_other_transfer); - patch_dsa_32(tmp->dsa, dsa_datain, 0, cmd_datain ? - virt_to_bus (cmd_datain) - : virt_to_bus (hostdata->script) + hostdata->E_other_transfer); - /* - * XXX - need to make endian aware, should use separate variables - * for both status and message bytes. - */ - patch_dsa_32(tmp->dsa, dsa_msgin, 0, 1); -/* - * FIXME : these only works for little endian. We probably want to - * provide message and status fields in the NCR53c7x0_cmd - * structure, and assign them to cmd->result when we're done. - */ - patch_dsa_32(tmp->dsa, dsa_msgin, 1, virt_to_bus(&cmd->result) + 1); - patch_dsa_32(tmp->dsa, dsa_status, 0, 1); - patch_dsa_32(tmp->dsa, dsa_status, 1, virt_to_bus(&cmd->result)); - patch_dsa_32(tmp->dsa, dsa_msgout_other, 0, 1); - patch_dsa_32(tmp->dsa, dsa_msgout_other, 1, - virt_to_bus(&(hostdata->NCR53c7xx_msg_nop))); - - /* - * Generate code for zero or more of the DATA IN, DATA OUT phases - * in the format - * - * CALL data_transfer, WHEN NOT phase - * MOVE first buffer length, first buffer address, WHEN phase - * ... - * MOVE last buffer length, last buffer address, WHEN phase - * JUMP other_transfer - */ - -/* - * See if we're getting to data transfer by generating an unconditional - * interrupt. - */ -#if 0 - if (datain) { - cmd_datain[0] = 0x98080000; - cmd_datain[1] = 0x03ffd00d; - cmd_datain += 2; - } -#endif - -/* - * XXX - I'm undecided whether all of this nonsense is faster - * in the long run, or whether I should just go and implement a loop - * on the NCR chip using table indirect mode? - * - * In any case, this is how it _must_ be done for 53c700/700-66 chips, - * so this stays even when we come up with something better. - * - * When we're limited to 1 simultaneous command, no overlapping processing, - * we're seeing 630K/sec, with 7% CPU usage on a slow Syquest 45M - * drive. - * - * Not bad, not good. We'll see. - */ - - for (i = 0; cmd->use_sg ? (i < cmd->use_sg) : !i; cmd_datain += 4, - cmd_dataout += 4, ++i) { - u32 buf = cmd->use_sg ? - virt_to_bus(((struct scatterlist *)cmd->buffer)[i].address) : - virt_to_bus(cmd->request_buffer); - u32 count = cmd->use_sg ? - ((struct scatterlist *)cmd->buffer)[i].length : - cmd->request_bufflen; - - if (datain) { - /* CALL other_in, WHEN NOT DATA_IN */ - cmd_datain[0] = ((DCMD_TYPE_TCI | DCMD_TCI_OP_CALL | - DCMD_TCI_IO) << 24) | - DBC_TCI_WAIT_FOR_VALID | DBC_TCI_COMPARE_PHASE; - cmd_datain[1] = virt_to_bus (hostdata->script) + - hostdata->E_other_in; - /* MOVE count, buf, WHEN DATA_IN */ - cmd_datain[2] = ((DCMD_TYPE_BMI | DCMD_BMI_OP_MOVE_I | DCMD_BMI_IO) - << 24) | count; - cmd_datain[3] = buf; -#if 0 - print_insn (host, cmd_datain, "dynamic ", 1); - print_insn (host, cmd_datain + 2, "dynamic ", 1); -#endif - } - if (dataout) { - /* CALL other_out, WHEN NOT DATA_OUT */ - cmd_dataout[0] = ((DCMD_TYPE_TCI | DCMD_TCI_OP_CALL) << 24) | - DBC_TCI_WAIT_FOR_VALID | DBC_TCI_COMPARE_PHASE; - cmd_dataout[1] = virt_to_bus(hostdata->script) + - hostdata->E_other_out; - /* MOVE count, buf, WHEN DATA+OUT */ - cmd_dataout[2] = ((DCMD_TYPE_BMI | DCMD_BMI_OP_MOVE_I) << 24) - | count; - cmd_dataout[3] = buf; -#if 0 - print_insn (host, cmd_dataout, "dynamic ", 1); - print_insn (host, cmd_dataout + 2, "dynamic ", 1); -#endif - } - } - - /* - * Install JUMP instructions after the data transfer routines to return - * control to the do_other_transfer routines. - */ - - - if (datain) { - cmd_datain[0] = ((DCMD_TYPE_TCI | DCMD_TCI_OP_JUMP) << 24) | - DBC_TCI_TRUE; - cmd_datain[1] = virt_to_bus(hostdata->script) + - hostdata->E_other_transfer; -#if 0 - print_insn (host, cmd_datain, "dynamic jump ", 1); -#endif - cmd_datain += 2; - } -#if 0 - if (datain) { - cmd_datain[0] = 0x98080000; - cmd_datain[1] = 0x03ffdeed; - cmd_datain += 2; - } -#endif - if (dataout) { - cmd_dataout[0] = ((DCMD_TYPE_TCI | DCMD_TCI_OP_JUMP) << 24) | - DBC_TCI_TRUE; - cmd_dataout[1] = virt_to_bus(hostdata->script) + - hostdata->E_other_transfer; -#if 0 - print_insn (host, cmd_dataout, "dynamic jump ", 1); -#endif - cmd_dataout += 2; - } - return tmp; -} - -/* - * Function : int NCR53c7xx_queue_command (Scsi_Cmnd *cmd, - * void (*done)(Scsi_Cmnd *)) - * - * Purpose : enqueues a SCSI command - * - * Inputs : cmd - SCSI command, done - function called on completion, with - * a pointer to the command descriptor. - * - * Returns : 0 - * - * Side effects : - * cmd is added to the per instance driver issue_queue, with major - * twiddling done to the host specific fields of cmd. If the - * process_issue_queue corouting isn't running, it is restarted. - * - * NOTE : we use the host_scribble field of the Scsi_Cmnd structure to - * hold our own data, and pervert the ptr field of the SCp field - * to create a linked list. - */ - -int -NCR53c7xx_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *)) { - struct Scsi_Host *host = cmd->host; - struct NCR53c7x0_hostdata *hostdata = - (struct NCR53c7x0_hostdata *) host->hostdata; - unsigned long flags; - Scsi_Cmnd *tmp; - - cmd->scsi_done = done; - cmd->host_scribble = NULL; - cmd->SCp.ptr = NULL; - cmd->SCp.buffer = NULL; - - save_flags(flags); - cli(); - if ((hostdata->options & (OPTION_DEBUG_INIT_ONLY|OPTION_DEBUG_PROBE_ONLY)) - || ((hostdata->options & OPTION_DEBUG_TARGET_LIMIT) && - !(hostdata->debug_lun_limit[cmd->target] & (1 << cmd->lun))) -#ifdef LINUX_1_2 - || cmd->target > 7 -#else - || cmd->target > host->max_id -#endif - || cmd->target == host->this_id - || hostdata->state == STATE_DISABLED) { - printk("scsi%d : disabled or bad target %d lun %d\n", host->host_no, - cmd->target, cmd->lun); - cmd->result = (DID_BAD_TARGET << 16); - } else if ((hostdata->options & OPTION_DEBUG_NCOMMANDS_LIMIT) && - (hostdata->debug_count_limit == 0)) { - printk("scsi%d : maximum commands exceeded\n", host->host_no); - cmd->result = (DID_BAD_TARGET << 16); - cmd->result = (DID_BAD_TARGET << 16); - } else if (hostdata->options & OPTION_DEBUG_READ_ONLY) { - switch (cmd->cmnd[0]) { - case WRITE_6: - case WRITE_10: - printk("scsi%d : WRITE attempted with NO_WRITE debugging flag set\n", - host->host_no); - cmd->result = (DID_BAD_TARGET << 16); - } - } else { - if ((hostdata->options & OPTION_DEBUG_TARGET_LIMIT) && - hostdata->debug_count_limit != -1) - --hostdata->debug_count_limit; - restore_flags (flags); - cmd->result = 0xffff; /* The NCR will overwrite message - and status with valid data */ - cmd->host_scribble = (unsigned char *) tmp = create_cmd (cmd); - } - cli(); - /* - * REQUEST SENSE commands are inserted at the head of the queue - * so that we do not clear the contingent allegience condition - * they may be looking at. - */ - - if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) { - cmd->SCp.ptr = (unsigned char *) hostdata->issue_queue; - hostdata->issue_queue = cmd; - } else { - for (tmp = (Scsi_Cmnd *) hostdata->issue_queue; tmp->SCp.ptr; - tmp = (Scsi_Cmnd *) tmp->SCp.ptr); - tmp->SCp.ptr = (unsigned char *) cmd; - } - restore_flags (flags); - run_process_issue_queue(); - return 0; -} - -/* - * Function : void to_schedule_list (struct Scsi_Host *host, - * struct NCR53c7x0_hostdata * hostdata, Scsi_Cmnd *cmd) - * - * Purpose : takes a SCSI command which was just removed from the - * issue queue, and deals with it by inserting it in the first - * free slot in the schedule list or by terminating it immediately. - * - * Inputs : - * host - SCSI host adater; hostdata - hostdata structure for - * this adapter; cmd - a pointer to the command; should have - * the host_scribble field initialized to point to a valid - * - * Side effects : - * cmd is added to the per instance schedule list, with minor - * twiddling done to the host specific fields of cmd. - * - */ - -static __inline__ void -to_schedule_list (struct Scsi_Host *host, struct NCR53c7x0_hostdata *hostdata, - struct NCR53c7x0_cmd *cmd) { - NCR53c7x0_local_declare(); - Scsi_Cmnd *tmp = cmd->cmd; - unsigned long flags; - /* dsa start is negative, so subtraction is used */ - volatile u32 *current; - - int i; - NCR53c7x0_local_setup(host); -#if 0 - printk("scsi%d : new dsa is 0x%lx (virt 0x%p)\n", host->host_no, - virt_to_bus(dsa), dsa); -#endif - - save_flags(flags); - cli(); - - /* - * Work arround race condition : if an interrupt fired and we - * got disabled forget about this command. - */ - - if (hostdata->state == STATE_DISABLED) { - printk("scsi%d : driver disabled\n", host->host_no); - tmp->result = (DID_BAD_TARGET << 16); - cmd->next = (struct NCR53c7x0_cmd *) hostdata->free; - hostdata->free = cmd; - tmp->scsi_done(tmp); - restore_flags (flags); - return; - } - - for (i = host->can_queue, current = hostdata->schedule; - i > 0 && current[0] != hostdata->NOP_insn; - --i, current += 2 /* JUMP instructions are two words */); - - if (i > 0) { - ++hostdata->busy[tmp->target][tmp->lun]; - cmd->next = hostdata->running_list; - hostdata->running_list = cmd; - - /* Restore this instruction to a NOP once the command starts */ - cmd->dsa [(hostdata->dsa_jump_dest - hostdata->dsa_start) / - sizeof(u32)] = (u32) virt_to_bus ((void *)current); - /* Replace the current jump operand. */ - current[1] = - virt_to_bus ((void *) cmd->dsa) + hostdata->E_dsa_code_begin - - hostdata->E_dsa_code_template; - /* Replace the NOP instruction with a JUMP */ - current[0] = ((DCMD_TYPE_TCI|DCMD_TCI_OP_JUMP) << 24) | - DBC_TCI_TRUE; - } else { - printk ("scsi%d: no free slot\n", host->host_no); - disable(host); - tmp->result = (DID_ERROR << 16); - cmd->next = (struct NCR53c7x0_cmd *) hostdata->free; - hostdata->free = cmd; - tmp->scsi_done(tmp); - restore_flags (flags); - return; - } - - /* - * If the NCR chip is in an idle state, start it running the scheduler - * immediately. Otherwise, signal the chip to jump to schedule as - * soon as it is idle. - */ - if (hostdata->idle) { - hostdata->idle = 0; - hostdata->state = STATE_RUNNING; - NCR53c7x0_write32 (DSP_REG, virt_to_bus ((void *)hostdata->schedule)); - } else { - NCR53c7x0_write8(hostdata->istat, ISTAT_10_SIGP); - } - - restore_flags(flags); -} - -/* - * Function : busyp (struct Scsi_Host *host, struct NCR53c7x0_hostdata - * *hostdata, Scsi_Cmnd *cmd) - * - * Purpose : decide if we can pass the given SCSI command on to the - * device in question or not. - * - * Returns : non-zero when we're busy, 0 when we aren't. - */ - -static __inline__ int -busyp (struct Scsi_Host *host, struct NCR53c7x0_hostdata *hostdata, - Scsi_Cmnd *cmd) { - /* FIXME : in the future, this needs to accomodate SCSI-II tagged - queuing, and we may be able to play with fairness here a bit. - */ - return hostdata->busy[cmd->target][cmd->lun]; -} - -/* - * Function : process_issue_queue (void) - * - * Purpose : transfer commands from the issue queue to NCR start queue - * of each NCR53c7/8xx in the system, avoiding kernel stack - * overflows when the scsi_done() function is invoked recursively. - * - * NOTE : process_issue_queue exits with interrupts *disabled*, so the - * caller must renable them if it desires. - * - * NOTE : process_issue_queue should be called from both - * NCR53c7x0_queue_command() and from the interrupt handler - * after command completion in case NCR53c7x0_queue_command() - * isn't invoked again but we've freed up resources that are - * needed. - */ - -static void -process_issue_queue (unsigned long flags) { - Scsi_Cmnd *tmp, *prev; - struct Scsi_Host *host; - struct NCR53c7x0_hostdata *hostdata; - int done; - - /* - * We run (with interrupts disabled) until we're sure that none of - * the host adapters have anything that can be done, at which point - * we set process_issue_queue_running to 0 and exit. - * - * Interrupts are enabled before doing various other internal - * instructions, after we've decided that we need to run through - * the loop again. - * - */ - - do { - cli(); /* Freeze request queues */ - done = 1; - for (host = first_host; host && host->hostt == the_template; - host = host->next) { - hostdata = (struct NCR53c7x0_hostdata *) host->hostdata; - cli(); - if (hostdata->issue_queue) { - if (hostdata->state == STATE_DISABLED) { - tmp = (Scsi_Cmnd *) hostdata->issue_queue; - hostdata->issue_queue = (Scsi_Cmnd *) tmp->SCp.ptr; - tmp->result = (DID_BAD_TARGET << 16); - if (tmp->host_scribble) { - ((struct NCR53c7x0_cmd *)tmp->host_scribble)->next = - hostdata->free; - hostdata->free = - (struct NCR53c7x0_cmd *)tmp->host_scribble; - tmp->host_scribble = NULL; - } - tmp->scsi_done (tmp); - done = 0; - } else - for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, - prev = NULL; tmp; prev = tmp, tmp = (Scsi_Cmnd *) - tmp->SCp.ptr) - if (!tmp->host_scribble || - !busyp (host, hostdata, tmp)) { - if (prev) - prev->SCp.ptr = tmp->SCp.ptr; - else - hostdata->issue_queue = (Scsi_Cmnd *) - tmp->SCp.ptr; - tmp->SCp.ptr = NULL; - if (tmp->host_scribble) { - if (hostdata->options & OPTION_DEBUG_QUEUES) - printk ("scsi%d : moving command for target %d lun %d to start list\n", - host->host_no, tmp->target, tmp->lun); - - - to_schedule_list (host, hostdata, - (struct NCR53c7x0_cmd *) - tmp->host_scribble); - } else { - if (((tmp->result & 0xff) == 0xff) || - ((tmp->result & 0xff00) == 0xff00)) { - printk ("scsi%d : danger Will Robinson!\n", - host->host_no); - tmp->result = DID_ERROR << 16; - disable (host); - } - tmp->scsi_done(tmp); - } - done = 0; - } /* if target/lun is not busy */ - } /* if hostdata->issue_queue */ - if (!done) - restore_flags (flags); - } /* for host */ - } while (!done); - process_issue_queue_running = 0; -} - -/* - * Function : static void intr_scsi (struct Scsi_Host *host, - * struct NCR53c7x0_cmd *cmd) - * - * Purpose : handle all SCSI interrupts, indicated by the setting - * of the SIP bit in the ISTAT register. - * - * Inputs : host, cmd - host and NCR command causing the interrupt, cmd - * may be NULL. - */ - -static void -intr_scsi (struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd) { - NCR53c7x0_local_declare(); - struct NCR53c7x0_hostdata *hostdata = - (struct NCR53c7x0_hostdata *) host->hostdata; - unsigned char sstat0_sist0, sist1, /* Registers */ - fatal; /* Did a fatal interrupt - occur ? */ - - int is_8xx_chip; - NCR53c7x0_local_setup(host); - - fatal = 0; - - is_8xx_chip = ((unsigned) (hostdata->chip - 800)) < 100; - if (is_8xx_chip) { - sstat0_sist0 = NCR53c7x0_read8(SIST0_REG_800); - udelay(1); - sist1 = NCR53c7x0_read8(SIST1_REG_800); - } else { - sstat0_sist0 = NCR53c7x0_read8(SSTAT0_REG); - sist1 = 0; - } - - if (hostdata->options & OPTION_DEBUG_INTR) - printk ("scsi%d : SIST0 0x%0x, SIST1 0x%0x\n", host->host_no, - sstat0_sist0, sist1); - - /* 250ms selection timeout */ - if ((is_8xx_chip && (sist1 & SIST1_800_STO)) || - (!is_8xx_chip && (sstat0_sist0 & SSTAT0_700_STO))) { - fatal = 1; - if (hostdata->options & OPTION_DEBUG_INTR) { - printk ("scsi%d : Selection Timeout\n", host->host_no); - if (cmd) { - printk("scsi%d : target %d, lun %d, command ", - host->host_no, cmd->cmd->target, cmd->cmd->lun); - print_command (cmd->cmd->cmnd); - printk("scsi%d : dsp = 0x%x (virt 0x%p)\n", host->host_no, - NCR53c7x0_read32(DSP_REG), - bus_to_virt(NCR53c7x0_read32(DSP_REG))); - } else { - printk("scsi%d : no command\n", host->host_no); - } - } -/* - * XXX - question : how do we want to handle the Illegal Instruction - * interrupt, which may occur before or after the Selection Timeout - * interrupt? - */ - - if (1) { - hostdata->idle = 1; - hostdata->expecting_sto = 0; - - if (hostdata->test_running) { - hostdata->test_running = 0; - hostdata->test_completed = 3; - } else if (cmd) { - abnormal_finished(cmd, DID_BAD_TARGET << 16); - } -#if 0 - hostdata->intrs = 0; -#endif - } - } - -/* - * FIXME : in theory, we can also get a UDC when a STO occurs. - */ - if (sstat0_sist0 & SSTAT0_UDC) { - fatal = 1; - if (cmd) { - printk("scsi%d : target %d lun %d unexpected disconnect\n", - host->host_no, cmd->cmd->target, cmd->cmd->lun); - print_lots (host); - abnormal_finished(cmd, DID_ERROR << 16); - } else - printk("scsi%d : unexpected disconnect (no command)\n", - host->host_no); - - hostdata->dsp = (u32 *) hostdata->schedule; - hostdata->dsp_changed = 1; - } - - /* SCSI PARITY error */ - if (sstat0_sist0 & SSTAT0_PAR) { - fatal = 1; - if (cmd && cmd->cmd) { - printk("scsi%d : target %d lun %d parity error.\n", - host->host_no, cmd->cmd->target, cmd->cmd->lun); - abnormal_finished (cmd, DID_PARITY << 16); - } else - printk("scsi%d : parity error\n", host->host_no); - /* Should send message out, parity error */ - - /* XXX - Reduce synchronous transfer rate! */ - hostdata->dsp = hostdata->script + hostdata->E_initiator_abort / - sizeof(u32); - hostdata->dsp_changed = 1; - /* SCSI GROSS error */ - } - - if (sstat0_sist0 & SSTAT0_SGE) { - fatal = 1; - printk("scsi%d : gross error\n", host->host_no); - /* Reset SCSI offset */ - if ((hostdata->chip / 100) == 8) { - NCR53c7x0_write8 (STEST2_REG_800, STEST2_800_ROF); - } - - /* - * A SCSI gross error may occur when we have - * - * - A synchronous offset which causes the SCSI FIFO to be overwritten. - * - * - A REQ which causes the maxmimum synchronous offset programmed in - * the SXFER register to be exceeded. - * - * - A phase change with an outstanding synchronous offset. - * - * - Residual data in the synchronous data FIFO, with a transfer - * other than a synchronous receive is started.$# - */ - - - /* XXX Should deduce synchronous transfer rate! */ - hostdata->dsp = hostdata->script + hostdata->E_initiator_abort / - sizeof(u32); - hostdata->dsp_changed = 1; - /* Phase mismatch */ - } - - if (sstat0_sist0 & SSTAT0_MA) { - fatal = 1; - if (hostdata->options & OPTION_DEBUG_INTR) - printk ("scsi%d : SSTAT0_MA\n", host->host_no); - intr_phase_mismatch (host, cmd); - } - -#if 0 - if (sstat0_sist0 & SIST0_800_RSL) - printk ("scsi%d : Oh no Mr. Bill!\n", host->host_no); -#endif - -/* - * If a fatal SCSI interrupt occurs, we must insure that the DMA and - * SCSI FIFOs were flushed. - */ - - if (fatal) { - if (!hostdata->dstat_valid) { - hostdata->dstat = NCR53c7x0_read8(DSTAT_REG); - hostdata->dstat_valid = 1; - } - -/* XXX - code check for 700/800 chips */ - if (!(hostdata->dstat & DSTAT_DFE)) { - printk ("scsi%d : DMA FIFO not empty\n", host->host_no); - if (NCR53c7x0_read8 (CTEST2_REG_800) & CTEST2_800_DDIR) { - printk ("scsi%d: Flushing DMA FIFO\n", - host->host_no); - NCR53c7x0_write8 (CTEST3_REG_800, CTEST3_800_FLF); - while (!((hostdata->dstat = NCR53c7x0_read8(DSTAT_REG)) & - DSTAT_DFE)); - } else { - NCR53c7x0_write8 (CTEST3_REG_800, CTEST3_800_CLF); - while (NCR53c7x0_read8 (CTEST3_REG_800) & CTEST3_800_CLF); - } - hostdata->dstat |= DSTAT_DFE; - } - } -} - -/* - * Function : static void NCR53c7x0_intr (int irq, struct pt_regs * regs) - * - * Purpose : handle NCR53c7x0 interrupts for all NCR devices sharing - * the same IRQ line. - * - * Inputs : Since we're using the SA_INTERRUPT interrupt handler - * semantics, irq indicates the interrupt which invoked - * this handler. - */ - -static void -NCR53c7x0_intr (int irq, struct pt_regs * regs) { - NCR53c7x0_local_declare(); - struct Scsi_Host *host; /* Host we are looking at */ - unsigned char istat; /* Values of interrupt regs */ - struct NCR53c7x0_hostdata *hostdata; /* host->hostdata */ - struct NCR53c7x0_cmd *cmd, /* command which halted */ - **cmd_prev_ptr; - u32 *dsa; /* DSA */ - int done = 1; /* Indicates when handler - should terminate */ - int interrupted = 0; /* This HA generated - an interrupt */ - int have_intfly; /* Don't print warning - messages when we stack - INTFLYs */ - unsigned long flags; - -#ifdef NCR_DEBUG - char buf[80]; /* Debugging sprintf buffer */ - size_t buflen; /* Length of same */ -#endif - - do { - done = 1; - for (host = first_host; host; host = host->next) - if (host->hostt == the_template && host->irq == irq) { - NCR53c7x0_local_setup(host); - - hostdata = (struct NCR53c7x0_hostdata *) host->hostdata; - hostdata->dsp_changed = 0; - interrupted = 0; - have_intfly = 0; - - do { - int is_8xx_chip; - - hostdata->dstat_valid = 0; - interrupted = 0; - /* - * Only read istat once, since reading it again will unstack - * interrupts? - */ - istat = NCR53c7x0_read8(hostdata->istat); - - /* - * INTFLY interrupts are used by the NCR53c720, NCR53c810, - * and NCR53c820 to signify completion of a command. Since - * the SCSI processor continues running, we can't just look - * at the contents of the DSA register and continue running. - */ -/* XXX - this is too big, offends my sense of aesthetics, and should - move to intr_intfly() */ - is_8xx_chip = ((unsigned) (hostdata->chip - 800)) < 100; - if ((hostdata->options & OPTION_INTFLY) && - (is_8xx_chip && (istat & ISTAT_800_INTF))) { - char search_found = 0; /* Got at least one ? */ - done = 0; - interrupted = 1; - - /* - * Clear the INTF bit by writing a one. - * This reset operation is self-clearing. - */ - NCR53c7x0_write8(hostdata->istat, istat|ISTAT_800_INTF); - - if (hostdata->options & OPTION_DEBUG_INTR) - printk ("scsi%d : INTFLY\n", host->host_no); - - /* - * Traverse our list of running commands, and look - * for those with valid (non-0xff ff) status and message - * bytes encoded in the result which signify command - * completion. - */ - - - save_flags(flags); - cli(); -restart: - for (cmd_prev_ptr = (struct NCR53c7x0_cmd **) - &(hostdata->running_list), cmd = - (struct NCR53c7x0_cmd *) hostdata->running_list; cmd ; - cmd_prev_ptr = (struct NCR53c7x0_cmd **) &(cmd->next), - cmd = (struct NCR53c7x0_cmd *) cmd->next) { - Scsi_Cmnd *tmp; - - if (!cmd) { - printk("scsi%d : very weird.\n", host->host_no); - break; - } - - if (!(tmp = cmd->cmd)) { - printk("scsi%d : weird. NCR53c7x0_cmd has no Scsi_Cmnd\n", - host->host_no); - continue; - } -#if 0 - printk ("scsi%d : looking at result of 0x%x\n", - host->host_no, cmd->cmd->result); -#endif - - if (((tmp->result & 0xff) == 0xff) || - ((tmp->result & 0xff00) == 0xff00)) - continue; - - search_found = 1; - - /* Important - remove from list _before_ done is called */ - if (cmd_prev_ptr) - *cmd_prev_ptr = (struct NCR53c7x0_cmd *) cmd->next; - - --hostdata->busy[tmp->target][tmp->lun]; - cmd->next = hostdata->free; - hostdata->free = cmd; - - tmp->host_scribble = NULL; - - if (hostdata->options & OPTION_DEBUG_INTR) { - printk ("scsi%d : command complete : pid %lu, id %d,lun %d result 0x%x ", - host->host_no, tmp->pid, tmp->target, tmp->lun, tmp->result); - print_command (tmp->cmnd); - } - -#if 0 - hostdata->options &= ~OPTION_DEBUG_INTR; -#endif - tmp->scsi_done(tmp); - goto restart; - - } - restore_flags(flags); - - /* - * I think that we're stacking INTFLY interrupts; taking care of - * all the finished commands on the first one, and then getting - * worried when we see the next one. The magic with have_intfly - * should tell if this is the case.. - */ - - if (!search_found && !have_intfly) { - printk ("scsi%d : WARNING : INTFLY with no completed commands.\n", - host->host_no); - } else if (!have_intfly) { - have_intfly = 1; - run_process_issue_queue(); - } - } - - if (istat & (ISTAT_SIP|ISTAT_DIP)) { - done = 0; - interrupted = 1; - hostdata->state = STATE_HALTED; - - if (NCR53c7x0_read8 ((hostdata->chip / 100) == 8 ? - SSTAT1_REG : SSTAT2_REG) & SSTAT2_FF_MASK) - printk ("scsi%d : SCSI FIFO not empty\n", - host->host_no); - - /* - * NCR53c700 and NCR53c700-66 change the current SCSI - * process, hostdata->current, in the Linux driver so - * cmd = hostdata->current. - * - * With other chips, we must look through the commands - * executing and find the command structure which - * corresponds to the DSA register. - */ - - if (hostdata->options & OPTION_700) { - cmd = (struct NCR53c7x0_cmd *) hostdata->current; - } else { - dsa = bus_to_virt(NCR53c7x0_read32(DSA_REG)); - for (cmd = (struct NCR53c7x0_cmd *) - hostdata->running_list; cmd && - (dsa + (hostdata->dsa_start / sizeof(u32))) != - cmd->dsa; - cmd = (struct NCR53c7x0_cmd *)(cmd->next)); - } - if (hostdata->options & OPTION_DEBUG_INTR) { - if (cmd) { - printk("scsi%d : interrupt for pid %lu, id %d, lun %d ", - host->host_no, cmd->cmd->pid, (int) cmd->cmd->target, - (int) cmd->cmd->lun); - print_command (cmd->cmd->cmnd); - } else { - printk("scsi%d : no active command\n", host->host_no); - } - } - - if (istat & ISTAT_SIP) { - if (hostdata->options & OPTION_DEBUG_INTR) - printk ("scsi%d : ISTAT_SIP\n", host->host_no); - intr_scsi (host, cmd); - } - - if (istat & ISTAT_DIP) { - if (hostdata->options & OPTION_DEBUG_INTR) - printk ("scsi%d : ISTAT_DIP\n", host->host_no); - intr_dma (host, cmd); - } - - if (!hostdata->dstat_valid) { - hostdata->dstat = NCR53c7x0_read8(DSTAT_REG); - hostdata->dstat_valid = 1; - } - - /* XXX - code check for 700/800 chips */ - if (!(hostdata->dstat & DSTAT_DFE)) { - printk ("scsi%d : DMA FIFO not empty\n", host->host_no); - if (NCR53c7x0_read8 (CTEST2_REG_800) & CTEST2_800_DDIR) { - printk ("scsi%d: Flushing DMA FIFO\n", - host->host_no); - NCR53c7x0_write8 (CTEST3_REG_800, CTEST3_800_FLF); - while (!((hostdata->dstat = NCR53c7x0_read8(DSTAT_REG)) & - DSTAT_DFE)); - } else - { - NCR53c7x0_write8 (CTEST3_REG_800, CTEST3_800_CLF); - while (NCR53c7x0_read8 (CTEST3_REG_800) & CTEST3_800_CLF); - } - hostdata->dstat |= DSTAT_DFE; - } - } - } while (interrupted); - - - - if (hostdata->intrs != -1) - hostdata->intrs++; -#if 0 - if (hostdata->intrs > 40) { - printk("scsi%d : too many interrupts, halting", host->host_no); - disable(host); - } -#endif - - if (!hostdata->idle && hostdata->state == STATE_HALTED) { - if (!hostdata->dsp_changed) { - hostdata->dsp = (u32 *) - bus_to_virt(NCR53c7x0_read32(DSP_REG)); - } - -#if 0 - printk("scsi%d : new dsp is 0x%lx (virt 0x%p)\n", - host->host_no, virt_to_bus(hostdata->dsp), hostdata->dsp); -#endif - - hostdata->state = STATE_RUNNING; - NCR53c7x0_write32 (DSP_REG, virt_to_bus(hostdata->dsp)); - } - } - } while (!done); -} - - -/* - * Function : static int abort_connected (struct Scsi_Host *host) - * - * Purpose : Assuming that the NCR SCSI processor is currently - * halted, break the currently established nexus. Clean - * up of the NCR53c7x0_cmd and Scsi_Cmnd structures should - * be done on receipt of the abort interrupt. - * - * Inputs : host - SCSI host - * - */ - -static int -abort_connected (struct Scsi_Host *host) { -#ifdef NEW_ABORT - NCR53c7x0_local_declare(); -#endif - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - host->hostdata; -/* FIXME : this probably should change for production kernels; at the - least, counter sould move to a per-host structure. */ - static int counter = 5; -#ifdef NEW_ABORT - int sstat, phase, offset; - u32 *script; - NCR53c7x0_local_setup(host); -#endif - - if (--counter <= 0) { - disable(host); - return 0; - } - - printk ("scsi%d : DANGER : abort_connected() called \n", - host->host_no); - -#ifdef NEW_ABORT - -/* - * New strategy : Rather than using a generic abort routine, - * we'll specifically try to source or sink the appropriate - * amount of data for the phase we're currently in (taking into - * account the current synchronous offset) - */ - - sstat = (NCR53c8x0_read8 ((chip / 100) == 8 ? SSTAT1_REG : SSTAT2_REG); - offset = OFFSET (sstat & SSTAT2_FF_MASK) >> SSTAT2_FF_SHIFT; - phase = sstat & SSTAT2_PHASE_MASK; - -/* - * SET ATN - * MOVE source_or_sink, WHEN CURRENT PHASE - * < repeat for each outstanding byte > - * JUMP send_abort_message - */ - - script = hostdata->abort_script = kmalloc ( - 8 /* instruction size */ * ( - 1 /* set ATN */ + - (!offset ? 1 : offset) /* One transfer per outstanding byte */ + - 1 /* send abort message */), - GFP_ATOMIC); - - -#else /* def NEW_ABORT */ - hostdata->dsp = hostdata->script + hostdata->E_initiator_abort / - sizeof(u32); -#endif /* def NEW_ABORT */ - hostdata->dsp_changed = 1; - -/* XXX - need to flag the command as aborted after the abort_connected - code runs - */ - return 0; -} - -/* - * Function : static int datapath_residual (Scsi_Host *host) - * - * Purpose : return residual data count of what's in the chip. - * - * Inputs : host - SCSI host - */ - -static int -datapath_residual (struct Scsi_Host *host) { - NCR53c7x0_local_declare(); - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - host->hostdata; - int count, synchronous, sstat; - NCR53c7x0_local_setup(host); - /* COMPAT : the 700 and 700-66 need to use DFIFO_00_BO_MASK */ - count = ((NCR53c7x0_read8 (DFIFO_REG) & DFIFO_10_BO_MASK) - - (NCR53c7x0_read32 (DBC_REG) & DFIFO_10_BO_MASK)) & DFIFO_10_BO_MASK; - synchronous = NCR53c7x0_read8 (SXFER_REG) & SXFER_MO_MASK; - /* COMPAT : DDIR is elsewhere on non-'8xx chips. */ - if (NCR53c7x0_read8 (CTEST2_REG_800) & CTEST2_800_DDIR) { - /* Receive */ - if (synchronous) - count += (NCR53c7x0_read8 ((hostdata->chip / 100) == 8 ? - SSTAT1_REG : SSTAT2_REG) & SSTAT2_FF_MASK) >> SSTAT2_FF_SHIFT; - else - if (NCR53c7x0_read8 ((hostdata->chip / 100) == 8 ? - SSTAT0_REG : SSTAT1_REG) & SSTAT1_ILF) - ++count; - } else { - /* Send */ - sstat = ((hostdata->chip / 100) == 8) ? NCR53c7x0_read8 (SSTAT0_REG) : - NCR53c7x0_read8 (SSTAT1_REG); - if (sstat & SSTAT1_OLF) - ++count; - if (synchronous && (sstat & SSTAT1_ORF)) - ++count; - } - return count; -} - -/* - * Function : static const char * sbcl_to_phase (int sbcl)_ - * - * Purpose : Convert SBCL register to user-parsable phase representation - * - * Inputs : sbcl - value of sbcl register - */ - - -static const char * -sbcl_to_phase (int sbcl) { - switch (sbcl & SBCL_PHASE_MASK) { - case SBCL_PHASE_DATAIN: - return "DATAIN"; - case SBCL_PHASE_DATAOUT: - return "DATAOUT"; - case SBCL_PHASE_MSGIN: - return "MSGIN"; - case SBCL_PHASE_MSGOUT: - return "MSGOUT"; - case SBCL_PHASE_CMDOUT: - return "CMDOUT"; - case SBCL_PHASE_STATIN: - return "STATUSIN"; - default: - return "unknown"; - } -} - -/* - * Function : static const char * sstat2_to_phase (int sstat)_ - * - * Purpose : Convert SSTAT2 register to user-parsable phase representation - * - * Inputs : sstat - value of sstat register - */ - - -static const char * -sstat2_to_phase (int sstat) { - switch (sstat & SSTAT2_PHASE_MASK) { - case SSTAT2_PHASE_DATAIN: - return "DATAIN"; - case SSTAT2_PHASE_DATAOUT: - return "DATAOUT"; - case SSTAT2_PHASE_MSGIN: - return "MSGIN"; - case SSTAT2_PHASE_MSGOUT: - return "MSGOUT"; - case SSTAT2_PHASE_CMDOUT: - return "CMDOUT"; - case SSTAT2_PHASE_STATIN: - return "STATUSIN"; - default: - return "unknown"; - } -} - -/* - * Function : static void intr_phase_mismatch (struct Scsi_Host *host, - * struct NCR53c7x0_cmd *cmd) - * - * Purpose : Handle phase mismatch interrupts - * - * Inputs : host, cmd - host and NCR command causing the interrupt, cmd - * may be NULL. - * - * Side effects : The abort_connected() routine is called or the NCR chip - * is restarted, jumping to the command_complete entry point, or - * patching the address and transfer count of the current instruction - * and calling the msg_in entry point as appropriate. - */ - -static void -intr_phase_mismatch (struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd) { - NCR53c7x0_local_declare(); - u32 dbc_dcmd, *dsp, *dsp_next; - unsigned char dcmd, sbcl; - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - host->hostdata; - int residual; - enum {ACTION_ABORT, ACTION_ABORT_PRINT, ACTION_CONTINUE} action = - ACTION_ABORT_PRINT; - const char *where = NULL; - NCR53c7x0_local_setup(host); - - /* - * Corrective action is based on where in the SCSI SCRIPT(tm) the error - * occurred, as well as which SCSI phase we are currently in. - */ - dsp_next = bus_to_virt(NCR53c7x0_read32(DSP_REG)); - - /* - * Fetch the current instruction, and remove the operands for easier - * interpretation. - */ - dbc_dcmd = NCR53c7x0_read32(DBC_REG); - dcmd = (dbc_dcmd & 0xff000000) >> 24; - /* - * Like other processors, the NCR adjusts the instruction pointer before - * instruction decode. Set the DSP address back to what it should - * be for this instruction based on its size (2 or 3 32 bit words). - */ - dsp = dsp_next - NCR53c7x0_insn_size(dcmd); - - - /* - * Read new SCSI phase from the SBCL lines. Since all of our code uses - * a WHEN conditional instead of an IF conditional, we don't need to - * wait for a new REQ. - */ - sbcl = NCR53c7x0_read8(SBCL_REG) & SBCL_PHASE_MASK; - - if (!cmd) { - action = ACTION_ABORT_PRINT; - where = "no current command"; - /* - * The way my SCSI SCRIPTS(tm) are architected, recoverable phase - * mismatches should only occur where we're doing a multi-byte - * BMI instruction. Specifically, this means - * - * - select messages (a SCSI-I target may ignore additional messages - * after the IDENTIFY; any target may reject a SDTR or WDTR) - * - * - command out (targets may send a message to signal an error - * condition, or go into STATUSIN after they've decided - * they don't like the command. - * - * - reply_message (targets may reject a multi-byte message in the - * middle) - * - * - data transfer routines (command completion with buffer space - * left, disconnect message, or error message) - */ - } else if (((dsp >= cmd->data_transfer_start && - dsp < cmd->data_transfer_end)) || dsp == (cmd->residual + 2)) { - if ((dcmd & (DCMD_TYPE_MASK|DCMD_BMI_OP_MASK|DCMD_BMI_INDIRECT| - DCMD_BMI_MSG|DCMD_BMI_CD)) == (DCMD_TYPE_BMI| - DCMD_BMI_OP_MOVE_I)) { - residual = datapath_residual (host); - if (hostdata->options & OPTION_DEBUG_DISCONNECT) - printk ("scsi%d : handling residual transfer (+ %d bytes from DMA FIFO)\n", - host->host_no, residual); - - /* - * The first instruction is a CALL to the alternate handler for - * this data transfer phase, so we can do calls to - * munge_msg_restart as we would if control were passed - * from normal dynamic code. - */ - if (dsp != cmd->residual + 2) { - cmd->residual[0] = ((DCMD_TYPE_TCI | DCMD_TCI_OP_CALL | - ((dcmd & DCMD_BMI_IO) ? DCMD_TCI_IO : 0)) << 24) | - DBC_TCI_WAIT_FOR_VALID | DBC_TCI_COMPARE_PHASE; - cmd->residual[1] = virt_to_bus(hostdata->script) - + ((dcmd & DCMD_BMI_IO) - ? hostdata->E_other_in : hostdata->E_other_out); - } - - /* - * The second instruction is the a data transfer block - * move instruction, reflecting the pointer and count at the - * time of the phase mismatch. - */ - cmd->residual[2] = dbc_dcmd + residual; - cmd->residual[3] = NCR53c7x0_read32(DNAD_REG) - residual; - - /* - * The third and final instruction is a jump to the instruction - * which follows the instruction which had to be 'split' - */ - if (dsp != cmd->residual + 2) { - cmd->residual[4] = ((DCMD_TYPE_TCI|DCMD_TCI_OP_JUMP) - << 24) | DBC_TCI_TRUE; - cmd->residual[5] = virt_to_bus(dsp_next); - } - - /* - * For the sake of simplicity, transfer control to the - * conditional CALL at the start of the residual buffer. - */ - hostdata->dsp = cmd->residual; - hostdata->dsp_changed = 1; - action = ACTION_CONTINUE; - } else { - where = "non-BMI dynamic DSA code"; - action = ACTION_ABORT_PRINT; - } - } else if (dsp == (hostdata->script + hostdata->E_select_msgout / 4)) { - /* Release ATN */ - NCR53c7x0_write8 (SOCL_REG, 0); - switch (sbcl) { - /* - * Some devices (SQ555 come to mind) grab the IDENTIFY message - * sent on selection, and decide to go into COMMAND OUT phase - * rather than accepting the rest of the messages or rejecting - * them. Handle these devices gracefully. - */ - case SBCL_PHASE_CMDOUT: - hostdata->dsp = dsp + 2 /* two _words_ */; - hostdata->dsp_changed = 1; - printk ("scsi%d : target %d ignored SDTR and went into COMMAND OUT\n", - host->host_no, cmd->cmd->target); - cmd->flags &= ~CMD_FLAG_SDTR; - action = ACTION_CONTINUE; - break; - case SBCL_PHASE_MSGIN: - hostdata->dsp = hostdata->script + hostdata->E_msg_in / - sizeof(u32); - hostdata->dsp_changed = 1; - action = ACTION_CONTINUE; - break; - default: - where="select message out"; - action = ACTION_ABORT_PRINT; - } - /* - * Some SCSI devices will interpret a command as they read the bytes - * off the SCSI bus, and may decide that the command is Bogus before - * they've read the entire commad off the bus. - */ - } else if (dsp == hostdata->script + hostdata->E_cmdout_cmdout / sizeof - (u32)) { - hostdata->dsp = hostdata->script + hostdata->E_data_transfer / - sizeof (u32); - hostdata->dsp_changed = 1; - action = ACTION_CONTINUE; - /* FIXME : we need to handle message reject, etc. within msg_respond. */ -#ifdef notyet - } else if (dsp == hostdata->script + hostdata->E_reply_message) { - switch (sbcl) { - /* Any other phase mismatches abort the currently executing command. */ -#endif - } else { - where = "unknown location"; - action = ACTION_ABORT_PRINT; - } - - /* Flush DMA FIFO */ - if (!hostdata->dstat_valid) { - hostdata->dstat = NCR53c7x0_read8(DSTAT_REG); - hostdata->dstat_valid = 1; - } - if (!(hostdata->dstat & DSTAT_DFE)) { - if (NCR53c7x0_read8 (CTEST2_REG_800) & CTEST2_800_DDIR) { - printk ("scsi%d: Flushing DMA FIFO\n", - host->host_no); - NCR53c7x0_write8 (CTEST3_REG_800, CTEST3_800_FLF); - /* FIXME : what about stacked DMA interrupts? */ - while (!((hostdata->dstat = NCR53c7x0_read8(DSTAT_REG)) & - DSTAT_DFE)); - } else { - NCR53c7x0_write8 (CTEST3_REG_800, CTEST3_800_CLF); - while (NCR53c7x0_read8 (CTEST3_REG_800) & CTEST3_800_CLF); - } - hostdata->dstat |= DSTAT_DFE; - } - - switch (action) { - case ACTION_ABORT_PRINT: - printk("scsi%d : %s : unexpected phase %s.\n", - host->host_no, where ? where : "unknown location", - sbcl_to_phase(sbcl)); - print_lots (host); - /* Fall through to ACTION_ABORT */ - case ACTION_ABORT: - abort_connected (host); - break; - case ACTION_CONTINUE: - break; - } - -#if 0 - if (hostdata->dsp_changed) { - printk("scsi%d: new dsp 0x%p\n", host->host_no, hostdata->dsp); - print_insn (host, hostdata->dsp, "", 1); - } -#endif - -} - -/* - * Function : static void intr_bf (struct Scsi_Host *host, - * struct NCR53c7x0_cmd *cmd) - * - * Purpose : handle BUS FAULT interrupts - * - * Inputs : host, cmd - host and NCR command causing the interrupt, cmd - * may be NULL. - */ - -static void -intr_bf (struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd) { - NCR53c7x0_local_declare(); - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - host->hostdata; - u32 *dsp, - *next_dsp, /* Current dsp */ - *dsa, - dbc_dcmd; /* DCMD (high eight bits) + DBC */ - unsigned short pci_status; - int tmp; - unsigned long flags; - char *reason = NULL; - /* Default behavior is for a silent error, with a retry until we've - exhausted retries. */ - enum {MAYBE, ALWAYS, NEVER} retry = MAYBE; - int report = 0; - NCR53c7x0_local_setup(host); - - dbc_dcmd = NCR53c7x0_read32 (DBC_REG); - next_dsp = bus_to_virt (NCR53c7x0_read32(DSP_REG)); - dsp = next_dsp - NCR53c7x0_insn_size ((dbc_dcmd >> 24) & 0xff); -/* FIXME - check chip type */ - dsa = bus_to_virt (NCR53c7x0_read32(DSA_REG)); - - /* - * Bus faults can be caused by either a Bad Address or - * Target Abort. We should check the Received Target Abort - * bit of the PCI status register and Master Abort Bit. - * - * - Master Abort bit indicates that no device claimed - * the address with DEVSEL within five clocks - * - * - Target Abort bit indicates that a target claimed it, - * but changed its mind once it saw the byte enables. - * - */ - - if ((hostdata->chip / 100) == 8) { - save_flags (flags); - cli(); - tmp = pcibios_read_config_word (hostdata->pci_bus, - hostdata->pci_device_fn, PCI_STATUS, &pci_status); - restore_flags (flags); - if (tmp == PCIBIOS_SUCCESSFUL) { - if (pci_status & PCI_STATUS_REC_TARGET_ABORT) { - reason = "PCI target abort"; - pci_status &= ~PCI_STATUS_REC_TARGET_ABORT; - } else if (pci_status & PCI_STATUS_REC_MASTER_ABORT) { - reason = "No device asserted PCI DEVSEL within five bus clocks"; - pci_status &= ~PCI_STATUS_REC_MASTER_ABORT; - } else if (pci_status & PCI_STATUS_PARITY) { - report = 1; - pci_status &= ~PCI_STATUS_PARITY; - } - } else { - printk ("scsi%d : couldn't read status register : %s\n", - host->host_no, pcibios_strerror (tmp)); - retry = NEVER; - } - } - -#ifndef notyet - report = 1; -#endif - if (report && reason) { - printk(KERN_ALERT "scsi%d : BUS FAULT reason = %s\n", - host->host_no, reason ? reason : "unknown"); - print_lots (host); - } - -#ifndef notyet - retry = NEVER; -#endif - - /* - * TODO : we should attempt to recover from any spurious bus - * faults. After X retries, we should figure that things are - * sufficiently wedged, and call NCR53c7xx_reset. - * - * This code should only get executed once we've decided that we - * cannot retry. - */ - - if (retry == NEVER) { - printk(KERN_ALERT " mail drew@PoohSticks.ORG\n"); - FATAL (host); - } -} - -/* - * Function : static void intr_dma (struct Scsi_Host *host, - * struct NCR53c7x0_cmd *cmd) - * - * Purpose : handle all DMA interrupts, indicated by the setting - * of the DIP bit in the ISTAT register. - * - * Inputs : host, cmd - host and NCR command causing the interrupt, cmd - * may be NULL. - */ - -static void -intr_dma (struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd) { - NCR53c7x0_local_declare(); - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - host->hostdata; - unsigned char dstat; /* DSTAT */ - u32 *dsp, - *next_dsp, /* Current dsp */ - *dsa, - dbc_dcmd; /* DCMD (high eight bits) + DBC */ - int tmp; - unsigned long flags; - NCR53c7x0_local_setup(host); - - if (!hostdata->dstat_valid) { - hostdata->dstat = NCR53c7x0_read8(DSTAT_REG); - hostdata->dstat_valid = 1; - } - - dstat = hostdata->dstat; - - if (hostdata->options & OPTION_DEBUG_INTR) - printk("scsi%d : DSTAT=0x%x\n", host->host_no, (int) dstat); - - dbc_dcmd = NCR53c7x0_read32 (DBC_REG); - next_dsp = bus_to_virt(NCR53c7x0_read32(DSP_REG)); - dsp = next_dsp - NCR53c7x0_insn_size ((dbc_dcmd >> 24) & 0xff); -/* XXX - check chip type */ - dsa = bus_to_virt(NCR53c7x0_read32(DSA_REG)); - - /* - * DSTAT_ABRT is the aborted interrupt. This is set whenever the - * SCSI chip is aborted. - * - * With NCR53c700 and NCR53c700-66 style chips, we should only - * get this when the chip is currently running the accept - * reselect/select code and we have set the abort bit in the - * ISTAT register. - * - */ - - if (dstat & DSTAT_ABRT) { -#if 0 - /* XXX - add code here to deal with normal abort */ - if ((hostdata->options & OPTION_700) && (hostdata->state == - STATE_ABORTING)) { - } else -#endif - { - printk(KERN_ALERT "scsi%d : unexpected abort interrupt at\n" - " ", host->host_no); - print_insn (host, dsp, KERN_ALERT "s ", 1); - FATAL (host); - } - } - - /* - * DSTAT_SSI is the single step interrupt. Should be generated - * whenever we have single stepped or are tracing. - */ - - if (dstat & DSTAT_SSI) { - if (hostdata->options & OPTION_DEBUG_TRACE) { - } else if (hostdata->options & OPTION_DEBUG_SINGLE) { - print_insn (host, dsp, "s ", 0); - save_flags(flags); - cli(); -/* XXX - should we do this, or can we get away with writing dsp? */ - - NCR53c7x0_write8 (DCNTL_REG, (NCR53c7x0_read8(DCNTL_REG) & - ~DCNTL_SSM) | DCNTL_STD); - restore_flags(flags); - } else { - printk(KERN_ALERT "scsi%d : unexpected single step interrupt at\n" - " ", host->host_no); - print_insn (host, dsp, KERN_ALERT "", 1); - printk(KERN_ALERT " mail drew@PoohSticks.ORG\n"); - FATAL (host); - } - } - - /* - * DSTAT_IID / DSTAT_OPC (same bit, same meaning, only the name - * is different) is generated whenever an illegal instruction is - * encountered. - * - * XXX - we may want to emulate INTFLY here, so we can use - * the same SCSI SCRIPT (tm) for NCR53c710 through NCR53c810 - * chips. - */ - - if (dstat & DSTAT_OPC) { - /* - * Ascertain if this IID interrupts occurred before or after a STO - * interrupt. Since the interrupt handling code now leaves - * DSP unmodified until _after_ all stacked interrupts have been - * processed, reading the DSP returns the original DSP register. - * This means that if dsp lies between the select code, and - * message out following the selection code (where the IID interrupt - * would have to have occurred by due to the implicit wait for REQ), - * we have an IID interrupt resulting from a STO condition and - * can ignore it. - */ - - if (((dsp >= (hostdata->script + hostdata->E_select / sizeof(u32))) && - (dsp <= (hostdata->script + hostdata->E_select_msgout / - sizeof(u32) + 8))) || (hostdata->test_running == 2)) { - if (hostdata->options & OPTION_DEBUG_INTR) - printk ("scsi%d : ignoring DSTAT_IID for SSTAT_STO\n", - host->host_no); - if (hostdata->expecting_iid) { - hostdata->expecting_iid = 0; - hostdata->idle = 1; - if (hostdata->test_running == 2) { - hostdata->test_running = 0; - hostdata->test_completed = 3; - } else if (cmd) - abnormal_finished (cmd, DID_BAD_TARGET << 16); - } else { - hostdata->expecting_sto = 1; - } - /* - * We can't guarantee we'll be able to execute the WAIT DISCONNECT - * instruction within the 3.4us of bus free and arbitration delay - * that a target can RESELECT in and assert REQ after we've dropped - * ACK. If this happens, we'll get an illegal instruction interrupt. - * Doing away with the WAIT DISCONNECT instructions broke everything, - * so instead I'll settle for moving one WAIT DISCONNECT a few - * instructions closer to the CLEAR ACK before it to minimize the - * chances of this happening, and handle it if it occurs anyway. - * - * Simply continue with what we were doing, and control should - * be transfered to the schedule routine which will ultimately - * pass control onto the reselection or selection (not yet) - * code. - */ - } else if (dbc_dcmd == 0x48000000 && (NCR53c7x0_read8 (SBCL_REG) & - SBCL_REQ)) { - if (!(hostdata->options & OPTION_NO_PRINT_RACE)) - { - printk("scsi%d: REQ before WAIT DISCONNECT IID\n", - host->host_no); - hostdata->options |= OPTION_NO_PRINT_RACE; - } - } else { - printk(KERN_ALERT "scsi%d : illegal instruction\n", host->host_no); - print_lots (host); - printk(KERN_ALERT " mail drew@PoohSticks.ORG with ALL\n" - " boot messages and diagnostic output\n"); - FATAL (host); - } - } - - /* - * DSTAT_BF are bus fault errors - */ - - if (dstat & DSTAT_800_BF) { - intr_bf (host, cmd); - } - - - /* - * DSTAT_SIR interrupts are generated by the execution of - * the INT instruction. Since the exact values available - * are determined entirely by the SCSI script running, - * and are local to a particular script, a unique handler - * is called for each script. - */ - - if (dstat & DSTAT_SIR) { - if (hostdata->options & OPTION_DEBUG_INTR) - printk ("scsi%d : DSTAT_SIR\n", host->host_no); - switch ((tmp = hostdata->dstat_sir_intr (host, cmd))) { - case SPECIFIC_INT_NOTHING: - case SPECIFIC_INT_RESTART: - break; - case SPECIFIC_INT_ABORT: - abort_connected(host); - break; - case SPECIFIC_INT_PANIC: - printk(KERN_ALERT "scsi%d : failure at ", host->host_no); - print_insn (host, dsp, KERN_ALERT "", 1); - printk(KERN_ALERT " dstat_sir_intr() returned SPECIFIC_INT_PANIC\n"); - FATAL (host); - break; - case SPECIFIC_INT_BREAK: - intr_break (host, cmd); - break; - default: - printk(KERN_ALERT "scsi%d : failure at ", host->host_no); - print_insn (host, dsp, KERN_ALERT "", 1); - printk(KERN_ALERT" dstat_sir_intr() returned unknown value %d\n", - tmp); - FATAL (host); - } - } - - if ((hostdata->chip / 100) == 8 && (dstat & DSTAT_800_MDPE)) { - printk(KERN_ALERT "scsi%d : Master Data Parity Error\n", - host->host_no); - FATAL (host); - } -} - -/* - * Function : static int print_insn (struct Scsi_Host *host, - * u32 *insn, int kernel) - * - * Purpose : print numeric representation of the instruction pointed - * to by insn to the debugging or kernel message buffer - * as appropriate. - * - * If desired, a user level program can interpret this - * information. - * - * Inputs : host, insn - host, pointer to instruction, prefix - - * string to prepend, kernel - use printk instead of debugging buffer. - * - * Returns : size, in u32s, of instruction printed. - */ - -/* - * FIXME: should change kernel parameter so that it takes an ENUM - * specifying severity - either KERN_ALERT or KERN_PANIC so - * all panic messages are output with the same severity. - */ - -static int -print_insn (struct Scsi_Host *host, const u32 *insn, - const char *prefix, int kernel) { - char buf[160], /* Temporary buffer and pointer. ICKY - arbitrary length. */ - - - *tmp; - unsigned char dcmd; /* dcmd register for *insn */ - int size; - - /* - * Check to see if the instruction pointer is not bogus before - * indirecting through it; avoiding red-zone at start of - * memory. - * - * FIXME: icky magic needs to happen here on non-intel boxes which - * don't have kernel memory mapped in like this. Might be reasonable - * to use vverify()? - */ - - if (MAP_NR(insn) < 1 || MAP_NR(insn + 8) > MAP_NR(high_memory) || - ((((dcmd = (insn[0] >> 24) & 0xff) & DCMD_TYPE_MMI) == DCMD_TYPE_MMI) && - MAP_NR(insn + 12) > MAP_NR(high_memory))) { - size = 0; - sprintf (buf, "%s%p: address out of range\n", - prefix, insn); - } else { -/* - * FIXME : (void *) cast in virt_to_bus should be unecessary, because - * it should take const void * as argument. - */ - sprintf(buf, "%s0x%lx (virt 0x%p) : 0x%08x 0x%08x (virt 0x%p)", - (prefix ? prefix : ""), virt_to_bus((void *) insn), insn, - insn[0], insn[1], bus_to_virt (insn[1])); - tmp = buf + strlen(buf); - if ((dcmd & DCMD_TYPE_MASK) == DCMD_TYPE_MMI) { - sprintf (tmp, " 0x%08x (virt 0x%p)\n", insn[2], - bus_to_virt(insn[2])); - size = 3; - } else { - sprintf (tmp, "\n"); - size = 2; - } - } - - if (kernel) - printk ("%s", buf); -#ifdef NCR_DEBUG - else { - size_t len = strlen(buf); - debugger_kernel_write(host, buf, len); - } -#endif - return size; -} - -/* - * Function : static const char *ncr_state (int state) - * - * Purpose : convert state (probably from hostdata->state) to a string - * - * Inputs : state - * - * Returns : char * representation of state, "unknown" on error. - */ - -static const char * -ncr_state (int state) { - switch (state) { - case STATE_HALTED: return "halted"; - case STATE_WAITING: return "waiting"; - case STATE_RUNNING: return "running"; - case STATE_ABORTING: return "aborting"; - case STATE_DISABLED: return "disabled"; - default: return "unknown"; - } -} - -/* - * Function : int NCR53c7xx_abort (Scsi_Cmnd *cmd) - * - * Purpose : Abort an errant SCSI command, doing all necessary - * cleanup of the issue_queue, running_list, shared Linux/NCR - * dsa issue and reconnect queues. - * - * Inputs : cmd - command to abort, code - entire result field - * - * Returns : 0 on success, -1 on failure. - */ - -int -NCR53c7xx_abort (Scsi_Cmnd *cmd) { - NCR53c7x0_local_declare(); - struct Scsi_Host *host = cmd->host; - struct NCR53c7x0_hostdata *hostdata = host ? (struct NCR53c7x0_hostdata *) - host->hostdata : NULL; - unsigned long flags; - struct NCR53c7x0_cmd *curr, **prev; - Scsi_Cmnd *me, **last; -#if 0 - static long cache_pid = -1; -#endif - - - if (!host) { - printk ("Bogus SCSI command pid %ld; no host structure\n", - cmd->pid); - return SCSI_ABORT_ERROR; - } else if (!hostdata) { - printk ("Bogus SCSI host %d; no hostdata\n", host->host_no); - return SCSI_ABORT_ERROR; - } - NCR53c7x0_local_setup(host); - -/* - * CHECK : I don't think that reading ISTAT will unstack any interrupts, - * since we need to write the INTF bit to clear it, and SCSI/DMA - * interrupts don't clear until we read SSTAT/SIST and DSTAT registers. - * - * See that this is the case. - * - * I suspect that several of our failures may be coming from a new fatal - * interrupt (possibly due to a phase mismatch) happening after we've left - * the interrupt handler, but before the PIC has had the interrupt condition - * cleared. - */ - - if (NCR53c7x0_read8(hostdata->istat) & - (ISTAT_DIP|ISTAT_SIP| - (hostdata->chip / 100 == 8 ? ISTAT_800_INTF : 0))) { - printk ("scsi%d : dropped interrupt for command %ld\n", host->host_no, - cmd->pid); - NCR53c7x0_intr (host->irq, NULL); - return SCSI_ABORT_BUSY; - } - - save_flags(flags); - cli(); -#if 0 - if (cache_pid == cmd->pid) - panic ("scsi%d : bloody fetus %d\n", host->host_no, cmd->pid); - else - cache_pid = cmd->pid; -#endif - - -/* - * The command could be hiding in the issue_queue. This would be very - * nice, as commands can't be moved from the high level driver's issue queue - * into the shared queue until an interrupt routine is serviced, and this - * moving is atomic. - * - * If this is the case, we don't have to worry about anything - we simply - * pull the command out of the old queue, and call it aborted. - */ - - for (me = (Scsi_Cmnd *) hostdata->issue_queue, - last = (Scsi_Cmnd **) &(hostdata->issue_queue); - me && me != cmd; last = (Scsi_Cmnd **)&(me->SCp.ptr), - me = (Scsi_Cmnd *)me->SCp.ptr); - - if (me) { - *last = (Scsi_Cmnd *) me->SCp.ptr; - if (me->host_scribble) { - ((struct NCR53c7x0_cmd *)me->host_scribble)->next = hostdata->free; - hostdata->free = (struct NCR53c7x0_cmd *) me->host_scribble; - me->host_scribble = NULL; - } - cmd->result = DID_ABORT << 16; - cmd->scsi_done(cmd); - printk ("scsi%d : found command %ld in Linux issue queue\n", - host->host_no, me->pid); - restore_flags(flags); - run_process_issue_queue(); - return SCSI_ABORT_SUCCESS; - } - -/* - * That failing, the command could be in our list of already executing - * commands. If this is the case, drastic measures are called for. - */ - - for (curr = (struct NCR53c7x0_cmd *) hostdata->running_list, - prev = (struct NCR53c7x0_cmd **) &(hostdata->running_list); - curr && curr->cmd != cmd; prev = (struct NCR53c7x0_cmd **) - &(curr->next), curr = (struct NCR53c7x0_cmd *) curr->next); - - if (curr) { - if ((cmd->result & 0xff) != 0xff && (cmd->result & 0xff00) != 0xff00) { - if (prev) - *prev = (struct NCR53c7x0_cmd *) curr->next; - curr->next = (struct NCR53c7x0_cmd *) hostdata->free; - cmd->host_scribble = NULL; - hostdata->free = curr; - cmd->scsi_done(cmd); - printk ("scsi%d : found finished command %ld in running list\n", - host->host_no, cmd->pid); - restore_flags(flags); - return SCSI_ABORT_NOT_RUNNING; - } else { - printk ("scsi%d : DANGER : command running, can not abort.\n", - cmd->host->host_no); - restore_flags(flags); - return SCSI_ABORT_BUSY; - } - } - -/* - * And if we couldn't find it in any of our queues, it must have been - * a dropped interrupt. - */ - - curr = (struct NCR53c7x0_cmd *) cmd->host_scribble; - if (curr) { - curr->next = hostdata->free; - hostdata->free = curr; - cmd->host_scribble = NULL; - } - - if (((cmd->result & 0xff00) == 0xff00) || - ((cmd->result & 0xff) == 0xff)) { - printk ("scsi%d : did this command ever run?\n", host->host_no); - cmd->result = DID_ABORT << 16; - } else { - printk ("scsi%d : probably lost INTFLY, normal completion\n", - host->host_no); -/* - * FIXME : We need to add an additional flag which indicates if a - * command was ever counted as BUSY, so if we end up here we can - * decrement the busy count if and only if it is necessary. - */ - --hostdata->busy[cmd->target][cmd->lun]; - } - restore_flags(flags); - cmd->scsi_done(cmd); - -/* - * We need to run process_issue_queue since termination of this command - * may allow another queued command to execute first? - */ - return SCSI_ABORT_NOT_RUNNING; -} - -/* - * Function : int NCR53c7xx_reset (Scsi_Cmnd *cmd) - * - * Purpose : perform a hard reset of the SCSI bus and NCR - * chip. - * - * Inputs : cmd - command which caused the SCSI RESET - * - * Returns : 0 on success. - */ - -int -NCR53c7xx_reset (Scsi_Cmnd *cmd) { - NCR53c7x0_local_declare(); - unsigned long flags; - int found = 0; - struct NCR53c7x0_cmd * c; - Scsi_Cmnd *tmp; - /* - * When we call scsi_done(), it's going to wake up anything sleeping on the - * resources which were in use by the aborted commands, and we'll start to - * get new commands. - * - * We can't let this happen until after we've re-initialized the driver - * structures, and can't reinitilize those structures until after we've - * dealt with their contents. - * - * So, we need to find all of the commands which were running, stick - * them on a linked list of completed commands (we'll use the host_scribble - * pointer), do our reinitialization, and then call the done function for - * each command. - */ - Scsi_Cmnd *nuke_list = NULL; - struct Scsi_Host *host = cmd->host; - struct NCR53c7x0_hostdata *hostdata = - (struct NCR53c7x0_hostdata *) host->hostdata; - - NCR53c7x0_local_setup(host); - save_flags(flags); - cli(); - ncr_halt (host); - print_lots (host); - dump_events (host, 30); - ncr_scsi_reset (host); - for (tmp = nuke_list = return_outstanding_commands (host, 1 /* free */, - 0 /* issue */ ); tmp; tmp = (Scsi_Cmnd *) tmp->SCp.buffer) - if (tmp == cmd) { - found = 1; - break; - } - - /* - * If we didn't find the command which caused this reset in our running - * list, then we've lost it. See that it terminates normally anyway. - */ - if (!found) { - c = (struct NCR53c7x0_cmd *) cmd->host_scribble; - if (c) { - cmd->host_scribble = NULL; - c->next = hostdata->free; - hostdata->free = c; - } else - printk ("scsi%d: lost command %ld\n", host->host_no, cmd->pid); - cmd->SCp.buffer = (struct scatterlist *) nuke_list; - nuke_list = cmd; - } - - NCR53c7x0_driver_init (host); - hostdata->soft_reset (host); - if (hostdata->resets == 0) - disable(host); - else if (hostdata->resets != -1) - --hostdata->resets; - sti(); - for (; nuke_list; nuke_list = tmp) { - tmp = (Scsi_Cmnd *) nuke_list->SCp.buffer; - nuke_list->result = DID_RESET << 16; - nuke_list->scsi_done (nuke_list); - } - restore_flags(flags); - return SCSI_RESET_SUCCESS; -} - -/* - * The NCR SDMS bios follows Annex A of the SCSI-CAM draft, and - * therefore shares the scsicam_bios_param function. - */ - -/* - * Function : int insn_to_offset (Scsi_Cmnd *cmd, u32 *insn) - * - * Purpose : convert instructions stored at NCR pointer into data - * pointer offset. - * - * Inputs : cmd - SCSI command; insn - pointer to instruction. Either current - * DSP, or saved data pointer. - * - * Returns : offset on success, -1 on failure. - */ - - -static int -insn_to_offset (Scsi_Cmnd *cmd, u32 *insn) { - struct NCR53c7x0_hostdata *hostdata = - (struct NCR53c7x0_hostdata *) cmd->host->hostdata; - struct NCR53c7x0_cmd *ncmd = - (struct NCR53c7x0_cmd *) cmd->host_scribble; - int offset = 0, buffers; - struct scatterlist *segment; - char *ptr; - int found = 0; - -/* - * With the current code implementation, if the insn is inside dynamically - * generated code, the data pointer will be the instruction preceeding - * the next transfer segment. - */ - - if (!check_address ((unsigned long) ncmd, sizeof (struct NCR53c7x0_cmd)) && - ((insn >= ncmd->data_transfer_start && - insn < ncmd->data_transfer_end) || - (insn >= ncmd->residual && - insn < (ncmd->residual + - sizeof(ncmd->residual))))) { - ptr = bus_to_virt(insn[3]); - - if ((buffers = cmd->use_sg)) { - for (offset = 0, - segment = (struct scatterlist *) cmd->buffer; - buffers && !((found = ((ptr >= segment->address) && - (ptr < (segment->address + segment->length))))); - --buffers, offset += segment->length, ++segment) -#if 0 - printk("scsi%d: comparing 0x%p to 0x%p\n", - cmd->host->host_no, saved, segment->address); -#else - ; -#endif - offset += ptr - segment->address; - } else { - found = 1; - offset = ptr - (char *) (cmd->request_buffer); - } - } else if ((insn >= hostdata->script + - hostdata->E_data_transfer / sizeof(u32)) && - (insn <= hostdata->script + - hostdata->E_end_data_transfer / sizeof(u32))) { - found = 1; - offset = 0; - } - return found ? offset : -1; -} - - - -/* - * Function : void print_progress (Scsi_Cmnd *cmd) - * - * Purpose : print the current location of the saved data pointer - * - * Inputs : cmd - command we are interested in - * - */ - -static void -print_progress (Scsi_Cmnd *cmd) { - NCR53c7x0_local_declare(); - struct NCR53c7x0_cmd *ncmd = - (struct NCR53c7x0_cmd *) cmd->host_scribble; - int offset, i; - char *where; - u32 *ptr; - NCR53c7x0_local_setup (cmd->host); - for (i = 0; i < 2; ++i) { - if (check_address ((unsigned long) ncmd, - sizeof (struct NCR53c7x0_cmd)) == -1) - continue; - if (!i) { - where = "saved"; - ptr = bus_to_virt(ncmd->saved_data_pointer); - } else { - where = "active"; - ptr = bus_to_virt (NCR53c7x0_read32 (DSP_REG) - - NCR53c7x0_insn_size (NCR53c7x0_read8 (DCMD_REG)) * - sizeof(u32)); - } - offset = insn_to_offset (cmd, ptr); - - if (offset != -1) - printk ("scsi%d : %s data pointer at offset %d\n", - cmd->host->host_no, where, offset); - else { - int size; - printk ("scsi%d : can't determine %s data pointer offset\n", - cmd->host->host_no, where); - if (ncmd) { - size = print_insn (cmd->host, - bus_to_virt(ncmd->saved_data_pointer), "", 1); - print_insn (cmd->host, - bus_to_virt(ncmd->saved_data_pointer) + size * sizeof(u32), - "", 1); - } - } - } -} - - -static void -print_dsa (struct Scsi_Host *host, u32 *dsa, const char *prefix) { - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - host->hostdata; - int i, len; - char *ptr; - Scsi_Cmnd *cmd; - - if (check_address ((unsigned long) dsa, hostdata->dsa_end - - hostdata->dsa_start) == -1) { - printk("scsi%d : bad dsa virt 0x%p\n", host->host_no, dsa); - return; - } - printk("%sscsi%d : dsa at phys 0x%lx (virt 0x%p)\n" - " + %d : dsa_msgout length = %u, data = 0x%x (virt 0x%p)\n" , - prefix ? prefix : "", - host->host_no, virt_to_bus (dsa), dsa, hostdata->dsa_msgout, - dsa[hostdata->dsa_msgout / sizeof(u32)], - dsa[hostdata->dsa_msgout / sizeof(u32) + 1], - bus_to_virt (dsa[hostdata->dsa_msgout / sizeof(u32) + 1])); - - /* - * Only print messages if they're sane in length so we don't - * blow the kernel printk buffer on something which won't buy us - * anything. - */ - - if (dsa[hostdata->dsa_msgout / sizeof(u32)] < - sizeof (hostdata->free->select)) - for (i = dsa[hostdata->dsa_msgout / sizeof(u32)], - ptr = bus_to_virt (dsa[hostdata->dsa_msgout / sizeof(u32) + 1]); - i > 0 && !check_address ((unsigned long) ptr, 1); - ptr += len, i -= len) { - printk(" "); - len = print_msg (ptr); - printk("\n"); - if (!len) - break; - } - - printk(" + %d : select_indirect = 0x%x\n", - hostdata->dsa_select, dsa[hostdata->dsa_select / sizeof(u32)]); - cmd = (Scsi_Cmnd *) bus_to_virt(dsa[hostdata->dsa_cmnd / sizeof(u32)]); - printk(" + %d : dsa_cmnd = 0x%x ", hostdata->dsa_cmnd, - (u32) virt_to_bus(cmd)); - if (cmd) { - printk(" result = 0x%x, target = %d, lun = %d, cmd = ", - cmd->result, cmd->target, cmd->lun); - print_command(cmd->cmnd); - } else - printk("\n"); - printk(" + %d : dsa_next = 0x%x\n", hostdata->dsa_next, - dsa[hostdata->dsa_next / sizeof(u32)]); - if (cmd) { - printk("scsi%d target %d : sxfer_sanity = 0x%x, scntl3_sanity = 0x%x\n" - " script : ", - host->host_no, cmd->target, - hostdata->sync[cmd->target].sxfer_sanity, - hostdata->sync[cmd->target].scntl3_sanity); - for (i = 0; i < (sizeof(hostdata->sync[cmd->target].script) / 4); ++i) - printk ("0x%x ", hostdata->sync[cmd->target].script[i]); - printk ("\n"); - print_progress (cmd); - } -} -/* - * Function : void print_queues (Scsi_Host *host) - * - * Purpose : print the contents of the NCR issue and reconnect queues - * - * Inputs : host - SCSI host we are interested in - * - */ - -static void -print_queues (struct Scsi_Host *host) { - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - host->hostdata; - u32 *dsa, *next_dsa; - volatile u32 *current; - int left; - Scsi_Cmnd *cmd, *next_cmd; - unsigned long flags; - - printk ("scsi%d : issue queue\n", host->host_no); - - for (left = host->can_queue, cmd = (Scsi_Cmnd *) hostdata->issue_queue; - left >= 0 && cmd; - cmd = next_cmd) { - next_cmd = (Scsi_Cmnd *) cmd->SCp.ptr; - save_flags(flags); - cli(); - if (cmd->host_scribble) { - if (check_address ((unsigned long) (cmd->host_scribble), - sizeof (cmd->host_scribble)) == -1) - printk ("scsi%d: scsi pid %ld bad pointer to NCR53c7x0_cmd\n", - host->host_no, cmd->pid); - /* print_dsa does sanity check on address, no need to check */ - else - print_dsa (host, ((struct NCR53c7x0_cmd *) cmd->host_scribble) - -> dsa, ""); - } else - printk ("scsi%d : scsi pid %ld for target %d lun %d has no NCR53c7x0_cmd\n", - host->host_no, cmd->pid, cmd->target, cmd->lun); - restore_flags(flags); - } - - if (left <= 0) { - printk ("scsi%d : loop detected in issue queue\n", - host->host_no); - } - - /* - * Traverse the NCR reconnect and start DSA structures, printing out - * each element until we hit the end or detect a loop. Currently, - * the reconnect structure is a linked list; and the start structure - * is an array. Eventually, the reconnect structure will become a - * list as well, since this simplifies the code. - */ - - printk ("scsi%d : schedule dsa array :\n", host->host_no); - for (left = host->can_queue, current = hostdata->schedule; - left > 0; current += 2, --left) - if (current[0] != hostdata->NOP_insn) -/* FIXME : convert pointer to dsa_begin to pointer to dsa. */ - print_dsa (host, bus_to_virt (current[1] - - (hostdata->E_dsa_code_begin - - hostdata->E_dsa_code_template)), ""); - printk ("scsi%d : end schedule dsa array\n", host->host_no); - - printk ("scsi%d : reconnect_dsa_head :\n", host->host_no); - - for (left = host->can_queue, - dsa = bus_to_virt (hostdata->reconnect_dsa_head); - left >= 0 && dsa; - dsa = next_dsa) { - save_flags (flags); - cli(); - if (check_address ((unsigned long) dsa, sizeof(dsa)) == -1) { - printk ("scsi%d: bad DSA pointer 0x%p", host->host_no, - dsa); - next_dsa = NULL; - } - else - { - next_dsa = bus_to_virt(dsa[hostdata->dsa_next / sizeof(u32)]); - print_dsa (host, dsa, ""); - } - restore_flags(flags); - } - printk ("scsi%d : end reconnect_dsa_head\n", host->host_no); - if (left < 0) - printk("scsi%d: possible loop in ncr reconnect list\n", - host->host_no); -} - -static void -print_lots (struct Scsi_Host *host) { - NCR53c7x0_local_declare(); - struct NCR53c7x0_hostdata *hostdata = - (struct NCR53c7x0_hostdata *) host->hostdata; - u32 *dsp_next, *dsp, *dsa, dbc_dcmd; - unsigned char dcmd, sbcl; - int i, size; - NCR53c7x0_local_setup(host); - - if ((dsp_next = bus_to_virt(NCR53c7x0_read32 (DSP_REG)))) { - dbc_dcmd = NCR53c7x0_read32(DBC_REG); - dcmd = (dbc_dcmd & 0xff000000) >> 24; - dsp = dsp_next - NCR53c7x0_insn_size(dcmd); - dsa = bus_to_virt(NCR53c7x0_read32(DSA_REG)); - sbcl = NCR53c7x0_read8 (SBCL_REG); - - - printk ("scsi%d : DCMD|DBC=0x%x, DNAD=0x%x (virt 0x%p)\n" - " DSA=0x%lx (virt 0x%p)\n" - " DSPS=0x%x, TEMP=0x%x (virt 0x%p), DMODE=0x%x\n" - " SXFER=0x%x, SCNTL3=0x%x\n" - " %s%s%sphase=%s, %d bytes in SCSI FIFO\n" - " STEST0=0x%x\n", - host->host_no, dbc_dcmd, NCR53c7x0_read32(DNAD_REG), - bus_to_virt(NCR53c7x0_read32(DNAD_REG)), - virt_to_bus(dsa), dsa, - NCR53c7x0_read32(DSPS_REG), NCR53c7x0_read32(TEMP_REG), - bus_to_virt (NCR53c7x0_read32(TEMP_REG)), - (int) NCR53c7x0_read8(hostdata->dmode), - (int) NCR53c7x0_read8(SXFER_REG), - (int) NCR53c7x0_read8(SCNTL3_REG_800), - (sbcl & SBCL_BSY) ? "BSY " : "", - (sbcl & SBCL_SEL) ? "SEL " : "", - (sbcl & SBCL_REQ) ? "REQ " : "", - sstat2_to_phase(NCR53c7x0_read8 (((hostdata->chip / 100) == 8) ? - SSTAT1_REG : SSTAT2_REG)), - (NCR53c7x0_read8 ((hostdata->chip / 100) == 8 ? - SSTAT1_REG : SSTAT2_REG) & SSTAT2_FF_MASK) >> SSTAT2_FF_SHIFT, - NCR53c7x0_read8 (STEST0_REG_800)); - printk ("scsi%d : DSP 0x%lx (virt 0x%p) ->\n", host->host_no, - virt_to_bus(dsp), dsp); - for (i = 6; i > 0; --i, dsp += size) - size = print_insn (host, dsp, "", 1); - if (NCR53c7x0_read8 (SCNTL1_REG) & SCNTL1_CON) { - printk ("scsi%d : connected (SDID=0x%x, SSID=0x%x)\n", - host->host_no, NCR53c7x0_read8 (SDID_REG_800), - NCR53c7x0_read8 (SSID_REG_800)); - print_dsa (host, dsa, ""); - } - -#if 1 - print_queues (host); -#endif - } -} - -/* - * Function : static int shutdown (struct Scsi_Host *host) - * - * Purpose : does a clean (we hope) shutdown of the NCR SCSI - * chip. Use prior to dumping core, unloading the NCR driver, - * - * Returns : 0 on success - */ -static int -shutdown (struct Scsi_Host *host) { - NCR53c7x0_local_declare(); - unsigned long flags; - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - host->hostdata; - NCR53c7x0_local_setup(host); - save_flags (flags); - cli(); -/* Get in a state where we can reset the SCSI bus */ - ncr_halt (host); - ncr_scsi_reset (host); - hostdata->soft_reset(host); - - disable (host); - restore_flags (flags); - return 0; -} - -/* - * Function : void ncr_scsi_reset (struct Scsi_Host *host) - * - * Purpose : reset the SCSI bus. - */ - -static void -ncr_scsi_reset (struct Scsi_Host *host) { - NCR53c7x0_local_declare(); - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - host->hostdata; - unsigned long flags; - int sien = 0; - NCR53c7x0_local_setup(host); - save_flags (flags); - cli(); - if ((hostdata->chip / 100) == 8) { - sien = NCR53c7x0_read8(SIEN0_REG_800); - NCR53c7x0_write8(SIEN0_REG_800, sien & ~SIEN_RST); - } - NCR53c7x0_write8(SCNTL1_REG, SCNTL1_RST); - udelay(25); /* Minimum amount of time to assert RST */ - NCR53c7x0_write8(SCNTL1_REG, 0); - if ((hostdata->chip / 100) == 8) { - NCR53c7x0_write8(SIEN0_REG_800, sien); - } - restore_flags (flags); -} - -/* - * Function : void hard_reset (struct Scsi_Host *host) - * - */ - -static void -hard_reset (struct Scsi_Host *host) { - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - host->hostdata; - unsigned long flags; - save_flags (flags); - cli(); - ncr_scsi_reset(host); - NCR53c7x0_driver_init (host); - if (hostdata->soft_reset) - hostdata->soft_reset (host); - restore_flags(flags); -} - - -/* - * Function : Scsi_Cmnd *return_outstanding_commands (struct Scsi_Host *host, - * int free, int issue) - * - * Purpose : return a linked list (using the SCp.buffer field as next, - * so we don't perturb hostdata. We don't use a field of the - * NCR53c7x0_cmd structure since we may not have allocated one - * for the command causing the reset.) of Scsi_Cmnd structures that - * had propogated bellow the Linux issue queue level. If free is set, - * free the NCR53c7x0_cmd structures which are associated with - * the Scsi_Cmnd structures, and clean up any internal - * NCR lists that the commands were on. If issue is set, - * also return commands in the issue queue. - * - * Returns : linked list of commands - * - * NOTE : the caller should insure that the NCR chip is halted - * if the free flag is set. - */ - -static Scsi_Cmnd * -return_outstanding_commands (struct Scsi_Host *host, int free, int issue) { - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - host->hostdata; - struct NCR53c7x0_cmd *c; - int i; - u32 *current; - Scsi_Cmnd *list = NULL, *tmp; - for (c = (struct NCR53c7x0_cmd *) hostdata->running_list; c; - c = (struct NCR53c7x0_cmd *) c->next) { - if (c->cmd->SCp.buffer) { - printk ("scsi%d : loop detected in running list!\n", host->host_no); - break; - } else { - printk ("The sti() implicit in a printk() prevents hangs\n"); - break; - } - - c->cmd->SCp.buffer = (struct scatterlist *) list; - list = c->cmd; - if (free) { - c->next = hostdata->free; - hostdata->free = c; - } - } - - if (free) { - for (i = 0, current = (u32 *) hostdata->schedule; - i < host->can_queue; ++i, current += 2) { - current[0] = hostdata->NOP_insn; - current[1] = 0xdeadbeef; - } - hostdata->current = NULL; - } - - if (issue) { - for (tmp = (Scsi_Cmnd *) hostdata->issue_queue; tmp; tmp = tmp->next) { - if (tmp->SCp.buffer) { - printk ("scsi%d : loop detected in issue queue!\n", - host->host_no); - break; - } - tmp->SCp.buffer = (struct scatterlist *) list; - list = tmp; - } - if (free) - hostdata->issue_queue = NULL; - - } - return list; -} - -/* - * Function : static int disable (struct Scsi_Host *host) - * - * Purpose : disables the given NCR host, causing all commands - * to return a driver error. Call this so we can unload the - * module during development and try again. Eventually, - * we should be able to find clean workarrounds for these - * problems. - * - * Inputs : host - hostadapter to twiddle - * - * Returns : 0 on success. - */ - -static int -disable (struct Scsi_Host *host) { - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - host->hostdata; - unsigned long flags; - Scsi_Cmnd *nuke_list, *tmp; - save_flags(flags); - cli(); - if (hostdata->state != STATE_HALTED) - ncr_halt (host); - nuke_list = return_outstanding_commands (host, 1 /* free */, 1 /* issue */); - hard_reset (host); - hostdata->state = STATE_DISABLED; - restore_flags(flags); - printk ("scsi%d : nuking commands\n", host->host_no); - for (; nuke_list; nuke_list = tmp) { - tmp = (Scsi_Cmnd *) nuke_list->SCp.buffer; - nuke_list->result = DID_ERROR << 16; - nuke_list->scsi_done(nuke_list); - } - printk ("scsi%d : done. \n", host->host_no); - printk (KERN_ALERT "scsi%d : disabled. Unload and reload\n", - host->host_no); - return 0; -} - -/* - * Function : static int ncr_halt (struct Scsi_Host *host) - * - * Purpose : halts the SCSI SCRIPTS(tm) processor on the NCR chip - * - * Inputs : host - SCSI chip to halt - * - * Returns : 0 on success - */ - -static int -ncr_halt (struct Scsi_Host *host) { - NCR53c7x0_local_declare(); - unsigned long flags; - unsigned char istat, tmp; - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - host->hostdata; - int stage; - NCR53c7x0_local_setup(host); - - save_flags(flags); - cli(); - /* Stage 0 : eat all interrupts - Stage 1 : set ABORT - Stage 2 : eat all but abort interrupts - Stage 3 : eat all interrupts - */ - for (stage = 0;;) { - if (stage == 1) { - NCR53c7x0_write8(hostdata->istat, ISTAT_ABRT); - ++stage; - } - istat = NCR53c7x0_read8 (hostdata->istat); - if (istat & ISTAT_SIP) { - if ((hostdata->chip / 100) == 8) { - tmp = NCR53c7x0_read8(SIST0_REG_800); - udelay(1); - tmp = NCR53c7x0_read8(SIST1_REG_800); - } else { - tmp = NCR53c7x0_read8(SSTAT0_REG); - } - } else if (istat & ISTAT_DIP) { - tmp = NCR53c7x0_read8(DSTAT_REG); - if (stage == 2) { - if (tmp & DSTAT_ABRT) { - NCR53c7x0_write8(hostdata->istat, 0); - ++stage; - } else { - printk(KERN_ALERT "scsi%d : could not halt NCR chip\n", - host->host_no); - disable (host); - } - } - } - if (!(istat & (ISTAT_SIP|ISTAT_DIP))) - if (stage == 0) - ++stage; - else if (stage == 3) - break; - } - hostdata->state = STATE_HALTED; - restore_flags(flags); -#if 0 - print_lots (host); -#endif - return 0; -} - -/* - * Function: event_name (int event) - * - * Purpose: map event enum into user-readable strings. - */ - -static const char * -event_name (int event) { - switch (event) { - case EVENT_NONE: return "none"; - case EVENT_ISSUE_QUEUE: return "to issue queue"; - case EVENT_START_QUEUE: return "to start queue"; - case EVENT_SELECT: return "selected"; - case EVENT_DISCONNECT: return "disconnected"; - case EVENT_RESELECT: return "reselected"; - case EVENT_COMPLETE: return "completed"; - case EVENT_IDLE: return "idle"; - case EVENT_SELECT_FAILED: return "select failed"; - case EVENT_BEFORE_SELECT: return "before select"; - case EVENT_RESELECT_FAILED: return "reselect failed"; - default: return "unknown"; - } -} - -/* - * Function : void dump_events (struct Scsi_Host *host, count) - * - * Purpose : print last count events which have occurred. - */ -static void -dump_events (struct Scsi_Host *host, int count) { - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - host->hostdata; - struct NCR53c7x0_event event; - int i; - unsigned long flags; - if (hostdata->events) { - if (count > hostdata->event_size) - count = hostdata->event_size; - for (i = hostdata->event_index; count > 0; - i = (i ? i - 1 : hostdata->event_size -1), --count) { - save_flags(flags); -/* - * By copying the event we're currently examinging with interrupts - * disabled, we can do multiple printk(), etc. operations and - * still be guaranteed that they're happening on the same - * event structure. - */ - cli(); -#if 0 - event = hostdata->events[i]; -#else - memcpy ((void *) &event, (void *) &(hostdata->events[i]), - sizeof(event)); -#endif - - restore_flags(flags); - printk ("scsi%d : %s event %d at %ld secs %ld usecs target %d lun %d\n", - host->host_no, event_name (event.event), count, - (long) event.time.tv_sec, (long) event.time.tv_usec, - event.target, event.lun); - if (event.dsa) - printk (" event for dsa 0x%lx (virt 0x%p)\n", - virt_to_bus(event.dsa), event.dsa); - if (event.pid != -1) { - printk (" event for pid %ld ", event.pid); - print_command (event.cmnd); - } - } - } -} - -/* - * Function: check_address - * - * Purpose: Check to see if a possibly corrupt pointer will fault the - * kernel. - * - * Inputs: addr - address; size - size of area - * - * Returns: 0 if area is OK, -1 on error. - * - * NOTES: should be implemented in terms of vverify on kernels - * that have it. - */ - -static int -check_address (unsigned long addr, int size) { - return (MAP_NR(addr) < 1 || MAP_NR(addr + size) > MAP_NR(high_memory) ? - -1 : 0); -} - -#ifdef MODULE -int -NCR53c7x0_release(struct Scsi_Host *host) { - struct NCR53c7x0_hostdata *hostdata = - (struct NCR53c7x0_hostdata *) host->hostdata; - struct NCR53c7x0_cmd *cmd, *tmp; - shutdown (host); - if (host->irq != IRQ_NONE) - { - int irq_count; - struct Scsi_Host *tmp; - for (irq_count = 0, tmp = first_host; tmp; tmp = tmp->next) - if (tmp->hostt == the_template && tmp->irq == host->irq) - ++irq_count; - if (irq_count == 1) - free_irq(host->irq); - } - if (host->dma_channel != DMA_NONE) - free_dma(host->dma_channel); - if (host->io_port) - release_region(host->io_port, host->n_io_port); - - for (cmd = (struct NCR53c7x0_cmd *) hostdata->free; cmd; cmd = tmp, - --hostdata->num_cmds) { - tmp = (struct NCR53c7x0_cmd *) cmd->next; - /* - * If we're going to loop, try to stop it to get a more accurate - * count of the leaked commands. - */ - cmd->next = NULL; - if (cmd->free) - cmd->free ((void *) cmd->real, cmd->size); - } - if (hostdata->num_cmds) - printk ("scsi%d : leaked %d NCR53c7x0_cmd structures\n", - host->host_no, hostdata->num_cmds); - if (hostdata->events) - vfree ((void *)hostdata->events); - return 1; -} -Scsi_Host_Template driver_template = NCR53c7xx; -#include "scsi_module.c" -#endif /* def MODULE */ diff --git a/i386/i386at/gpl/linux/scsi/53c8xx_d.h b/i386/i386at/gpl/linux/scsi/53c8xx_d.h deleted file mode 100644 index dd45baee..00000000 --- a/i386/i386at/gpl/linux/scsi/53c8xx_d.h +++ /dev/null @@ -1,2677 +0,0 @@ -u32 SCRIPT[] = { -/* - - -; NCR 53c810 driver, main script -; Sponsored by -; iX Multiuser Multitasking Magazine -; hm@ix.de -; -; Copyright 1993, 1994, 1995 Drew Eckhardt -; Visionary Computing -; (Unix and Linux consulting and custom programming) -; drew@PoohSticks.ORG -; +1 (303) 786-7975 -; -; TolerANT and SCSI SCRIPTS are registered trademarks of NCR Corporation. -; -; PRE-ALPHA -; -; For more information, please consult -; -; NCR 53C810 -; PCI-SCSI I/O Processor -; Data Manual -; -; NCR 53C710 -; SCSI I/O Processor -; Programmers Guide -; -; NCR Microelectronics -; 1635 Aeroplaza Drive -; Colorado Springs, CO 80916 -; 1+ (719) 578-3400 -; -; Toll free literature number -; +1 (800) 334-5454 -; -; IMPORTANT : This code is self modifying due to the limitations of -; the NCR53c7,8xx series chips. Persons debugging this code with -; the remote debugger should take this into account, and NOT set -; breakpoints in modified instructions. -; -; Design: -; The NCR53c7,8xx family of SCSI chips are busmasters with an onboard -; microcontroller using a simple instruction set. -; -; So, to minimize the effects of interrupt latency, and to maximize -; throughput, this driver offloads the practical maximum amount -; of processing to the SCSI chip while still maintaining a common -; structure. -; -; Where tradeoffs were needed between efficiency on the older -; chips and the newer NCR53c800 series, the NCR53c800 series -; was chosen. -; -; While the NCR53c700 and NCR53c700-66 lacked the facilities to fully -; automate SCSI transfers without host processor intervention, this -; isn't the case with the NCR53c710 and newer chips which allow -; -; - reads and writes to the internal registers from within the SCSI -; scripts, allowing the SCSI SCRIPTS(tm) code to save processor -; state so that multiple threads of execution are possible, and also -; provide an ALU for loop control, etc. -; -; - table indirect addressing for some instructions. This allows -; pointers to be located relative to the DSA ((Data Structure -; Address) register. -; -; These features make it possible to implement a mailbox style interface, -; where the same piece of code is run to handle I/O for multiple threads -; at once minimizing our need to relocate code. Since the NCR53c700/ -; NCR53c800 series have a unique combination of features, making a -; a standard ingoing/outgoing mailbox system, costly, I've modified it. -; -; - Mailboxes are a mixture of code and data. This lets us greatly -; simplify the NCR53c810 code and do things that would otherwise -; not be possible. -; -; The saved data pointer is now implemented as follows : -; -; Control flow has been architected such that if control reaches -; munge_save_data_pointer, on a restore pointers message or -; reconnection, a jump to the address formerly in the TEMP register -; will allow the SCSI command to resume execution. -; - -; -; Note : the DSA structures must be aligned on 32 bit boundaries, -; since the source and destination of MOVE MEMORY instructions -; must share the same alignment and this is the alignment of the -; NCR registers. -; - -ABSOLUTE dsa_temp_lun = 0 ; Patch to lun for current dsa -ABSOLUTE dsa_temp_next = 0 ; Patch to dsa next for current dsa -ABSOLUTE dsa_temp_addr_next = 0 ; Patch to address of dsa next address - ; for current dsa -ABSOLUTE dsa_temp_sync = 0 ; Patch to address of per-target - ; sync routine -ABSOLUTE dsa_temp_target = 0 ; Patch to id for current dsa -ABSOLUTE dsa_temp_addr_saved_pointer = 0; Patch to address of per-command - ; saved data pointer -ABSOLUTE dsa_temp_addr_residual = 0 ; Patch to address of per-command - ; current residual code -ABSOLUTE dsa_temp_addr_saved_residual = 0; Patch to address of per-command - ; saved residual code -ABSOLUTE dsa_temp_addr_new_value = 0 ; Address of value for JUMP operand -ABSOLUTE dsa_temp_addr_array_value = 0 ; Address to copy to -ABSOLUTE dsa_temp_addr_dsa_value = 0 ; Address of this DSA value - -; -; Once a device has initiated reselection, we need to compare it -; against the singly linked list of commands which have disconnected -; and are pending reselection. These commands are maintained in -; an unordered singly linked list of DSA structures, through the -; DSA pointers at their 'centers' headed by the reconnect_dsa_head -; pointer. -; -; To avoid complications in removing commands from the list, -; I minimize the amount of expensive (at eight operations per -; addition @ 500-600ns each) pointer operations which must -; be done in the NCR driver by precomputing them on the -; host processor during dsa structure generation. -; -; The fixed-up per DSA code knows how to recognize the nexus -; associated with the corresponding SCSI command, and modifies -; the source and destination pointers for the MOVE MEMORY -; instruction which is executed when reselected_ok is called -; to remove the command from the list. Similarly, DSA is -; loaded with the address of the next DSA structure and -; reselected_check_next is called if a failure occurs. -; -; Perhaps more conscisely, the net effect of the mess is -; -; for (dsa = reconnect_dsa_head, dest = &reconnect_dsa_head, -; src = NULL; dsa; dest = &dsa->next, dsa = dsa->next) { -; src = &dsa->next; -; if (target_id == dsa->id && target_lun == dsa->lun) { -; *dest = *src; -; break; -; } -; } -; -; if (!dsa) -; error (int_err_unexpected_reselect); -; else -; longjmp (dsa->jump_resume, 0); -; -; - - -; Define DSA structure used for mailboxes -ENTRY dsa_code_template -dsa_code_template: -ENTRY dsa_code_begin -dsa_code_begin: - MOVE dmode_memory_to_ncr TO DMODE - -at 0x00000000 : */ 0x78380000,0x00000000, -/* - MOVE MEMORY 4, dsa_temp_addr_dsa_value, addr_scratch - -at 0x00000002 : */ 0xc0000004,0x00000000,0x00000000, -/* - MOVE dmode_memory_to_memory TO DMODE - -at 0x00000005 : */ 0x78380000,0x00000000, -/* - CALL scratch_to_dsa - -at 0x00000007 : */ 0x88080000,0x00000980, -/* - CALL select - -at 0x00000009 : */ 0x88080000,0x000001fc, -/* -; Handle the phase mismatch which may have resulted from the -; MOVE FROM dsa_msgout if we returned here. The CLEAR ATN -; may or may not be necessary, and we should update script_asm.pl -; to handle multiple pieces. - CLEAR ATN - -at 0x0000000b : */ 0x60000008,0x00000000, -/* - CLEAR ACK - -at 0x0000000d : */ 0x60000040,0x00000000, -/* - -; Replace second operand with address of JUMP instruction dest operand -; in schedule table for this DSA. Becomes dsa_jump_dest in 53c7,8xx.c. -ENTRY dsa_code_fix_jump -dsa_code_fix_jump: - MOVE MEMORY 4, NOP_insn, 0 - -at 0x0000000f : */ 0xc0000004,0x00000000,0x00000000, -/* - JUMP select_done - -at 0x00000012 : */ 0x80080000,0x00000224, -/* - -; wrong_dsa loads the DSA register with the value of the dsa_next -; field. -; -wrong_dsa: -; Patch the MOVE MEMORY INSTRUCTION such that -; the destination address is the address of the OLD -; next pointer. -; - MOVE MEMORY 4, dsa_temp_addr_next, reselected_ok + 8 - -at 0x00000014 : */ 0xc0000004,0x00000000,0x00000758, -/* - MOVE dmode_memory_to_ncr TO DMODE - -at 0x00000017 : */ 0x78380000,0x00000000, -/* -; -; Move the _contents_ of the next pointer into the DSA register as -; the next I_T_L or I_T_L_Q tupple to check against the established -; nexus. -; - MOVE MEMORY 4, dsa_temp_next, addr_scratch - -at 0x00000019 : */ 0xc0000004,0x00000000,0x00000000, -/* - MOVE dmode_memory_to_memory TO DMODE - -at 0x0000001c : */ 0x78380000,0x00000000, -/* - CALL scratch_to_dsa - -at 0x0000001e : */ 0x88080000,0x00000980, -/* - JUMP reselected_check_next - -at 0x00000020 : */ 0x80080000,0x000006a4, -/* - -ABSOLUTE dsa_save_data_pointer = 0 -ENTRY dsa_code_save_data_pointer -dsa_code_save_data_pointer: - MOVE dmode_ncr_to_memory TO DMODE - -at 0x00000022 : */ 0x78380000,0x00000000, -/* - MOVE MEMORY 4, addr_temp, dsa_temp_addr_saved_pointer - -at 0x00000024 : */ 0xc0000004,0x00000000,0x00000000, -/* - MOVE dmode_memory_to_memory TO DMODE - -at 0x00000027 : */ 0x78380000,0x00000000, -/* -; HARD CODED : 24 bytes needs to agree with 53c7,8xx.h - MOVE MEMORY 24, dsa_temp_addr_residual, dsa_temp_addr_saved_residual - -at 0x00000029 : */ 0xc0000018,0x00000000,0x00000000, -/* - CLEAR ACK - -at 0x0000002c : */ 0x60000040,0x00000000, -/* - - - - RETURN - -at 0x0000002e : */ 0x90080000,0x00000000, -/* -ABSOLUTE dsa_restore_pointers = 0 -ENTRY dsa_code_restore_pointers -dsa_code_restore_pointers: - MOVE dmode_memory_to_ncr TO DMODE - -at 0x00000030 : */ 0x78380000,0x00000000, -/* - MOVE MEMORY 4, dsa_temp_addr_saved_pointer, addr_temp - -at 0x00000032 : */ 0xc0000004,0x00000000,0x00000000, -/* - MOVE dmode_memory_to_memory TO DMODE - -at 0x00000035 : */ 0x78380000,0x00000000, -/* -; HARD CODED : 24 bytes needs to agree with 53c7,8xx.h - MOVE MEMORY 24, dsa_temp_addr_saved_residual, dsa_temp_addr_residual - -at 0x00000037 : */ 0xc0000018,0x00000000,0x00000000, -/* - CLEAR ACK - -at 0x0000003a : */ 0x60000040,0x00000000, -/* - - - - RETURN - -at 0x0000003c : */ 0x90080000,0x00000000, -/* - -ABSOLUTE dsa_check_reselect = 0 -; dsa_check_reselect determines whether or not the current target and -; lun match the current DSA -ENTRY dsa_code_check_reselect -dsa_code_check_reselect: - MOVE SSID TO SFBR ; SSID contains 3 bit target ID - -at 0x0000003e : */ 0x720a0000,0x00000000, -/* -; FIXME : we need to accomodate bit fielded and binary here for '7xx/'8xx chips - JUMP REL (wrong_dsa), IF NOT dsa_temp_target, AND MASK 0xf8 - -at 0x00000040 : */ 0x8084f800,0x00ffff48, -/* -; -; Hack - move to scratch first, since SFBR is not writeable -; via the CPU and hence a MOVE MEMORY instruction. -; - MOVE dmode_memory_to_ncr TO DMODE - -at 0x00000042 : */ 0x78380000,0x00000000, -/* - MOVE MEMORY 1, reselected_identify, addr_scratch - -at 0x00000044 : */ 0xc0000001,0x00000000,0x00000000, -/* - MOVE dmode_memory_to_memory TO DMODE - -at 0x00000047 : */ 0x78380000,0x00000000, -/* - MOVE SCRATCH0 TO SFBR - -at 0x00000049 : */ 0x72340000,0x00000000, -/* -; FIXME : we need to accomodate bit fielded and binary here for '7xx/'8xx chips - JUMP REL (wrong_dsa), IF NOT dsa_temp_lun, AND MASK 0xf8 - -at 0x0000004b : */ 0x8084f800,0x00ffff1c, -/* -; Patch the MOVE MEMORY INSTRUCTION such that -; the source address is the address of this dsa's -; next pointer. - MOVE MEMORY 4, dsa_temp_addr_next, reselected_ok + 4 - -at 0x0000004d : */ 0xc0000004,0x00000000,0x00000754, -/* - CALL reselected_ok - -at 0x00000050 : */ 0x88080000,0x00000750, -/* - CALL dsa_temp_sync - -at 0x00000052 : */ 0x88080000,0x00000000, -/* -; Release ACK on the IDENTIFY message _after_ we've set the synchronous -; transfer parameters! - CLEAR ACK - -at 0x00000054 : */ 0x60000040,0x00000000, -/* -; Implicitly restore pointers on reselection, so a RETURN -; will transfer control back to the right spot. - CALL REL (dsa_code_restore_pointers) - -at 0x00000056 : */ 0x88880000,0x00ffff60, -/* - RETURN - -at 0x00000058 : */ 0x90080000,0x00000000, -/* -ENTRY dsa_zero -dsa_zero: -ENTRY dsa_code_template_end -dsa_code_template_end: - -; Perform sanity check for dsa_fields_start == dsa_code_template_end - -; dsa_zero, puke. - -ABSOLUTE dsa_fields_start = 0 ; Sanity marker - ; pad 48 bytes (fix this RSN) -ABSOLUTE dsa_next = 48 ; len 4 Next DSA - ; del 4 Previous DSA address -ABSOLUTE dsa_cmnd = 56 ; len 4 Scsi_Cmnd * for this thread. -ABSOLUTE dsa_select = 60 ; len 4 Device ID, Period, Offset for - ; table indirect select -ABSOLUTE dsa_msgout = 64 ; len 8 table indirect move parameter for - ; select message -ABSOLUTE dsa_cmdout = 72 ; len 8 table indirect move parameter for - ; command -ABSOLUTE dsa_dataout = 80 ; len 4 code pointer for dataout -ABSOLUTE dsa_datain = 84 ; len 4 code pointer for datain -ABSOLUTE dsa_msgin = 88 ; len 8 table indirect move for msgin -ABSOLUTE dsa_status = 96 ; len 8 table indirect move for status byte -ABSOLUTE dsa_msgout_other = 104 ; len 8 table indirect for normal message out - ; (Synchronous transfer negotiation, etc). -ABSOLUTE dsa_end = 112 - -ABSOLUTE schedule = 0 ; Array of JUMP dsa_begin or JUMP (next), - ; terminated by a call to JUMP wait_reselect - -; Linked lists of DSA structures -ABSOLUTE reconnect_dsa_head = 0 ; Link list of DSAs which can reconnect -ABSOLUTE addr_reconnect_dsa_head = 0 ; Address of variable contataining - ; address of reconnect_dsa_head - -; These select the source and destination of a MOVE MEMORY instruction -ABSOLUTE dmode_memory_to_memory = 0x0 -ABSOLUTE dmode_memory_to_ncr = 0x0 -ABSOLUTE dmode_ncr_to_memory = 0x0 - -ABSOLUTE addr_scratch = 0x0 -ABSOLUTE addr_temp = 0x0 - - -; Interrupts - -; MSB indicates type -; 0 handle error condition -; 1 handle message -; 2 handle normal condition -; 3 debugging interrupt -; 4 testing interrupt -; Next byte indicates specific error - -; XXX not yet implemented, I'm not sure if I want to - -; Next byte indicates the routine the error occurred in -; The LSB indicates the specific place the error occurred - -ABSOLUTE int_err_unexpected_phase = 0x00000000 ; Unexpected phase encountered -ABSOLUTE int_err_selected = 0x00010000 ; SELECTED (nee RESELECTED) -ABSOLUTE int_err_unexpected_reselect = 0x00020000 -ABSOLUTE int_err_check_condition = 0x00030000 -ABSOLUTE int_err_no_phase = 0x00040000 -ABSOLUTE int_msg_wdtr = 0x01000000 ; WDTR message received -ABSOLUTE int_msg_sdtr = 0x01010000 ; SDTR received -ABSOLUTE int_msg_1 = 0x01020000 ; single byte special message - ; received - -ABSOLUTE int_norm_select_complete = 0x02000000 ; Select complete, reprogram - ; registers. -ABSOLUTE int_norm_reselect_complete = 0x02010000 ; Nexus established -ABSOLUTE int_norm_command_complete = 0x02020000 ; Command complete -ABSOLUTE int_norm_disconnected = 0x02030000 ; Disconnected -ABSOLUTE int_norm_aborted =0x02040000 ; Aborted *dsa -ABSOLUTE int_norm_reset = 0x02050000 ; Generated BUS reset. -ABSOLUTE int_debug_break = 0x03000000 ; Break point - -ABSOLUTE int_debug_panic = 0x030b0000 ; Panic driver - - -ABSOLUTE int_test_1 = 0x04000000 ; Test 1 complete -ABSOLUTE int_test_2 = 0x04010000 ; Test 2 complete -ABSOLUTE int_test_3 = 0x04020000 ; Test 3 complete - - -; These should start with 0x05000000, with low bits incrementing for -; each one. - - - -ABSOLUTE NCR53c7xx_msg_abort = 0 ; Pointer to abort message -ABSOLUTE NCR53c7xx_msg_reject = 0 ; Pointer to reject message -ABSOLUTE NCR53c7xx_zero = 0 ; long with zero in it, use for source -ABSOLUTE NCR53c7xx_sink = 0 ; long to dump worthless data in -ABSOLUTE NOP_insn = 0 ; NOP instruction - -; Pointer to message, potentially multi-byte -ABSOLUTE msg_buf = 0 - -; Pointer to holding area for reselection information -ABSOLUTE reselected_identify = 0 -ABSOLUTE reselected_tag = 0 - -; Request sense command pointer, it's a 6 byte command, should -; be constant for all commands since we always want 16 bytes of -; sense and we don't need to change any fields as we did under -; SCSI-I when we actually cared about the LUN field. -;EXTERNAL NCR53c7xx_sense ; Request sense command - - -; dsa_schedule -; PURPOSE : after a DISCONNECT message has been received, and pointers -; saved, insert the current DSA structure at the head of the -; disconnected queue and fall through to the scheduler. -; -; CALLS : OK -; -; INPUTS : dsa - current DSA structure, reconnect_dsa_head - list -; of disconnected commands -; -; MODIFIES : SCRATCH, reconnect_dsa_head -; -; EXITS : always passes control to schedule - -ENTRY dsa_schedule -dsa_schedule: - - - - -; -; Calculate the address of the next pointer within the DSA -; structure of the command that is currently disconnecting -; - CALL dsa_to_scratch - -at 0x0000005a : */ 0x88080000,0x00000938, -/* - MOVE SCRATCH0 + dsa_next TO SCRATCH0 - -at 0x0000005c : */ 0x7e343000,0x00000000, -/* - MOVE SCRATCH1 + 0 TO SCRATCH1 WITH CARRY - -at 0x0000005e : */ 0x7f350000,0x00000000, -/* - MOVE SCRATCH2 + 0 TO SCRATCH2 WITH CARRY - -at 0x00000060 : */ 0x7f360000,0x00000000, -/* - MOVE SCRATCH3 + 0 TO SCRATCH3 WITH CARRY - -at 0x00000062 : */ 0x7f370000,0x00000000, -/* - -; Point the next field of this DSA structure at the current disconnected -; list - MOVE dmode_ncr_to_memory TO DMODE - -at 0x00000064 : */ 0x78380000,0x00000000, -/* - MOVE MEMORY 4, addr_scratch, dsa_schedule_insert + 8 - -at 0x00000066 : */ 0xc0000004,0x00000000,0x000001b4, -/* - MOVE dmode_memory_to_memory TO DMODE - -at 0x00000069 : */ 0x78380000,0x00000000, -/* -dsa_schedule_insert: - MOVE MEMORY 4, reconnect_dsa_head, 0 - -at 0x0000006b : */ 0xc0000004,0x00000000,0x00000000, -/* - -; And update the head pointer. - CALL dsa_to_scratch - -at 0x0000006e : */ 0x88080000,0x00000938, -/* - MOVE dmode_ncr_to_memory TO DMODE - -at 0x00000070 : */ 0x78380000,0x00000000, -/* - MOVE MEMORY 4, addr_scratch, reconnect_dsa_head - -at 0x00000072 : */ 0xc0000004,0x00000000,0x00000000, -/* - MOVE dmode_memory_to_memory TO DMODE - -at 0x00000075 : */ 0x78380000,0x00000000, -/* - - - MOVE SCNTL2 & 0x7f TO SCNTL2 - -at 0x00000077 : */ 0x7c027f00,0x00000000, -/* - CLEAR ACK - -at 0x00000079 : */ 0x60000040,0x00000000, -/* - - WAIT DISCONNECT - -at 0x0000007b : */ 0x48000000,0x00000000, -/* - - - - - - - JUMP schedule - -at 0x0000007d : */ 0x80080000,0x00000000, -/* - - -; -; select -; -; PURPOSE : establish a nexus for the SCSI command referenced by DSA. -; On success, the current DSA structure is removed from the issue -; queue. Usually, this is entered as a fall-through from schedule, -; although the contingent allegiance handling code will write -; the select entry address to the DSP to restart a command as a -; REQUEST SENSE. A message is sent (usually IDENTIFY, although -; additional SDTR or WDTR messages may be sent). COMMAND OUT -; is handled. -; -; INPUTS : DSA - SCSI command, issue_dsa_head -; -; CALLS : NOT OK -; -; MODIFIES : SCRATCH, issue_dsa_head -; -; EXITS : on reselection or selection, go to select_failed -; otherwise, RETURN so control is passed back to -; dsa_begin. -; - -ENTRY select -select: - - - - - - - - - - - - - CLEAR TARGET - -at 0x0000007f : */ 0x60000200,0x00000000, -/* - -; XXX -; -; In effect, SELECTION operations are backgrounded, with execution -; continuing until code which waits for REQ or a fatal interrupt is -; encountered. -; -; So, for more performance, we could overlap the code which removes -; the command from the NCRs issue queue with the selection, but -; at this point I don't want to deal with the error recovery. -; - - - SELECT ATN FROM dsa_select, select_failed - -at 0x00000081 : */ 0x4300003c,0x000007a4, -/* - JUMP select_msgout, WHEN MSG_OUT - -at 0x00000083 : */ 0x860b0000,0x00000214, -/* -ENTRY select_msgout -select_msgout: - MOVE FROM dsa_msgout, WHEN MSG_OUT - -at 0x00000085 : */ 0x1e000000,0x00000040, -/* - - - - - - - - - - - RETURN - -at 0x00000087 : */ 0x90080000,0x00000000, -/* - -; -; select_done -; -; PURPOSE: continue on to normal data transfer; called as the exit -; point from dsa_begin. -; -; INPUTS: dsa -; -; CALLS: OK -; -; - -select_done: - - - - - - - -; After a successful selection, we should get either a CMD phase or -; some transfer request negotiation message. - - JUMP cmdout, WHEN CMD - -at 0x00000089 : */ 0x820b0000,0x00000244, -/* - INT int_err_unexpected_phase, WHEN NOT MSG_IN - -at 0x0000008b : */ 0x9f030000,0x00000000, -/* - -select_msg_in: - CALL msg_in, WHEN MSG_IN - -at 0x0000008d : */ 0x8f0b0000,0x00000404, -/* - JUMP select_msg_in, WHEN MSG_IN - -at 0x0000008f : */ 0x870b0000,0x00000234, -/* - -cmdout: - INT int_err_unexpected_phase, WHEN NOT CMD - -at 0x00000091 : */ 0x9a030000,0x00000000, -/* - - - -ENTRY cmdout_cmdout -cmdout_cmdout: - - MOVE FROM dsa_cmdout, WHEN CMD - -at 0x00000093 : */ 0x1a000000,0x00000048, -/* - - - - -; -; data_transfer -; other_out -; other_in -; other_transfer -; -; PURPOSE : handle the main data transfer for a SCSI command in -; several parts. In the first part, data_transfer, DATA_IN -; and DATA_OUT phases are allowed, with the user provided -; code (usually dynamically generated based on the scatter/gather -; list associated with a SCSI command) called to handle these -; phases. -; -; After control has passed to one of the user provided -; DATA_IN or DATA_OUT routines, back calls are made to -; other_tranfer_in or other_transfer_out to handle non-DATA IN -; and DATA OUT phases respectively, with the state of the active -; data pointer being preserved in TEMP. -; -; On completion, the user code passes control to other_transfer -; which causes DATA_IN and DATA_OUT to result in unexpected_phase -; interrupts so that data overruns may be trapped. -; -; INPUTS : DSA - SCSI command -; -; CALLS : OK in data_transfer_start, not ok in other_out and other_in, ok in -; other_transfer -; -; MODIFIES : SCRATCH -; -; EXITS : if STATUS IN is detected, signifying command completion, -; the NCR jumps to command_complete. If MSG IN occurs, a -; CALL is made to msg_in. Otherwise, other_transfer runs in -; an infinite loop. -; - -ENTRY data_transfer -data_transfer: - JUMP cmdout_cmdout, WHEN CMD - -at 0x00000095 : */ 0x820b0000,0x0000024c, -/* - CALL msg_in, WHEN MSG_IN - -at 0x00000097 : */ 0x8f0b0000,0x00000404, -/* - INT int_err_unexpected_phase, WHEN MSG_OUT - -at 0x00000099 : */ 0x9e0b0000,0x00000000, -/* - JUMP do_dataout, WHEN DATA_OUT - -at 0x0000009b : */ 0x800b0000,0x0000028c, -/* - JUMP do_datain, WHEN DATA_IN - -at 0x0000009d : */ 0x810b0000,0x000002e4, -/* - JUMP command_complete, WHEN STATUS - -at 0x0000009f : */ 0x830b0000,0x0000060c, -/* - JUMP data_transfer - -at 0x000000a1 : */ 0x80080000,0x00000254, -/* -ENTRY end_data_transfer -end_data_transfer: - -; -; FIXME: On NCR53c700 and NCR53c700-66 chips, do_dataout/do_datain -; should be fixed up whenever the nexus changes so it can point to the -; correct routine for that command. -; - - -; Nasty jump to dsa->dataout -do_dataout: - CALL dsa_to_scratch - -at 0x000000a3 : */ 0x88080000,0x00000938, -/* - MOVE SCRATCH0 + dsa_dataout TO SCRATCH0 - -at 0x000000a5 : */ 0x7e345000,0x00000000, -/* - MOVE SCRATCH1 + 0 TO SCRATCH1 WITH CARRY - -at 0x000000a7 : */ 0x7f350000,0x00000000, -/* - MOVE SCRATCH2 + 0 TO SCRATCH2 WITH CARRY - -at 0x000000a9 : */ 0x7f360000,0x00000000, -/* - MOVE SCRATCH3 + 0 TO SCRATCH3 WITH CARRY - -at 0x000000ab : */ 0x7f370000,0x00000000, -/* - MOVE dmode_ncr_to_memory TO DMODE - -at 0x000000ad : */ 0x78380000,0x00000000, -/* - MOVE MEMORY 4, addr_scratch, dataout_to_jump + 4 - -at 0x000000af : */ 0xc0000004,0x00000000,0x000002d4, -/* - MOVE dmode_memory_to_memory TO DMODE - -at 0x000000b2 : */ 0x78380000,0x00000000, -/* -dataout_to_jump: - MOVE MEMORY 4, 0, dataout_jump + 4 - -at 0x000000b4 : */ 0xc0000004,0x00000000,0x000002e0, -/* -dataout_jump: - JUMP 0 - -at 0x000000b7 : */ 0x80080000,0x00000000, -/* - -; Nasty jump to dsa->dsain -do_datain: - CALL dsa_to_scratch - -at 0x000000b9 : */ 0x88080000,0x00000938, -/* - MOVE SCRATCH0 + dsa_datain TO SCRATCH0 - -at 0x000000bb : */ 0x7e345400,0x00000000, -/* - MOVE SCRATCH1 + 0 TO SCRATCH1 WITH CARRY - -at 0x000000bd : */ 0x7f350000,0x00000000, -/* - MOVE SCRATCH2 + 0 TO SCRATCH2 WITH CARRY - -at 0x000000bf : */ 0x7f360000,0x00000000, -/* - MOVE SCRATCH3 + 0 TO SCRATCH3 WITH CARRY - -at 0x000000c1 : */ 0x7f370000,0x00000000, -/* - MOVE dmode_ncr_to_memory TO DMODE - -at 0x000000c3 : */ 0x78380000,0x00000000, -/* - MOVE MEMORY 4, addr_scratch, datain_to_jump + 4 - -at 0x000000c5 : */ 0xc0000004,0x00000000,0x0000032c, -/* - MOVE dmode_memory_to_memory TO DMODE - -at 0x000000c8 : */ 0x78380000,0x00000000, -/* -ENTRY datain_to_jump -datain_to_jump: - MOVE MEMORY 4, 0, datain_jump + 4 - -at 0x000000ca : */ 0xc0000004,0x00000000,0x00000338, -/* - - - -datain_jump: - JUMP 0 - -at 0x000000cd : */ 0x80080000,0x00000000, -/* - - - -; Note that other_out and other_in loop until a non-data phase -; is discoverred, so we only execute return statements when we -; can go on to the next data phase block move statement. - -ENTRY other_out -other_out: - - - - INT int_err_unexpected_phase, WHEN CMD - -at 0x000000cf : */ 0x9a0b0000,0x00000000, -/* - JUMP msg_in_restart, WHEN MSG_IN - -at 0x000000d1 : */ 0x870b0000,0x000003e4, -/* - INT int_err_unexpected_phase, WHEN MSG_OUT - -at 0x000000d3 : */ 0x9e0b0000,0x00000000, -/* - INT int_err_unexpected_phase, WHEN DATA_IN - -at 0x000000d5 : */ 0x990b0000,0x00000000, -/* - JUMP command_complete, WHEN STATUS - -at 0x000000d7 : */ 0x830b0000,0x0000060c, -/* - JUMP other_out, WHEN NOT DATA_OUT - -at 0x000000d9 : */ 0x80030000,0x0000033c, -/* - RETURN - -at 0x000000db : */ 0x90080000,0x00000000, -/* - -ENTRY other_in -other_in: - - - - INT int_err_unexpected_phase, WHEN CMD - -at 0x000000dd : */ 0x9a0b0000,0x00000000, -/* - JUMP msg_in_restart, WHEN MSG_IN - -at 0x000000df : */ 0x870b0000,0x000003e4, -/* - INT int_err_unexpected_phase, WHEN MSG_OUT - -at 0x000000e1 : */ 0x9e0b0000,0x00000000, -/* - INT int_err_unexpected_phase, WHEN DATA_OUT - -at 0x000000e3 : */ 0x980b0000,0x00000000, -/* - JUMP command_complete, WHEN STATUS - -at 0x000000e5 : */ 0x830b0000,0x0000060c, -/* - JUMP other_in, WHEN NOT DATA_IN - -at 0x000000e7 : */ 0x81030000,0x00000374, -/* - RETURN - -at 0x000000e9 : */ 0x90080000,0x00000000, -/* - - -ENTRY other_transfer -other_transfer: - INT int_err_unexpected_phase, WHEN CMD - -at 0x000000eb : */ 0x9a0b0000,0x00000000, -/* - CALL msg_in, WHEN MSG_IN - -at 0x000000ed : */ 0x8f0b0000,0x00000404, -/* - INT int_err_unexpected_phase, WHEN MSG_OUT - -at 0x000000ef : */ 0x9e0b0000,0x00000000, -/* - INT int_err_unexpected_phase, WHEN DATA_OUT - -at 0x000000f1 : */ 0x980b0000,0x00000000, -/* - INT int_err_unexpected_phase, WHEN DATA_IN - -at 0x000000f3 : */ 0x990b0000,0x00000000, -/* - JUMP command_complete, WHEN STATUS - -at 0x000000f5 : */ 0x830b0000,0x0000060c, -/* - JUMP other_transfer - -at 0x000000f7 : */ 0x80080000,0x000003ac, -/* - -; -; msg_in_restart -; msg_in -; munge_msg -; -; PURPOSE : process messages from a target. msg_in is called when the -; caller hasn't read the first byte of the message. munge_message -; is called when the caller has read the first byte of the message, -; and left it in SFBR. msg_in_restart is called when the caller -; hasnt read the first byte of the message, and wishes RETURN -; to transfer control back to the address of the conditional -; CALL instruction rather than to the instruction after it. -; -; Various int_* interrupts are generated when the host system -; needs to intervene, as is the case with SDTR, WDTR, and -; INITIATE RECOVERY messages. -; -; When the host system handles one of these interrupts, -; it can respond by reentering at reject_message, -; which rejects the message and returns control to -; the caller of msg_in or munge_msg, accept_message -; which clears ACK and returns control, or reply_message -; which sends the message pointed to by the DSA -; msgout_other table indirect field. -; -; DISCONNECT messages are handled by moving the command -; to the reconnect_dsa_queue. -; -; INPUTS : DSA - SCSI COMMAND, SFBR - first byte of message (munge_msg -; only) -; -; CALLS : NO. The TEMP register isn't backed up to allow nested calls. -; -; MODIFIES : SCRATCH, DSA on DISCONNECT -; -; EXITS : On receipt of SAVE DATA POINTER, RESTORE POINTERS, -; and normal return from message handlers running under -; Linux, control is returned to the caller. Receipt -; of DISCONNECT messages pass control to dsa_schedule. -; -ENTRY msg_in_restart -msg_in_restart: -; XXX - hackish -; -; Since it's easier to debug changes to the statically -; compiled code, rather than the dynamically generated -; stuff, such as -; -; MOVE x, y, WHEN data_phase -; CALL other_z, WHEN NOT data_phase -; MOVE x, y, WHEN data_phase -; -; I'd like to have certain routines (notably the message handler) -; restart on the conditional call rather than the next instruction. -; -; So, subtract 8 from the return address - - MOVE TEMP0 + 0xf8 TO TEMP0 - -at 0x000000f9 : */ 0x7e1cf800,0x00000000, -/* - MOVE TEMP1 + 0xff TO TEMP1 WITH CARRY - -at 0x000000fb : */ 0x7f1dff00,0x00000000, -/* - MOVE TEMP2 + 0xff TO TEMP2 WITH CARRY - -at 0x000000fd : */ 0x7f1eff00,0x00000000, -/* - MOVE TEMP3 + 0xff TO TEMP3 WITH CARRY - -at 0x000000ff : */ 0x7f1fff00,0x00000000, -/* - -ENTRY msg_in -msg_in: - MOVE 1, msg_buf, WHEN MSG_IN - -at 0x00000101 : */ 0x0f000001,0x00000000, -/* - -munge_msg: - JUMP munge_extended, IF 0x01 ; EXTENDED MESSAGE - -at 0x00000103 : */ 0x800c0001,0x00000524, -/* - JUMP munge_2, IF 0x20, AND MASK 0xdf ; two byte message - -at 0x00000105 : */ 0x800cdf20,0x0000044c, -/* -; -; XXX - I've seen a handful of broken SCSI devices which fail to issue -; a SAVE POINTERS message before disconnecting in the middle of -; a transfer, assuming that the DATA POINTER will be implicitly -; restored. -; -; Historically, I've often done an implicit save when the DISCONNECT -; message is processed. We may want to consider having the option of -; doing that here. -; - JUMP munge_save_data_pointer, IF 0x02 ; SAVE DATA POINTER - -at 0x00000107 : */ 0x800c0002,0x00000454, -/* - JUMP munge_restore_pointers, IF 0x03 ; RESTORE POINTERS - -at 0x00000109 : */ 0x800c0003,0x000004b8, -/* - JUMP munge_disconnect, IF 0x04 ; DISCONNECT - -at 0x0000010b : */ 0x800c0004,0x0000051c, -/* - INT int_msg_1, IF 0x07 ; MESSAGE REJECT - -at 0x0000010d : */ 0x980c0007,0x01020000, -/* - INT int_msg_1, IF 0x0f ; INITIATE RECOVERY - -at 0x0000010f : */ 0x980c000f,0x01020000, -/* - - - - JUMP reject_message - -at 0x00000111 : */ 0x80080000,0x000005b4, -/* - -munge_2: - JUMP reject_message - -at 0x00000113 : */ 0x80080000,0x000005b4, -/* -; -; The SCSI standard allows targets to recover from transient -; error conditions by backing up the data pointer with a -; RESTORE POINTERS message. -; -; So, we must save and restore the _residual_ code as well as -; the current instruction pointer. Because of this messiness, -; it is simpler to put dynamic code in the dsa for this and to -; just do a simple jump down there. -; - -munge_save_data_pointer: - MOVE DSA0 + dsa_save_data_pointer TO SFBR - -at 0x00000115 : */ 0x76100000,0x00000000, -/* - MOVE SFBR TO SCRATCH0 - -at 0x00000117 : */ 0x6a340000,0x00000000, -/* - MOVE DSA1 + 0xff TO SFBR WITH CARRY - -at 0x00000119 : */ 0x7711ff00,0x00000000, -/* - MOVE SFBR TO SCRATCH1 - -at 0x0000011b : */ 0x6a350000,0x00000000, -/* - MOVE DSA2 + 0xff TO SFBR WITH CARRY - -at 0x0000011d : */ 0x7712ff00,0x00000000, -/* - MOVE SFBR TO SCRATCH2 - -at 0x0000011f : */ 0x6a360000,0x00000000, -/* - MOVE DSA3 + 0xff TO SFBR WITH CARRY - -at 0x00000121 : */ 0x7713ff00,0x00000000, -/* - MOVE SFBR TO SCRATCH3 - -at 0x00000123 : */ 0x6a370000,0x00000000, -/* - - MOVE dmode_ncr_to_memory TO DMODE - -at 0x00000125 : */ 0x78380000,0x00000000, -/* - MOVE MEMORY 4, addr_scratch, jump_dsa_save + 4 - -at 0x00000127 : */ 0xc0000004,0x00000000,0x000004b4, -/* - MOVE dmode_memory_to_memory TO DMODE - -at 0x0000012a : */ 0x78380000,0x00000000, -/* -jump_dsa_save: - JUMP 0 - -at 0x0000012c : */ 0x80080000,0x00000000, -/* - -munge_restore_pointers: - MOVE DSA0 + dsa_restore_pointers TO SFBR - -at 0x0000012e : */ 0x76100000,0x00000000, -/* - MOVE SFBR TO SCRATCH0 - -at 0x00000130 : */ 0x6a340000,0x00000000, -/* - MOVE DSA1 + 0xff TO SFBR WITH CARRY - -at 0x00000132 : */ 0x7711ff00,0x00000000, -/* - MOVE SFBR TO SCRATCH1 - -at 0x00000134 : */ 0x6a350000,0x00000000, -/* - MOVE DSA2 + 0xff TO SFBR WITH CARRY - -at 0x00000136 : */ 0x7712ff00,0x00000000, -/* - MOVE SFBR TO SCRATCH2 - -at 0x00000138 : */ 0x6a360000,0x00000000, -/* - MOVE DSA3 + 0xff TO SFBR WITH CARRY - -at 0x0000013a : */ 0x7713ff00,0x00000000, -/* - MOVE SFBR TO SCRATCH3 - -at 0x0000013c : */ 0x6a370000,0x00000000, -/* - - MOVE dmode_ncr_to_memory TO DMODE - -at 0x0000013e : */ 0x78380000,0x00000000, -/* - MOVE MEMORY 4, addr_scratch, jump_dsa_restore + 4 - -at 0x00000140 : */ 0xc0000004,0x00000000,0x00000518, -/* - MOVE dmode_memory_to_memory TO DMODE - -at 0x00000143 : */ 0x78380000,0x00000000, -/* -jump_dsa_restore: - JUMP 0 - -at 0x00000145 : */ 0x80080000,0x00000000, -/* - - -munge_disconnect: - - - - - - - - - - - - - - - - - JUMP dsa_schedule - -at 0x00000147 : */ 0x80080000,0x00000168, -/* - - - - - -munge_extended: - CLEAR ACK - -at 0x00000149 : */ 0x60000040,0x00000000, -/* - INT int_err_unexpected_phase, WHEN NOT MSG_IN - -at 0x0000014b : */ 0x9f030000,0x00000000, -/* - MOVE 1, msg_buf + 1, WHEN MSG_IN - -at 0x0000014d : */ 0x0f000001,0x00000001, -/* - JUMP munge_extended_2, IF 0x02 - -at 0x0000014f : */ 0x800c0002,0x00000554, -/* - JUMP munge_extended_3, IF 0x03 - -at 0x00000151 : */ 0x800c0003,0x00000584, -/* - JUMP reject_message - -at 0x00000153 : */ 0x80080000,0x000005b4, -/* - -munge_extended_2: - CLEAR ACK - -at 0x00000155 : */ 0x60000040,0x00000000, -/* - MOVE 1, msg_buf + 2, WHEN MSG_IN - -at 0x00000157 : */ 0x0f000001,0x00000002, -/* - JUMP reject_message, IF NOT 0x02 ; Must be WDTR - -at 0x00000159 : */ 0x80040002,0x000005b4, -/* - CLEAR ACK - -at 0x0000015b : */ 0x60000040,0x00000000, -/* - MOVE 1, msg_buf + 3, WHEN MSG_IN - -at 0x0000015d : */ 0x0f000001,0x00000003, -/* - INT int_msg_wdtr - -at 0x0000015f : */ 0x98080000,0x01000000, -/* - -munge_extended_3: - CLEAR ACK - -at 0x00000161 : */ 0x60000040,0x00000000, -/* - MOVE 1, msg_buf + 2, WHEN MSG_IN - -at 0x00000163 : */ 0x0f000001,0x00000002, -/* - JUMP reject_message, IF NOT 0x01 ; Must be SDTR - -at 0x00000165 : */ 0x80040001,0x000005b4, -/* - CLEAR ACK - -at 0x00000167 : */ 0x60000040,0x00000000, -/* - MOVE 2, msg_buf + 3, WHEN MSG_IN - -at 0x00000169 : */ 0x0f000002,0x00000003, -/* - INT int_msg_sdtr - -at 0x0000016b : */ 0x98080000,0x01010000, -/* - -ENTRY reject_message -reject_message: - SET ATN - -at 0x0000016d : */ 0x58000008,0x00000000, -/* - CLEAR ACK - -at 0x0000016f : */ 0x60000040,0x00000000, -/* - MOVE 1, NCR53c7xx_msg_reject, WHEN MSG_OUT - -at 0x00000171 : */ 0x0e000001,0x00000000, -/* - RETURN - -at 0x00000173 : */ 0x90080000,0x00000000, -/* - -ENTRY accept_message -accept_message: - CLEAR ATN - -at 0x00000175 : */ 0x60000008,0x00000000, -/* - CLEAR ACK - -at 0x00000177 : */ 0x60000040,0x00000000, -/* - RETURN - -at 0x00000179 : */ 0x90080000,0x00000000, -/* - -ENTRY respond_message -respond_message: - SET ATN - -at 0x0000017b : */ 0x58000008,0x00000000, -/* - CLEAR ACK - -at 0x0000017d : */ 0x60000040,0x00000000, -/* - MOVE FROM dsa_msgout_other, WHEN MSG_OUT - -at 0x0000017f : */ 0x1e000000,0x00000068, -/* - RETURN - -at 0x00000181 : */ 0x90080000,0x00000000, -/* - -; -; command_complete -; -; PURPOSE : handle command termination when STATUS IN is detected by reading -; a status byte followed by a command termination message. -; -; Normal termination results in an INTFLY instruction, and -; the host system can pick out which command terminated by -; examining the MESSAGE and STATUS buffers of all currently -; executing commands; -; -; Abnormal (CHECK_CONDITION) termination results in an -; int_err_check_condition interrupt so that a REQUEST SENSE -; command can be issued out-of-order so that no other command -; clears the contingent allegiance condition. -; -; -; INPUTS : DSA - command -; -; CALLS : OK -; -; EXITS : On successful termination, control is passed to schedule. -; On abnormal termination, the user will usually modify the -; DSA fields and corresponding buffers and return control -; to select. -; - -ENTRY command_complete -command_complete: - MOVE FROM dsa_status, WHEN STATUS - -at 0x00000183 : */ 0x1b000000,0x00000060, -/* - - MOVE SFBR TO SCRATCH0 ; Save status - -at 0x00000185 : */ 0x6a340000,0x00000000, -/* - -ENTRY command_complete_msgin -command_complete_msgin: - MOVE FROM dsa_msgin, WHEN MSG_IN - -at 0x00000187 : */ 0x1f000000,0x00000058, -/* -; Indicate that we should be expecting a disconnect - MOVE SCNTL2 & 0x7f TO SCNTL2 - -at 0x00000189 : */ 0x7c027f00,0x00000000, -/* - CLEAR ACK - -at 0x0000018b : */ 0x60000040,0x00000000, -/* - - WAIT DISCONNECT - -at 0x0000018d : */ 0x48000000,0x00000000, -/* - -; -; The SCSI specification states that when a UNIT ATTENTION condition -; is pending, as indicated by a CHECK CONDITION status message, -; the target shall revert to asynchronous transfers. Since -; synchronous transfers parameters are maintained on a per INITIATOR/TARGET -; basis, and returning control to our scheduler could work on a command -; running on another lun on that target using the old parameters, we must -; interrupt the host processor to get them changed, or change them ourselves. -; -; Once SCSI-II tagged queueing is implemented, things will be even more -; hairy, since contingent allegiance conditions exist on a per-target/lun -; basis, and issuing a new command with a different tag would clear it. -; In these cases, we must interrupt the host processor to get a request -; added to the HEAD of the queue with the request sense command, or we -; must automatically issue the request sense command. - - - - - - INTFLY - -at 0x0000018f : */ 0x98180000,0x00000000, -/* - - - - - - JUMP schedule - -at 0x00000191 : */ 0x80080000,0x00000000, -/* -command_failed: - INT int_err_check_condition - -at 0x00000193 : */ 0x98080000,0x00030000, -/* - - - - -; -; wait_reselect -; -; PURPOSE : This is essentially the idle routine, where control lands -; when there are no new processes to schedule. wait_reselect -; waits for reselection, selection, and new commands. -; -; When a successful reselection occurs, with the aid -; of fixed up code in each DSA, wait_reselect walks the -; reconnect_dsa_queue, asking each dsa if the target ID -; and LUN match its. -; -; If a match is found, a call is made back to reselected_ok, -; which through the miracles of self modifying code, extracts -; the found DSA from the reconnect_dsa_queue and then -; returns control to the DSAs thread of execution. -; -; INPUTS : NONE -; -; CALLS : OK -; -; MODIFIES : DSA, -; -; EXITS : On successful reselection, control is returned to the -; DSA which called reselected_ok. If the WAIT RESELECT -; was interrupted by a new commands arrival signaled by -; SIG_P, control is passed to schedule. If the NCR is -; selected, the host system is interrupted with an -; int_err_selected which is usually responded to by -; setting DSP to the target_abort address. - -ENTRY wait_reselect -wait_reselect: - - - - - - - WAIT RESELECT wait_reselect_failed - -at 0x00000195 : */ 0x50000000,0x0000076c, -/* - -reselected: - - - - CLEAR TARGET - -at 0x00000197 : */ 0x60000200,0x00000000, -/* - MOVE dmode_memory_to_memory TO DMODE - -at 0x00000199 : */ 0x78380000,0x00000000, -/* - ; Read all data needed to reestablish the nexus - - MOVE 1, reselected_identify, WHEN MSG_IN - -at 0x0000019b : */ 0x0f000001,0x00000000, -/* - ; We used to CLEAR ACK here. - - - - - - ; Point DSA at the current head of the disconnected queue. - MOVE dmode_memory_to_ncr TO DMODE - -at 0x0000019d : */ 0x78380000,0x00000000, -/* - MOVE MEMORY 4, reconnect_dsa_head, addr_scratch - -at 0x0000019f : */ 0xc0000004,0x00000000,0x00000000, -/* - MOVE dmode_memory_to_memory TO DMODE - -at 0x000001a2 : */ 0x78380000,0x00000000, -/* - CALL scratch_to_dsa - -at 0x000001a4 : */ 0x88080000,0x00000980, -/* - - ; Fix the update-next pointer so that the reconnect_dsa_head - ; pointer is the one that will be updated if this DSA is a hit - ; and we remove it from the queue. - - MOVE MEMORY 4, addr_reconnect_dsa_head, reselected_ok + 8 - -at 0x000001a6 : */ 0xc0000004,0x00000000,0x00000758, -/* - -ENTRY reselected_check_next -reselected_check_next: - - - - ; Check for a NULL pointer. - MOVE DSA0 TO SFBR - -at 0x000001a9 : */ 0x72100000,0x00000000, -/* - JUMP reselected_not_end, IF NOT 0 - -at 0x000001ab : */ 0x80040000,0x000006ec, -/* - MOVE DSA1 TO SFBR - -at 0x000001ad : */ 0x72110000,0x00000000, -/* - JUMP reselected_not_end, IF NOT 0 - -at 0x000001af : */ 0x80040000,0x000006ec, -/* - MOVE DSA2 TO SFBR - -at 0x000001b1 : */ 0x72120000,0x00000000, -/* - JUMP reselected_not_end, IF NOT 0 - -at 0x000001b3 : */ 0x80040000,0x000006ec, -/* - MOVE DSA3 TO SFBR - -at 0x000001b5 : */ 0x72130000,0x00000000, -/* - JUMP reselected_not_end, IF NOT 0 - -at 0x000001b7 : */ 0x80040000,0x000006ec, -/* - INT int_err_unexpected_reselect - -at 0x000001b9 : */ 0x98080000,0x00020000, -/* - -reselected_not_end: - ; - ; XXX the ALU is only eight bits wide, and the assembler - ; wont do the dirt work for us. As long as dsa_check_reselect - ; is negative, we need to sign extend with 1 bits to the full - ; 32 bit width of the address. - ; - ; A potential work around would be to have a known alignment - ; of the DSA structure such that the base address plus - ; dsa_check_reselect doesn't require carrying from bytes - ; higher than the LSB. - ; - - MOVE DSA0 TO SFBR - -at 0x000001bb : */ 0x72100000,0x00000000, -/* - MOVE SFBR + dsa_check_reselect TO SCRATCH0 - -at 0x000001bd : */ 0x6e340000,0x00000000, -/* - MOVE DSA1 TO SFBR - -at 0x000001bf : */ 0x72110000,0x00000000, -/* - MOVE SFBR + 0xff TO SCRATCH1 WITH CARRY - -at 0x000001c1 : */ 0x6f35ff00,0x00000000, -/* - MOVE DSA2 TO SFBR - -at 0x000001c3 : */ 0x72120000,0x00000000, -/* - MOVE SFBR + 0xff TO SCRATCH2 WITH CARRY - -at 0x000001c5 : */ 0x6f36ff00,0x00000000, -/* - MOVE DSA3 TO SFBR - -at 0x000001c7 : */ 0x72130000,0x00000000, -/* - MOVE SFBR + 0xff TO SCRATCH3 WITH CARRY - -at 0x000001c9 : */ 0x6f37ff00,0x00000000, -/* - - MOVE dmode_ncr_to_memory TO DMODE - -at 0x000001cb : */ 0x78380000,0x00000000, -/* - MOVE MEMORY 4, addr_scratch, reselected_check + 4 - -at 0x000001cd : */ 0xc0000004,0x00000000,0x0000074c, -/* - MOVE dmode_memory_to_memory TO DMODE - -at 0x000001d0 : */ 0x78380000,0x00000000, -/* -reselected_check: - JUMP 0 - -at 0x000001d2 : */ 0x80080000,0x00000000, -/* - - -; -; -ENTRY reselected_ok -reselected_ok: - MOVE MEMORY 4, 0, 0 ; Patched : first word - -at 0x000001d4 : */ 0xc0000004,0x00000000,0x00000000, -/* - ; is address of - ; successful dsa_next - ; Second word is last - ; unsuccessful dsa_next, - ; starting with - ; dsa_reconnect_head - ; We used to CLEAR ACK here. - - - - - - - RETURN ; Return control to where - -at 0x000001d7 : */ 0x90080000,0x00000000, -/* - - - - -selected: - INT int_err_selected; - -at 0x000001d9 : */ 0x98080000,0x00010000, -/* - -; -; A select or reselect failure can be caused by one of two conditions : -; 1. SIG_P was set. This will be the case if the user has written -; a new value to a previously NULL head of the issue queue. -; -; 2. The NCR53c810 was selected or reselected by another device. -; -; 3. The bus was allready busy since we were selected or reselected -; before starting the command. - -wait_reselect_failed: - - - -; Check selected bit. - MOVE SIST0 & 0x20 TO SFBR - -at 0x000001db : */ 0x74422000,0x00000000, -/* - JUMP selected, IF 0x20 - -at 0x000001dd : */ 0x800c0020,0x00000764, -/* -; Reading CTEST2 clears the SIG_P bit in the ISTAT register. - MOVE CTEST2 & 0x40 TO SFBR - -at 0x000001df : */ 0x741a4000,0x00000000, -/* - JUMP schedule, IF 0x40 - -at 0x000001e1 : */ 0x800c0040,0x00000000, -/* -; Check connected bit. -; FIXME: this needs to change if we support target mode - MOVE ISTAT & 0x08 TO SFBR - -at 0x000001e3 : */ 0x74140800,0x00000000, -/* - JUMP reselected, IF 0x08 - -at 0x000001e5 : */ 0x800c0008,0x0000065c, -/* -; FIXME : Something bogus happened, and we shouldn't fail silently. - - - - INT int_debug_panic - -at 0x000001e7 : */ 0x98080000,0x030b0000, -/* - - - -select_failed: - - - -; Otherwise, mask the selected and reselected bits off SIST0 - MOVE SIST0 & 0x30 TO SFBR - -at 0x000001e9 : */ 0x74423000,0x00000000, -/* - JUMP selected, IF 0x20 - -at 0x000001eb : */ 0x800c0020,0x00000764, -/* - JUMP reselected, IF 0x10 - -at 0x000001ed : */ 0x800c0010,0x0000065c, -/* -; If SIGP is set, the user just gave us another command, and -; we should restart or return to the scheduler. -; Reading CTEST2 clears the SIG_P bit in the ISTAT register. - MOVE CTEST2 & 0x40 TO SFBR - -at 0x000001ef : */ 0x741a4000,0x00000000, -/* - JUMP select, IF 0x40 - -at 0x000001f1 : */ 0x800c0040,0x000001fc, -/* -; Check connected bit. -; FIXME: this needs to change if we support target mode -; FIXME: is this really necessary? - MOVE ISTAT & 0x08 TO SFBR - -at 0x000001f3 : */ 0x74140800,0x00000000, -/* - JUMP reselected, IF 0x08 - -at 0x000001f5 : */ 0x800c0008,0x0000065c, -/* -; FIXME : Something bogus happened, and we shouldn't fail silently. - - - - INT int_debug_panic - -at 0x000001f7 : */ 0x98080000,0x030b0000, -/* - - -; -; test_1 -; test_2 -; -; PURPOSE : run some verification tests on the NCR. test_1 -; copies test_src to test_dest and interrupts the host -; processor, testing for cache coherency and interrupt -; problems in the processes. -; -; test_2 runs a command with offsets relative to the -; DSA on entry, and is useful for miscellaneous experimentation. -; - -; Verify that interrupts are working correctly and that we don't -; have a cache invalidation problem. - -ABSOLUTE test_src = 0, test_dest = 0 -ENTRY test_1 -test_1: - MOVE MEMORY 4, test_src, test_dest - -at 0x000001f9 : */ 0xc0000004,0x00000000,0x00000000, -/* - INT int_test_1 - -at 0x000001fc : */ 0x98080000,0x04000000, -/* - -; -; Run arbitrary commands, with test code establishing a DSA -; - -ENTRY test_2 -test_2: - CLEAR TARGET - -at 0x000001fe : */ 0x60000200,0x00000000, -/* - SELECT ATN FROM 0, test_2_fail - -at 0x00000200 : */ 0x43000000,0x00000850, -/* - JUMP test_2_msgout, WHEN MSG_OUT - -at 0x00000202 : */ 0x860b0000,0x00000810, -/* -ENTRY test_2_msgout -test_2_msgout: - MOVE FROM 8, WHEN MSG_OUT - -at 0x00000204 : */ 0x1e000000,0x00000008, -/* - MOVE FROM 16, WHEN CMD - -at 0x00000206 : */ 0x1a000000,0x00000010, -/* - MOVE FROM 24, WHEN DATA_IN - -at 0x00000208 : */ 0x19000000,0x00000018, -/* - MOVE FROM 32, WHEN STATUS - -at 0x0000020a : */ 0x1b000000,0x00000020, -/* - MOVE FROM 40, WHEN MSG_IN - -at 0x0000020c : */ 0x1f000000,0x00000028, -/* - MOVE SCNTL2 & 0x7f TO SCNTL2 - -at 0x0000020e : */ 0x7c027f00,0x00000000, -/* - CLEAR ACK - -at 0x00000210 : */ 0x60000040,0x00000000, -/* - WAIT DISCONNECT - -at 0x00000212 : */ 0x48000000,0x00000000, -/* -test_2_fail: - INT int_test_2 - -at 0x00000214 : */ 0x98080000,0x04010000, -/* - -ENTRY debug_break -debug_break: - INT int_debug_break - -at 0x00000216 : */ 0x98080000,0x03000000, -/* - -; -; initiator_abort -; target_abort -; -; PURPOSE : Abort the currently established nexus from with initiator -; or target mode. -; -; - -ENTRY target_abort -target_abort: - SET TARGET - -at 0x00000218 : */ 0x58000200,0x00000000, -/* - DISCONNECT - -at 0x0000021a : */ 0x48000000,0x00000000, -/* - CLEAR TARGET - -at 0x0000021c : */ 0x60000200,0x00000000, -/* - JUMP schedule - -at 0x0000021e : */ 0x80080000,0x00000000, -/* - -ENTRY initiator_abort -initiator_abort: - SET ATN - -at 0x00000220 : */ 0x58000008,0x00000000, -/* -; -; The SCSI-I specification says that targets may go into MSG out at -; their leisure upon receipt of the ATN single. On all versions of the -; specification, we can't change phases until REQ transitions true->false, -; so we need to sink/source one byte of data to allow the transition. -; -; For the sake of safety, we'll only source one byte of data in all -; cases, but to accomodate the SCSI-I dain bramage, we'll sink an -; arbitrary number of bytes. - JUMP spew_cmd, WHEN CMD - -at 0x00000222 : */ 0x820b0000,0x000008b8, -/* - JUMP eat_msgin, WHEN MSG_IN - -at 0x00000224 : */ 0x870b0000,0x000008c8, -/* - JUMP eat_datain, WHEN DATA_IN - -at 0x00000226 : */ 0x810b0000,0x000008f8, -/* - JUMP eat_status, WHEN STATUS - -at 0x00000228 : */ 0x830b0000,0x000008e0, -/* - JUMP spew_dataout, WHEN DATA_OUT - -at 0x0000022a : */ 0x800b0000,0x00000910, -/* - JUMP sated - -at 0x0000022c : */ 0x80080000,0x00000918, -/* -spew_cmd: - MOVE 1, NCR53c7xx_zero, WHEN CMD - -at 0x0000022e : */ 0x0a000001,0x00000000, -/* - JUMP sated - -at 0x00000230 : */ 0x80080000,0x00000918, -/* -eat_msgin: - MOVE 1, NCR53c7xx_sink, WHEN MSG_IN - -at 0x00000232 : */ 0x0f000001,0x00000000, -/* - JUMP eat_msgin, WHEN MSG_IN - -at 0x00000234 : */ 0x870b0000,0x000008c8, -/* - JUMP sated - -at 0x00000236 : */ 0x80080000,0x00000918, -/* -eat_status: - MOVE 1, NCR53c7xx_sink, WHEN STATUS - -at 0x00000238 : */ 0x0b000001,0x00000000, -/* - JUMP eat_status, WHEN STATUS - -at 0x0000023a : */ 0x830b0000,0x000008e0, -/* - JUMP sated - -at 0x0000023c : */ 0x80080000,0x00000918, -/* -eat_datain: - MOVE 1, NCR53c7xx_sink, WHEN DATA_IN - -at 0x0000023e : */ 0x09000001,0x00000000, -/* - JUMP eat_datain, WHEN DATA_IN - -at 0x00000240 : */ 0x810b0000,0x000008f8, -/* - JUMP sated - -at 0x00000242 : */ 0x80080000,0x00000918, -/* -spew_dataout: - MOVE 1, NCR53c7xx_zero, WHEN DATA_OUT - -at 0x00000244 : */ 0x08000001,0x00000000, -/* -sated: - MOVE SCNTL2 & 0x7f TO SCNTL2 - -at 0x00000246 : */ 0x7c027f00,0x00000000, -/* - MOVE 1, NCR53c7xx_msg_abort, WHEN MSG_OUT - -at 0x00000248 : */ 0x0e000001,0x00000000, -/* - WAIT DISCONNECT - -at 0x0000024a : */ 0x48000000,0x00000000, -/* - INT int_norm_aborted - -at 0x0000024c : */ 0x98080000,0x02040000, -/* - -; -; dsa_to_scratch -; scratch_to_dsa -; -; PURPOSE : -; The NCR chips cannot do a move memory instruction with the DSA register -; as the source or destination. So, we provide a couple of subroutines -; that let us switch between the DSA register and scratch register. -; -; Memory moves to/from the DSPS register also don't work, but we -; don't use them. -; -; - - -dsa_to_scratch: - MOVE DSA0 TO SFBR - -at 0x0000024e : */ 0x72100000,0x00000000, -/* - MOVE SFBR TO SCRATCH0 - -at 0x00000250 : */ 0x6a340000,0x00000000, -/* - MOVE DSA1 TO SFBR - -at 0x00000252 : */ 0x72110000,0x00000000, -/* - MOVE SFBR TO SCRATCH1 - -at 0x00000254 : */ 0x6a350000,0x00000000, -/* - MOVE DSA2 TO SFBR - -at 0x00000256 : */ 0x72120000,0x00000000, -/* - MOVE SFBR TO SCRATCH2 - -at 0x00000258 : */ 0x6a360000,0x00000000, -/* - MOVE DSA3 TO SFBR - -at 0x0000025a : */ 0x72130000,0x00000000, -/* - MOVE SFBR TO SCRATCH3 - -at 0x0000025c : */ 0x6a370000,0x00000000, -/* - RETURN - -at 0x0000025e : */ 0x90080000,0x00000000, -/* - -scratch_to_dsa: - MOVE SCRATCH0 TO SFBR - -at 0x00000260 : */ 0x72340000,0x00000000, -/* - MOVE SFBR TO DSA0 - -at 0x00000262 : */ 0x6a100000,0x00000000, -/* - MOVE SCRATCH1 TO SFBR - -at 0x00000264 : */ 0x72350000,0x00000000, -/* - MOVE SFBR TO DSA1 - -at 0x00000266 : */ 0x6a110000,0x00000000, -/* - MOVE SCRATCH2 TO SFBR - -at 0x00000268 : */ 0x72360000,0x00000000, -/* - MOVE SFBR TO DSA2 - -at 0x0000026a : */ 0x6a120000,0x00000000, -/* - MOVE SCRATCH3 TO SFBR - -at 0x0000026c : */ 0x72370000,0x00000000, -/* - MOVE SFBR TO DSA3 - -at 0x0000026e : */ 0x6a130000,0x00000000, -/* - RETURN - -at 0x00000270 : */ 0x90080000,0x00000000, -}; - -#define A_NCR53c7xx_msg_abort 0x00000000 -u32 A_NCR53c7xx_msg_abort_used[] = { - 0x00000249, -}; - -#define A_NCR53c7xx_msg_reject 0x00000000 -u32 A_NCR53c7xx_msg_reject_used[] = { - 0x00000172, -}; - -#define A_NCR53c7xx_sink 0x00000000 -u32 A_NCR53c7xx_sink_used[] = { - 0x00000233, - 0x00000239, - 0x0000023f, -}; - -#define A_NCR53c7xx_zero 0x00000000 -u32 A_NCR53c7xx_zero_used[] = { - 0x0000022f, - 0x00000245, -}; - -#define A_NOP_insn 0x00000000 -u32 A_NOP_insn_used[] = { - 0x00000010, -}; - -#define A_addr_reconnect_dsa_head 0x00000000 -u32 A_addr_reconnect_dsa_head_used[] = { - 0x000001a7, -}; - -#define A_addr_scratch 0x00000000 -u32 A_addr_scratch_used[] = { - 0x00000004, - 0x0000001b, - 0x00000046, - 0x00000067, - 0x00000073, - 0x000000b0, - 0x000000c6, - 0x00000128, - 0x00000141, - 0x000001a1, - 0x000001ce, -}; - -#define A_addr_temp 0x00000000 -u32 A_addr_temp_used[] = { - 0x00000025, - 0x00000034, -}; - -#define A_dmode_memory_to_memory 0x00000000 -u32 A_dmode_memory_to_memory_used[] = { - 0x00000005, - 0x0000001c, - 0x00000027, - 0x00000035, - 0x00000047, - 0x00000069, - 0x00000075, - 0x000000b2, - 0x000000c8, - 0x0000012a, - 0x00000143, - 0x00000199, - 0x000001a2, - 0x000001d0, -}; - -#define A_dmode_memory_to_ncr 0x00000000 -u32 A_dmode_memory_to_ncr_used[] = { - 0x00000000, - 0x00000017, - 0x00000030, - 0x00000042, - 0x0000019d, -}; - -#define A_dmode_ncr_to_memory 0x00000000 -u32 A_dmode_ncr_to_memory_used[] = { - 0x00000022, - 0x00000064, - 0x00000070, - 0x000000ad, - 0x000000c3, - 0x00000125, - 0x0000013e, - 0x000001cb, -}; - -#define A_dsa_check_reselect 0x00000000 -u32 A_dsa_check_reselect_used[] = { - 0x000001bd, -}; - -#define A_dsa_cmdout 0x00000048 -u32 A_dsa_cmdout_used[] = { - 0x00000094, -}; - -#define A_dsa_cmnd 0x00000038 -u32 A_dsa_cmnd_used[] = { -}; - -#define A_dsa_datain 0x00000054 -u32 A_dsa_datain_used[] = { - 0x000000bb, -}; - -#define A_dsa_dataout 0x00000050 -u32 A_dsa_dataout_used[] = { - 0x000000a5, -}; - -#define A_dsa_end 0x00000070 -u32 A_dsa_end_used[] = { -}; - -#define A_dsa_fields_start 0x00000000 -u32 A_dsa_fields_start_used[] = { -}; - -#define A_dsa_msgin 0x00000058 -u32 A_dsa_msgin_used[] = { - 0x00000188, -}; - -#define A_dsa_msgout 0x00000040 -u32 A_dsa_msgout_used[] = { - 0x00000086, -}; - -#define A_dsa_msgout_other 0x00000068 -u32 A_dsa_msgout_other_used[] = { - 0x00000180, -}; - -#define A_dsa_next 0x00000030 -u32 A_dsa_next_used[] = { - 0x0000005c, -}; - -#define A_dsa_restore_pointers 0x00000000 -u32 A_dsa_restore_pointers_used[] = { - 0x0000012e, -}; - -#define A_dsa_save_data_pointer 0x00000000 -u32 A_dsa_save_data_pointer_used[] = { - 0x00000115, -}; - -#define A_dsa_select 0x0000003c -u32 A_dsa_select_used[] = { - 0x00000081, -}; - -#define A_dsa_status 0x00000060 -u32 A_dsa_status_used[] = { - 0x00000184, -}; - -#define A_dsa_temp_addr_array_value 0x00000000 -u32 A_dsa_temp_addr_array_value_used[] = { -}; - -#define A_dsa_temp_addr_dsa_value 0x00000000 -u32 A_dsa_temp_addr_dsa_value_used[] = { - 0x00000003, -}; - -#define A_dsa_temp_addr_new_value 0x00000000 -u32 A_dsa_temp_addr_new_value_used[] = { -}; - -#define A_dsa_temp_addr_next 0x00000000 -u32 A_dsa_temp_addr_next_used[] = { - 0x00000015, - 0x0000004e, -}; - -#define A_dsa_temp_addr_residual 0x00000000 -u32 A_dsa_temp_addr_residual_used[] = { - 0x0000002a, - 0x00000039, -}; - -#define A_dsa_temp_addr_saved_pointer 0x00000000 -u32 A_dsa_temp_addr_saved_pointer_used[] = { - 0x00000026, - 0x00000033, -}; - -#define A_dsa_temp_addr_saved_residual 0x00000000 -u32 A_dsa_temp_addr_saved_residual_used[] = { - 0x0000002b, - 0x00000038, -}; - -#define A_dsa_temp_lun 0x00000000 -u32 A_dsa_temp_lun_used[] = { - 0x0000004b, -}; - -#define A_dsa_temp_next 0x00000000 -u32 A_dsa_temp_next_used[] = { - 0x0000001a, -}; - -#define A_dsa_temp_sync 0x00000000 -u32 A_dsa_temp_sync_used[] = { - 0x00000053, -}; - -#define A_dsa_temp_target 0x00000000 -u32 A_dsa_temp_target_used[] = { - 0x00000040, -}; - -#define A_int_debug_break 0x03000000 -u32 A_int_debug_break_used[] = { - 0x00000217, -}; - -#define A_int_debug_panic 0x030b0000 -u32 A_int_debug_panic_used[] = { - 0x000001e8, - 0x000001f8, -}; - -#define A_int_err_check_condition 0x00030000 -u32 A_int_err_check_condition_used[] = { - 0x00000194, -}; - -#define A_int_err_no_phase 0x00040000 -u32 A_int_err_no_phase_used[] = { -}; - -#define A_int_err_selected 0x00010000 -u32 A_int_err_selected_used[] = { - 0x000001da, -}; - -#define A_int_err_unexpected_phase 0x00000000 -u32 A_int_err_unexpected_phase_used[] = { - 0x0000008c, - 0x00000092, - 0x0000009a, - 0x000000d0, - 0x000000d4, - 0x000000d6, - 0x000000de, - 0x000000e2, - 0x000000e4, - 0x000000ec, - 0x000000f0, - 0x000000f2, - 0x000000f4, - 0x0000014c, -}; - -#define A_int_err_unexpected_reselect 0x00020000 -u32 A_int_err_unexpected_reselect_used[] = { - 0x000001ba, -}; - -#define A_int_msg_1 0x01020000 -u32 A_int_msg_1_used[] = { - 0x0000010e, - 0x00000110, -}; - -#define A_int_msg_sdtr 0x01010000 -u32 A_int_msg_sdtr_used[] = { - 0x0000016c, -}; - -#define A_int_msg_wdtr 0x01000000 -u32 A_int_msg_wdtr_used[] = { - 0x00000160, -}; - -#define A_int_norm_aborted 0x02040000 -u32 A_int_norm_aborted_used[] = { - 0x0000024d, -}; - -#define A_int_norm_command_complete 0x02020000 -u32 A_int_norm_command_complete_used[] = { -}; - -#define A_int_norm_disconnected 0x02030000 -u32 A_int_norm_disconnected_used[] = { -}; - -#define A_int_norm_reselect_complete 0x02010000 -u32 A_int_norm_reselect_complete_used[] = { -}; - -#define A_int_norm_reset 0x02050000 -u32 A_int_norm_reset_used[] = { -}; - -#define A_int_norm_select_complete 0x02000000 -u32 A_int_norm_select_complete_used[] = { -}; - -#define A_int_test_1 0x04000000 -u32 A_int_test_1_used[] = { - 0x000001fd, -}; - -#define A_int_test_2 0x04010000 -u32 A_int_test_2_used[] = { - 0x00000215, -}; - -#define A_int_test_3 0x04020000 -u32 A_int_test_3_used[] = { -}; - -#define A_msg_buf 0x00000000 -u32 A_msg_buf_used[] = { - 0x00000102, - 0x0000014e, - 0x00000158, - 0x0000015e, - 0x00000164, - 0x0000016a, -}; - -#define A_reconnect_dsa_head 0x00000000 -u32 A_reconnect_dsa_head_used[] = { - 0x0000006c, - 0x00000074, - 0x000001a0, -}; - -#define A_reselected_identify 0x00000000 -u32 A_reselected_identify_used[] = { - 0x00000045, - 0x0000019c, -}; - -#define A_reselected_tag 0x00000000 -u32 A_reselected_tag_used[] = { -}; - -#define A_schedule 0x00000000 -u32 A_schedule_used[] = { - 0x0000007e, - 0x00000192, - 0x000001e2, - 0x0000021f, -}; - -#define A_test_dest 0x00000000 -u32 A_test_dest_used[] = { - 0x000001fb, -}; - -#define A_test_src 0x00000000 -u32 A_test_src_used[] = { - 0x000001fa, -}; - -#define Ent_accept_message 0x000005d4 -#define Ent_cmdout_cmdout 0x0000024c -#define Ent_command_complete 0x0000060c -#define Ent_command_complete_msgin 0x0000061c -#define Ent_data_transfer 0x00000254 -#define Ent_datain_to_jump 0x00000328 -#define Ent_debug_break 0x00000858 -#define Ent_dsa_code_begin 0x00000000 -#define Ent_dsa_code_check_reselect 0x000000f8 -#define Ent_dsa_code_fix_jump 0x0000003c -#define Ent_dsa_code_restore_pointers 0x000000c0 -#define Ent_dsa_code_save_data_pointer 0x00000088 -#define Ent_dsa_code_template 0x00000000 -#define Ent_dsa_code_template_end 0x00000168 -#define Ent_dsa_schedule 0x00000168 -#define Ent_dsa_zero 0x00000168 -#define Ent_end_data_transfer 0x0000028c -#define Ent_initiator_abort 0x00000880 -#define Ent_msg_in 0x00000404 -#define Ent_msg_in_restart 0x000003e4 -#define Ent_other_in 0x00000374 -#define Ent_other_out 0x0000033c -#define Ent_other_transfer 0x000003ac -#define Ent_reject_message 0x000005b4 -#define Ent_reselected_check_next 0x000006a4 -#define Ent_reselected_ok 0x00000750 -#define Ent_respond_message 0x000005ec -#define Ent_select 0x000001fc -#define Ent_select_msgout 0x00000214 -#define Ent_target_abort 0x00000860 -#define Ent_test_1 0x000007e4 -#define Ent_test_2 0x000007f8 -#define Ent_test_2_msgout 0x00000810 -#define Ent_wait_reselect 0x00000654 -u32 LABELPATCHES[] = { - 0x00000008, - 0x0000000a, - 0x00000013, - 0x00000016, - 0x0000001f, - 0x00000021, - 0x0000004f, - 0x00000051, - 0x0000005b, - 0x00000068, - 0x0000006f, - 0x00000082, - 0x00000084, - 0x0000008a, - 0x0000008e, - 0x00000090, - 0x00000096, - 0x00000098, - 0x0000009c, - 0x0000009e, - 0x000000a0, - 0x000000a2, - 0x000000a4, - 0x000000b1, - 0x000000b6, - 0x000000ba, - 0x000000c7, - 0x000000cc, - 0x000000d2, - 0x000000d8, - 0x000000da, - 0x000000e0, - 0x000000e6, - 0x000000e8, - 0x000000ee, - 0x000000f6, - 0x000000f8, - 0x00000104, - 0x00000106, - 0x00000108, - 0x0000010a, - 0x0000010c, - 0x00000112, - 0x00000114, - 0x00000129, - 0x00000142, - 0x00000148, - 0x00000150, - 0x00000152, - 0x00000154, - 0x0000015a, - 0x00000166, - 0x00000196, - 0x000001a5, - 0x000001a8, - 0x000001ac, - 0x000001b0, - 0x000001b4, - 0x000001b8, - 0x000001cf, - 0x000001de, - 0x000001e6, - 0x000001ec, - 0x000001ee, - 0x000001f2, - 0x000001f6, - 0x00000201, - 0x00000203, - 0x00000223, - 0x00000225, - 0x00000227, - 0x00000229, - 0x0000022b, - 0x0000022d, - 0x00000231, - 0x00000235, - 0x00000237, - 0x0000023b, - 0x0000023d, - 0x00000241, - 0x00000243, -}; - -struct { - u32 offset; - void *address; -} EXTERNAL_PATCHES[] = { -}; - -u32 INSTRUCTIONS = 301; -u32 PATCHES = 81; -u32 EXTERNAL_PATCHES_LEN = 0; diff --git a/i386/i386at/gpl/linux/scsi/53c8xx_u.h b/i386/i386at/gpl/linux/scsi/53c8xx_u.h deleted file mode 100644 index c3d486fe..00000000 --- a/i386/i386at/gpl/linux/scsi/53c8xx_u.h +++ /dev/null @@ -1,97 +0,0 @@ -#undef A_NCR53c7xx_msg_abort -#undef A_NCR53c7xx_msg_reject -#undef A_NCR53c7xx_sink -#undef A_NCR53c7xx_zero -#undef A_NOP_insn -#undef A_addr_reconnect_dsa_head -#undef A_addr_scratch -#undef A_addr_temp -#undef A_dmode_memory_to_memory -#undef A_dmode_memory_to_ncr -#undef A_dmode_ncr_to_memory -#undef A_dsa_check_reselect -#undef A_dsa_cmdout -#undef A_dsa_cmnd -#undef A_dsa_datain -#undef A_dsa_dataout -#undef A_dsa_end -#undef A_dsa_fields_start -#undef A_dsa_msgin -#undef A_dsa_msgout -#undef A_dsa_msgout_other -#undef A_dsa_next -#undef A_dsa_restore_pointers -#undef A_dsa_save_data_pointer -#undef A_dsa_select -#undef A_dsa_status -#undef A_dsa_temp_addr_array_value -#undef A_dsa_temp_addr_dsa_value -#undef A_dsa_temp_addr_new_value -#undef A_dsa_temp_addr_next -#undef A_dsa_temp_addr_residual -#undef A_dsa_temp_addr_saved_pointer -#undef A_dsa_temp_addr_saved_residual -#undef A_dsa_temp_lun -#undef A_dsa_temp_next -#undef A_dsa_temp_sync -#undef A_dsa_temp_target -#undef A_int_debug_break -#undef A_int_debug_panic -#undef A_int_err_check_condition -#undef A_int_err_no_phase -#undef A_int_err_selected -#undef A_int_err_unexpected_phase -#undef A_int_err_unexpected_reselect -#undef A_int_msg_1 -#undef A_int_msg_sdtr -#undef A_int_msg_wdtr -#undef A_int_norm_aborted -#undef A_int_norm_command_complete -#undef A_int_norm_disconnected -#undef A_int_norm_reselect_complete -#undef A_int_norm_reset -#undef A_int_norm_select_complete -#undef A_int_test_1 -#undef A_int_test_2 -#undef A_int_test_3 -#undef A_msg_buf -#undef A_reconnect_dsa_head -#undef A_reselected_identify -#undef A_reselected_tag -#undef A_schedule -#undef A_test_dest -#undef A_test_src -#undef Ent_accept_message -#undef Ent_cmdout_cmdout -#undef Ent_command_complete -#undef Ent_command_complete_msgin -#undef Ent_data_transfer -#undef Ent_datain_to_jump -#undef Ent_debug_break -#undef Ent_dsa_code_begin -#undef Ent_dsa_code_check_reselect -#undef Ent_dsa_code_fix_jump -#undef Ent_dsa_code_restore_pointers -#undef Ent_dsa_code_save_data_pointer -#undef Ent_dsa_code_template -#undef Ent_dsa_code_template_end -#undef Ent_dsa_schedule -#undef Ent_dsa_zero -#undef Ent_end_data_transfer -#undef Ent_initiator_abort -#undef Ent_msg_in -#undef Ent_msg_in_restart -#undef Ent_other_in -#undef Ent_other_out -#undef Ent_other_transfer -#undef Ent_reject_message -#undef Ent_reselected_check_next -#undef Ent_reselected_ok -#undef Ent_respond_message -#undef Ent_select -#undef Ent_select_msgout -#undef Ent_target_abort -#undef Ent_test_1 -#undef Ent_test_2 -#undef Ent_test_2_msgout -#undef Ent_wait_reselect diff --git a/i386/i386at/gpl/linux/scsi/AM53C974.c b/i386/i386at/gpl/linux/scsi/AM53C974.c deleted file mode 100644 index 5d092c9a..00000000 --- a/i386/i386at/gpl/linux/scsi/AM53C974.c +++ /dev/null @@ -1,2249 +0,0 @@ -#include <linux/config.h> -#include <linux/delay.h> -#include <linux/signal.h> -#include <linux/sched.h> -#include <linux/errno.h> -#include <linux/bios32.h> -#include <linux/pci.h> -#include <linux/string.h> -#include <linux/blk.h> - -#include <asm/io.h> -#include <asm/system.h> - -#include "scsi.h" -#include "hosts.h" -#include "AM53C974.h" -#include "constants.h" -#include "sd.h" - -/* AM53/79C974 (PCscsi) driver release 0.5 - * - * The architecture and much of the code of this device - * driver was originally developed by Drew Eckhardt for - * the NCR5380. The following copyrights apply: - * For the architecture and all pieces of code which can also be found - * in the NCR5380 device driver: - * Copyright 1993, Drew Eckhardt - * Visionary Computing - * (Unix and Linux consulting and custom programming) - * drew@colorado.edu - * +1 (303) 666-5836 - * - * The AM53C974_nobios_detect code was origininally developed by - * Robin Cutshaw (robin@xfree86.org) and is used here in a - * slightly modified form. - * - * For the remaining code: - * Copyright 1994, D. Frieauff - * EMail: fri@rsx42sun0.dofn.de - * Phone: x49-7545-8-2256 , x49-7541-42305 - */ - -/* - * $Log: AM53C974.c,v $ - * Revision 1.1.1.1 1996/10/30 01:39:58 thomas - * Imported from UK22 - * - * Revision 1.1 1996/03/25 20:25:05 goel - * Linux driver merge. - * - */ - -#ifdef AM53C974_DEBUG - #define DEB(x) x - #ifdef AM53C974_DEBUG_KEYWAIT - #define KEYWAIT() AM53C974_keywait() - #else - #define KEYWAIT() - #endif - #ifdef AM53C974_DEBUG_INIT - #define DEB_INIT(x) x - #else - #define DEB_INIT(x) - #endif - #ifdef AM53C974_DEBUG_MSG - #define DEB_MSG(x) x - #else - #define DEB_MSG(x) - #endif - #ifdef AM53C974_DEB_RESEL - #define DEB_RESEL(x) x - #else - #define DEB_RESEL(x) - #endif - #ifdef AM53C974_DEBUG_QUEUE - #define DEB_QUEUE(x) x - #define LIST(x,y) {printk("LINE:%d Adding %p to %p\n", __LINE__, (void*)(x), (void*)(y)); if ((x)==(y)) udelay(5); } - #define REMOVE(w,x,y,z) {printk("LINE:%d Removing: %p->%p %p->%p \n", __LINE__, (void*)(w), (void*)(x), (void*)(y), (void*)(z)); if ((x)==(y)) udelay(5); } - #else - #define DEB_QUEUE(x) - #define LIST(x,y) - #define REMOVE(w,x,y,z) - #endif - #ifdef AM53C974_DEBUG_INFO - #define DEB_INFO(x) x - #else - #define DEB_INFO(x) - #endif - #ifdef AM53C974_DEBUG_LINKED - #define DEB_LINKED(x) x - #else - #define DEB_LINKED(x) - #endif - #ifdef AM53C974_DEBUG_INTR - #define DEB_INTR(x) x - #else - #define DEB_INTR(x) - #endif -#else - #define DEB_INIT(x) - #define DEB(x) - #define DEB_QUEUE(x) - #define LIST(x,y) - #define REMOVE(w,x,y,z) - #define DEB_INFO(x) - #define DEB_LINKED(x) - #define DEB_INTR(x) - #define DEB_MSG(x) - #define DEB_RESEL(x) - #define KEYWAIT() -#endif - #ifdef AM53C974_DEBUG_ABORT - #define DEB_ABORT(x) x - #else - #define DEB_ABORT(x) - #endif - -#ifdef VERBOSE_AM53C974_DEBUG -#define VDEB(x) x -#else -#define VDEB(x) -#endif - -#define INSIDE(x,l,h) ( ((x) >= (l)) && ((x) <= (h)) ) - -#ifdef AM53C974_DEBUG -static void AM53C974_print_pci(struct Scsi_Host *instance); -static void AM53C974_print_phase(struct Scsi_Host *instance); -static void AM53C974_print_queues(struct Scsi_Host *instance); -#endif /* AM53C974_DEBUG */ -static void AM53C974_print(struct Scsi_Host *instance); -static void AM53C974_keywait(void); -static int AM53C974_bios_detect(Scsi_Host_Template *tpnt); -static int AM53C974_nobios_detect(Scsi_Host_Template *tpnt); -static int AM53C974_init(Scsi_Host_Template *tpnt, pci_config_t pci_config); -static void AM53C974_config_after_reset(struct Scsi_Host *instance); -static __inline__ void initialize_SCp(Scsi_Cmnd *cmd); -static __inline__ void run_main(void); -static void AM53C974_main (void); -static void AM53C974_intr(int irq, struct pt_regs *regs); -static void AM53C974_intr_disconnect(struct Scsi_Host *instance); -static int AM53C974_sync_neg(struct Scsi_Host *instance, int target, unsigned char *msg); -static __inline__ void AM53C974_set_async(struct Scsi_Host *instance, int target); -static __inline__ void AM53C974_set_sync(struct Scsi_Host *instance, int target); -static void AM53C974_information_transfer(struct Scsi_Host *instance, - unsigned char statreg, unsigned char isreg, - unsigned char instreg, unsigned char cfifo, - unsigned char dmastatus); -static int AM53C974_message(struct Scsi_Host *instance, Scsi_Cmnd *cmd, unsigned char msg); -static void AM53C974_select(struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag); -static void AM53C974_intr_reselect(struct Scsi_Host *instance, unsigned char statreg); -static __inline__ void AM53C974_transfer_dma(struct Scsi_Host *instance, short dir, - unsigned long length, char *data); -static void AM53C974_dma_blast(struct Scsi_Host *instance, unsigned char dmastatus, - unsigned char statreg); -static void AM53C974_intr_bus_reset(struct Scsi_Host *instance); - -static struct Scsi_Host *first_instance = NULL; -static Scsi_Host_Template *the_template = NULL; -static struct Scsi_Host *first_host = NULL; /* Head of list of AMD boards */ -static volatile int main_running = 0; -static int commandline_current = 0; -override_t overrides[7] = { {-1, 0, 0, 0}, }; /* LILO overrides */ - -#ifdef AM53C974_DEBUG -static int deb_stop = 1; - -/************************************************************************** - * Function : void AM53C974_print_pci(struct Scsi_Host *instance) - * - * Purpose : dump the PCI registers for debugging purposes - * - * Input : instance - which AM53C974 - **************************************************************************/ -static void AM53C974_print_pci(struct Scsi_Host *instance) -{ -int i; -unsigned short vendor_id, device_id, command, status, scratch[8]; -unsigned long class_revision, base; -unsigned char irq, cache_line_size, latency_timer, header_type; - -AM53C974_PCIREG_OPEN(); - -for (i = 0; i < 8; i++) *(scratch + i) = AM53C974_PCIREG_READ_WORD(instance, PCI_SCRATCH_REG_0 + 2*i); -vendor_id = AM53C974_PCIREG_READ_WORD(instance, PCI_VENDOR_ID); -device_id = AM53C974_PCIREG_READ_WORD(instance, PCI_DEVICE_ID); -command = AM53C974_PCIREG_READ_WORD(instance, PCI_COMMAND); -status = AM53C974_PCIREG_READ_WORD(instance, PCI_STATUS); -class_revision = AM53C974_PCIREG_READ_DWORD(instance, PCI_CLASS_REVISION); -cache_line_size = AM53C974_PCIREG_READ_BYTE(instance, PCI_CACHE_LINE_SIZE); -latency_timer = AM53C974_PCIREG_READ_BYTE(instance, PCI_LATENCY_TIMER); -header_type = AM53C974_PCIREG_READ_BYTE(instance, PCI_HEADER_TYPE); -base = AM53C974_PCIREG_READ_DWORD(instance, PCI_BASE_ADDRESS_0); -irq = AM53C974_PCIREG_READ_BYTE(instance, PCI_INTERRUPT_LINE); - -AM53C974_PCIREG_CLOSE(); - - -printk("------------- start of PCI register dump -------------\n"); -printk("PCI_VENDOR_ID: 0x%x\n", vendor_id); -printk("PCI_DEVICE_ID: 0x%x\n", device_id); -printk("PCI_COMMAND: 0x%x\n", command); -printk("PCI_STATUS: 0x%x\n", status); -printk("PCI_CLASS_REVISION: 0x%lx\n", class_revision); -printk("PCI_CACHE_LINE_SIZE: 0x%x\n", cache_line_size); -printk("PCI_LATENCY_TIMER: 0x%x\n", latency_timer); -printk("PCI_HEADER_TYPE: 0x%x\n", header_type); -printk("PCI_BASE_ADDRESS_0: 0x%lx\n", base); -printk("PCI_INTERRUPT_LINE: %d\n", irq); -for (i = 0; i < 8; i++) printk("PCI_SCRATCH_%d: 0x%x\n", i, scratch[i]); -printk("------------- end of PCI register dump -------------\n\n"); -} - -static struct { - unsigned char value; - char *name; -} phases[] = { -{PHASE_DATAOUT, "DATAOUT"}, {PHASE_DATAIN, "DATAIN"}, {PHASE_CMDOUT, "CMDOUT"}, -{PHASE_STATIN, "STATIN"}, {PHASE_MSGOUT, "MSGOUT"}, {PHASE_MSGIN, "MSGIN"}, -{PHASE_RES_0, "RESERVED 0"}, {PHASE_RES_1, "RESERVED 1"}}; - -/************************************************************************** - * Function : void AM53C974_print_phase(struct Scsi_Host *instance) - * - * Purpose : print the current SCSI phase for debugging purposes - * - * Input : instance - which AM53C974 - **************************************************************************/ -static void AM53C974_print_phase(struct Scsi_Host *instance) -{ -AM53C974_local_declare(); -unsigned char statreg, latched; -int i; -AM53C974_setio(instance); - -latched = (AM53C974_read_8(CNTLREG2)) & CNTLREG2_ENF; -statreg = AM53C974_read_8(STATREG); -for (i = 0; (phases[i].value != PHASE_RES_1) && - (phases[i].value != (statreg & STATREG_PHASE)); ++i); -if (latched) - printk("scsi%d : phase %s, latched at end of last command\n", instance->host_no, phases[i].name); - else - printk("scsi%d : phase %s, real time\n", instance->host_no, phases[i].name); -} - -/************************************************************************** - * Function : void AM53C974_print_queues(struct Scsi_Host *instance) - * - * Purpose : print commands in the various queues - * - * Inputs : instance - which AM53C974 - **************************************************************************/ -static void AM53C974_print_queues(struct Scsi_Host *instance) -{ -struct AM53C974_hostdata *hostdata = (struct AM53C974_hostdata *)instance->hostdata; -Scsi_Cmnd *ptr; - -printk("AM53C974: coroutine is%s running.\n", main_running ? "" : "n't"); - -cli(); - -if (!hostdata->connected) { - printk ("scsi%d: no currently connected command\n", instance->host_no); } - else { - print_Scsi_Cmnd ((Scsi_Cmnd *)hostdata->connected); } -if (!hostdata->sel_cmd) { - printk ("scsi%d: no currently arbitrating command\n", instance->host_no); } - else { - print_Scsi_Cmnd ((Scsi_Cmnd *)hostdata->sel_cmd); } - -printk ("scsi%d: issue_queue ", instance->host_no); -if (!hostdata->issue_queue) - printk("empty\n"); - else { - printk(":\n"); - for (ptr = (Scsi_Cmnd *)hostdata->issue_queue; ptr; ptr = (Scsi_Cmnd *)ptr->host_scribble) - print_Scsi_Cmnd (ptr); } - -printk ("scsi%d: disconnected_queue ", instance->host_no); -if (!hostdata->disconnected_queue) - printk("empty\n"); - else { - printk(":\n"); - for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr; ptr = (Scsi_Cmnd *)ptr->host_scribble) - print_Scsi_Cmnd (ptr); } - -sti(); -} - -#endif /* AM53C974_DEBUG */ - -/************************************************************************** - * Function : void AM53C974_print(struct Scsi_Host *instance) - * - * Purpose : dump the chip registers for debugging purposes - * - * Input : instance - which AM53C974 - **************************************************************************/ -static void AM53C974_print(struct Scsi_Host *instance) -{ -AM53C974_local_declare(); -unsigned long ctcreg, dmastc, dmaspa, dmawbc, dmawac; -unsigned char cmdreg, statreg, isreg, cfireg, cntlreg[4], dmacmd, dmastatus; -AM53C974_setio(instance); - -cli(); -ctcreg = AM53C974_read_8(CTCHREG) << 16; -ctcreg |= AM53C974_read_8(CTCMREG) << 8; -ctcreg |= AM53C974_read_8(CTCLREG); -cmdreg = AM53C974_read_8(CMDREG); -statreg = AM53C974_read_8(STATREG); -isreg = AM53C974_read_8(ISREG); -cfireg = AM53C974_read_8(CFIREG); -cntlreg[0] = AM53C974_read_8(CNTLREG1); -cntlreg[1] = AM53C974_read_8(CNTLREG2); -cntlreg[2] = AM53C974_read_8(CNTLREG3); -cntlreg[3] = AM53C974_read_8(CNTLREG4); -dmacmd = AM53C974_read_8(DMACMD); -dmastc = AM53C974_read_32(DMASTC); -dmaspa = AM53C974_read_32(DMASPA); -dmawbc = AM53C974_read_32(DMAWBC); -dmawac = AM53C974_read_32(DMAWAC); -dmastatus = AM53C974_read_8(DMASTATUS); -sti(); - -printk("AM53C974 register dump:\n"); -printk("IO base: 0x%04lx; CTCREG: 0x%04lx; CMDREG: 0x%02x; STATREG: 0x%02x; ISREG: 0x%02x\n", - io_port, ctcreg, cmdreg, statreg, isreg); -printk("CFIREG: 0x%02x; CNTLREG1-4: 0x%02x; 0x%02x; 0x%02x; 0x%02x\n", - cfireg, cntlreg[0], cntlreg[1], cntlreg[2], cntlreg[3]); -printk("DMACMD: 0x%02x; DMASTC: 0x%04lx; DMASPA: 0x%04lx\n", dmacmd, dmastc, dmaspa); -printk("DMAWBC: 0x%04lx; DMAWAC: 0x%04lx; DMASTATUS: 0x%02x\n", dmawbc, dmawac, dmastatus); -printk("---------------------------------------------------------\n"); -} - -/************************************************************************** -* Function : void AM53C974_keywait(void) -* -* Purpose : wait until a key is pressed, if it was the 'r' key leave singlestep mode; -* this function is used for debugging only -* -* Input : none -**************************************************************************/ -static void AM53C974_keywait(void) -{ -#ifdef AM53C974_DEBUG -int key; - -if (!deb_stop) return; -#endif - -cli(); -while ((inb_p(0x64) & 0x01) != 0x01) ; -#ifdef AM53C974_DEBUG -key = inb(0x60); -if (key == 0x93) deb_stop = 0; /* don't stop if 'r' was pressed */ -#endif -sti(); -} - -/************************************************************************** -* Function : AM53C974_setup(char *str, int *ints) -* -* Purpose : LILO command line initialization of the overrides array, -* -* Inputs : str - unused, ints - array of integer parameters with ints[0] -* equal to the number of ints. -* -* NOTE : this function needs to be declared as an external function -* in init/main.c and included there in the bootsetups list -***************************************************************************/ -void AM53C974_setup(char *str, int *ints) -{ -if (ints[0] < 4) - printk("AM53C974_setup: wrong number of parameters;\n correct syntax is: AM53C974=host-scsi-id, target-scsi-id, max-rate, max-offset\n"); - else { - if (commandline_current < (sizeof(overrides) / sizeof(override_t))) { - if ((ints[1] < 0) || (ints[1] > 7) || - (ints[2] < 0) || (ints[2] > 7) || - (ints[1] == ints[2]) || - (ints[3] < (DEF_CLK / MAX_PERIOD)) || (ints[3] > (DEF_CLK / MIN_PERIOD)) || - (ints[4] < 0) || (ints[4] > MAX_OFFSET)) - printk("AM53C974_setup: illegal parameter\n"); - else { - overrides[commandline_current].host_scsi_id = ints[1]; - overrides[commandline_current].target_scsi_id = ints[2]; - overrides[commandline_current].max_rate = ints[3]; - overrides[commandline_current].max_offset = ints[4]; - commandline_current++; } - } - else - printk("AM53C974_setup: too many overrides\n"); - } -} - -#if defined (CONFIG_PCI) -/************************************************************************** -* Function : int AM53C974_bios_detect(Scsi_Host_Template *tpnt) -* -* Purpose : detects and initializes AM53C974 SCSI chips with PCI Bios -* -* Inputs : tpnt - host template -* -* Returns : number of host adapters detected -**************************************************************************/ -int AM53C974_bios_detect(Scsi_Host_Template *tpnt) -{ -int count = 0; /* number of boards detected */ -int pci_index; -pci_config_t pci_config; - -for (pci_index = 0; pci_index <= 16; ++pci_index) { - unsigned char pci_bus, pci_device_fn; - if (pcibios_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_SCSI, pci_index, &pci_bus, &pci_device_fn) != 0) - break; - - pcibios_read_config_word(pci_bus, pci_device_fn, PCI_VENDOR_ID, &pci_config._vendor); - pcibios_read_config_word(pci_bus, pci_device_fn, PCI_DEVICE_ID, &pci_config._device); - pcibios_read_config_word(pci_bus, pci_device_fn, PCI_COMMAND, &pci_config._command); - pcibios_read_config_word(pci_bus, pci_device_fn, PCI_STATUS, &pci_config._status); - pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_CLASS_REVISION, &pci_config._class_revision); - pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_CACHE_LINE_SIZE, &pci_config._cache_line_size); - pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_LATENCY_TIMER, &pci_config._latency_timer); - pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_HEADER_TYPE, &pci_config._header_type); - pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_BIST, &pci_config._bist); - pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_0, &pci_config._base0); - pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_1, &pci_config._base1); - pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_2, &pci_config._base2); - pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_3, &pci_config._base3); - pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_4, &pci_config._base4); - pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_5, &pci_config._base5); - pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_ROM_ADDRESS, &pci_config._baserom); - pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_INTERRUPT_LINE, &pci_config._int_line); - pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_INTERRUPT_PIN, &pci_config._int_pin); - pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_MIN_GNT, &pci_config._min_gnt); - pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_MAX_LAT, &pci_config._max_lat); - pci_config._pcibus = 0xFFFFFFFF; - pci_config._cardnum = 0xFFFFFFFF; - - /* check whether device is I/O mapped -- should be */ - if (!(pci_config._command & PCI_COMMAND_IO)) continue; - - /* PCI Spec 2.1 states that it is either the driver's or the PCI card's responsibility - to set the PCI Master Enable Bit if needed. - (from Mark Stockton <marks@schooner.sys.hou.compaq.com>) */ - if (!(pci_config._command & PCI_COMMAND_MASTER)) { - pci_config._command |= PCI_COMMAND_MASTER; - printk("PCI Master Bit has not been set. Setting...\n"); - pcibios_write_config_word(pci_bus, pci_device_fn, PCI_COMMAND, pci_config._command); } - - /* everything seems OK now, so initialize */ - if (AM53C974_init(tpnt, pci_config)) count++ ; - } -return (count); -} -#endif - -/************************************************************************** -* Function : int AM53C974_nobios_detect(Scsi_Host_Template *tpnt) -* -* Purpose : detects and initializes AM53C974 SCSI chips using PCI config 2 -* -* Inputs : tpnt - host template -* -* Returns : number of host adapters detected -* -* NOTE : This code assumes the controller on PCI bus 0. -* -* Origin: Robin Cutshaw (robin@xfree86.org) -**************************************************************************/ -int AM53C974_nobios_detect(Scsi_Host_Template *tpnt) -{ -int count = 0; /* number of boards detected */ -pci_config_t pci_config; - -/* first try PCI config method 1 */ -for (pci_config._pcibus = 0; pci_config._pcibus < 0x10; pci_config._pcibus++) { - for (pci_config._cardnum = 0; pci_config._cardnum < 0x20; pci_config._cardnum++) { - unsigned long config_cmd; - config_cmd = 0x80000000 | (pci_config._pcibus<<16) | (pci_config._cardnum<<11); - - outl(config_cmd, 0xCF8); /* ioreg 0 */ - pci_config._device_vendor = inl(0xCFC); - - if ((pci_config._vendor == PCI_VENDOR_ID_AMD) && (pci_config._device == PCI_DEVICE_ID_AMD_SCSI)) { - outl(config_cmd | PCI_COMMAND, 0xCF8); pci_config._status_command = inl(0xCFC); - outl(config_cmd | PCI_CLASS_REVISION, 0xCF8); pci_config._class_revision = inl(0xCFC); - outl(config_cmd | PCI_CACHE_LINE_SIZE, 0xCF8); pci_config._bist_header_latency_cache = inl(0xCFC); - outl(config_cmd | PCI_BASE_ADDRESS_0, 0xCF8); pci_config._base0 = inl(0xCFC); - outl(config_cmd | PCI_BASE_ADDRESS_1, 0xCF8); pci_config._base1 = inl(0xCFC); - outl(config_cmd | PCI_BASE_ADDRESS_2, 0xCF8); pci_config._base2 = inl(0xCFC); - outl(config_cmd | PCI_BASE_ADDRESS_3, 0xCF8); pci_config._base3 = inl(0xCFC); - outl(config_cmd | PCI_BASE_ADDRESS_4, 0xCF8); pci_config._base4 = inl(0xCFC); - outl(config_cmd | PCI_BASE_ADDRESS_5, 0xCF8); pci_config._base5 = inl(0xCFC); - outl(config_cmd | PCI_ROM_ADDRESS, 0xCF8); pci_config._baserom = inl(0xCFC); - outl(config_cmd | PCI_INTERRUPT_LINE, 0xCF8); pci_config._max_min_ipin_iline = inl(0xCFC); - - /* check whether device is I/O mapped -- should be */ - if (!(pci_config._command & PCI_COMMAND_IO)) continue; - - /* PCI Spec 2.1 states that it is either the driver's or the PCI card's responsibility - to set the PCI Master Enable Bit if needed. - From Mark Stockton <marks@schooner.sys.hou.compaq.com> */ - if (!(pci_config._command & PCI_COMMAND_MASTER)) { - pci_config._command |= PCI_COMMAND_MASTER; - printk("Config 1; PCI Master Bit has not been set. Setting...\n"); - outl(config_cmd | PCI_COMMAND, 0xCF8); outw(pci_config._command, 0xCFC); } - - /* everything seems OK now, so initialize */ - if (AM53C974_init(tpnt, pci_config)) count++ ; - } - } - } -outb(0, 0xCF8); /* is this really necessary? */ - -/* try PCI config method 2, if no device was detected by method 1 */ -if (!count) { - AM53C974_PCIREG_OPEN(); - - pci_config._pcibus = 0xFFFFFFFF; - pci_config._cardnum = 0xFFFFFFFF; - - for (pci_config._ioaddr = 0xC000; pci_config._ioaddr < 0xD000; pci_config._ioaddr += 0x0100) { - pci_config._device_vendor = inl(pci_config._ioaddr); - - if ((pci_config._vendor == PCI_VENDOR_ID_AMD) && (pci_config._device == PCI_DEVICE_ID_AMD_SCSI)) { - pci_config._status_command = inl(pci_config._ioaddr + PCI_COMMAND); - pci_config._class_revision = inl(pci_config._ioaddr + PCI_CLASS_REVISION); - pci_config._bist_header_latency_cache = inl(pci_config._ioaddr + PCI_CACHE_LINE_SIZE); - pci_config._base0 = inl(pci_config._ioaddr + PCI_BASE_ADDRESS_0); - pci_config._base1 = inl(pci_config._ioaddr + PCI_BASE_ADDRESS_1); - pci_config._base2 = inl(pci_config._ioaddr + PCI_BASE_ADDRESS_2); - pci_config._base3 = inl(pci_config._ioaddr + PCI_BASE_ADDRESS_3); - pci_config._base4 = inl(pci_config._ioaddr + PCI_BASE_ADDRESS_4); - pci_config._base5 = inl(pci_config._ioaddr + PCI_BASE_ADDRESS_5); - pci_config._baserom = inl(pci_config._ioaddr + PCI_ROM_ADDRESS); - pci_config._max_min_ipin_iline = inl(pci_config._ioaddr + PCI_INTERRUPT_LINE); - - /* check whether device is I/O mapped -- should be */ - if (!(pci_config._command & PCI_COMMAND_IO)) continue; - - /* PCI Spec 2.1 states that it is either the driver's or the PCI card's responsibility - to set the PCI Master Enable Bit if needed. - From Mark Stockton <marks@schooner.sys.hou.compaq.com> */ - if (!(pci_config._command & PCI_COMMAND_MASTER)) { - pci_config._command |= PCI_COMMAND_MASTER; - printk("Config 2; PCI Master Bit has not been set. Setting...\n"); - outw(pci_config._command, pci_config._ioaddr + PCI_COMMAND); } - - /* everything seems OK now, so initialize */ - if (AM53C974_init(tpnt, pci_config)) count++ ; - } - } - AM53C974_PCIREG_CLOSE(); - } - -return(count); -} - -/************************************************************************** -* Function : int AM53C974_detect(Scsi_Host_Template *tpnt) -* -* Purpose : detects and initializes AM53C974 SCSI chips -* -* Inputs : tpnt - host template -* -* Returns : number of host adapters detected -**************************************************************************/ -int AM53C974_detect(Scsi_Host_Template *tpnt) -{ -int count; /* number of boards detected */ - -#if defined (CONFIG_PCI) -if (pcibios_present()) - count = AM53C974_bios_detect(tpnt); - else -#endif -count = AM53C974_nobios_detect(tpnt); -return (count); -} - -/************************************************************************** -* Function : int AM53C974_init(Scsi_Host_Template *tpnt, pci_config_t pci_config) -* -* Purpose : initializes instance and corresponding AM53/79C974 chip, -* -* Inputs : tpnt - template, pci_config - PCI configuration, -* -* Returns : 1 on success, 0 on failure. -* -* NOTE: If no override for the controller's SCSI id is given and AM53C974_SCSI_ID -* is not defined we assume that the SCSI address of this controller is correctly -* set up by the BIOS (as reflected by contents of register CNTLREG1). -* This is the only BIOS assistance we need. -**************************************************************************/ -static int AM53C974_init(Scsi_Host_Template *tpnt, pci_config_t pci_config) -{ -AM53C974_local_declare(); -int i, j; -struct Scsi_Host *instance, *search; -struct AM53C974_hostdata *hostdata; - -#ifdef AM53C974_OPTION_DEBUG_PROBE_ONLY - printk ("AM53C974: probe only enabled, aborting initialization\n"); - return -1; -#endif - -instance = scsi_register(tpnt, sizeof(struct AM53C974_hostdata)); -hostdata = (struct AM53C974_hostdata *)instance->hostdata; -instance->base = NULL; -instance->io_port = pci_config._base0 & (pci_config._base0 & 0x1 ? - 0xFFFFFFFC : 0xFFFFFFF0); -instance->irq = pci_config._int_line; -instance->dma_channel = -1; -AM53C974_setio(instance); - -#ifdef AM53C974_SCSI_ID -instance->this_id = AM53C974_SCSI_ID; -AM53C974_write_8(CNTLREG1, instance->this_id & CNTLREG1_SID); -#else -instance->this_id = AM53C974_read_8(CNTLREG1) & CNTLREG1_SID; -if (instance->this_id != 7) - printk("scsi%d: WARNING: unusual hostadapter SCSI id %d; please verify!\n", - instance->host_no, instance->this_id); -#endif - -for (i = 0; i < sizeof(hostdata->msgout); i++) { - hostdata->msgout[i] = NOP; - hostdata->last_message[i] = NOP; } -for (i = 0; i < 8; i++) { - hostdata->busy[i] = 0; - hostdata->sync_per[i] = DEF_STP; - hostdata->sync_off[i] = 0; - hostdata->sync_neg[i] = 0; - hostdata->sync_en[i] = DEFAULT_SYNC_NEGOTIATION_ENABLED; - hostdata->max_rate[i] = DEFAULT_RATE; - hostdata->max_offset[i] = DEFAULT_SYNC_OFFSET; } - -/* overwrite defaults by LILO overrides */ -for (i = 0; i < commandline_current; i++) { - if (overrides[i].host_scsi_id == instance->this_id) { - j = overrides[i].target_scsi_id; - hostdata->sync_en[j] = 1; - hostdata->max_rate[j] = overrides[i].max_rate; - hostdata->max_offset[j] = overrides[i].max_offset; - } - } - -hostdata->sel_cmd = NULL; -hostdata->connected = NULL; -hostdata->issue_queue = NULL; -hostdata->disconnected_queue = NULL; -hostdata->in_reset = 0; -hostdata->aborted = 0; -hostdata->selecting = 0; -hostdata->disconnecting = 0; -hostdata->dma_busy = 0; - -/* Set up an interrupt handler if we aren't already sharing an IRQ with another board */ -for (search = first_host; - search && ( ((the_template != NULL) && (search->hostt != the_template)) || - (search->irq != instance->irq) || (search == instance) ); - search = search->next); -if (!search) { - if (request_irq(instance->irq, AM53C974_intr, SA_INTERRUPT, "AM53C974")) { - printk("scsi%d: IRQ%d not free, detaching\n", instance->host_no, instance->irq); - scsi_unregister(instance); - return -1; } - } - else { - printk("scsi%d: using interrupt handler previously installed for scsi%d\n", - instance->host_no, search->host_no); } - -if (!the_template) { - the_template = instance->hostt; - first_instance = instance; } - -/* do hard reset */ -AM53C974_write_8(CMDREG, CMDREG_RDEV); /* reset device */ -udelay(5); -AM53C974_write_8(CMDREG, CMDREG_NOP); -AM53C974_write_8(CNTLREG1, CNTLREG1_DISR | instance->this_id); -AM53C974_write_8(CMDREG, CMDREG_RBUS); /* reset SCSI bus */ -udelay(10); -AM53C974_config_after_reset(instance); - -return(0); -} - -/********************************************************************* -* Function : AM53C974_config_after_reset(struct Scsi_Host *instance) * -* * -* Purpose : initializes chip registers after reset * -* * -* Inputs : instance - which AM53C974 * -* * -* Returns : nothing * -**********************************************************************/ -static void AM53C974_config_after_reset(struct Scsi_Host *instance) -{ -AM53C974_local_declare(); -AM53C974_setio(instance); - -/* clear SCSI FIFO */ -AM53C974_write_8(CMDREG, CMDREG_CFIFO); - -/* configure device */ -AM53C974_write_8(STIMREG, DEF_SCSI_TIMEOUT); -AM53C974_write_8(STPREG, DEF_STP & STPREG_STP); -AM53C974_write_8(SOFREG, (DEF_SOF_RAD<<6) | (DEF_SOF_RAA<<4)); -AM53C974_write_8(CLKFREG, DEF_CLKF & CLKFREG_MASK); -AM53C974_write_8(CNTLREG1, (DEF_ETM<<7) | CNTLREG1_DISR | (DEF_PERE<<4) | instance->this_id); -AM53C974_write_8(CNTLREG2, (DEF_ENF<<6)); -AM53C974_write_8(CNTLREG3, (DEF_ADIDCHK<<7) | (DEF_FASTSCSI<<4) | (DEF_FASTCLK<<3)); -AM53C974_write_8(CNTLREG4, (DEF_GLITCH<<6) | (DEF_PWD<<5) | (DEF_RAE<<3) | (DEF_RADE<<2) | CNTLREG4_RES); -} - -/*********************************************************************** -* Function : const char *AM53C974_info(struct Scsi_Host *instance) * -* * -* Purpose : return device driver information * -* * -* Inputs : instance - which AM53C974 * -* * -* Returns : info string * -************************************************************************/ -const char *AM53C974_info(struct Scsi_Host *instance) -{ -static char info[100]; - -sprintf(info, "AM53/79C974 PCscsi driver rev. %d.%d; host I/O address: 0x%x; irq: %d\n", - AM53C974_DRIVER_REVISION_MAJOR, AM53C974_DRIVER_REVISION_MINOR, - instance->io_port, instance->irq); -return (info); -} - -/************************************************************************** -* Function : int AM53C974_command (Scsi_Cmnd *SCpnt) * -* * -* Purpose : the unqueued SCSI command function, replaced by the * -* AM53C974_queue_command function * -* * -* Inputs : SCpnt - pointer to command structure * -* * -* Returns :status, see hosts.h for details * -***************************************************************************/ -int AM53C974_command(Scsi_Cmnd *SCpnt) -{ -DEB(printk("AM53C974_command called\n")); -return 0; -} - -/************************************************************************** -* Function : void initialize_SCp(Scsi_Cmnd *cmd) * -* * -* Purpose : initialize the saved data pointers for cmd to point to the * -* start of the buffer. * -* * -* Inputs : cmd - Scsi_Cmnd structure to have pointers reset. * -* * -* Returns : nothing * -**************************************************************************/ -static __inline__ void initialize_SCp(Scsi_Cmnd *cmd) -{ -if (cmd->use_sg) { - cmd->SCp.buffer = (struct scatterlist *)cmd->buffer; - cmd->SCp.buffers_residual = cmd->use_sg - 1; - cmd->SCp.ptr = (char *)cmd->SCp.buffer->address; - cmd->SCp.this_residual = cmd->SCp.buffer->length; } - else { - cmd->SCp.buffer = NULL; - cmd->SCp.buffers_residual = 0; - cmd->SCp.ptr = (char *)cmd->request_buffer; - cmd->SCp.this_residual = cmd->request_bufflen; } -} - -/************************************************************************** -* Function : run_main(void) * -* * -* Purpose : insure that the coroutine is running and will process our * -* request. main_running is checked/set here (in an inline * -* function rather than in AM53C974_main itself to reduce the * -* chances of stack overflow. * -* * -* * -* Inputs : none * -* * -* Returns : nothing * -**************************************************************************/ -static __inline__ void run_main(void) -{ -cli(); -if (!main_running) { - /* main_running is cleared in AM53C974_main once it can't do - more work, and AM53C974_main exits with interrupts disabled. */ - main_running = 1; - AM53C974_main(); - sti(); } - else - sti(); -} - -/************************************************************************** -* Function : int AM53C974_queue_command(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) -* -* Purpose : writes SCSI command into AM53C974 FIFO -* -* Inputs : cmd - SCSI command, done - function called on completion, with -* a pointer to the command descriptor. -* -* Returns : status, see hosts.h for details -* -* Side effects : -* cmd is added to the per instance issue_queue, with minor -* twiddling done to the host specific fields of cmd. If the -* main coroutine is not running, it is restarted. -**************************************************************************/ -int AM53C974_queue_command(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) -{ -struct Scsi_Host *instance = cmd->host; -struct AM53C974_hostdata *hostdata = (struct AM53C974_hostdata *)instance->hostdata; -Scsi_Cmnd *tmp; - -cli(); -DEB_QUEUE(printk(SEPARATOR_LINE)); -DEB_QUEUE(printk("scsi%d: AM53C974_queue_command called\n", instance->host_no)); -DEB_QUEUE(printk("cmd=%02x target=%02x lun=%02x bufflen=%d use_sg = %02x\n", - cmd->cmnd[0], cmd->target, cmd->lun, cmd->request_bufflen, cmd->use_sg)); - -/* We use the host_scribble field as a pointer to the next command in a queue */ -cmd->host_scribble = NULL; -cmd->scsi_done = done; -cmd->result = 0; -cmd->device->disconnect = 0; - -/* Insert the cmd into the issue queue. Note that REQUEST SENSE - * commands are added to the head of the queue since any command will - * clear the contingent allegiance condition that exists and the - * sense data is only guaranteed to be valid while the condition exists. */ -if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) { - LIST(cmd, hostdata->issue_queue); - cmd->host_scribble = (unsigned char *)hostdata->issue_queue; - hostdata->issue_queue = cmd; } - else { - for (tmp = (Scsi_Cmnd *)hostdata->issue_queue; tmp->host_scribble; - tmp = (Scsi_Cmnd *)tmp->host_scribble); - LIST(cmd, tmp); - tmp->host_scribble = (unsigned char *)cmd; } - -DEB_QUEUE(printk("scsi%d : command added to %s of queue\n", instance->host_no, - (cmd->cmnd[0] == REQUEST_SENSE) ? "head" : "tail")); - -/* Run the coroutine if it isn't already running. */ -run_main(); -return 0; -} - -/************************************************************************** - * Function : AM53C974_main (void) - * - * Purpose : AM53C974_main is a coroutine that runs as long as more work can - * be done on the AM53C974 host adapters in a system. Both - * AM53C974_queue_command() and AM53C974_intr() will try to start it - * in case it is not running. - * - * NOTE : AM53C974_main exits with interrupts *disabled*, the caller should - * reenable them. This prevents reentrancy and kernel stack overflow. - **************************************************************************/ -static void AM53C974_main(void) -{ -AM53C974_local_declare(); -Scsi_Cmnd *tmp, *prev; -struct Scsi_Host *instance; -struct AM53C974_hostdata *hostdata; -int done; - -/* We run (with interrupts disabled) until we're sure that none of - * the host adapters have anything that can be done, at which point - * we set main_running to 0 and exit. */ - -do { - cli(); /* Freeze request queues */ - done = 1; - for (instance = first_instance; instance && instance->hostt == the_template; - instance = instance->next) { - hostdata = (struct AM53C974_hostdata *)instance->hostdata; - AM53C974_setio(instance); - /* start to select target if we are not connected and not in the - selection process */ - if (!hostdata->connected && !hostdata->sel_cmd) { - /* Search through the issue_queue for a command destined for a target - that is not busy. */ - for (tmp = (Scsi_Cmnd *)hostdata->issue_queue, prev = NULL; tmp; - prev = tmp, tmp = (Scsi_Cmnd *)tmp->host_scribble) { - /* When we find one, remove it from the issue queue. */ - if (!(hostdata->busy[tmp->target] & (1 << tmp->lun))) { - if (prev) { - REMOVE(prev, (Scsi_Cmnd *)(prev->host_scribble), tmp, - (Scsi_Cmnd *)(tmp->host_scribble)); - prev->host_scribble = tmp->host_scribble; } - else { - REMOVE(-1, hostdata->issue_queue, tmp, tmp->host_scribble); - hostdata->issue_queue = (Scsi_Cmnd *)tmp->host_scribble; } - tmp->host_scribble = NULL; - - /* go into selection mode, disable reselection and wait for - SO interrupt which will continue with the selection process */ - hostdata->selecting = 1; - hostdata->sel_cmd = tmp; - AM53C974_write_8(CMDREG, CMDREG_DSR); - break; - } /* if target/lun is not busy */ - - } /* for */ - } /* if (!hostdata->connected) */ - else { - DEB(printk("main: connected; cmd = 0x%lx, sel_cmd = 0x%lx\n", - (long)hostdata->connected, (long)hostdata->sel_cmd)); - } - } /* for instance */ - } while (!done); -main_running = 0; -} - -/********************************************************************* -* Function : AM53C974_intr(int irq, struct pt_regs *regs) * -* * -* Purpose : interrupt handler * -* * -* Inputs : irq - interrupt line, regs - ? * -* * -* Returns : nothing * -**********************************************************************/ -static void AM53C974_intr(int irq, struct pt_regs *regs) -{ -AM53C974_local_declare(); -struct Scsi_Host *instance; -struct AM53C974_hostdata *hostdata; -unsigned char cmdreg, dmastatus, statreg, isreg, instreg, cfifo; - -/* find AM53C974 hostadapter responsible for this interrupt */ -for (instance = first_instance; instance; instance = instance->next) - if ((instance->irq == irq) && (instance->hostt == the_template)) goto FOUND; -sti(); -return; - -/* found; now decode and process */ -FOUND: -hostdata = (struct AM53C974_hostdata *)instance->hostdata; -AM53C974_setio(instance); -dmastatus = AM53C974_read_8(DMASTATUS); - -DEB_INTR(printk(SEPARATOR_LINE)); -DEB_INTR(printk("AM53C974 interrupt; dmastatus=0x%02x\n", dmastatus)); -KEYWAIT(); - -/*** DMA related interrupts ***/ -if (hostdata->connected && (dmastatus & (DMASTATUS_ERROR | DMASTATUS_PWDN | - DMASTATUS_ABORT))) { - /* DMA error or POWERDOWN */ - printk("scsi%d: DMA error or powerdown; dmastatus: 0x%02x\n", - instance->host_no, dmastatus); -#ifdef AM53C974_DEBUG - deb_stop = 1; -#endif - panic("scsi%d: cannot recover\n", instance->host_no); } - -if (hostdata->connected && (dmastatus & DMASTATUS_DONE)) { - /* DMA transfer done */ - unsigned long residual; - cli(); - if (!(AM53C974_read_8(DMACMD) & DMACMD_DIR)) { - do { - dmastatus = AM53C974_read_8(DMASTATUS); - residual = AM53C974_read_8(CTCLREG) | (AM53C974_read_8(CTCMREG) << 8) | - (AM53C974_read_8(CTCHREG) << 16); - residual += AM53C974_read_8(CFIREG) & CFIREG_CF; - } while (!(dmastatus & DMASTATUS_SCSIINT) && residual); - residual = AM53C974_read_8(CTCLREG) | (AM53C974_read_8(CTCMREG) << 8) | - (AM53C974_read_8(CTCHREG) << 16); - residual += AM53C974_read_8(CFIREG) & CFIREG_CF; - } - else - residual = 0; - hostdata->connected->SCp.ptr += hostdata->connected->SCp.this_residual - residual; - hostdata->connected->SCp.this_residual = residual; - - AM53C974_write_8(DMACMD, DMACMD_IDLE); - - /* if service request missed before, process it now (ugly) */ - if (hostdata->dma_busy) { - hostdata->dma_busy = 0; - cmdreg = AM53C974_read_8(CMDREG); - statreg = AM53C974_read_8(STATREG); - isreg = AM53C974_read_8(ISREG); - instreg = AM53C974_read_8(INSTREG); - cfifo = AM53C974_cfifo(); - AM53C974_information_transfer(instance, statreg, isreg, instreg, cfifo, - dmastatus); } - sti(); - } - -if (!(dmastatus & DMASTATUS_SCSIINT)) { - sti(); - return; } - -/*** SCSI related interrupts ***/ -cmdreg = AM53C974_read_8(CMDREG); -statreg = AM53C974_read_8(STATREG); -isreg = AM53C974_read_8(ISREG); -instreg = AM53C974_read_8(INSTREG); -cfifo = AM53C974_cfifo(); - -DEB_INTR(printk("scsi%d: statreg: 0x%02x; isreg: 0x%02x; instreg: 0x%02x; cfifo: 0x%02x\n", - instance->host_no, statreg, isreg, instreg, cfifo)); - -if (statreg & STATREG_PE) { - /* parity error */ -#ifdef AM53C974_DEBUG - deb_stop = 1; -#endif - printk("scsi%d : PARITY error\n", instance->host_no); - if (hostdata->connected) hostdata->sync_off[hostdata->connected->target] = 0; /* setup asynchronous transfer */ - hostdata->aborted = 1; } - -if (statreg & STATREG_IOE) { - /* illegal operation error */ -#ifdef AM53C974_DEBUG - deb_stop = 1; -#endif - printk("scsi%d : ILLEGAL OPERATION error\n", instance->host_no); - printk("cmdreg: 0x%02x; dmacmd: 0x%02x; statreg: 0x%02x; \n" - "isreg: 0x%02x; instreg: 0x%02x; cfifo: 0x%02x\n", - cmdreg, AM53C974_read_8(DMACMD), statreg, isreg, instreg, cfifo); } -if (hostdata->in_reset && (instreg & INSTREG_SRST)) { - /* RESET INTERRUPT */ -#ifdef AM53C974_DEBUG - deb_stop = 1; -#endif - DEB(printk("Bus reset interrupt received\n")); - AM53C974_intr_bus_reset(instance); - cli(); - if (hostdata->connected) { - hostdata->connected->result = DID_RESET << 16; - hostdata->connected->scsi_done((Scsi_Cmnd *)hostdata->connected); - hostdata->connected = NULL; } - else { - if (hostdata->sel_cmd) { - hostdata->sel_cmd->result = DID_RESET << 16; - hostdata->sel_cmd->scsi_done((Scsi_Cmnd *)hostdata->sel_cmd); - hostdata->sel_cmd = NULL; } - } - sti(); - if (hostdata->in_reset == 1) goto EXIT; - else return; - } - -if (instreg & INSTREG_ICMD) { - /* INVALID COMMAND INTERRUPT */ -#ifdef AM53C974_DEBUG - deb_stop = 1; -#endif - printk("scsi%d: Invalid command interrupt\n", instance->host_no); - printk("cmdreg: 0x%02x; dmacmd: 0x%02x; statreg: 0x%02x; dmastatus: 0x%02x; \n" - "isreg: 0x%02x; instreg: 0x%02x; cfifo: 0x%02x\n", - cmdreg, AM53C974_read_8(DMACMD), statreg, dmastatus, isreg, instreg, cfifo); - panic("scsi%d: cannot recover\n", instance->host_no); } - -if (instreg & INSTREG_DIS) { - /* DISCONNECT INTERRUPT */ - DEB_INTR(printk("Disconnect interrupt received; ")); - cli(); - AM53C974_intr_disconnect(instance); - sti(); - goto EXIT; } - -if (instreg & INSTREG_RESEL) { - /* RESELECTION INTERRUPT */ - DEB_INTR(printk("Reselection interrupt received\n")); - cli(); - AM53C974_intr_reselect(instance, statreg); - sti(); - goto EXIT; } - -if (instreg & INSTREG_SO) { - DEB_INTR(printk("Successful operation interrupt received\n")); - if (hostdata->selecting) { - DEB_INTR(printk("DSR completed, starting select\n")); - cli(); - AM53C974_select(instance, (Scsi_Cmnd *)hostdata->sel_cmd, - (hostdata->sel_cmd->cmnd[0] == REQUEST_SENSE) ? - TAG_NONE : TAG_NEXT); - hostdata->selecting = 0; - AM53C974_set_sync(instance, hostdata->sel_cmd->target); - sti(); - return; } - - if (hostdata->sel_cmd != NULL) { - if ( ((isreg & ISREG_IS) != ISREG_OK_NO_STOP) && - ((isreg & ISREG_IS) != ISREG_OK_STOP) ) { - /* UNSUCCESSFUL SELECTION */ - DEB_INTR(printk("unsuccessful selection\n")); - cli(); - hostdata->dma_busy = 0; - LIST(hostdata->sel_cmd, hostdata->issue_queue); - hostdata->sel_cmd->host_scribble = (unsigned char *)hostdata->issue_queue; - hostdata->issue_queue = hostdata->sel_cmd; - hostdata->sel_cmd = NULL; - hostdata->selecting = 0; - sti(); - goto EXIT; } - else { - /* SUCCESSFUL SELECTION */ - DEB(printk("successful selection; cmd=0x%02lx\n", (long)hostdata->sel_cmd)); - cli(); - hostdata->dma_busy = 0; - hostdata->disconnecting = 0; - hostdata->connected = hostdata->sel_cmd; - hostdata->sel_cmd = NULL; - hostdata->selecting = 0; -#ifdef SCSI2 - if (!hostdata->connected->device->tagged_queue) -#endif - hostdata->busy[hostdata->connected->target] |= (1 << hostdata->connected->lun); - /* very strange -- use_sg is sometimes nonzero for request sense commands !! */ - if ((hostdata->connected->cmnd[0] == REQUEST_SENSE) && hostdata->connected->use_sg) { - DEB(printk("scsi%d: REQUEST_SENSE command with nonzero use_sg\n", instance->host_no)); - KEYWAIT(); - hostdata->connected->use_sg = 0; } - initialize_SCp((Scsi_Cmnd *)hostdata->connected); - hostdata->connected->SCp.phase = PHASE_CMDOUT; - AM53C974_information_transfer(instance, statreg, isreg, instreg, cfifo, dmastatus); - sti(); - return; } - } - else { - cli(); - AM53C974_information_transfer(instance, statreg, isreg, instreg, cfifo, dmastatus); - sti(); - return; } - } - -if (instreg & INSTREG_SR) { - DEB_INTR(printk("Service request interrupt received, ")); - if (hostdata->connected) { - DEB_INTR(printk("calling information_transfer\n")); - cli(); - AM53C974_information_transfer(instance, statreg, isreg, instreg, cfifo, dmastatus); - sti(); } - else { - printk("scsi%d: weird: service request when no command connected\n", instance->host_no); - AM53C974_write_8(CMDREG, CMDREG_CFIFO); } /* clear FIFO */ - return; - } - -EXIT: - DEB_INTR(printk("intr: starting main\n")); - run_main(); - DEB_INTR(printk("end of intr\n")); -} - -/************************************************************************** -* Function : AM53C974_intr_disconnect(struct Scsi_Host *instance) -* -* Purpose : manage target disconnection -* -* Inputs : instance -- which AM53C974 -* -* Returns : nothing -**************************************************************************/ -static void AM53C974_intr_disconnect(struct Scsi_Host *instance) -{ -AM53C974_local_declare(); -struct AM53C974_hostdata *hostdata = (struct AM53C974_hostdata *)instance->hostdata; -Scsi_Cmnd *cmd; -AM53C974_setio(instance); - -if (hostdata->sel_cmd != NULL) { - /* normal selection timeout, typical for nonexisting targets */ - cmd = (Scsi_Cmnd *)hostdata->sel_cmd; - DEB_INTR(printk("bad target\n")); - cmd->result = DID_BAD_TARGET << 16; - goto EXIT_FINISHED; } - -if (!hostdata->connected) { - /* can happen if controller was reset, a device tried to reconnect, - failed and disconnects now */ - AM53C974_write_8(CMDREG, CMDREG_CFIFO); - return; } - -if (hostdata->disconnecting) { - /* target sent disconnect message, so we are prepared */ - cmd = (Scsi_Cmnd *)hostdata->connected; - AM53C974_set_async(instance, cmd->target); - DEB_INTR(printk("scsi%d : disc. from cmnd %d for ta %d, lun %d\n", - instance->host_no, cmd->cmnd[0], cmd->target, cmd->lun)); - if (cmd->device->disconnect) { - /* target wants to reselect later */ - DEB_INTR(printk("ok, re-enabling selection\n")); - LIST(cmd,hostdata->disconnected_queue); - cmd->host_scribble = (unsigned char *)hostdata->disconnected_queue; - hostdata->disconnected_queue = cmd; - DEB_QUEUE(printk("scsi%d : command for target %d lun %d this %d was moved from connected to" - " the disconnected_queue\n", instance->host_no, cmd->target, - cmd->lun, hostdata->disconnected_queue->SCp.this_residual)); - DEB_QUEUE(AM53C974_print_queues(instance)); - goto EXIT_UNFINISHED; } - else { - /* target does not want to reselect later, we are really finished */ -#ifdef AM53C974_DEBUG - if (cmd->cmnd[0] == REQUEST_SENSE) { - int i; - printk("Request sense data dump:\n"); - for (i = 0; i < cmd->request_bufflen; i++) { - printk("%02x ", *((char *)(cmd->request_buffer) + i)); - if (i && !(i % 16)) printk("\n"); } - printk("\n"); } -#endif - goto EXIT_FINISHED; } /* !cmd->device->disconnect */ - } /* if (hostdata->disconnecting) */ - -/* no disconnect message received; unexpected disconnection */ -cmd = (Scsi_Cmnd *)hostdata->connected; -if (cmd) { -#ifdef AM53C974_DEBUG - deb_stop = 1; -#endif - AM53C974_set_async(instance, cmd->target); - printk("scsi%d: Unexpected disconnect; phase: %d; target: %d; this_residual: %d; buffers_residual: %d; message: %d\n", - instance->host_no, cmd->SCp.phase, cmd->target, cmd->SCp.this_residual, cmd->SCp.buffers_residual, - cmd->SCp.Message); - printk("cmdreg: 0x%02x; statreg: 0x%02x; isreg: 0x%02x; cfifo: 0x%02x\n", - AM53C974_read_8(CMDREG), AM53C974_read_8(STATREG), AM53C974_read_8(ISREG), - AM53C974_read_8(CFIREG) & CFIREG_CF); - - if ((hostdata->last_message[0] == EXTENDED_MESSAGE) && - (hostdata->last_message[2] == EXTENDED_SDTR)) { - /* sync. negotiation was aborted, setup asynchronous transfer with target */ - hostdata->sync_off[cmd->target] = 0; } - if (hostdata->aborted || hostdata->msgout[0] == ABORT) - cmd->result = DID_ABORT << 16; - else - cmd->result = DID_ERROR << 16; - goto EXIT_FINISHED; } - -EXIT_FINISHED: -hostdata->aborted = 0; -hostdata->msgout[0] = NOP; -hostdata->sel_cmd = NULL; -hostdata->connected = NULL; -hostdata->selecting = 0; -hostdata->disconnecting = 0; -hostdata->dma_busy = 0; -hostdata->busy[cmd->target] &= ~(1 << cmd->lun); -AM53C974_write_8(CMDREG, CMDREG_CFIFO); -DEB(printk("disconnect; issue_queue: 0x%lx, disconnected_queue: 0x%lx\n", - (long)hostdata->issue_queue, (long)hostdata->disconnected_queue)); -cmd->scsi_done(cmd); - -if (!hostdata->selecting) { - AM53C974_set_async(instance, cmd->target); - AM53C974_write_8(CMDREG, CMDREG_ESR); } /* allow reselect */ -return; - -EXIT_UNFINISHED: -hostdata->msgout[0] = NOP; -hostdata->sel_cmd = NULL; -hostdata->connected = NULL; -hostdata->aborted = 0; -hostdata->selecting = 0; -hostdata->disconnecting = 0; -hostdata->dma_busy = 0; -DEB(printk("disconnect; issue_queue: 0x%lx, disconnected_queue: 0x%lx\n", - (long)hostdata->issue_queue, (long)hostdata->disconnected_queue)); -if (!hostdata->selecting) { - AM53C974_set_async(instance, cmd->target); - AM53C974_write_8(CMDREG, CMDREG_ESR); } /* allow reselect */ -return; -} - -/************************************************************************** -* Function : int AM53C974_sync_neg(struct Scsi_Host *instance, int target, unsigned char *msg) -* -* Purpose : setup message string for sync. negotiation -* -* Inputs : instance -- which AM53C974 -* target -- which SCSI target to deal with -* msg -- input message string -* -* Returns : 0 if parameters accepted or 1 if not accepted -* -* Side effects: hostdata is changed -* -* Note: we assume here that fastclk is enabled -**************************************************************************/ -static int AM53C974_sync_neg(struct Scsi_Host *instance, int target, unsigned char *msg) -{ -AM53C974_local_declare(); -struct AM53C974_hostdata *hostdata = (struct AM53C974_hostdata *)instance->hostdata; -int period, offset, i, rate, rate_rem; -AM53C974_setio(instance); - -period = (DEF_CLK * msg[3] * 8 + 1000) / 2000; -if (period < MIN_PERIOD) { - period = MIN_PERIOD; - hostdata->msgout[3] = period / 4; } - else - if (period > MAX_PERIOD) { - period = MAX_PERIOD; - hostdata->msgout[3] = period / 4; } - else - hostdata->msgout[3] = msg[3]; -offset = msg[4]; -if (offset > MAX_OFFSET) offset = MAX_OFFSET; -hostdata->msgout[4] = offset; -hostdata->sync_per[target] = period; -hostdata->sync_off[target] = offset; -for (i = 0; i < 3; i++) hostdata->msgout[i] = msg[i]; -if ((hostdata->msgout[3] != msg[3]) || (msg[4] != offset)) return(1); - -rate = DEF_CLK / period; -rate_rem = 10 * (DEF_CLK - period * rate) / period; - -if (offset) - printk("\ntarget %d: rate=%d.%d Mhz, synchronous, sync offset=%d bytes\n", - target, rate, rate_rem, offset); - else - printk("\ntarget %d: rate=%d.%d Mhz, asynchronous\n", target, rate, rate_rem); - -return(0); -} - -/************************************************************************** -* Function : AM53C974_set_async(struct Scsi_Host *instance, int target) -* -* Purpose : put controller into async. mode -* -* Inputs : instance -- which AM53C974 -* target -- which SCSI target to deal with -* -* Returns : nothing -**************************************************************************/ -static __inline__ void AM53C974_set_async(struct Scsi_Host *instance, int target) -{ -AM53C974_local_declare(); -struct AM53C974_hostdata *hostdata = (struct AM53C974_hostdata *)instance->hostdata; -AM53C974_setio(instance); - -AM53C974_write_8(STPREG, hostdata->sync_per[target]); -AM53C974_write_8(SOFREG, (DEF_SOF_RAD<<6) | (DEF_SOF_RAA<<4)); -} - -/************************************************************************** -* Function : AM53C974_set_sync(struct Scsi_Host *instance, int target) -* -* Purpose : put controller into sync. mode -* -* Inputs : instance -- which AM53C974 -* target -- which SCSI target to deal with -* -* Returns : nothing -**************************************************************************/ -static __inline__ void AM53C974_set_sync(struct Scsi_Host *instance, int target) -{ -AM53C974_local_declare(); -struct AM53C974_hostdata *hostdata = (struct AM53C974_hostdata *)instance->hostdata; -AM53C974_setio(instance); - -AM53C974_write_8(STPREG, hostdata->sync_per[target]); -AM53C974_write_8(SOFREG, (SOFREG_SO & hostdata->sync_off[target]) | - (DEF_SOF_RAD<<6) | (DEF_SOF_RAA<<4)); -} - -/*********************************************************************** -* Function : AM53C974_information_transfer(struct Scsi_Host *instance, * -* unsigned char statreg, unsigned char isreg, * -* unsigned char instreg, unsigned char cfifo, * -* unsigned char dmastatus) * -* * -* Purpose : handle phase changes * -* * -* Inputs : instance - which AM53C974 * -* statreg - stus register * -* isreg - internal state register * -* instreg - interrupt status register * -* cfifo - number of bytes in FIFO * -* dmastatus - dma status register * -* * -* Returns : nothing * -************************************************************************/ -static void AM53C974_information_transfer(struct Scsi_Host *instance, - unsigned char statreg, unsigned char isreg, - unsigned char instreg, unsigned char cfifo, - unsigned char dmastatus) -{ -AM53C974_local_declare(); -struct AM53C974_hostdata *hostdata = (struct AM53C974_hostdata *)instance->hostdata; -Scsi_Cmnd *cmd = (Scsi_Cmnd *)hostdata->connected; -int ret, i, len, residual=-1; -AM53C974_setio(instance); - -DEB_INFO(printk(SEPARATOR_LINE)); -switch (statreg & STATREG_PHASE) { /* scsi phase */ - case PHASE_DATAOUT: - DEB_INFO(printk("Dataout phase; cmd=0x%lx, sel_cmd=0x%lx, this_residual=%d, buffers_residual=%d\n", - (long)hostdata->connected, (long)hostdata->sel_cmd, cmd->SCp.this_residual, cmd->SCp.buffers_residual)); - cmd->SCp.phase = PHASE_DATAOUT; - goto PHASE_DATA_IO; - - case PHASE_DATAIN: - DEB_INFO(printk("Datain phase; cmd=0x%lx, sel_cmd=0x%lx, this_residual=%d, buffers_residual=%d\n", - (long)hostdata->connected, (long)hostdata->sel_cmd, cmd->SCp.this_residual, cmd->SCp.buffers_residual)); - cmd->SCp.phase = PHASE_DATAIN; - PHASE_DATA_IO: - if (hostdata->aborted) { - AM53C974_write_8(DMACMD, DMACMD_IDLE); - AM53C974_write_8(CMDREG, CMDREG_CFIFO); - AM53C974_write_8(CMDREG, CMDREG_SATN); - return; } - if ((!cmd->SCp.this_residual) && cmd->SCp.buffers_residual) { - cmd->SCp.buffer++; - cmd->SCp.buffers_residual--; - cmd->SCp.ptr = (unsigned char *)cmd->SCp.buffer->address; - cmd->SCp.this_residual = cmd->SCp.buffer->length; } - if (cmd->SCp.this_residual) { - if (!(AM53C974_read_8(DMACMD) & DMACMD_START)) { - hostdata->dma_busy = 0; - AM53C974_transfer_dma(instance, statreg & STATREG_IO, - (unsigned long)cmd->SCp.this_residual, - cmd->SCp.ptr); } - else - hostdata->dma_busy = 1; - } - return; - - case PHASE_MSGIN: - DEB_INFO(printk("Message-In phase; cmd=0x%lx, sel_cmd=0x%lx\n", - (long)hostdata->connected, (long)hostdata->sel_cmd)); - AM53C974_set_async(instance, cmd->target); - if (cmd->SCp.phase == PHASE_DATAIN) - AM53C974_dma_blast(instance, dmastatus, statreg); - if ((cmd->SCp.phase == PHASE_DATAOUT) && (AM53C974_read_8(DMACMD) & DMACMD_START)) { - AM53C974_write_8(DMACMD, DMACMD_IDLE); - residual = cfifo + (AM53C974_read_8(CTCLREG) | (AM53C974_read_8(CTCMREG) << 8) | - (AM53C974_read_8(CTCHREG) << 16)); - cmd->SCp.ptr += cmd->SCp.this_residual - residual; - cmd->SCp.this_residual = residual; - if (cfifo) { AM53C974_write_8(CMDREG, CMDREG_CFIFO); cfifo = 0; } - } - if (cmd->SCp.phase == PHASE_STATIN) { - while ((AM53C974_read_8(CFIREG) & CFIREG_CF) < 2) ; - cmd->SCp.Status = AM53C974_read_8(FFREG); - cmd->SCp.Message = AM53C974_read_8(FFREG); - DEB_INFO(printk("Message-In phase; status=0x%02x, message=0x%02x\n", - cmd->SCp.Status, cmd->SCp.Message)); - ret = AM53C974_message(instance, cmd, cmd->SCp.Message); } - else { - if (!cfifo) { - AM53C974_write_8(CMDREG, CMDREG_IT); - AM53C974_poll_int(); - cmd->SCp.Message = AM53C974_read_8(FFREG); - } - ret = AM53C974_message(instance, cmd, cmd->SCp.Message); - } - cmd->SCp.phase = PHASE_MSGIN; - AM53C974_set_sync(instance, cmd->target); - break; - case PHASE_MSGOUT: - DEB_INFO(printk("Message-Out phase; cfifo=%d; msgout[0]=0x%02x\n", - AM53C974_read_8(CFIREG) & CFIREG_CF, hostdata->msgout[0])); - AM53C974_write_8(DMACMD, DMACMD_IDLE); - AM53C974_set_async(instance, cmd->target); - for (i = 0; i < sizeof(hostdata->last_message); i++) - hostdata->last_message[i] = hostdata->msgout[i]; - if ((hostdata->msgout[0] == 0) || INSIDE(hostdata->msgout[0], 0x02, 0x1F) || - INSIDE(hostdata->msgout[0], 0x80, 0xFF)) - len = 1; - else { - if (hostdata->msgout[0] == EXTENDED_MESSAGE) { -#ifdef AM53C974_DEBUG_INFO - printk("Extended message dump:\n"); - for (i = 0; i < hostdata->msgout[1] + 2; i++) { - printk("%02x ", hostdata->msgout[i]); - if (i && !(i % 16)) printk("\n"); } - printk("\n"); -#endif - len = hostdata->msgout[1] + 2; } - else - len = 2; - } - for (i = 0; i < len; i++) AM53C974_write_8(FFREG, hostdata->msgout[i]); - AM53C974_write_8(CMDREG, CMDREG_IT); - cmd->SCp.phase = PHASE_MSGOUT; - hostdata->msgout[0] = NOP; - AM53C974_set_sync(instance, cmd->target); - break; - - case PHASE_CMDOUT: - DEB_INFO(printk("Command-Out phase\n")); - AM53C974_set_async(instance, cmd->target); - for (i = 0; i < cmd->cmd_len; i++) AM53C974_write_8(FFREG, cmd->cmnd[i]); - AM53C974_write_8(CMDREG, CMDREG_IT); - cmd->SCp.phase = PHASE_CMDOUT; - AM53C974_set_sync(instance, cmd->target); - break; - - case PHASE_STATIN: - DEB_INFO(printk("Status phase\n")); - if (cmd->SCp.phase == PHASE_DATAIN) - AM53C974_dma_blast(instance, dmastatus, statreg); - AM53C974_set_async(instance, cmd->target); - if (cmd->SCp.phase == PHASE_DATAOUT) { - unsigned long residual; - - if (AM53C974_read_8(DMACMD) & DMACMD_START) { - AM53C974_write_8(DMACMD, DMACMD_IDLE); - residual = cfifo + (AM53C974_read_8(CTCLREG) | (AM53C974_read_8(CTCMREG) << 8) | - (AM53C974_read_8(CTCHREG) << 16)); - cmd->SCp.ptr += cmd->SCp.this_residual - residual; - cmd->SCp.this_residual = residual; } - if (cfifo) { AM53C974_write_8(CMDREG, CMDREG_CFIFO); cfifo = 0; } - } - cmd->SCp.phase = PHASE_STATIN; - AM53C974_write_8(CMDREG, CMDREG_ICCS); /* command complete */ - break; - - case PHASE_RES_0: - case PHASE_RES_1: -#ifdef AM53C974_DEBUG - deb_stop = 1; -#endif - DEB_INFO(printk("Reserved phase\n")); - break; - } -KEYWAIT(); -} - -/****************************************************************************** -* Function : int AM53C974_message(struct Scsi_Host *instance, Scsi_Cmnd *cmd, -* unsigned char msg) -* -* Purpose : handle SCSI messages -* -* Inputs : instance -- which AM53C974 -* cmd -- SCSI command the message belongs to -* msg -- message id byte -* -* Returns : 1 on success, 0 on failure. -**************************************************************************/ -static int AM53C974_message(struct Scsi_Host *instance, Scsi_Cmnd *cmd, - unsigned char msg) -{ -AM53C974_local_declare(); -static unsigned char extended_msg[10]; -unsigned char statreg; -int len, ret = 0; -unsigned char *p; -#ifdef AM53C974_DEBUG_MSG -int j; -#endif -struct AM53C974_hostdata *hostdata = (struct AM53C974_hostdata *)instance->hostdata; -AM53C974_setio(instance); - -DEB_MSG(printk(SEPARATOR_LINE)); - -/* Linking lets us reduce the time required to get the - * next command out to the device, hopefully this will - * mean we don't waste another revolution due to the delays - * required by ARBITRATION and another SELECTION. - * In the current implementation proposal, low level drivers - * merely have to start the next command, pointed to by - * next_link, done() is called as with unlinked commands. */ -switch (msg) { -#ifdef LINKED - case LINKED_CMD_COMPLETE: - case LINKED_FLG_CMD_COMPLETE: - /* Accept message by releasing ACK */ - DEB_LINKED(printk("scsi%d : target %d lun %d linked command complete.\n", - instance->host_no, cmd->target, cmd->lun)); - /* Sanity check : A linked command should only terminate with - * one of these messages if there are more linked commands available. */ - if (!cmd->next_link) { - printk("scsi%d : target %d lun %d linked command complete, no next_link\n" - instance->host_no, cmd->target, cmd->lun); - hostdata->aborted = 1; - AM53C974_write_8(CMDREG, CMDREG_SATN); - AM53C974_write_8(CMDREG, CMDREG_MA); - break; } - if (hostdata->aborted) { - DEB_ABORT(printk("ATN set for cmnd %d upon reception of LINKED_CMD_COMPLETE or" - "LINKED_FLG_CMD_COMPLETE message\n", cmd->cmnd[0])); - AM53C974_write_8(CMDREG, CMDREG_SATN); } - AM53C974_write_8(CMDREG, CMDREG_MA); - - initialize_SCp(cmd->next_link); - /* The next command is still part of this process */ - cmd->next_link->tag = cmd->tag; - cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8); - DEB_LINKED(printk("scsi%d : target %d lun %d linked request done, calling scsi_done().\n", - instance->host_no, cmd->target, cmd->lun)); - cmd->scsi_done(cmd); - cmd = hostdata->connected; - break; - -#endif /* def LINKED */ - - case ABORT: - case COMMAND_COMPLETE: - DEB_MSG(printk("scsi%d: command complete message received; cmd %d for target %d, lun %d\n", - instance->host_no, cmd->cmnd[0], cmd->target, cmd->lun)); - hostdata->disconnecting = 1; - cmd->device->disconnect = 0; - - /* I'm not sure what the correct thing to do here is : - * - * If the command that just executed is NOT a request - * sense, the obvious thing to do is to set the result - * code to the values of the stored parameters. - * If it was a REQUEST SENSE command, we need some way - * to differentiate between the failure code of the original - * and the failure code of the REQUEST sense - the obvious - * case is success, where we fall through and leave the result - * code unchanged. - * - * The non-obvious place is where the REQUEST SENSE failed */ - if (cmd->cmnd[0] != REQUEST_SENSE) - cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8); - else if (cmd->SCp.Status != GOOD) - cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16); - if (hostdata->aborted) { - AM53C974_write_8(CMDREG, CMDREG_SATN); - AM53C974_write_8(CMDREG, CMDREG_MA); - DEB_ABORT(printk("ATN set for cmnd %d upon reception of ABORT or" - "COMMAND_COMPLETE message\n", cmd->cmnd[0])); - break; } - if ((cmd->cmnd[0] != REQUEST_SENSE) && (cmd->SCp.Status == CHECK_CONDITION)) { - DEB_MSG(printk("scsi%d : performing request sense\n", instance->host_no)); - cmd->cmnd[0] = REQUEST_SENSE; - cmd->cmnd[1] &= 0xe0; - cmd->cmnd[2] = 0; - cmd->cmnd[3] = 0; - cmd->cmnd[4] = sizeof(cmd->sense_buffer); - cmd->cmnd[5] = 0; - cmd->SCp.buffer = NULL; - cmd->SCp.buffers_residual = 0; - cmd->SCp.ptr = (char *)cmd->sense_buffer; - cmd->SCp.this_residual = sizeof(cmd->sense_buffer); - LIST(cmd,hostdata->issue_queue); - cmd->host_scribble = (unsigned char *)hostdata->issue_queue; - hostdata->issue_queue = (Scsi_Cmnd *)cmd; - DEB_MSG(printk("scsi%d : REQUEST SENSE added to head of issue queue\n",instance->host_no)); - } - - /* Accept message by clearing ACK */ - AM53C974_write_8(CMDREG, CMDREG_MA); - break; - - case MESSAGE_REJECT: - DEB_MSG(printk("scsi%d: reject message received; cmd %d for target %d, lun %d\n", - instance->host_no, cmd->cmnd[0], cmd->target, cmd->lun)); - switch (hostdata->last_message[0]) { - case EXTENDED_MESSAGE: - if (hostdata->last_message[2] == EXTENDED_SDTR) { - /* sync. negotiation was rejected, setup asynchronous transfer with target */ - printk("\ntarget %d: rate=%d Mhz, asynchronous (sync. negotiation rejected)\n", - cmd->target, DEF_CLK / DEF_STP); - hostdata->sync_off[cmd->target] = 0; - hostdata->sync_per[cmd->target] = DEF_STP; } - break; - case HEAD_OF_QUEUE_TAG: - case ORDERED_QUEUE_TAG: - case SIMPLE_QUEUE_TAG: - cmd->device->tagged_queue = 0; - hostdata->busy[cmd->target] |= (1 << cmd->lun); - break; - default: - break; - } - if (hostdata->aborted) AM53C974_write_8(CMDREG, CMDREG_SATN); - AM53C974_write_8(CMDREG, CMDREG_MA); - break; - - case DISCONNECT: - DEB_MSG(printk("scsi%d: disconnect message received; cmd %d for target %d, lun %d\n", - instance->host_no, cmd->cmnd[0], cmd->target, cmd->lun)); - cmd->device->disconnect = 1; - hostdata->disconnecting = 1; - AM53C974_write_8(CMDREG, CMDREG_MA); /* Accept message by clearing ACK */ - break; - - case SAVE_POINTERS: - case RESTORE_POINTERS: - DEB_MSG(printk("scsi%d: save/restore pointers message received; cmd %d for target %d, lun %d\n", - instance->host_no, cmd->cmnd[0], cmd->target, cmd->lun)); - /* The SCSI data pointer is *IMPLICITLY* saved on a disconnect - * operation, in violation of the SCSI spec so we can safely - * ignore SAVE/RESTORE pointers calls. - * - * Unfortunately, some disks violate the SCSI spec and - * don't issue the required SAVE_POINTERS message before - * disconnecting, and we have to break spec to remain - * compatible. */ - if (hostdata->aborted) { - DEB_ABORT(printk("ATN set for cmnd %d upon reception of SAVE/REST. POINTERS message\n", - cmd->cmnd[0])); - AM53C974_write_8(CMDREG, CMDREG_SATN); } - AM53C974_write_8(CMDREG, CMDREG_MA); - break; - - case EXTENDED_MESSAGE: - DEB_MSG(printk("scsi%d: extended message received; cmd %d for target %d, lun %d\n", - instance->host_no, cmd->cmnd[0], cmd->target, cmd->lun)); - /* Extended messages are sent in the following format : - * Byte - * 0 EXTENDED_MESSAGE == 1 - * 1 length (includes one byte for code, doesn't include first two bytes) - * 2 code - * 3..length+1 arguments - */ - /* BEWARE!! THIS CODE IS EXTREMELY UGLY */ - extended_msg[0] = EXTENDED_MESSAGE; - AM53C974_read_8(INSTREG) ; /* clear int */ - AM53C974_write_8(CMDREG, CMDREG_MA); /* ack. msg byte, then wait for SO */ - AM53C974_poll_int(); - /* get length */ - AM53C974_write_8(CMDREG, CMDREG_IT); - AM53C974_poll_int(); - AM53C974_write_8(CMDREG, CMDREG_MA); /* ack. msg byte, then wait for SO */ - AM53C974_poll_int(); - extended_msg[1] = len = AM53C974_read_8(FFREG); /* get length */ - p = extended_msg+2; - /* read the remaining (len) bytes */ - while (len) { - AM53C974_write_8(CMDREG, CMDREG_IT); - AM53C974_poll_int(); - if (len > 1) { - AM53C974_write_8(CMDREG, CMDREG_MA); /* ack. msg byte, then wait for SO */ - AM53C974_poll_int(); } - *p = AM53C974_read_8(FFREG); - p++; len--; } - -#ifdef AM53C974_DEBUG_MSG - printk("scsi%d: received extended message: ", instance->host_no); - for (j = 0; j < extended_msg[1] + 2; j++) { - printk("0x%02x ", extended_msg[j]); - if (j && !(j % 16)) printk("\n"); } - printk("\n"); -#endif - - /* check message */ - if (extended_msg[2] == EXTENDED_SDTR) - ret = AM53C974_sync_neg(instance, cmd->target, extended_msg); - if (ret || hostdata->aborted) AM53C974_write_8(CMDREG, CMDREG_SATN); - - AM53C974_write_8(CMDREG, CMDREG_MA); - break; - - default: - printk("scsi%d: unknown message 0x%02x received\n",instance->host_no, msg); -#ifdef AM53C974_DEBUG - deb_stop = 1; -#endif - /* reject message */ - hostdata->msgout[0] = MESSAGE_REJECT; - AM53C974_write_8(CMDREG, CMDREG_SATN); - AM53C974_write_8(CMDREG, CMDREG_MA); - return(0); - break; - - } /* switch (msg) */ -KEYWAIT(); -return(1); -} - -/************************************************************************** -* Function : AM53C974_select(struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag) -* -* Purpose : try to establish nexus for the command; -* start sync negotiation via start stop and transfer the command in -* cmdout phase in case of an inquiry or req. sense command with no -* sync. neg. performed yet -* -* Inputs : instance -- which AM53C974 -* cmd -- command which requires the selection -* tag -- tagged queueing -* -* Returns : nothing -* -* Note: this function initializes the selection process, which is continued -* in the interrupt handler -**************************************************************************/ -static void AM53C974_select(struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag) -{ -AM53C974_local_declare(); -struct AM53C974_hostdata *hostdata = (struct AM53C974_hostdata *)instance->hostdata; -unsigned char cfifo, tmp[3]; -unsigned int i, len, cmd_size = COMMAND_SIZE(cmd->cmnd[0]); -AM53C974_setio(instance); - -cfifo = AM53C974_cfifo(); -if (cfifo) { - printk("scsi%d: select error; %d residual bytes in FIFO\n", instance->host_no, cfifo); - AM53C974_write_8(CMDREG, CMDREG_CFIFO); /* clear FIFO */ - } - -tmp[0] = IDENTIFY(1, cmd->lun); - -#ifdef SCSI2 -if (cmd->device->tagged_queue && (tag != TAG_NONE)) { - tmp[1] = SIMPLE_QUEUE_TAG; - if (tag == TAG_NEXT) { - /* 0 is TAG_NONE, used to imply no tag for this command */ - if (cmd->device->current_tag == 0) cmd->device->current_tag = 1; - cmd->tag = cmd->device->current_tag; - cmd->device->current_tag++; } - else - cmd->tag = (unsigned char)tag; - tmp[2] = cmd->tag; - hostdata->last_message[0] = SIMPLE_QUEUE_TAG; - len = 3; - AM53C974_write_8(FFREG, tmp[0]); - AM53C974_write_8(FFREG, tmp[1]); - AM53C974_write_8(FFREG, tmp[2]); - } - else -#endif /* def SCSI2 */ - { - len = 1; - AM53C974_write_8(FFREG, tmp[0]); - cmd->tag = 0; } - -/* in case of an inquiry or req. sense command with no sync. neg performed yet, we start - sync negotiation via start stops and transfer the command in cmdout phase */ -if (((cmd->cmnd[0] == INQUIRY) || (cmd->cmnd[0] == REQUEST_SENSE)) && - !(hostdata->sync_neg[cmd->target]) && hostdata->sync_en[cmd->target]) { - hostdata->sync_neg[cmd->target] = 1; - hostdata->msgout[0] = EXTENDED_MESSAGE; - hostdata->msgout[1] = 3; - hostdata->msgout[2] = EXTENDED_SDTR; - hostdata->msgout[3] = 250 / (int)hostdata->max_rate[cmd->target]; - hostdata->msgout[4] = hostdata->max_offset[cmd->target]; - len += 5; } - -AM53C974_write_8(SDIDREG, SDIREG_MASK & cmd->target); /* setup dest. id */ -AM53C974_write_8(STIMREG, DEF_SCSI_TIMEOUT); /* setup timeout reg */ -switch (len) { - case 1: - for (i = 0; i < cmd_size; i++) AM53C974_write_8(FFREG, cmd->cmnd[i]); - AM53C974_write_8(CMDREG, CMDREG_SAS); /* select with ATN, 1 msg byte */ - hostdata->msgout[0] = NOP; - break; - case 3: - for (i = 0; i < cmd_size; i++) AM53C974_write_8(FFREG, cmd->cmnd[i]); - AM53C974_write_8(CMDREG, CMDREG_SA3S); /* select with ATN, 3 msg bytes */ - hostdata->msgout[0] = NOP; - break; - default: - AM53C974_write_8(CMDREG, CMDREG_SASS); /* select with ATN, stop steps; continue in message out phase */ - break; - } -} - -/************************************************************************** -* Function : AM53C974_intr_select(struct Scsi_Host *instance, unsigned char statreg) -* -* Purpose : handle reselection -* -* Inputs : instance -- which AM53C974 -* statreg -- status register -* -* Returns : nothing -* -* side effects: manipulates hostdata -**************************************************************************/ -static void AM53C974_intr_reselect(struct Scsi_Host *instance, unsigned char statreg) -{ -AM53C974_local_declare(); -struct AM53C974_hostdata *hostdata = (struct AM53C974_hostdata *)instance->hostdata; -unsigned char cfifo, msg[3], lun, t, target = 0; -#ifdef SCSI2 - unsigned char tag; -#endif -Scsi_Cmnd *tmp = NULL, *prev; -AM53C974_setio(instance); - -cfifo = AM53C974_cfifo(); - -if (hostdata->selecting) { - /* caught reselect interrupt in selection process; - put selecting command back into the issue queue and continue with the - reselecting command */ - DEB_RESEL(printk("AM53C974_intr_reselect: in selection process\n")); - LIST(hostdata->sel_cmd, hostdata->issue_queue); - hostdata->sel_cmd->host_scribble = (unsigned char *)hostdata->issue_queue; - hostdata->issue_queue = hostdata->sel_cmd; - hostdata->sel_cmd = NULL; - hostdata->selecting = 0; } - -/* 2 bytes must be in the FIFO now */ -if (cfifo != 2) { - printk("scsi %d: error: %d bytes in fifo, 2 expected\n", instance->host_no, cfifo); - hostdata->aborted = 1; - goto EXIT_ABORT; } - -/* determine target which reselected */ -t = AM53C974_read_8(FFREG); -if (!(t & (1 << instance->this_id))) { - printk("scsi %d: error: invalid host id\n", instance->host_no); - hostdata->aborted = 1; - goto EXIT_ABORT; } -t ^= (1 << instance->this_id); -target = 0; while (t != 1) { t >>= 1; target++; } -DEB_RESEL(printk("scsi %d: reselect; target: %d\n", instance->host_no, target)); - -if (hostdata->aborted) goto EXIT_ABORT; - -if ((statreg & STATREG_PHASE) != PHASE_MSGIN) { - printk("scsi %d: error: upon reselection interrupt not in MSGIN\n", instance->host_no); - hostdata->aborted = 1; - goto EXIT_ABORT; } - -msg[0] = AM53C974_read_8(FFREG); -if (!msg[0] & 0x80) { - printk("scsi%d: error: expecting IDENTIFY message, got ", instance->host_no); - print_msg(msg); - hostdata->aborted = 1; - goto EXIT_ABORT; } - -lun = (msg[0] & 0x07); - -/* We need to add code for SCSI-II to track which devices have - * I_T_L_Q nexuses established, and which have simple I_T_L - * nexuses so we can chose to do additional data transfer. */ -#ifdef SCSI2 -#error "SCSI-II tagged queueing is not supported yet" -#endif - -/* Find the command corresponding to the I_T_L or I_T_L_Q nexus we - * just reestablished, and remove it from the disconnected queue. */ -for (tmp = (Scsi_Cmnd *)hostdata->disconnected_queue, prev = NULL; - tmp; prev = tmp, tmp = (Scsi_Cmnd *)tmp->host_scribble) - if ((target == tmp->target) && (lun == tmp->lun) -#ifdef SCSI2 - && (tag == tmp->tag) -#endif - ) { - if (prev) { - REMOVE(prev, (Scsi_Cmnd *)(prev->host_scribble), tmp, - (Scsi_Cmnd *)(tmp->host_scribble)); - prev->host_scribble = tmp->host_scribble; } - else { - REMOVE(-1, hostdata->disconnected_queue, tmp, tmp->host_scribble); - hostdata->disconnected_queue = (Scsi_Cmnd *)tmp->host_scribble; } - tmp->host_scribble = NULL; - hostdata->connected = tmp; - break; } - -if (!tmp) { -#ifdef SCSI2 - printk("scsi%d: warning : target %d lun %d tag %d not in disconnect_queue.\n", - instance->host_no, target, lun, tag); -#else - printk("scsi%d: warning : target %d lun %d not in disconnect_queue.\n", - instance->host_no, target, lun); -#endif - /* Since we have an established nexus that we can't do anything with, we must abort it. */ - hostdata->aborted = 1; - DEB(AM53C974_keywait()); - goto EXIT_ABORT; } - else - goto EXIT_OK; - -EXIT_ABORT: -AM53C974_write_8(CMDREG, CMDREG_SATN); -AM53C974_write_8(CMDREG, CMDREG_MA); -return; - -EXIT_OK: -DEB_RESEL(printk("scsi%d: nexus established, target = %d, lun = %d, tag = %d\n", - instance->host_no, target, tmp->lun, tmp->tag)); -AM53C974_set_sync(instance, target); -AM53C974_write_8(SDIDREG, SDIREG_MASK & target); /* setup dest. id */ -AM53C974_write_8(CMDREG, CMDREG_MA); -hostdata->dma_busy = 0; -hostdata->connected->SCp.phase = PHASE_CMDOUT; -} - -/************************************************************************** -* Function : AM53C974_transfer_dma(struct Scsi_Host *instance, short dir, -* unsigned long length, char *data) -* -* Purpose : setup DMA transfer -* -* Inputs : instance -- which AM53C974 -* dir -- direction flag, 0: write to device, read from memory; -* 1: read from device, write to memory -* length -- number of bytes to transfer to from buffer -* data -- pointer to data buffer -* -* Returns : nothing -**************************************************************************/ -static __inline__ void AM53C974_transfer_dma(struct Scsi_Host *instance, short dir, - unsigned long length, char *data) -{ -AM53C974_local_declare(); -AM53C974_setio(instance); - -AM53C974_write_8(CMDREG, CMDREG_NOP); -AM53C974_write_8(DMACMD, (dir << 7) | DMACMD_INTE_D); /* idle command */ -AM53C974_write_8(STCLREG, (unsigned char)(length & 0xff)); -AM53C974_write_8(STCMREG, (unsigned char)((length & 0xff00) >> 8)); -AM53C974_write_8(STCHREG, (unsigned char)((length & 0xff0000) >> 16)); -AM53C974_write_32(DMASTC, length & 0xffffff); -AM53C974_write_32(DMASPA, (unsigned long)data); -AM53C974_write_8(CMDREG, CMDREG_IT | CMDREG_DMA); -AM53C974_write_8(DMACMD, (dir << 7) | DMACMD_INTE_D | DMACMD_START); -} - -/************************************************************************** -* Function : AM53C974_dma_blast(struct Scsi_Host *instance, unsigned char dmastatus, -* unsigned char statreg) -* -* Purpose : cleanup DMA transfer -* -* Inputs : instance -- which AM53C974 -* dmastatus -- dma status register -* statreg -- status register -* -* Returns : nothing -**************************************************************************/ -static void AM53C974_dma_blast(struct Scsi_Host *instance, unsigned char dmastatus, - unsigned char statreg) -{ -AM53C974_local_declare(); -struct AM53C974_hostdata *hostdata = (struct AM53C974_hostdata *)instance->hostdata; -unsigned long ctcreg; -int dir = statreg & STATREG_IO; -int cfifo, pio, i = 0; -AM53C974_setio(instance); - -do { - cfifo = AM53C974_cfifo(); - i++; - } while (cfifo && (i < 50000)); -pio = (i == 50000) ? 1: 0; - -if (statreg & STATREG_CTZ) { AM53C974_write_8(DMACMD, DMACMD_IDLE); return; } - -if (dmastatus & DMASTATUS_DONE) { AM53C974_write_8(DMACMD, DMACMD_IDLE); return; } - -AM53C974_write_8(DMACMD, ((dir << 7) & DMACMD_DIR) | DMACMD_BLAST); -while(!(AM53C974_read_8(DMASTATUS) & DMASTATUS_BCMPLT)) ; -AM53C974_write_8(DMACMD, DMACMD_IDLE); - -if (pio) { - /* transfer residual bytes via PIO */ - unsigned char *wac = (unsigned char *)AM53C974_read_32(DMAWAC); - printk("pio mode, residual=%d\n", AM53C974_read_8(CFIREG) & CFIREG_CF); - while (AM53C974_read_8(CFIREG) & CFIREG_CF) *(wac++) = AM53C974_read_8(FFREG); - } - -ctcreg = AM53C974_read_8(CTCLREG) | (AM53C974_read_8(CTCMREG) << 8) | - (AM53C974_read_8(CTCHREG) << 16); - -hostdata->connected->SCp.ptr += hostdata->connected->SCp.this_residual - ctcreg; -hostdata->connected->SCp.this_residual = ctcreg; -} - -/************************************************************************** -* Function : AM53C974_intr_bus_reset(struct Scsi_Host *instance) -* -* Purpose : handle bus reset interrupt -* -* Inputs : instance -- which AM53C974 -* -* Returns : nothing -**************************************************************************/ -static void AM53C974_intr_bus_reset(struct Scsi_Host *instance) -{ -AM53C974_local_declare(); -unsigned char cntlreg1; -AM53C974_setio(instance); - -AM53C974_write_8(CMDREG, CMDREG_CFIFO); -AM53C974_write_8(CMDREG, CMDREG_NOP); - -cntlreg1 = AM53C974_read_8(CNTLREG1); -AM53C974_write_8(CNTLREG1, cntlreg1 | CNTLREG1_DISR); -} - -/************************************************************************** -* Function : int AM53C974_abort(Scsi_Cmnd *cmd) -* -* Purpose : abort a command -* -* Inputs : cmd - the Scsi_Cmnd to abort, code - code to set the -* host byte of the result field to, if zero DID_ABORTED is -* used. -* -* Returns : 0 - success, -1 on failure. - **************************************************************************/ -int AM53C974_abort(Scsi_Cmnd *cmd) -{ -AM53C974_local_declare(); -struct Scsi_Host *instance = cmd->host; -struct AM53C974_hostdata *hostdata = (struct AM53C974_hostdata *)instance->hostdata; -Scsi_Cmnd *tmp, **prev; - -#ifdef AM53C974_DEBUG - deb_stop = 1; -#endif -cli(); -AM53C974_setio(instance); - -DEB_ABORT(printk(SEPARATOR_LINE)); -DEB_ABORT(printk("scsi%d : AM53C974_abort called -- trouble starts!!\n", instance->host_no)); -DEB_ABORT(AM53C974_print(instance)); -DEB_ABORT(AM53C974_keywait()); - -/* Case 1 : If the command is the currently executing command, - we'll set the aborted flag and return control so that the - information transfer routine can exit cleanly. */ -if ((hostdata->connected == cmd) || (hostdata->sel_cmd == cmd)) { - DEB_ABORT(printk("scsi%d: aborting connected command\n", instance->host_no)); - hostdata->aborted = 1; - hostdata->msgout[0] = ABORT; - sti(); - return(SCSI_ABORT_PENDING); } - -/* Case 2 : If the command hasn't been issued yet, - we simply remove it from the issue queue. */ -for (prev = (Scsi_Cmnd **)&(hostdata->issue_queue), - tmp = (Scsi_Cmnd *)hostdata->issue_queue; tmp; - prev = (Scsi_Cmnd **)&(tmp->host_scribble), - tmp = (Scsi_Cmnd *)tmp->host_scribble) { - if (cmd == tmp) { - DEB_ABORT(printk("scsi%d : abort removed command from issue queue.\n", instance->host_no)); - REMOVE(5, *prev, tmp, tmp->host_scribble); - (*prev) = (Scsi_Cmnd *)tmp->host_scribble; - tmp->host_scribble = NULL; - tmp->result = DID_ABORT << 16; - sti(); - tmp->done(tmp); - return(SCSI_ABORT_SUCCESS); } -#ifdef AM53C974_DEBUG_ABORT - else { - if (prev == (Scsi_Cmnd **)tmp) - printk("scsi%d : LOOP\n", instance->host_no); - } -#endif - } - -/* Case 3 : If any commands are connected, we're going to fail the abort - * and let the high level SCSI driver retry at a later time or - * issue a reset. - * - * Timeouts, and therefore aborted commands, will be highly unlikely - * and handling them cleanly in this situation would make the common - * case of noresets less efficient, and would pollute our code. So, - * we fail. */ -if (hostdata->connected || hostdata->sel_cmd) { - DEB_ABORT(printk("scsi%d : abort failed, other command connected.\n", instance->host_no)); - sti(); - return(SCSI_ABORT_NOT_RUNNING); } - -/* Case 4: If the command is currently disconnected from the bus, and - * there are no connected commands, we reconnect the I_T_L or - * I_T_L_Q nexus associated with it, go into message out, and send - * an abort message. */ -for (tmp = (Scsi_Cmnd *)hostdata->disconnected_queue; tmp; - tmp = (Scsi_Cmnd *)tmp->host_scribble) { - if (cmd == tmp) { - DEB_ABORT(printk("scsi%d: aborting disconnected command\n", instance->host_no)); - hostdata->aborted = 1; - hostdata->msgout[0] = ABORT; - hostdata->selecting = 1; - hostdata->sel_cmd = tmp; - AM53C974_write_8(CMDREG, CMDREG_DSR); - sti(); - return(SCSI_ABORT_PENDING); } - } - -/* Case 5 : If we reached this point, the command was not found in any of - * the queues. - * - * We probably reached this point because of an unlikely race condition - * between the command completing successfully and the abortion code, - * so we won't panic, but we will notify the user in case something really - * broke. */ -DEB_ABORT(printk("scsi%d : abort failed, command not found.\n", instance->host_no)); -sti(); -return(SCSI_ABORT_NOT_RUNNING); -} - -/************************************************************************** -* Function : int AM53C974_reset(Scsi_Cmnd *cmd) -* -* Purpose : reset the SCSI controller and bus -* -* Inputs : cmd -- which command within the command block was responsible for the reset -* -* Returns : status (SCSI_ABORT_SUCCESS) -**************************************************************************/ -int AM53C974_reset(Scsi_Cmnd *cmd) -{ -AM53C974_local_declare(); -int i; -struct Scsi_Host *instance = cmd->host; -struct AM53C974_hostdata *hostdata = (struct AM53C974_hostdata *)instance->hostdata; -AM53C974_setio(instance); - -cli(); -DEB(printk("AM53C974_reset called; ")); - -printk("AM53C974_reset called\n"); -AM53C974_print(instance); -AM53C974_keywait(); - -/* do hard reset */ -AM53C974_write_8(CMDREG, CMDREG_RDEV); -AM53C974_write_8(CMDREG, CMDREG_NOP); -hostdata->msgout[0] = NOP; -for (i = 0; i < 8; i++) { - hostdata->busy[i] = 0; - hostdata->sync_per[i] = DEF_STP; - hostdata->sync_off[i] = 0; - hostdata->sync_neg[i] = 0; } -hostdata->last_message[0] = NOP; -hostdata->sel_cmd = NULL; -hostdata->connected = NULL; -hostdata->issue_queue = NULL; -hostdata->disconnected_queue = NULL; -hostdata->in_reset = 0; -hostdata->aborted = 0; -hostdata->selecting = 0; -hostdata->disconnecting = 0; -hostdata->dma_busy = 0; - -/* reset bus */ -AM53C974_write_8(CNTLREG1, CNTLREG1_DISR | instance->this_id); /* disable interrupt upon SCSI RESET */ -AM53C974_write_8(CMDREG, CMDREG_RBUS); /* reset SCSI bus */ -udelay(40); -AM53C974_config_after_reset(instance); - -sti(); -cmd->result = DID_RESET << 16; -cmd->scsi_done(cmd); -return SCSI_ABORT_SUCCESS; -} diff --git a/i386/i386at/gpl/linux/scsi/AM53C974.h b/i386/i386at/gpl/linux/scsi/AM53C974.h deleted file mode 100644 index 2a07a5a4..00000000 --- a/i386/i386at/gpl/linux/scsi/AM53C974.h +++ /dev/null @@ -1,419 +0,0 @@ -/* AM53/79C974 (PCscsi) driver release 0.5 - * - * The architecture and much of the code of this device - * driver was originally developed by Drew Eckhardt for - * the NCR5380. The following copyrights apply: - * For the architecture and all parts similar to the NCR5380: - * Copyright 1993, Drew Eckhardt - * Visionary Computing - * (Unix and Linux consulting and custom programming) - * drew@colorado.edu - * +1 (303) 666-5836 - * - * The AM53C974_nobios_detect code was origininally developed by - * Robin Cutshaw (robin@xfree86.org) and is used here in a - * modified form. - * - * For the other parts: - * Copyright 1994, D. Frieauff - * EMail: fri@rsx42sun0.dofn.de - * Phone: x49-7545-8-2256 , x49-7541-42305 - */ - -/* - * $Log: AM53C974.h,v $ - * Revision 1.1.1.1 1996/10/30 01:39:58 thomas - * Imported from UK22 - * - * Revision 1.1 1996/03/25 20:25:06 goel - * Linux driver merge. - * - */ - -#ifndef AM53C974_H -#define AM53C974_H - -#include <linux/scsicam.h> - -/*************************************************************************************** -* Default setting of the controller's SCSI id. Edit and uncomment this only if your * -* BIOS does not correctly initialize the controller's SCSI id. * -* If you don't get a warning during boot, it is correctly initialized. * -****************************************************************************************/ -/* #define AM53C974_SCSI_ID 7 */ - -/*************************************************************************************** -* Default settings for sync. negotiation enable, transfer rate and sync. offset. * -* These settings can be replaced by LILO overrides (append) with the following syntax: * -* AM53C974=host-scsi-id, target-scsi-id, max-rate, max-offset * -* Sync. negotiation is disabled by default and will be enabled for those targets which * -* are specified in the LILO override * -****************************************************************************************/ -#define DEFAULT_SYNC_NEGOTIATION_ENABLED 0 /* 0 or 1 */ -#define DEFAULT_RATE 5 /* MHz, min: 3; max: 10 */ -#define DEFAULT_SYNC_OFFSET 0 /* bytes, min: 0; max: 15; use 0 for async. mode */ - - -/* --------------------- don't edit below here --------------------- */ - -#define AM53C974_DRIVER_REVISION_MAJOR 0 -#define AM53C974_DRIVER_REVISION_MINOR 5 -#define SEPARATOR_LINE \ -"--------------------------------------------------------------------------\n" - -/* debug control */ -/* #define AM53C974_DEBUG */ -/* #define AM53C974_DEBUG_MSG */ -/* #define AM53C974_DEBUG_KEYWAIT */ -/* #define AM53C974_DEBUG_INIT */ -/* #define AM53C974_DEBUG_QUEUE */ -/* #define AM53C974_DEBUG_INFO */ -/* #define AM53C974_DEBUG_LINKED */ -/* #define VERBOSE_AM53C974_DEBUG */ -/* #define AM53C974_DEBUG_INTR */ -/* #define AM53C974_DEB_RESEL */ -#define AM53C974_DEBUG_ABORT -/* #define AM53C974_OPTION_DEBUG_PROBE_ONLY */ - -/* special options/constants */ -#define DEF_CLK 40 /* chip clock freq. in MHz */ -#define MIN_PERIOD 4 /* for negotiation: min. number of clocks per cycle */ -#define MAX_PERIOD 13 /* for negotiation: max. number of clocks per cycle */ -#define MAX_OFFSET 15 /* for negotiation: max. offset (0=async) */ - -#define DEF_SCSI_TIMEOUT 245 /* STIMREG value, 40 Mhz */ -#define DEF_STP 8 /* STPREG value assuming 5.0 MB/sec, FASTCLK, FASTSCSI */ -#define DEF_SOF_RAD 0 /* REQ/ACK deassertion delay */ -#define DEF_SOF_RAA 0 /* REQ/ACK assertion delay */ -#define DEF_ETM 0 /* CNTLREG1, ext. timing mode */ -#define DEF_PERE 1 /* CNTLREG1, parity error reporting */ -#define DEF_CLKF 0 /* CLKFREG, 0=40 Mhz */ -#define DEF_ENF 1 /* CNTLREG2, enable features */ -#define DEF_ADIDCHK 0 /* CNTLREG3, additional ID check */ -#define DEF_FASTSCSI 1 /* CNTLREG3, fast SCSI */ -#define DEF_FASTCLK 1 /* CNTLREG3, fast clocking, 5 MB/sec at 40MHz chip clk */ -#define DEF_GLITCH 1 /* CNTLREG4, glitch eater, 0=12ns, 1=35ns, 2=25ns, 3=off */ -#define DEF_PWD 0 /* CNTLREG4, reduced power feature */ -#define DEF_RAE 0 /* CNTLREG4, RAE active negation on REQ, ACK only */ -#define DEF_RADE 1 /* 1CNTLREG4, active negation on REQ, ACK and data */ - -/*** PCI block ***/ -/* standard registers are defined in <linux/pci.h> */ -#ifndef PCI_VENDOR_ID_AMD -#define PCI_VENDOR_ID_AMD 0x1022 -#define PCI_DEVICE_ID_AMD_SCSI 0x2020 -#endif -#define PCI_BASE_MASK 0xFFFFFFE0 -#define PCI_COMMAND_PERREN 0x40 -#define PCI_SCRATCH_REG_0 0x40 /* 16 bits */ -#define PCI_SCRATCH_REG_1 0x42 /* 16 bits */ -#define PCI_SCRATCH_REG_2 0x44 /* 16 bits */ -#define PCI_SCRATCH_REG_3 0x46 /* 16 bits */ -#define PCI_SCRATCH_REG_4 0x48 /* 16 bits */ -#define PCI_SCRATCH_REG_5 0x4A /* 16 bits */ -#define PCI_SCRATCH_REG_6 0x4C /* 16 bits */ -#define PCI_SCRATCH_REG_7 0x4E /* 16 bits */ - -/*** SCSI block ***/ -#define CTCLREG 0x00 /* r current transf. count, low byte */ -#define CTCMREG 0x04 /* r current transf. count, middle byte */ -#define CTCHREG 0x38 /* r current transf. count, high byte */ -#define STCLREG 0x00 /* w start transf. count, low byte */ -#define STCMREG 0x04 /* w start transf. count, middle byte */ -#define STCHREG 0x38 /* w start transf. count, high byte */ -#define FFREG 0x08 /* rw SCSI FIFO reg. */ -#define STIMREG 0x14 /* w SCSI timeout reg. */ - -#define SDIDREG 0x10 /* w SCSI destination ID reg. */ -#define SDIREG_MASK 0x07 /* mask */ - -#define STPREG 0x18 /* w synchronous transf. period reg. */ -#define STPREG_STP 0x1F /* synchr. transfer period */ - -#define CLKFREG 0x24 /* w clock factor reg. */ -#define CLKFREG_MASK 0x07 /* mask */ - -#define CMDREG 0x0C /* rw SCSI command reg. */ -#define CMDREG_DMA 0x80 /* set DMA mode (set together with opcodes below) */ -#define CMDREG_IT 0x10 /* information transfer */ -#define CMDREG_ICCS 0x11 /* initiator command complete steps */ -#define CMDREG_MA 0x12 /* message accepted */ -#define CMDREG_TPB 0x98 /* transfer pad bytes, DMA mode only */ -#define CMDREG_SATN 0x1A /* set ATN */ -#define CMDREG_RATN 0x1B /* reset ATN */ -#define CMDREG_SOAS 0x41 /* select without ATN steps */ -#define CMDREG_SAS 0x42 /* select with ATN steps (1 msg byte) */ -#define CMDREG_SASS 0x43 /* select with ATN and stop steps */ -#define CMDREG_ESR 0x44 /* enable selection/reselection */ -#define CMDREG_DSR 0x45 /* disable selection/reselection */ -#define CMDREG_SA3S 0x46 /* select with ATN 3 steps (3 msg bytes) */ -#define CMDREG_NOP 0x00 /* no operation */ -#define CMDREG_CFIFO 0x01 /* clear FIFO */ -#define CMDREG_RDEV 0x02 /* reset device */ -#define CMDREG_RBUS 0x03 /* reset SCSI bus */ - -#define STATREG 0x10 /* r SCSI status reg. */ -#define STATREG_INT 0x80 /* SCSI interrupt condition detected */ -#define STATREG_IOE 0x40 /* SCSI illegal operation error detected */ -#define STATREG_PE 0x20 /* SCSI parity error detected */ -#define STATREG_CTZ 0x10 /* CTC reg decremented to zero */ -#define STATREG_MSG 0x04 /* SCSI MSG phase (latched?) */ -#define STATREG_CD 0x02 /* SCSI C/D phase (latched?) */ -#define STATREG_IO 0x01 /* SCSI I/O phase (latched?) */ -#define STATREG_PHASE 0x07 /* SCSI phase mask */ - -#define INSTREG 0x14 /* r interrupt status reg. */ -#define INSTREG_SRST 0x80 /* SCSI reset detected */ -#define INSTREG_ICMD 0x40 /* SCSI invalid command detected */ -#define INSTREG_DIS 0x20 /* target disconnected or sel/resel timeout*/ -#define INSTREG_SR 0x10 /* device on bus has service request */ -#define INSTREG_SO 0x08 /* successful operation */ -#define INSTREG_RESEL 0x04 /* device reselected as initiator */ - -#define ISREG 0x18 /* r internal state reg. */ -#define ISREG_SOF 0x08 /* synchronous offset flag (act. low) */ -#define ISREG_IS 0x07 /* status of intermediate op. */ -#define ISREG_OK_NO_STOP 0x04 /* selection successful */ -#define ISREG_OK_STOP 0x01 /* selection successful */ - -#define CFIREG 0x1C /* r current FIFO/internal state reg. */ -#define CFIREG_IS 0xE0 /* status of intermediate op. */ -#define CFIREG_CF 0x1F /* number of bytes in SCSI FIFO */ - -#define SOFREG 0x1C /* w synchr. offset reg. */ -#define SOFREG_RAD 0xC0 /* REQ/ACK deassertion delay (sync.) */ -#define SOFREG_RAA 0x30 /* REQ/ACK assertion delay (sync.) */ -#define SOFREG_SO 0x0F /* synch. offset (sync.) */ - -#define CNTLREG1 0x20 /* rw control register one */ -#define CNTLREG1_ETM 0x80 /* set extended timing mode */ -#define CNTLREG1_DISR 0x40 /* disable interrupt on SCSI reset */ -#define CNTLREG1_PERE 0x10 /* enable parity error reporting */ -#define CNTLREG1_SID 0x07 /* host adapter SCSI ID */ - -#define CNTLREG2 0x2C /* rw control register two */ -#define CNTLREG2_ENF 0x40 /* enable features */ - -#define CNTLREG3 0x30 /* rw control register three */ -#define CNTLREG3_ADIDCHK 0x80 /* additional ID check */ -#define CNTLREG3_FASTSCSI 0x10 /* fast SCSI */ -#define CNTLREG3_FASTCLK 0x08 /* fast SCSI clocking */ - -#define CNTLREG4 0x34 /* rw control register four */ -#define CNTLREG4_GLITCH 0xC0 /* glitch eater */ -#define CNTLREG4_PWD 0x20 /* reduced power feature */ -#define CNTLREG4_RAE 0x08 /* write only, active negot. ctrl. */ -#define CNTLREG4_RADE 0x04 /* active negot. ctrl. */ -#define CNTLREG4_RES 0x10 /* reserved bit, must be 1 */ - -/*** DMA block ***/ -#define DMACMD 0x40 /* rw command */ -#define DMACMD_DIR 0x80 /* transfer direction (1=read from device) */ -#define DMACMD_INTE_D 0x40 /* DMA transfer interrupt enable */ -#define DMACMD_INTE_P 0x20 /* page transfer interrupt enable */ -#define DMACMD_MDL 0x10 /* map to memory descriptor list */ -#define DMACMD_DIAG 0x04 /* diagnostics, set to 0 */ -#define DMACMD_IDLE 0x00 /* idle cmd */ -#define DMACMD_BLAST 0x01 /* flush FIFO to memory */ -#define DMACMD_ABORT 0x02 /* terminate DMA */ -#define DMACMD_START 0x03 /* start DMA */ - -#define DMASTATUS 0x54 /* r status register */ -#define DMASTATUS_BCMPLT 0x20 /* BLAST complete */ -#define DMASTATUS_SCSIINT 0x10 /* SCSI interrupt pending */ -#define DMASTATUS_DONE 0x08 /* DMA transfer terminated */ -#define DMASTATUS_ABORT 0x04 /* DMA transfer aborted */ -#define DMASTATUS_ERROR 0x02 /* DMA transfer error */ -#define DMASTATUS_PWDN 0x02 /* power down indicator */ - -#define DMASTC 0x44 /* rw starting transfer count */ -#define DMASPA 0x48 /* rw starting physical address */ -#define DMAWBC 0x4C /* r working byte counter */ -#define DMAWAC 0x50 /* r working address counter */ -#define DMASMDLA 0x58 /* rw starting MDL address */ -#define DMAWMAC 0x5C /* r working MDL counter */ - -/*** SCSI phases ***/ -#define PHASE_MSGIN 0x07 -#define PHASE_MSGOUT 0x06 -#define PHASE_RES_1 0x05 -#define PHASE_RES_0 0x04 -#define PHASE_STATIN 0x03 -#define PHASE_CMDOUT 0x02 -#define PHASE_DATAIN 0x01 -#define PHASE_DATAOUT 0x00 - -struct AM53C974_hostdata { - volatile unsigned in_reset:1; /* flag, says bus reset pending */ - volatile unsigned aborted:1; /* flag, says aborted */ - volatile unsigned selecting:1; /* selection started, but not yet finished */ - volatile unsigned disconnecting: 1; /* disconnection started, but not yet finished */ - volatile unsigned dma_busy:1; /* dma busy when service request for info transfer received */ - volatile unsigned char msgout[10]; /* message to output in MSGOUT_PHASE */ - volatile unsigned char last_message[10]; /* last message OUT */ - volatile Scsi_Cmnd *issue_queue; /* waiting to be issued */ - volatile Scsi_Cmnd *disconnected_queue; /* waiting for reconnect */ - volatile Scsi_Cmnd *sel_cmd; /* command for selection */ - volatile Scsi_Cmnd *connected; /* currently connected command */ - volatile unsigned char busy[8]; /* index = target, bit = lun */ - unsigned char sync_per[8]; /* synchronous transfer period (in effect) */ - unsigned char sync_off[8]; /* synchronous offset (in effect) */ - unsigned char sync_neg[8]; /* sync. negotiation performed (in effect) */ - unsigned char sync_en[8]; /* sync. negotiation performed (in effect) */ - unsigned char max_rate[8]; /* max. transfer rate (setup) */ - unsigned char max_offset[8]; /* max. sync. offset (setup), only valid if corresponding sync_en is nonzero */ - }; - -#define AM53C974 { \ - NULL, /* pointer to next in list */ \ - NULL, /* long * usage_count */ \ - NULL, /* struct proc_dir_entry *proc_dir */ \ - NULL, /* int (*proc_info)(char *, char **, off_t, int, int, int); */ \ - "AM53C974", /* name */ \ - AM53C974_detect, /* int (* detect)(struct SHT *) */ \ - NULL, /* int (*release)(struct Scsi_Host *) */ \ - AM53C974_info, /* const char *(* info)(struct Scsi_Host *) */ \ - AM53C974_command, /* int (* command)(Scsi_Cmnd *) */ \ - AM53C974_queue_command, /* int (* queuecommand)(Scsi_Cmnd *, \ - void (*done)(Scsi_Cmnd *)) */ \ - AM53C974_abort, /* int (* abort)(Scsi_Cmnd *) */ \ - AM53C974_reset, /* int (* reset)(Scsi_Cmnd *) */ \ - NULL, /* int (* slave_attach)(int, int) */ \ - scsicam_bios_param, /* int (* bios_param)(Disk *, int, int[]) */ \ - 12, /* can_queue */ \ - -1, /* this_id */ \ - SG_ALL, /* sg_tablesize */ \ - 1, /* cmd_per_lun */ \ - 0, /* present, i.e. how many adapters of this kind */ \ - 0, /* unchecked_isa_dma */ \ - DISABLE_CLUSTERING /* use_clustering */ \ - } - -void AM53C974_setup(char *str, int *ints); -int AM53C974_detect(Scsi_Host_Template *tpnt); -int AM53C974_biosparm(Disk *disk, int dev, int *info_array); -const char *AM53C974_info(struct Scsi_Host *); -int AM53C974_command(Scsi_Cmnd *SCpnt); -int AM53C974_queue_command(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)); -int AM53C974_abort(Scsi_Cmnd *cmd); -int AM53C974_reset (Scsi_Cmnd *cmd); - -#define AM53C974_local_declare() unsigned long io_port -#define AM53C974_setio(instance) io_port = instance->io_port -#define AM53C974_read_8(addr) inb(io_port + (addr)) -#define AM53C974_write_8(addr,x) outb((x), io_port + (addr)) -#define AM53C974_read_16(addr) inw(io_port + (addr)) -#define AM53C974_write_16(addr,x) outw((x), io_port + (addr)) -#define AM53C974_read_32(addr) inl(io_port + (addr)) -#define AM53C974_write_32(addr,x) outl((x), io_port + (addr)) - -#define AM53C974_poll_int() { do { statreg = AM53C974_read_8(STATREG); } \ - while (!(statreg & STATREG_INT)) ; \ - AM53C974_read_8(INSTREG) ; } /* clear int */ -#define AM53C974_cfifo() (AM53C974_read_8(CFIREG) & CFIREG_CF) - -/* These are "special" values for the tag parameter passed to AM53C974_select. */ -#define TAG_NEXT -1 /* Use next free tag */ -#define TAG_NONE -2 /* Establish I_T_L nexus instead of I_T_L_Q - * even on SCSI-II devices */ - -/************ LILO overrides *************/ -typedef struct _override_t { - int host_scsi_id; /* SCSI id of the bus controller */ - int target_scsi_id; /* SCSI id of target */ - int max_rate; /* max. transfer rate */ - int max_offset; /* max. sync. offset, 0 = asynchronous */ - } override_t; - -/************ PCI stuff *************/ -#define AM53C974_PCIREG_OPEN() outb(0xF1, 0xCF8); outb(0, 0xCFA) -#define AM53C974_PCIREG_CLOSE() outb(0, 0xCF8) -#define AM53C974_PCIREG_READ_BYTE(instance,a) ( inb((a) + (instance)->io_port) ) -#define AM53C974_PCIREG_READ_WORD(instance,a) ( inw((a) + (instance)->io_port) ) -#define AM53C974_PCIREG_READ_DWORD(instance,a) ( inl((a) + (instance)->io_port) ) -#define AM53C974_PCIREG_WRITE_BYTE(instance,x,a) ( outb((x), (a) + (instance)->io_port) ) -#define AM53C974_PCIREG_WRITE_WORD(instance,x,a) ( outw((x), (a) + (instance)->io_port) ) -#define AM53C974_PCIREG_WRITE_DWORD(instance,x,a) ( outl((x), (a) + (instance)->io_port) ) - -typedef struct _pci_config_t { - /* start of official PCI config space header */ - union { - unsigned int device_vendor; - struct { - unsigned short vendor; - unsigned short device; - } dv; - } dv_id; -#define _device_vendor dv_id.device_vendor -#define _vendor dv_id.dv.vendor -#define _device dv_id.dv.device - union { - unsigned int status_command; - struct { - unsigned short command; - unsigned short status; - } sc; - } stat_cmd; -#define _status_command stat_cmd.status_command -#define _command stat_cmd.sc.command -#define _status stat_cmd.sc.status - union { - unsigned int class_revision; - struct { - unsigned char rev_id; - unsigned char prog_if; - unsigned char sub_class; - unsigned char base_class; - } cr; - } class_rev; -#define _class_revision class_rev.class_revision -#define _rev_id class_rev.cr.rev_id -#define _prog_if class_rev.cr.prog_if -#define _sub_class class_rev.cr.sub_class -#define _base_class class_rev.cr.base_class - union { - unsigned int bist_header_latency_cache; - struct { - unsigned char cache_line_size; - unsigned char latency_timer; - unsigned char header_type; - unsigned char bist; - } bhlc; - } bhlc; -#define _bist_header_latency_cache bhlc.bist_header_latency_cache -#define _cache_line_size bhlc.bhlc.cache_line_size -#define _latency_timer bhlc.bhlc.latency_timer -#define _header_type bhlc.bhlc.header_type -#define _bist bhlc.bhlc.bist - unsigned int _base0; - unsigned int _base1; - unsigned int _base2; - unsigned int _base3; - unsigned int _base4; - unsigned int _base5; - unsigned int rsvd1; - unsigned int rsvd2; - unsigned int _baserom; - unsigned int rsvd3; - unsigned int rsvd4; - union { - unsigned int max_min_ipin_iline; - struct { - unsigned char int_line; - unsigned char int_pin; - unsigned char min_gnt; - unsigned char max_lat; - } mmii; - } mmii; -#define _max_min_ipin_iline mmii.max_min_ipin_iline -#define _int_line mmii.mmii.int_line -#define _int_pin mmii.mmii.int_pin -#define _min_gnt mmii.mmii.min_gnt -#define _max_lat mmii.mmii.max_lat - /* end of official PCI config space header */ - unsigned short _ioaddr; /* config type 1 - private I/O addr */ - unsigned int _pcibus; /* config type 2 - private bus id */ - unsigned int _cardnum; /* config type 2 - private card number */ -} pci_config_t; - -#endif /* AM53C974_H */ diff --git a/i386/i386at/gpl/linux/scsi/BusLogic.c b/i386/i386at/gpl/linux/scsi/BusLogic.c deleted file mode 100644 index 7472dc3d..00000000 --- a/i386/i386at/gpl/linux/scsi/BusLogic.c +++ /dev/null @@ -1,2779 +0,0 @@ -/* - - Linux Driver for BusLogic MultiMaster SCSI Host Adapters - - Copyright 1995 by Leonard N. Zubkoff <lnz@dandelion.com> - - This program is free software; you may redistribute and/or modify it under - the terms of the GNU General Public License Version 2 as published by the - Free Software Foundation, provided that none of the source code or runtime - copyright notices are removed or modified. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - for complete details. - - The author respectfully requests that all modifications to this software be - sent directly to him for evaluation and testing. - - Special thanks to Alex T. Win of BusLogic, whose advice has been invaluable, - to David B. Gentzel, for writing the original Linux BusLogic driver, and to - Paul Gortmaker, for being such a dedicated test site. - -*/ - - -#define BusLogic_DriverVersion "1.3.1" -#define BusLogic_DriverDate "31 December 1995" - - -#include <linux/module.h> -#include <linux/config.h> -#include <linux/types.h> -#include <linux/blkdev.h> -#include <linux/delay.h> -#include <linux/ioport.h> -#include <linux/kernel_stat.h> -#include <linux/mm.h> -#include <linux/sched.h> -#include <linux/stat.h> -#include <linux/pci.h> -#include <linux/bios32.h> -#include <asm/dma.h> -#include <asm/io.h> -#include <asm/system.h> -#include "scsi.h" -#include "hosts.h" -#include "sd.h" -#include "BusLogic.h" - - -/* - BusLogic_CommandLineEntryCount is a count of the number of "BusLogic=" - entries provided on the Linux Kernel Command Line. -*/ - -static int - BusLogic_CommandLineEntryCount = 0; - - -/* - BusLogic_CommandLineEntries is an array of Command Line Entry structures - representing the "BusLogic=" entries provided on the Linux Kernel Command - Line. -*/ - -static BusLogic_CommandLineEntry_T - BusLogic_CommandLineEntries[BusLogic_MaxHostAdapters]; - - -/* - BusLogic_GlobalOptions is a bit mask of Global Options to be applied - across all Host Adapters. -*/ - -static int - BusLogic_GlobalOptions = 0; - - -/* - BusLogic_RegisteredHostAdapters is a linked list of all the registered - BusLogic Host Adapters. -*/ - -static BusLogic_HostAdapter_T - *BusLogic_RegisteredHostAdapters = NULL; - - -/* - BusLogic_Standard_IO_Addresses is the list of standard I/O Addresses at which - BusLogic Host Adapters may potentially be found. -*/ - -static unsigned short - BusLogic_IO_StandardAddresses[] = - { 0x330, 0x334, 0x230, 0x234, 0x130, 0x134, 0 }; - - -/* - BusLogic_IO_AddressProbeList is the list of I/O Addresses to be probed for - potential BusLogic Host Adapters. It is initialized by interrogating the - PCI Configuration Space on PCI machines as well as from the list of - standard BusLogic I/O Addresses. -*/ - -static unsigned short - BusLogic_IO_AddressProbeList[BusLogic_IO_MaxProbeAddresses+1] = { 0 }; - - -/* - BusLogic_IRQ_UsageCount stores a count of the number of Host Adapters using - a given IRQ Channel, which is necessary to support PCI, EISA, or MCA shared - interrupts. Only IRQ Channels 9, 10, 11, 12, 14, and 15 are supported by - BusLogic Host Adapters. -*/ - -static short - BusLogic_IRQ_UsageCount[7] = { 0 }; - - -/* - BusLogic_CommandFailureReason holds a string identifying the reason why a - call to BusLogic_Command failed. It is only valid when BusLogic_Command - returns a failure code. -*/ - -static char - *BusLogic_CommandFailureReason; - - -/* - BusLogic_ProcDirectoryEntry is the BusLogic /proc/scsi directory entry. -*/ - -static struct proc_dir_entry - BusLogic_ProcDirectoryEntry = - { PROC_SCSI_BUSLOGIC, 8, "BusLogic", S_IFDIR | S_IRUGO | S_IXUGO, 2 }; - - -/* - BusLogic_AnnounceDriver announces the Driver Version and Date, Author's - Name, Copyright Notice, and Contact Address. -*/ - -static void BusLogic_AnnounceDriver(void) -{ - static boolean DriverAnnouncementPrinted = false; - if (DriverAnnouncementPrinted) return; - printk("scsi: ***** BusLogic SCSI Driver Version " - BusLogic_DriverVersion " of " BusLogic_DriverDate " *****\n"); - printk("scsi: Copyright 1995 by Leonard N. Zubkoff <lnz@dandelion.com>\n"); - DriverAnnouncementPrinted = true; -} - - -/* - BusLogic_DriverInfo returns the Board Name to identify this SCSI Driver - and Host Adapter. -*/ - -const char *BusLogic_DriverInfo(SCSI_Host_T *Host) -{ - BusLogic_HostAdapter_T *HostAdapter = - (BusLogic_HostAdapter_T *) Host->hostdata; - return HostAdapter->BoardName; -} - - -/* - BusLogic_InitializeAddressProbeList initializes the list of I/O Addresses - to be probed for potential BusLogic SCSI Host Adapters by interrogating the - PCI Configuration Space on PCI machines as well as from the list of standard - BusLogic I/O Addresses. -*/ - -static void BusLogic_InitializeAddressProbeList(void) -{ - int DestinationIndex = 0, SourceIndex = 0; - /* - If BusLogic_Setup has been called, do not override the Kernel Command - Line specifications. - */ - if (BusLogic_IO_AddressProbeList[0] != 0) return; -#ifdef CONFIG_PCI - /* - Interrogate PCI Configuration Space for any BusLogic SCSI Host Adapters. - */ - if (pcibios_present()) - { - unsigned short Index = 0, VendorID; - unsigned char Bus, DeviceAndFunction; - unsigned int BaseAddress0; - while (pcibios_find_class(PCI_CLASS_STORAGE_SCSI<<8, Index++, - &Bus, &DeviceAndFunction) == 0) - if (pcibios_read_config_word(Bus, DeviceAndFunction, - PCI_VENDOR_ID, &VendorID) == 0 && - VendorID == PCI_VENDOR_ID_BUSLOGIC && - pcibios_read_config_dword(Bus, DeviceAndFunction, - PCI_BASE_ADDRESS_0, &BaseAddress0) == 0 && - (BaseAddress0 & PCI_BASE_ADDRESS_SPACE) == - PCI_BASE_ADDRESS_SPACE_IO) - { - BusLogic_IO_AddressProbeList[DestinationIndex++] = - BaseAddress0 & PCI_BASE_ADDRESS_IO_MASK; - } - } -#endif - /* - Append the list of standard BusLogic I/O Addresses. - */ - while (DestinationIndex < BusLogic_IO_MaxProbeAddresses && - BusLogic_IO_StandardAddresses[SourceIndex] > 0) - BusLogic_IO_AddressProbeList[DestinationIndex++] = - BusLogic_IO_StandardAddresses[SourceIndex++]; - BusLogic_IO_AddressProbeList[DestinationIndex] = 0; -} - - -/* - BusLogic_RegisterHostAdapter adds Host Adapter to the list of registered - BusLogic Host Adapters. -*/ - -static void BusLogic_RegisterHostAdapter(BusLogic_HostAdapter_T *HostAdapter) -{ - HostAdapter->Next = NULL; - if (BusLogic_RegisteredHostAdapters != NULL) - { - BusLogic_HostAdapter_T *LastHostAdapter = BusLogic_RegisteredHostAdapters; - BusLogic_HostAdapter_T *NextHostAdapter; - while ((NextHostAdapter = LastHostAdapter->Next) != NULL) - LastHostAdapter = NextHostAdapter; - LastHostAdapter->Next = HostAdapter; - } - else BusLogic_RegisteredHostAdapters = HostAdapter; -} - - -/* - BusLogic_UnregisterHostAdapter removes Host Adapter from the list of - registered BusLogic Host Adapters. -*/ - -static void BusLogic_UnregisterHostAdapter(BusLogic_HostAdapter_T *HostAdapter) -{ - if (BusLogic_RegisteredHostAdapters != HostAdapter) - { - BusLogic_HostAdapter_T *LastHostAdapter = BusLogic_RegisteredHostAdapters; - while (LastHostAdapter != NULL && LastHostAdapter->Next != HostAdapter) - LastHostAdapter = LastHostAdapter->Next; - if (LastHostAdapter != NULL) - LastHostAdapter->Next = HostAdapter->Next; - } - else BusLogic_RegisteredHostAdapters = HostAdapter->Next; - HostAdapter->Next = NULL; -} - - -/* - BusLogic_CreateCCBs allocates the initial Command Control Blocks (CCBs) - for Host Adapter. -*/ - -static boolean BusLogic_CreateCCBs(BusLogic_HostAdapter_T *HostAdapter) -{ - int i; - for (i = 0; i < BusLogic_InitialCCBs; i++) - { - BusLogic_CCB_T *CCB = (BusLogic_CCB_T *) - scsi_init_malloc(sizeof(BusLogic_CCB_T), GFP_ATOMIC | GFP_DMA); - if (CCB == NULL) - { - printk("scsi%d: UNABLE TO ALLOCATE CCB %d - DETACHING\n", - HostAdapter->HostNumber, i); - return false; - } - memset(CCB, 0, sizeof(BusLogic_CCB_T)); - CCB->HostAdapter = HostAdapter; - CCB->Status = BusLogic_CCB_Free; - CCB->Next = HostAdapter->Free_CCBs; - CCB->NextAll = HostAdapter->All_CCBs; - HostAdapter->Free_CCBs = CCB; - HostAdapter->All_CCBs = CCB; - } - return true; -} - - -/* - BusLogic_DestroyCCBs deallocates the CCBs for Host Adapter. -*/ - -static void BusLogic_DestroyCCBs(BusLogic_HostAdapter_T *HostAdapter) -{ - BusLogic_CCB_T *NextCCB = HostAdapter->All_CCBs, *CCB; - HostAdapter->All_CCBs = NULL; - HostAdapter->Free_CCBs = NULL; - while ((CCB = NextCCB) != NULL) - { - NextCCB = CCB->NextAll; - scsi_init_free((char *) CCB, sizeof(BusLogic_CCB_T)); - } -} - - -/* - BusLogic_AllocateCCB allocates a CCB from the Host Adapter's free list, - allocating more memory from the Kernel if necessary. -*/ - -static BusLogic_CCB_T *BusLogic_AllocateCCB(BusLogic_HostAdapter_T *HostAdapter) -{ - static unsigned int SerialNumber = 0; - BusLogic_CCB_T *CCB; - BusLogic_LockHostAdapter(HostAdapter); - CCB = HostAdapter->Free_CCBs; - if (CCB != NULL) - { - CCB->SerialNumber = ++SerialNumber; - HostAdapter->Free_CCBs = CCB->Next; - CCB->Next = NULL; - BusLogic_UnlockHostAdapter(HostAdapter); - return CCB; - } - BusLogic_UnlockHostAdapter(HostAdapter); - CCB = (BusLogic_CCB_T *) scsi_init_malloc(sizeof(BusLogic_CCB_T), - GFP_ATOMIC | GFP_DMA); - if (CCB == NULL) - { - printk("scsi%d: Failed to allocate an additional CCB\n", - HostAdapter->HostNumber); - return NULL; - } - printk("scsi%d: Allocated an additional CCB\n", HostAdapter->HostNumber); - memset(CCB, 0, sizeof(BusLogic_CCB_T)); - CCB->HostAdapter = HostAdapter; - CCB->Status = BusLogic_CCB_Free; - BusLogic_LockHostAdapter(HostAdapter); - CCB->SerialNumber = ++SerialNumber; - CCB->NextAll = HostAdapter->All_CCBs; - HostAdapter->All_CCBs = CCB; - BusLogic_UnlockHostAdapter(HostAdapter); - return CCB; -} - - -/* - BusLogic_DeallocateCCB deallocates a CCB, returning it to the Host Adapter's - free list. -*/ - -static void BusLogic_DeallocateCCB(BusLogic_CCB_T *CCB) -{ - BusLogic_HostAdapter_T *HostAdapter = CCB->HostAdapter; - BusLogic_LockHostAdapter(HostAdapter); - CCB->Command = NULL; - CCB->Status = BusLogic_CCB_Free; - CCB->Next = HostAdapter->Free_CCBs; - HostAdapter->Free_CCBs = CCB; - BusLogic_UnlockHostAdapter(HostAdapter); -} - - -/* - BusLogic_Command sends the command OperationCode to HostAdapter, optionally - providing ParameterLength bytes of ParameterData and receiving at most - ReplyLength bytes of ReplyData; any excess reply data is received but - discarded. - - On success, this function returns the number of reply bytes read from - the Host Adapter (including any discarded data); on failure, it returns - -1 if the command was invalid, or -2 if a timeout occurred. - - This function is only called during board detection and initialization, so - performance and latency are not critical, and exclusive access to the Host - Adapter hardware is assumed. Once the board and driver are initialized, the - only Host Adapter command that is issued is the single byte Start Mailbox - Scan command, which does not require waiting for the Host Adapter Ready bit - to be set in the Status Register. -*/ - -static int BusLogic_Command(BusLogic_HostAdapter_T *HostAdapter, - BusLogic_OperationCode_T OperationCode, - void *ParameterData, - int ParameterLength, - void *ReplyData, - int ReplyLength) -{ - unsigned char *ParameterPointer = (unsigned char *) ParameterData; - unsigned char *ReplyPointer = (unsigned char *) ReplyData; - unsigned char StatusRegister = 0, InterruptRegister; - long TimeoutCounter; - int ReplyBytes = 0; - /* - Clear out the Reply Data if provided. - */ - if (ReplyLength > 0) - memset(ReplyData, 0, ReplyLength); - /* - Wait for the Host Adapter Ready bit to be set and the Command/Parameter - Register Busy bit to be reset in the Status Register. - */ - TimeoutCounter = loops_per_sec >> 3; - while (--TimeoutCounter >= 0) - { - StatusRegister = BusLogic_ReadStatusRegister(HostAdapter); - if ((StatusRegister & BusLogic_HostAdapterReady) && - !(StatusRegister & BusLogic_CommandParameterRegisterBusy)) - break; - } - BusLogic_CommandFailureReason = "Timeout waiting for Host Adapter Ready"; - if (TimeoutCounter < 0) return -2; - /* - Write the OperationCode to the Command/Parameter Register. - */ - HostAdapter->HostAdapterCommandCompleted = false; - BusLogic_WriteCommandParameterRegister(HostAdapter, OperationCode); - /* - Write any additional Parameter Bytes. - */ - TimeoutCounter = 10000; - while (ParameterLength > 0 && --TimeoutCounter >= 0) - { - /* - Wait 100 microseconds to give the Host Adapter enough time to determine - whether the last value written to the Command/Parameter Register was - valid or not. If the Command Complete bit is set in the Interrupt - Register, then the Command Invalid bit in the Status Register will be - reset if the Operation Code or Parameter was valid and the command - has completed, or set if the Operation Code or Parameter was invalid. - If the Data In Register Ready bit is set in the Status Register, then - the Operation Code was valid, and data is waiting to be read back - from the Host Adapter. Otherwise, wait for the Command/Parameter - Register Busy bit in the Status Register to be reset. - */ - udelay(100); - InterruptRegister = BusLogic_ReadInterruptRegister(HostAdapter); - StatusRegister = BusLogic_ReadStatusRegister(HostAdapter); - if (InterruptRegister & BusLogic_CommandComplete) break; - if (HostAdapter->HostAdapterCommandCompleted) break; - if (StatusRegister & BusLogic_DataInRegisterReady) break; - if (StatusRegister & BusLogic_CommandParameterRegisterBusy) continue; - BusLogic_WriteCommandParameterRegister(HostAdapter, *ParameterPointer++); - ParameterLength--; - } - BusLogic_CommandFailureReason = "Timeout waiting for Parameter Acceptance"; - if (TimeoutCounter < 0) return -2; - /* - The Modify I/O Address command does not cause a Command Complete Interrupt. - */ - if (OperationCode == BusLogic_ModifyIOAddress) - { - StatusRegister = BusLogic_ReadStatusRegister(HostAdapter); - BusLogic_CommandFailureReason = "Modify I/O Address Invalid"; - if (StatusRegister & BusLogic_CommandInvalid) return -1; - BusLogic_CommandFailureReason = NULL; - return 0; - } - /* - Select an appropriate timeout value for awaiting command completion. - */ - switch (OperationCode) - { - case BusLogic_InquireInstalledDevicesID0to7: - case BusLogic_InquireInstalledDevicesID8to15: - /* Approximately 60 seconds. */ - TimeoutCounter = loops_per_sec << 2; - break; - default: - /* Approximately 1 second. */ - TimeoutCounter = loops_per_sec >> 4; - break; - } - /* - Receive any Reply Bytes, waiting for either the Command Complete bit to - be set in the Interrupt Register, or for the Interrupt Handler to set the - Host Adapter Command Completed bit in the Host Adapter structure. - */ - while (--TimeoutCounter >= 0) - { - InterruptRegister = BusLogic_ReadInterruptRegister(HostAdapter); - StatusRegister = BusLogic_ReadStatusRegister(HostAdapter); - if (InterruptRegister & BusLogic_CommandComplete) break; - if (HostAdapter->HostAdapterCommandCompleted) break; - if (StatusRegister & BusLogic_DataInRegisterReady) - if (++ReplyBytes <= ReplyLength) - *ReplyPointer++ = BusLogic_ReadDataInRegister(HostAdapter); - else BusLogic_ReadDataInRegister(HostAdapter); - } - BusLogic_CommandFailureReason = "Timeout waiting for Command Complete"; - if (TimeoutCounter < 0) return -2; - /* - If testing Command Complete Interrupts, wait a short while in case the - loop immediately above terminated due to the Command Complete bit being - set in the Interrupt Register, but the interrupt hasn't actually been - processed yet. Otherwise, acknowledging the interrupt here could prevent - the interrupt test from succeeding. - */ - if (OperationCode == BusLogic_TestCommandCompleteInterrupt) - udelay(10000); - /* - Clear any pending Command Complete Interrupt. - */ - BusLogic_WriteControlRegister(HostAdapter, BusLogic_InterruptReset); - if (BusLogic_GlobalOptions & BusLogic_TraceConfiguration) - if (OperationCode != BusLogic_TestCommandCompleteInterrupt) - { - int i; - printk("BusLogic_Command(%02X) Status = %02X: %2d ==> %2d:", - OperationCode, StatusRegister, ReplyLength, ReplyBytes); - if (ReplyLength > ReplyBytes) ReplyLength = ReplyBytes; - for (i = 0; i < ReplyLength; i++) - printk(" %02X", ((unsigned char *) ReplyData)[i]); - printk("\n"); - } - /* - Process Command Invalid conditions. - */ - if (StatusRegister & BusLogic_CommandInvalid) - { - /* - Some early BusLogic Host Adapters may not recover properly from - a Command Invalid condition, so if this appears to be the case, - a Soft Reset is issued to the Host Adapter. Potentially invalid - commands are never attempted after Mailbox Initialization is - performed, so there should be no Host Adapter state lost by a - Soft Reset in response to a Command Invalid condition. - */ - udelay(1000); - StatusRegister = BusLogic_ReadStatusRegister(HostAdapter); - if (StatusRegister != (BusLogic_HostAdapterReady | - BusLogic_InitializationRequired)) - { - BusLogic_WriteControlRegister(HostAdapter, BusLogic_SoftReset); - udelay(1000); - } - BusLogic_CommandFailureReason = "Command Invalid"; - return -1; - } - /* - Handle Excess Parameters Supplied conditions. - */ - BusLogic_CommandFailureReason = "Excess Parameters Supplied"; - if (ParameterLength > 0) return -1; - /* - Indicate the command completed successfully. - */ - BusLogic_CommandFailureReason = NULL; - return ReplyBytes; -} - - -/* - BusLogic_Failure prints a standardized error message, and then returns false. -*/ - -static boolean BusLogic_Failure(BusLogic_HostAdapter_T *HostAdapter, - char *ErrorMessage) -{ - BusLogic_AnnounceDriver(); - printk("While configuring BusLogic Host Adapter at I/O Address 0x%X:\n", - HostAdapter->IO_Address); - printk("%s FAILED - DETACHING\n", ErrorMessage); - if (BusLogic_CommandFailureReason != NULL) - printk("ADDITIONAL FAILURE INFO - %s\n", BusLogic_CommandFailureReason); - return false; -} - - -/* - BusLogic_ProbeHostAdapter probes for a BusLogic Host Adapter. -*/ - -static boolean BusLogic_ProbeHostAdapter(BusLogic_HostAdapter_T *HostAdapter) -{ - boolean TraceProbe = (BusLogic_GlobalOptions & BusLogic_TraceProbe); - unsigned char StatusRegister, GeometryRegister; - /* - Read the Status Register to test if there is an I/O port that responds. A - nonexistent I/O port will return 0xFF, in which case there is definitely no - BusLogic Host Adapter at this base I/O Address. - */ - StatusRegister = BusLogic_ReadStatusRegister(HostAdapter); - if (TraceProbe) - printk("BusLogic_Probe(0x%X): Status 0x%02X\n", - HostAdapter->IO_Address, StatusRegister); - if (StatusRegister == 0xFF) return false; - /* - Read the undocumented BusLogic Geometry Register to test if there is an I/O - port that responds. Adaptec Host Adapters do not implement the Geometry - Register, so this test helps serve to avoid incorrectly recognizing an - Adaptec 1542A or 1542B as a BusLogic. Unfortunately, the Adaptec 1542C - series does respond to the Geometry Register I/O port, but it will be - rejected later when the Inquire Extended Setup Information command is - issued in BusLogic_CheckHostAdapter. The AMI FastDisk Host Adapter is a - BusLogic clone that implements the same interface as earlier BusLogic - boards, including the undocumented commands, and is therefore supported by - this driver. However, the AMI FastDisk always returns 0x00 upon reading - the Geometry Register, so the extended translation option should always be - left disabled on the AMI FastDisk. - */ - GeometryRegister = BusLogic_ReadGeometryRegister(HostAdapter); - if (TraceProbe) - printk("BusLogic_Probe(0x%X): Geometry 0x%02X\n", - HostAdapter->IO_Address, GeometryRegister); - if (GeometryRegister == 0xFF) return false; - /* - Indicate the Host Adapter Probe completed successfully. - */ - return true; -} - - -/* - BusLogic_HardResetHostAdapter issues a Hard Reset to the Host Adapter, - and waits for Host Adapter Diagnostics to complete. -*/ - -static boolean BusLogic_HardResetHostAdapter(BusLogic_HostAdapter_T - *HostAdapter) -{ - boolean TraceHardReset = (BusLogic_GlobalOptions & BusLogic_TraceHardReset); - long TimeoutCounter = loops_per_sec >> 2; - unsigned char StatusRegister = 0; - /* - Issue a Hard Reset Command to the Host Adapter. The Host Adapter should - respond by setting Diagnostic Active in the Status Register. - */ - BusLogic_WriteControlRegister(HostAdapter, BusLogic_HardReset); - /* - Wait until Diagnostic Active is set in the Status Register. - */ - while (--TimeoutCounter >= 0) - { - StatusRegister = BusLogic_ReadStatusRegister(HostAdapter); - if ((StatusRegister & BusLogic_DiagnosticActive)) break; - } - if (TraceHardReset) - printk("BusLogic_HardReset(0x%X): Diagnostic Active, Status 0x%02X\n", - HostAdapter->IO_Address, StatusRegister); - if (TimeoutCounter < 0) return false; - /* - Wait 100 microseconds to allow completion of any initial diagnostic - activity which might leave the contents of the Status Register - unpredictable. - */ - udelay(100); - /* - Wait until Diagnostic Active is reset in the Status Register. - */ - while (--TimeoutCounter >= 0) - { - StatusRegister = BusLogic_ReadStatusRegister(HostAdapter); - if (!(StatusRegister & BusLogic_DiagnosticActive)) break; - } - if (TraceHardReset) - printk("BusLogic_HardReset(0x%X): Diagnostic Completed, Status 0x%02X\n", - HostAdapter->IO_Address, StatusRegister); - if (TimeoutCounter < 0) return false; - /* - Wait until at least one of the Diagnostic Failure, Host Adapter Ready, - or Data In Register Ready bits is set in the Status Register. - */ - while (--TimeoutCounter >= 0) - { - StatusRegister = BusLogic_ReadStatusRegister(HostAdapter); - if (StatusRegister & (BusLogic_DiagnosticFailure | - BusLogic_HostAdapterReady | - BusLogic_DataInRegisterReady)) - break; - } - if (TraceHardReset) - printk("BusLogic_HardReset(0x%X): Host Adapter Ready, Status 0x%02X\n", - HostAdapter->IO_Address, StatusRegister); - if (TimeoutCounter < 0) return false; - /* - If Diagnostic Failure is set or Host Adapter Ready is reset, then an - error occurred during the Host Adapter diagnostics. If Data In Register - Ready is set, then there is an Error Code available. - */ - if ((StatusRegister & BusLogic_DiagnosticFailure) || - !(StatusRegister & BusLogic_HostAdapterReady)) - { - BusLogic_CommandFailureReason = NULL; - BusLogic_Failure(HostAdapter, "HARD RESET DIAGNOSTICS"); - printk("HOST ADAPTER STATUS REGISTER = %02X\n", StatusRegister); - if (StatusRegister & BusLogic_DataInRegisterReady) - { - unsigned char ErrorCode = BusLogic_ReadDataInRegister(HostAdapter); - printk("HOST ADAPTER ERROR CODE = %d\n", ErrorCode); - } - return false; - } - /* - Indicate the Host Adapter Hard Reset completed successfully. - */ - return true; -} - - -/* - BusLogic_CheckHostAdapter checks to be sure this really is a BusLogic - Host Adapter. -*/ - -static boolean BusLogic_CheckHostAdapter(BusLogic_HostAdapter_T *HostAdapter) -{ - BusLogic_ExtendedSetupInformation_T ExtendedSetupInformation; - BusLogic_RequestedReplyLength_T RequestedReplyLength; - unsigned long ProcessorFlags; - int Result; - /* - Issue the Inquire Extended Setup Information command. Only genuine - BusLogic Host Adapters and true clones support this command. Adaptec 1542C - series Host Adapters that respond to the Geometry Register I/O port will - fail this command. Interrupts must be disabled around the call to - BusLogic_Command since a Command Complete interrupt could occur if the IRQ - Channel was previously enabled for another BusLogic Host Adapter sharing - the same IRQ Channel. - */ - save_flags(ProcessorFlags); - cli(); - RequestedReplyLength = sizeof(ExtendedSetupInformation); - Result = BusLogic_Command(HostAdapter, - BusLogic_InquireExtendedSetupInformation, - &RequestedReplyLength, sizeof(RequestedReplyLength), - &ExtendedSetupInformation, - sizeof(ExtendedSetupInformation)); - restore_flags(ProcessorFlags); - if (BusLogic_GlobalOptions & BusLogic_TraceProbe) - printk("BusLogic_Check(0x%X): Result %d\n", - HostAdapter->IO_Address, Result); - return (Result == sizeof(ExtendedSetupInformation)); -} - - -/* - BusLogic_ReadHostAdapterConfiguration reads the Configuration Information - from Host Adapter. -*/ - -static boolean BusLogic_ReadHostAdapterConfiguration(BusLogic_HostAdapter_T - *HostAdapter) -{ - BusLogic_BoardID_T BoardID; - BusLogic_Configuration_T Configuration; - BusLogic_SetupInformation_T SetupInformation; - BusLogic_ExtendedSetupInformation_T ExtendedSetupInformation; - BusLogic_BoardModelNumber_T BoardModelNumber; - BusLogic_FirmwareVersion3rdDigit_T FirmwareVersion3rdDigit; - BusLogic_FirmwareVersionLetter_T FirmwareVersionLetter; - BusLogic_RequestedReplyLength_T RequestedReplyLength; - unsigned char GeometryRegister, *TargetPointer, Character; - unsigned short AllTargetsMask, DisconnectPermitted; - unsigned short TaggedQueuingPermitted, TaggedQueuingPermittedDefault; - boolean CommonErrorRecovery; - int TargetID, i; - /* - Issue the Inquire Board ID command. - */ - if (BusLogic_Command(HostAdapter, BusLogic_InquireBoardID, NULL, 0, - &BoardID, sizeof(BoardID)) != sizeof(BoardID)) - return BusLogic_Failure(HostAdapter, "INQUIRE BOARD ID"); - /* - Issue the Inquire Configuration command. - */ - if (BusLogic_Command(HostAdapter, BusLogic_InquireConfiguration, NULL, 0, - &Configuration, sizeof(Configuration)) - != sizeof(Configuration)) - return BusLogic_Failure(HostAdapter, "INQUIRE CONFIGURATION"); - /* - Issue the Inquire Setup Information command. - */ - RequestedReplyLength = sizeof(SetupInformation); - if (BusLogic_Command(HostAdapter, BusLogic_InquireSetupInformation, - &RequestedReplyLength, sizeof(RequestedReplyLength), - &SetupInformation, sizeof(SetupInformation)) - != sizeof(SetupInformation)) - return BusLogic_Failure(HostAdapter, "INQUIRE SETUP INFORMATION"); - /* - Issue the Inquire Extended Setup Information command. - */ - RequestedReplyLength = sizeof(ExtendedSetupInformation); - if (BusLogic_Command(HostAdapter, BusLogic_InquireExtendedSetupInformation, - &RequestedReplyLength, sizeof(RequestedReplyLength), - &ExtendedSetupInformation, - sizeof(ExtendedSetupInformation)) - != sizeof(ExtendedSetupInformation)) - return BusLogic_Failure(HostAdapter, "INQUIRE EXTENDED SETUP INFORMATION"); - /* - Issue the Inquire Board Model Number command. - */ - if (!(BoardID.FirmwareVersion1stDigit == '2' && - ExtendedSetupInformation.BusType == 'A')) - { - RequestedReplyLength = sizeof(BoardModelNumber); - if (BusLogic_Command(HostAdapter, BusLogic_InquireBoardModelNumber, - &RequestedReplyLength, sizeof(RequestedReplyLength), - &BoardModelNumber, sizeof(BoardModelNumber)) - != sizeof(BoardModelNumber)) - return BusLogic_Failure(HostAdapter, "INQUIRE BOARD MODEL NUMBER"); - } - else strcpy(BoardModelNumber, "542B"); - /* - Issue the Inquire Firmware Version 3rd Digit command. - */ - if (BusLogic_Command(HostAdapter, BusLogic_InquireFirmwareVersion3rdDigit, - NULL, 0, &FirmwareVersion3rdDigit, - sizeof(FirmwareVersion3rdDigit)) - != sizeof(FirmwareVersion3rdDigit)) - return BusLogic_Failure(HostAdapter, "INQUIRE FIRMWARE 3RD DIGIT"); - /* - Issue the Inquire Firmware Version Letter command. - */ - FirmwareVersionLetter = '\0'; - if (BoardID.FirmwareVersion1stDigit > '3' || - (BoardID.FirmwareVersion1stDigit == '3' && - BoardID.FirmwareVersion2ndDigit >= '3')) - if (BusLogic_Command(HostAdapter, BusLogic_InquireFirmwareVersionLetter, - NULL, 0, &FirmwareVersionLetter, - sizeof(FirmwareVersionLetter)) - != sizeof(FirmwareVersionLetter)) - return BusLogic_Failure(HostAdapter, "INQUIRE FIRMWARE VERSION LETTER"); - /* - BusLogic Host Adapters can be identified by their model number and - the major version number of their firmware as follows: - - 4.xx BusLogic "C" Series Host Adapters: - BT-946C/956C/956CD/747C/757C/757CD/445C/545C/540CF - 3.xx BusLogic "S" Series Host Adapters: - BT-747S/747D/757S/757D/445S/545S/542D - BT-542B/742A (revision H) - 2.xx BusLogic "A" Series Host Adapters: - BT-542B/742A (revision G and below) - 0.xx AMI FastDisk VLB/EISA BusLogic Clone Host Adapter - */ - /* - Save the Model Name and Board Name in the Host Adapter structure. - */ - TargetPointer = HostAdapter->ModelName; - *TargetPointer++ = 'B'; - *TargetPointer++ = 'T'; - *TargetPointer++ = '-'; - for (i = 0; i < sizeof(BoardModelNumber); i++) - { - Character = BoardModelNumber[i]; - if (Character == ' ' || Character == '\0') break; - *TargetPointer++ = Character; - } - *TargetPointer++ = '\0'; - strcpy(HostAdapter->BoardName, "BusLogic "); - strcat(HostAdapter->BoardName, HostAdapter->ModelName); - strcpy(HostAdapter->InterruptLabel, HostAdapter->BoardName); - /* - Save the Firmware Version in the Host Adapter structure. - */ - TargetPointer = HostAdapter->FirmwareVersion; - *TargetPointer++ = BoardID.FirmwareVersion1stDigit; - *TargetPointer++ = '.'; - *TargetPointer++ = BoardID.FirmwareVersion2ndDigit; - if (FirmwareVersion3rdDigit != ' ' && FirmwareVersion3rdDigit != '\0') - *TargetPointer++ = FirmwareVersion3rdDigit; - if (FirmwareVersionLetter != ' ' && FirmwareVersionLetter != '\0') - *TargetPointer++ = FirmwareVersionLetter; - *TargetPointer++ = '\0'; - /* - Determine the IRQ Channel and save it in the Host Adapter structure. - */ - if (Configuration.IRQ_Channel9) - HostAdapter->IRQ_Channel = 9; - else if (Configuration.IRQ_Channel10) - HostAdapter->IRQ_Channel = 10; - else if (Configuration.IRQ_Channel11) - HostAdapter->IRQ_Channel = 11; - else if (Configuration.IRQ_Channel12) - HostAdapter->IRQ_Channel = 12; - else if (Configuration.IRQ_Channel14) - HostAdapter->IRQ_Channel = 14; - else if (Configuration.IRQ_Channel15) - HostAdapter->IRQ_Channel = 15; - /* - Determine the DMA Channel and save it in the Host Adapter structure. - */ - if (Configuration.DMA_Channel5) - HostAdapter->DMA_Channel = 5; - else if (Configuration.DMA_Channel6) - HostAdapter->DMA_Channel = 6; - else if (Configuration.DMA_Channel7) - HostAdapter->DMA_Channel = 7; - /* - Save the Host Adapter SCSI ID in the Host Adapter structure. - */ - HostAdapter->SCSI_ID = Configuration.HostAdapterID; - /* - Save the Synchronous Initiation flag and SCSI Parity Checking flag - in the Host Adapter structure. - */ - HostAdapter->SynchronousInitiation = - SetupInformation.SynchronousInitiationEnabled; - HostAdapter->ParityChecking = SetupInformation.ParityCheckEnabled; - /* - Determine the Bus Type and save it in the Host Adapter structure, - overriding the DMA Channel if it is inappropriate for the bus type. - */ - if (ExtendedSetupInformation.BusType == 'A') - HostAdapter->BusType = BusLogic_ISA_Bus; - else - switch (HostAdapter->ModelName[3]) - { - case '4': - HostAdapter->BusType = BusLogic_VESA_Bus; - HostAdapter->DMA_Channel = 0; - break; - case '5': - HostAdapter->BusType = BusLogic_ISA_Bus; - break; - case '6': - HostAdapter->BusType = BusLogic_MCA_Bus; - HostAdapter->DMA_Channel = 0; - break; - case '7': - HostAdapter->BusType = BusLogic_EISA_Bus; - HostAdapter->DMA_Channel = 0; - break; - case '9': - HostAdapter->BusType = BusLogic_PCI_Bus; - HostAdapter->DMA_Channel = 0; - break; - } - /* - Determine whether Extended Translation is enabled and save it in - the Host Adapter structure. - */ - GeometryRegister = BusLogic_ReadGeometryRegister(HostAdapter); - if (GeometryRegister & BusLogic_ExtendedTranslationEnabled) - HostAdapter->ExtendedTranslation = true; - /* - Save the Disconnect/Reconnect Permitted flag bits in the Host Adapter - structure. The Disconnect Permitted information is only valid on "C" - Series boards, but Disconnect/Reconnect is always permitted on "S" and - "A" Series boards. - */ - if (HostAdapter->FirmwareVersion[0] >= '4') - HostAdapter->DisconnectPermitted = - (SetupInformation.DisconnectPermittedID8to15 << 8) - | SetupInformation.DisconnectPermittedID0to7; - else HostAdapter->DisconnectPermitted = 0xFF; - /* - Save the Scatter Gather Limits, Level Sensitive Interrupts flag, - Wide SCSI flag, and Differential SCSI flag in the Host Adapter structure. - */ - HostAdapter->HostAdapterScatterGatherLimit = - ExtendedSetupInformation.ScatterGatherLimit; - HostAdapter->DriverScatterGatherLimit = - HostAdapter->HostAdapterScatterGatherLimit; - if (HostAdapter->HostAdapterScatterGatherLimit > BusLogic_ScatterGatherLimit) - HostAdapter->DriverScatterGatherLimit = BusLogic_ScatterGatherLimit; - if (ExtendedSetupInformation.Misc.LevelSensitiveInterrupts) - HostAdapter->LevelSensitiveInterrupts = true; - if (ExtendedSetupInformation.HostWideSCSI) - { - HostAdapter->HostWideSCSI = true; - HostAdapter->MaxTargetIDs = 16; - HostAdapter->MaxLogicalUnits = 64; - } - else - { - HostAdapter->HostWideSCSI = false; - HostAdapter->MaxTargetIDs = 8; - HostAdapter->MaxLogicalUnits = 8; - } - HostAdapter->HostDifferentialSCSI = - ExtendedSetupInformation.HostDifferentialSCSI; - /* - Determine the Host Adapter BIOS Address if the BIOS is enabled and - save it in the Host Adapter structure. The BIOS is disabled if the - BIOS_Address is 0. - */ - HostAdapter->BIOS_Address = ExtendedSetupInformation.BIOS_Address << 12; - /* - BusLogic BT-445S Host Adapters prior to board revision D have a hardware - bug whereby when the BIOS is enabled, transfers to/from the same address - range the BIOS occupies modulo 16MB are handled incorrectly. Only properly - functioning BT-445S boards have firmware version 3.37, so we require that - ISA bounce buffers be used for the buggy BT-445S models as well as for all - ISA models. - */ - if (HostAdapter->BusType == BusLogic_ISA_Bus || - (HostAdapter->BIOS_Address > 0 && - strcmp(HostAdapter->ModelName, "BT-445S") == 0 && - strcmp(HostAdapter->FirmwareVersion, "3.37") < 0)) - HostAdapter->BounceBuffersRequired = true; - /* - Select an appropriate value for Concurrency (Commands per Logical Unit) - either from a Command Line Entry, or based on whether this Host Adapter - requires that ISA bounce buffers be used. - */ - if (HostAdapter->CommandLineEntry != NULL && - HostAdapter->CommandLineEntry->Concurrency > 0) - HostAdapter->Concurrency = HostAdapter->CommandLineEntry->Concurrency; - else if (HostAdapter->BounceBuffersRequired) - HostAdapter->Concurrency = BusLogic_Concurrency_BB; - else HostAdapter->Concurrency = BusLogic_Concurrency; - /* - Select an appropriate value for Bus Settle Time either from a Command - Line Entry, or from BusLogic_DefaultBusSettleTime. - */ - if (HostAdapter->CommandLineEntry != NULL && - HostAdapter->CommandLineEntry->BusSettleTime > 0) - HostAdapter->BusSettleTime = HostAdapter->CommandLineEntry->BusSettleTime; - else HostAdapter->BusSettleTime = BusLogic_DefaultBusSettleTime; - /* - Select an appropriate value for Local Options from a Command Line Entry. - */ - if (HostAdapter->CommandLineEntry != NULL) - HostAdapter->LocalOptions = HostAdapter->CommandLineEntry->LocalOptions; - /* - Select appropriate values for the Error Recovery Option array either from - a Command Line Entry, or using BusLogic_ErrorRecoveryDefault. - */ - if (HostAdapter->CommandLineEntry != NULL) - memcpy(HostAdapter->ErrorRecoveryOption, - HostAdapter->CommandLineEntry->ErrorRecoveryOption, - sizeof(HostAdapter->ErrorRecoveryOption)); - else memset(HostAdapter->ErrorRecoveryOption, - BusLogic_ErrorRecoveryDefault, - sizeof(HostAdapter->ErrorRecoveryOption)); - /* - Tagged Queuing support is available and operates properly only on "C" - Series boards with firmware version 4.22 and above and on "S" Series - boards with firmware version 3.35 and above. Tagged Queuing is disabled - by default when the Concurrency value is 1 since queuing multiple commands - is not possible. - */ - TaggedQueuingPermittedDefault = 0; - if (HostAdapter->Concurrency > 1) - switch (HostAdapter->FirmwareVersion[0]) - { - case '5': - TaggedQueuingPermittedDefault = 0xFFFF; - break; - case '4': - if (strcmp(HostAdapter->FirmwareVersion, "4.22") >= 0) - TaggedQueuingPermittedDefault = 0xFFFF; - break; - case '3': - if (strcmp(HostAdapter->FirmwareVersion, "3.35") >= 0) - TaggedQueuingPermittedDefault = 0xFFFF; - break; - } - /* - Tagged Queuing is only useful if Disconnect/Reconnect is permitted. - Therefore, mask the Tagged Queuing Permitted Default bits with the - Disconnect/Reconnect Permitted bits. - */ - TaggedQueuingPermittedDefault &= HostAdapter->DisconnectPermitted; - /* - Combine the default Tagged Queuing Permitted Default bits with any - Command Line Entry Tagged Queuing specification. - */ - if (HostAdapter->CommandLineEntry != NULL) - HostAdapter->TaggedQueuingPermitted = - (HostAdapter->CommandLineEntry->TaggedQueuingPermitted & - HostAdapter->CommandLineEntry->TaggedQueuingPermittedMask) | - (TaggedQueuingPermittedDefault & - ~HostAdapter->CommandLineEntry->TaggedQueuingPermittedMask); - else HostAdapter->TaggedQueuingPermitted = TaggedQueuingPermittedDefault; - /* - Announce the Host Adapter Configuration. - */ - printk("scsi%d: Configuring BusLogic Model %s %s%s%s SCSI Host Adapter\n", - HostAdapter->HostNumber, HostAdapter->ModelName, - BusLogic_BusNames[HostAdapter->BusType], - (HostAdapter->HostWideSCSI ? " Wide" : ""), - (HostAdapter->HostDifferentialSCSI ? " Differential" : "")); - printk("scsi%d: Firmware Version: %s, I/O Address: 0x%X, " - "IRQ Channel: %d/%s\n", - HostAdapter->HostNumber, HostAdapter->FirmwareVersion, - HostAdapter->IO_Address, HostAdapter->IRQ_Channel, - (HostAdapter->LevelSensitiveInterrupts ? "Level" : "Edge")); - printk("scsi%d: DMA Channel: ", HostAdapter->HostNumber); - if (HostAdapter->DMA_Channel > 0) - printk("%d, ", HostAdapter->DMA_Channel); - else printk("None, "); - if (HostAdapter->BIOS_Address > 0) - printk("BIOS Address: 0x%lX, ", HostAdapter->BIOS_Address); - else printk("BIOS Address: None, "); - printk("Host Adapter SCSI ID: %d\n", HostAdapter->SCSI_ID); - printk("scsi%d: Scatter/Gather Limit: %d segments, " - "Synchronous Initiation: %s\n", HostAdapter->HostNumber, - HostAdapter->HostAdapterScatterGatherLimit, - (HostAdapter->SynchronousInitiation ? "Enabled" : "Disabled")); - printk("scsi%d: SCSI Parity Checking: %s, " - "Extended Disk Translation: %s\n", HostAdapter->HostNumber, - (HostAdapter->ParityChecking ? "Enabled" : "Disabled"), - (HostAdapter->ExtendedTranslation ? "Enabled" : "Disabled")); - AllTargetsMask = (1 << HostAdapter->MaxTargetIDs) - 1; - DisconnectPermitted = HostAdapter->DisconnectPermitted & AllTargetsMask; - printk("scsi%d: Disconnect/Reconnect: ", HostAdapter->HostNumber); - if (DisconnectPermitted == 0) - printk("Disabled"); - else if (DisconnectPermitted == AllTargetsMask) - printk("Enabled"); - else - for (TargetID = 0; TargetID < HostAdapter->MaxTargetIDs; TargetID++) - printk("%c", (DisconnectPermitted & (1 << TargetID)) ? 'Y' : 'N'); - printk(", Tagged Queuing: "); - TaggedQueuingPermitted = - HostAdapter->TaggedQueuingPermitted & AllTargetsMask; - if (TaggedQueuingPermitted == 0) - printk("Disabled"); - else if (TaggedQueuingPermitted == AllTargetsMask) - printk("Enabled"); - else - for (TargetID = 0; TargetID < HostAdapter->MaxTargetIDs; TargetID++) - printk("%c", (TaggedQueuingPermitted & (1 << TargetID)) ? 'Y' : 'N'); - printk("\n"); - CommonErrorRecovery = true; - for (TargetID = 1; TargetID < HostAdapter->MaxTargetIDs; TargetID++) - if (HostAdapter->ErrorRecoveryOption[TargetID] != - HostAdapter->ErrorRecoveryOption[0]) - { - CommonErrorRecovery = false; - break; - } - printk("scsi%d: Error Recovery: ", HostAdapter->HostNumber); - if (CommonErrorRecovery) - printk("%s", BusLogic_ErrorRecoveryOptions[ - HostAdapter->ErrorRecoveryOption[0]]); - else - for (TargetID = 0; TargetID < HostAdapter->MaxTargetIDs; TargetID++) - printk("%s", BusLogic_ErrorRecoveryOptions2[ - HostAdapter->ErrorRecoveryOption[TargetID]]); - printk(", Mailboxes: %d, Initial CCBs: %d\n", - BusLogic_MailboxCount, BusLogic_InitialCCBs); - printk("scsi%d: Driver Scatter/Gather Limit: %d segments, " - "Concurrency: %d\n", HostAdapter->HostNumber, - HostAdapter->DriverScatterGatherLimit, HostAdapter->Concurrency); - /* - Indicate reading the Host Adapter Configuration completed successfully. - */ - return true; -} - - -/* - BusLogic_AcquireResources acquires the system resources necessary to use Host - Adapter, and initializes the fields in the SCSI Host structure. The base, - io_port, n_io_ports, irq, and dma_channel fields in the SCSI Host structure - are intentionally left uninitialized, as this driver handles acquisition and - release of these resources explicitly, as well as ensuring exclusive access - to the Host Adapter hardware and data structures through explicit locking. -*/ - -static boolean BusLogic_AcquireResources(BusLogic_HostAdapter_T *HostAdapter, - SCSI_Host_T *Host) -{ - /* - Acquire exclusive or shared access to the IRQ Channel. A usage count is - maintained so that PCI, EISA, or MCA shared Interrupts can be supported. - */ - if (BusLogic_IRQ_UsageCount[HostAdapter->IRQ_Channel - 9]++ == 0) - { - if (request_irq(HostAdapter->IRQ_Channel, BusLogic_InterruptHandler, - SA_INTERRUPT, HostAdapter->InterruptLabel) < 0) - { - BusLogic_IRQ_UsageCount[HostAdapter->IRQ_Channel - 9]--; - printk("scsi%d: UNABLE TO ACQUIRE IRQ CHANNEL %d - DETACHING\n", - HostAdapter->HostNumber, HostAdapter->IRQ_Channel); - return false; - } - } - else - { - BusLogic_HostAdapter_T *FirstHostAdapter = - BusLogic_RegisteredHostAdapters; - while (FirstHostAdapter != NULL) - { - if (FirstHostAdapter->IRQ_Channel == HostAdapter->IRQ_Channel) - { - if (strlen(FirstHostAdapter->InterruptLabel) + 11 - < sizeof(FirstHostAdapter->InterruptLabel)) - { - strcat(FirstHostAdapter->InterruptLabel, " + "); - strcat(FirstHostAdapter->InterruptLabel, - HostAdapter->ModelName); - } - break; - } - FirstHostAdapter = FirstHostAdapter->Next; - } - } - HostAdapter->IRQ_ChannelAcquired = true; - /* - Acquire exclusive access to the DMA Channel. - */ - if (HostAdapter->DMA_Channel > 0) - { - if (request_dma(HostAdapter->DMA_Channel, HostAdapter->BoardName) < 0) - { - printk("scsi%d: UNABLE TO ACQUIRE DMA CHANNEL %d - DETACHING\n", - HostAdapter->HostNumber, HostAdapter->DMA_Channel); - return false; - } - set_dma_mode(HostAdapter->DMA_Channel, DMA_MODE_CASCADE); - enable_dma(HostAdapter->DMA_Channel); - HostAdapter->DMA_ChannelAcquired = true; - } - /* - Initialize necessary fields in the SCSI Host structure. - */ - Host->max_id = HostAdapter->MaxTargetIDs; - Host->max_lun = HostAdapter->MaxLogicalUnits; - Host->max_channel = 0; - Host->this_id = HostAdapter->SCSI_ID; - Host->can_queue = BusLogic_MailboxCount; - Host->cmd_per_lun = HostAdapter->Concurrency; - Host->sg_tablesize = HostAdapter->DriverScatterGatherLimit; - Host->unchecked_isa_dma = HostAdapter->BounceBuffersRequired; - /* - Indicate the System Resource Acquisition completed successfully, - */ - return true; -} - - -/* - BusLogic_ReleaseResources releases any system resources previously acquired - by BusLogic_AcquireResources. -*/ - -static void BusLogic_ReleaseResources(BusLogic_HostAdapter_T *HostAdapter) -{ - /* - Release exclusive or shared access to the IRQ Channel. - */ - if (HostAdapter->IRQ_ChannelAcquired) - if (--BusLogic_IRQ_UsageCount[HostAdapter->IRQ_Channel - 9] == 0) - free_irq(HostAdapter->IRQ_Channel); - /* - Release exclusive access to the DMA Channel. - */ - if (HostAdapter->DMA_ChannelAcquired) - free_dma(HostAdapter->DMA_Channel); -} - - -/* - BusLogic_TestInterrupts tests for proper functioning of the Host Adapter - Interrupt Register and that interrupts generated by the Host Adapter are - getting through to the Interrupt Handler. A large proportion of initial - problems with installing PCI Host Adapters are due to configuration problems - where either the Host Adapter or Motherboard is configured incorrectly, and - interrupts do not get through as a result. -*/ - -static boolean BusLogic_TestInterrupts(BusLogic_HostAdapter_T *HostAdapter) -{ - unsigned int InitialInterruptCount, FinalInterruptCount; - int TestCount = 5, i; - InitialInterruptCount = kstat.interrupts[HostAdapter->IRQ_Channel]; - /* - Issue the Test Command Complete Interrupt commands. - */ - for (i = 0; i < TestCount; i++) - BusLogic_Command(HostAdapter, BusLogic_TestCommandCompleteInterrupt, - NULL, 0, NULL, 0); - /* - Verify that BusLogic_InterruptHandler was called at least TestCount times. - Shared IRQ Channels could cause more than TestCount interrupts to occur, - but there should never be fewer than TestCount. - */ - FinalInterruptCount = kstat.interrupts[HostAdapter->IRQ_Channel]; - if (FinalInterruptCount < InitialInterruptCount + TestCount) - { - BusLogic_Failure(HostAdapter, "HOST ADAPTER INTERRUPT TEST"); - printk("\n\ -Interrupts are not getting through from the Host Adapter to the BusLogic\n\ -Driver Interrupt Handler. The most likely cause is that either the Host\n\ -Adapter or Motherboard is configured incorrectly. Please check the Host\n\ -Adapter configuration with AutoSCSI or by examining any dip switch and\n\ -jumper settings on the Host Adapter, and verify that no other device is\n\ -attempting to use the same IRQ Channel. For PCI Host Adapters, it may also\n\ -be necessary to investigate and manually set the PCI interrupt assignments\n\ -and edge/level interrupt type selection in the BIOS Setup Program or with\n\ -Motherboard jumpers.\n\n"); - return false; - } - /* - Indicate the Host Adapter Interrupt Test completed successfully. - */ - return true; -} - - -/* - BusLogic_InitializeHostAdapter initializes Host Adapter. This is the only - function called during SCSI Host Adapter detection which modifies the state - of the Host Adapter from its initial power on or hard reset state. -*/ - -static boolean BusLogic_InitializeHostAdapter(BusLogic_HostAdapter_T - *HostAdapter) -{ - BusLogic_ExtendedMailboxRequest_T ExtendedMailboxRequest; - BusLogic_RoundRobinModeRequest_T RoundRobinModeRequest; - BusLogic_WideModeCCBRequest_T WideModeCCBRequest; - BusLogic_ModifyIOAddressRequest_T ModifyIOAddressRequest; - /* - Initialize the Command Successful Flag, Read/Write Operation Count, - and Queued Operation Count for each Target. - */ - memset(HostAdapter->CommandSuccessfulFlag, false, - sizeof(HostAdapter->CommandSuccessfulFlag)); - memset(HostAdapter->ReadWriteOperationCount, 0, - sizeof(HostAdapter->ReadWriteOperationCount)); - memset(HostAdapter->QueuedOperationCount, 0, - sizeof(HostAdapter->QueuedOperationCount)); - /* - Initialize the Outgoing and Incoming Mailbox structures. - */ - memset(HostAdapter->OutgoingMailboxes, 0, - sizeof(HostAdapter->OutgoingMailboxes)); - memset(HostAdapter->IncomingMailboxes, 0, - sizeof(HostAdapter->IncomingMailboxes)); - /* - Initialize the pointers to the First, Last, and Next Mailboxes. - */ - HostAdapter->FirstOutgoingMailbox = &HostAdapter->OutgoingMailboxes[0]; - HostAdapter->LastOutgoingMailbox = - &HostAdapter->OutgoingMailboxes[BusLogic_MailboxCount-1]; - HostAdapter->NextOutgoingMailbox = HostAdapter->FirstOutgoingMailbox; - HostAdapter->FirstIncomingMailbox = &HostAdapter->IncomingMailboxes[0]; - HostAdapter->LastIncomingMailbox = - &HostAdapter->IncomingMailboxes[BusLogic_MailboxCount-1]; - HostAdapter->NextIncomingMailbox = HostAdapter->FirstIncomingMailbox; - /* - Initialize the Host Adapter's Pointer to the Outgoing/Incoming Mailboxes. - */ - ExtendedMailboxRequest.MailboxCount = BusLogic_MailboxCount; - ExtendedMailboxRequest.BaseMailboxAddress = HostAdapter->OutgoingMailboxes; - if (BusLogic_Command(HostAdapter, BusLogic_InitializeExtendedMailbox, - &ExtendedMailboxRequest, - sizeof(ExtendedMailboxRequest), NULL, 0) < 0) - return BusLogic_Failure(HostAdapter, "MAILBOX INITIALIZATION"); - /* - Enable Strict Round Robin Mode if supported by the Host Adapter. In Strict - Round Robin Mode, the Host Adapter only looks at the next Outgoing Mailbox - for each new command, rather than scanning through all the Outgoing - Mailboxes to find any that have new commands in them. BusLogic indicates - that Strict Round Robin Mode is significantly more efficient. - */ - if (strcmp(HostAdapter->FirmwareVersion, "3.31") >= 0) - { - RoundRobinModeRequest = BusLogic_StrictRoundRobinMode; - if (BusLogic_Command(HostAdapter, BusLogic_EnableStrictRoundRobinMode, - &RoundRobinModeRequest, - sizeof(RoundRobinModeRequest), NULL, 0) < 0) - return BusLogic_Failure(HostAdapter, "ENABLE STRICT ROUND ROBIN MODE"); - } - /* - For Wide SCSI Host Adapters, issue the Enable Wide Mode CCB command to - allow more than 8 Logical Units per Target to be supported. - */ - if (HostAdapter->HostWideSCSI) - { - WideModeCCBRequest = BusLogic_WideModeCCB; - if (BusLogic_Command(HostAdapter, BusLogic_EnableWideModeCCB, - &WideModeCCBRequest, - sizeof(WideModeCCBRequest), NULL, 0) < 0) - return BusLogic_Failure(HostAdapter, "ENABLE WIDE MODE CCB"); - } - /* - For PCI Host Adapters being accessed through the PCI compliant I/O - Address, disable the ISA compatible I/O Address to avoid detecting the - same Host Adapter at both I/O Addresses. - */ - if (HostAdapter->BusType == BusLogic_PCI_Bus) - { - int Index; - for (Index = 0; BusLogic_IO_StandardAddresses[Index] > 0; Index++) - if (HostAdapter->IO_Address == BusLogic_IO_StandardAddresses[Index]) - break; - if (BusLogic_IO_StandardAddresses[Index] == 0) - { - ModifyIOAddressRequest = BusLogic_ModifyIO_Disable; - if (BusLogic_Command(HostAdapter, BusLogic_ModifyIOAddress, - &ModifyIOAddressRequest, - sizeof(ModifyIOAddressRequest), NULL, 0) < 0) - return BusLogic_Failure(HostAdapter, "MODIFY I/O ADDRESS"); - } - } - /* - Announce Successful Initialization. - */ - printk("scsi%d: *** %s Initialized Successfully ***\n", - HostAdapter->HostNumber, HostAdapter->BoardName); - /* - Indicate the Host Adapter Initialization completed successfully. - */ - return true; -} - - -/* - BusLogic_InquireTargetDevices inquires about the Target Devices accessible - through Host Adapter and reports on the results. -*/ - -static boolean BusLogic_InquireTargetDevices(BusLogic_HostAdapter_T - *HostAdapter) -{ - BusLogic_InstalledDevices8_T InstalledDevicesID0to7; - BusLogic_InstalledDevices8_T InstalledDevicesID8to15; - BusLogic_SetupInformation_T SetupInformation; - BusLogic_SynchronousPeriod_T SynchronousPeriod; - BusLogic_RequestedReplyLength_T RequestedReplyLength; - int TargetDevicesFound = 0, TargetID; - /* - Wait a few seconds between the Host Adapter Hard Reset which initiates - a SCSI Bus Reset and issuing any SCSI commands. Some SCSI devices get - confused if they receive SCSI commands too soon after a SCSI Bus Reset. - */ - BusLogic_Delay(HostAdapter->BusSettleTime); - /* - Inhibit the Target Devices Inquiry if requested. - */ - if (HostAdapter->LocalOptions & BusLogic_InhibitTargetInquiry) - { - printk("scsi%d: Target Device Inquiry Inhibited\n", - HostAdapter->HostNumber); - return true; - } - /* - Issue the Inquire Installed Devices ID 0 to 7 command, and for Wide SCSI - Host Adapters the Inquire Installed Devices ID 8 to 15 command. This is - necessary to force Synchronous Transfer Negotiation so that the Inquire - Setup Information and Inquire Synchronous Period commands will return - valid data. - */ - if (BusLogic_Command(HostAdapter, BusLogic_InquireInstalledDevicesID0to7, - NULL, 0, &InstalledDevicesID0to7, - sizeof(InstalledDevicesID0to7)) - != sizeof(InstalledDevicesID0to7)) - return BusLogic_Failure(HostAdapter, "INQUIRE INSTALLED DEVICES ID 0 TO 7"); - if (HostAdapter->HostWideSCSI) - if (BusLogic_Command(HostAdapter, BusLogic_InquireInstalledDevicesID8to15, - NULL, 0, &InstalledDevicesID8to15, - sizeof(InstalledDevicesID8to15)) - != sizeof(InstalledDevicesID8to15)) - return BusLogic_Failure(HostAdapter, - "INQUIRE INSTALLED DEVICES ID 8 TO 15"); - /* - Issue the Inquire Setup Information command. - */ - RequestedReplyLength = sizeof(SetupInformation); - if (BusLogic_Command(HostAdapter, BusLogic_InquireSetupInformation, - &RequestedReplyLength, sizeof(RequestedReplyLength), - &SetupInformation, sizeof(SetupInformation)) - != sizeof(SetupInformation)) - return BusLogic_Failure(HostAdapter, "INQUIRE SETUP INFORMATION"); - /* - Issue the Inquire Synchronous Period command. - */ - if (HostAdapter->FirmwareVersion[0] >= '3') - { - RequestedReplyLength = sizeof(SynchronousPeriod); - if (BusLogic_Command(HostAdapter, BusLogic_InquireSynchronousPeriod, - &RequestedReplyLength, sizeof(RequestedReplyLength), - &SynchronousPeriod, sizeof(SynchronousPeriod)) - != sizeof(SynchronousPeriod)) - return BusLogic_Failure(HostAdapter, "INQUIRE SYNCHRONOUS PERIOD"); - } - else - for (TargetID = 0; TargetID < HostAdapter->MaxTargetIDs; TargetID++) - if (SetupInformation.SynchronousValuesID0to7[TargetID].Offset > 0) - SynchronousPeriod[TargetID] = - 20 + 5 * SetupInformation.SynchronousValuesID0to7[TargetID] - .TransferPeriod; - else SynchronousPeriod[TargetID] = 0; - /* - Save the Installed Devices, Synchronous Values, and Synchronous Period - information in the Host Adapter structure. - */ - memcpy(HostAdapter->InstalledDevices, InstalledDevicesID0to7, - sizeof(BusLogic_InstalledDevices8_T)); - memcpy(HostAdapter->SynchronousValues, - SetupInformation.SynchronousValuesID0to7, - sizeof(BusLogic_SynchronousValues8_T)); - if (HostAdapter->HostWideSCSI) - { - memcpy(&HostAdapter->InstalledDevices[8], InstalledDevicesID8to15, - sizeof(BusLogic_InstalledDevices8_T)); - memcpy(&HostAdapter->SynchronousValues[8], - SetupInformation.SynchronousValuesID8to15, - sizeof(BusLogic_SynchronousValues8_T)); - } - memcpy(HostAdapter->SynchronousPeriod, SynchronousPeriod, - sizeof(BusLogic_SynchronousPeriod_T)); - for (TargetID = 0; TargetID < HostAdapter->MaxTargetIDs; TargetID++) - if (HostAdapter->InstalledDevices[TargetID] != 0) - { - int SynchronousPeriod = HostAdapter->SynchronousPeriod[TargetID]; - if (SynchronousPeriod > 10) - { - int SynchronousTransferRate = 100000000 / SynchronousPeriod; - int RoundedSynchronousTransferRate = - (SynchronousTransferRate + 5000) / 10000; - printk("scsi%d: Target %d: Synchronous at " - "%d.%02d mega-transfers/second, offset %d\n", - HostAdapter->HostNumber, TargetID, - RoundedSynchronousTransferRate / 100, - RoundedSynchronousTransferRate % 100, - HostAdapter->SynchronousValues[TargetID].Offset); - } - else if (SynchronousPeriod > 0) - { - int SynchronousTransferRate = 100000000 / SynchronousPeriod; - int RoundedSynchronousTransferRate = - (SynchronousTransferRate + 50000) / 100000; - printk("scsi%d: Target %d: Synchronous at " - "%d.%01d mega-transfers/second, offset %d\n", - HostAdapter->HostNumber, TargetID, - RoundedSynchronousTransferRate / 10, - RoundedSynchronousTransferRate % 10, - HostAdapter->SynchronousValues[TargetID].Offset); - } - else printk("scsi%d: Target %d: Asynchronous\n", - HostAdapter->HostNumber, TargetID); - TargetDevicesFound++; - } - if (TargetDevicesFound == 0) - printk("scsi%d: No Target Devices Found\n", HostAdapter->HostNumber); - /* - Indicate the Target Device Inquiry completed successfully. - */ - return true; -} - - -/* - BusLogic_DetectHostAdapter probes for BusLogic Host Adapters at the standard - I/O Addresses where they may be located, initializing, registering, and - reporting the configuration of each BusLogic Host Adapter it finds. It - returns the number of BusLogic Host Adapters successfully initialized and - registered. -*/ - -int BusLogic_DetectHostAdapter(SCSI_Host_Template_T *HostTemplate) -{ - int BusLogicHostAdapterCount = 0, CommandLineEntryIndex = 0; - int AddressProbeIndex = 0; - BusLogic_InitializeAddressProbeList(); - while (BusLogic_IO_AddressProbeList[AddressProbeIndex] > 0) - { - BusLogic_HostAdapter_T HostAdapterPrototype; - BusLogic_HostAdapter_T *HostAdapter = &HostAdapterPrototype; - SCSI_Host_T *Host; - memset(HostAdapter, 0, sizeof(BusLogic_HostAdapter_T)); - HostAdapter->IO_Address = - BusLogic_IO_AddressProbeList[AddressProbeIndex++]; - /* - Initialize the Command Line Entry field if an explicit I/O Address - was specified. - */ - if (CommandLineEntryIndex < BusLogic_CommandLineEntryCount && - BusLogic_CommandLineEntries[CommandLineEntryIndex].IO_Address == - HostAdapter->IO_Address) - HostAdapter->CommandLineEntry = - &BusLogic_CommandLineEntries[CommandLineEntryIndex++]; - /* - Check whether the I/O Address range is already in use. - */ - if (check_region(HostAdapter->IO_Address, BusLogic_IO_PortCount) < 0) - continue; - /* - Probe the Host Adapter. If unsuccessful, abort further initialization. - */ - if (!BusLogic_ProbeHostAdapter(HostAdapter)) continue; - /* - Hard Reset the Host Adapter. If unsuccessful, abort further - initialization. - */ - if (!BusLogic_HardResetHostAdapter(HostAdapter)) continue; - /* - Check the Host Adapter. If unsuccessful, abort further initialization. - */ - if (!BusLogic_CheckHostAdapter(HostAdapter)) continue; - /* - Initialize the Command Line Entry field if an explicit I/O Address - was not specified. - */ - if (CommandLineEntryIndex < BusLogic_CommandLineEntryCount && - BusLogic_CommandLineEntries[CommandLineEntryIndex].IO_Address == 0) - HostAdapter->CommandLineEntry = - &BusLogic_CommandLineEntries[CommandLineEntryIndex++]; - /* - Announce the Driver Version and Date, Author's Name, Copyright Notice, - and Contact Address. - */ - BusLogic_AnnounceDriver(); - /* - Register usage of the I/O Address range. From this point onward, any - failure will be assumed to be due to a problem with the Host Adapter, - rather than due to having mistakenly identified this port as belonging - to a BusLogic Host Adapter. The I/O Address range will not be - released, thereby preventing it from being incorrectly identified as - any other type of Host Adapter. - */ - request_region(HostAdapter->IO_Address, BusLogic_IO_PortCount, - "BusLogic"); - /* - Register the SCSI Host structure. - */ - HostTemplate->proc_dir = &BusLogic_ProcDirectoryEntry; - Host = scsi_register(HostTemplate, sizeof(BusLogic_HostAdapter_T)); - HostAdapter = (BusLogic_HostAdapter_T *) Host->hostdata; - memcpy(HostAdapter, &HostAdapterPrototype, - sizeof(BusLogic_HostAdapter_T)); - HostAdapter->SCSI_Host = Host; - HostAdapter->HostNumber = Host->host_no; - /* - Add Host Adapter to the end of the list of registered BusLogic - Host Adapters. In order for Command Complete Interrupts to be - properly dismissed by BusLogic_InterruptHandler, the Host Adapter - must be registered. This must be done before the IRQ Channel is - acquired, and in a shared IRQ Channel environment, must be done - before any Command Complete Interrupts occur, since the IRQ Channel - may have already been acquired by a previous BusLogic Host Adapter. - */ - BusLogic_RegisterHostAdapter(HostAdapter); - /* - Read the Host Adapter Configuration, Acquire the System Resources - necessary to use Host Adapter and initialize the fields in the SCSI - Host structure, then Test Interrupts, Create the CCBs, Initialize - the Host Adapter, and finally Inquire about the Target Devices. - */ - if (BusLogic_ReadHostAdapterConfiguration(HostAdapter) && - BusLogic_AcquireResources(HostAdapter, Host) && - BusLogic_TestInterrupts(HostAdapter) && - BusLogic_CreateCCBs(HostAdapter) && - BusLogic_InitializeHostAdapter(HostAdapter) && - BusLogic_InquireTargetDevices(HostAdapter)) - { - /* - Initialization has been completed successfully. Release and - re-register usage of the I/O Address range so that the Model - Name of the Host Adapter will appear. - */ - release_region(HostAdapter->IO_Address, BusLogic_IO_PortCount); - request_region(HostAdapter->IO_Address, BusLogic_IO_PortCount, - HostAdapter->BoardName); - BusLogicHostAdapterCount++; - } - else - { - /* - An error occurred during Host Adapter Configuration Querying, - Resource Acquisition, Interrupt Testing, CCB Creation, Host - Adapter Initialization, or Target Device Inquiry, so remove - Host Adapter from the list of registered BusLogic Host Adapters, - destroy the CCBs, Release the System Resources, and Unregister - the SCSI Host. - */ - BusLogic_DestroyCCBs(HostAdapter); - BusLogic_ReleaseResources(HostAdapter); - BusLogic_UnregisterHostAdapter(HostAdapter); - scsi_unregister(Host); - } - } - return BusLogicHostAdapterCount; -} - - -/* - BusLogic_ReleaseHostAdapter releases all resources previously acquired to - support a specific Host Adapter, including the I/O Address range, and - unregisters the BusLogic Host Adapter. -*/ - -int BusLogic_ReleaseHostAdapter(SCSI_Host_T *Host) -{ - BusLogic_HostAdapter_T *HostAdapter = - (BusLogic_HostAdapter_T *) Host->hostdata; - /* - Destroy the CCBs and release any system resources acquired to use - Host Adapter. - */ - BusLogic_DestroyCCBs(HostAdapter); - BusLogic_ReleaseResources(HostAdapter); - /* - Release usage of the I/O Address range. - */ - release_region(HostAdapter->IO_Address, BusLogic_IO_PortCount); - /* - Remove Host Adapter from the list of registered BusLogic Host Adapters. - */ - BusLogic_UnregisterHostAdapter(HostAdapter); - return 0; -} - - -/* - BusLogic_ComputeResultCode computes a SCSI Subsystem Result Code from - the Host Adapter Status and Target Device Status. -*/ - -static int BusLogic_ComputeResultCode(BusLogic_HostAdapterStatus_T - HostAdapterStatus, - BusLogic_TargetDeviceStatus_T - TargetDeviceStatus) -{ - int HostStatus; - switch (HostAdapterStatus) - { - case BusLogic_CommandCompletedNormally: - case BusLogic_LinkedCommandCompleted: - case BusLogic_LinkedCommandCompletedWithFlag: - HostStatus = DID_OK; - break; - case BusLogic_SCSISelectionTimeout: - HostStatus = DID_TIME_OUT; - break; - case BusLogic_InvalidOutgoingMailboxActionCode: - case BusLogic_InvalidCommandOperationCode: - case BusLogic_InvalidCommandParameter: - printk("BusLogic: BusLogic Driver Protocol Error 0x%02X\n", - HostAdapterStatus); - case BusLogic_DataOverUnderRun: - case BusLogic_UnexpectedBusFree: - case BusLogic_LinkedCCBhasInvalidLUN: - case BusLogic_AutoRequestSenseFailed: - case BusLogic_TaggedQueuingMessageRejected: - case BusLogic_UnsupportedMessageReceived: - case BusLogic_HostAdapterHardwareFailed: - case BusLogic_TargetDeviceReconnectedImproperly: - case BusLogic_AbortQueueGenerated: - case BusLogic_HostAdapterSoftwareError: - case BusLogic_HostAdapterHardwareTimeoutError: - case BusLogic_SCSIParityErrorDetected: - HostStatus = DID_ERROR; - break; - case BusLogic_InvalidBusPhaseRequested: - case BusLogic_TargetFailedResponseToATN: - case BusLogic_HostAdapterAssertedRST: - case BusLogic_OtherDeviceAssertedRST: - case BusLogic_HostAdapterAssertedBusDeviceReset: - HostStatus = DID_RESET; - break; - default: - printk("BusLogic: unknown Host Adapter Status 0x%02X\n", - HostAdapterStatus); - HostStatus = DID_ERROR; - break; - } - return (HostStatus << 16) | TargetDeviceStatus; -} - - -/* - BusLogic_InterruptHandler handles hardware interrupts from BusLogic Host - Adapters. To simplify handling shared IRQ Channels, all installed BusLogic - Host Adapters are scanned whenever any one of them signals a hardware - interrupt. -*/ - -static void BusLogic_InterruptHandler(int IRQ_Channel, - Registers_T *InterruptRegisters) -{ - BusLogic_CCB_T *FirstCompletedCCB = NULL, *LastCompletedCCB = NULL; - BusLogic_HostAdapter_T *HostAdapter; - int HostAdapterResetPendingCount = 0; - /* - Iterate over the installed BusLogic Host Adapters accepting any Incoming - Mailbox entries and saving the completed CCBs for processing. This - interrupt handler is installed with SA_INTERRUPT, so interrupts are - disabled when the interrupt handler is entered. - */ - for (HostAdapter = BusLogic_RegisteredHostAdapters; - HostAdapter != NULL; - HostAdapter = HostAdapter->Next) - { - unsigned char InterruptRegister; - /* - Acquire exclusive access to Host Adapter. - */ - BusLogic_LockHostAdapterID(HostAdapter); - /* - Read the Host Adapter Interrupt Register. - */ - InterruptRegister = BusLogic_ReadInterruptRegister(HostAdapter); - if (InterruptRegister & BusLogic_InterruptValid) - { - /* - Acknowledge the interrupt and reset the Host Adapter - Interrupt Register. - */ - BusLogic_WriteControlRegister(HostAdapter, BusLogic_InterruptReset); - /* - Process valid SCSI Reset State and Incoming Mailbox Loaded - interrupts. Command Complete interrupts are noted, and - Outgoing Mailbox Available interrupts are ignored, as they - are never enabled. - */ - if (InterruptRegister & BusLogic_SCSIResetState) - { - HostAdapter->HostAdapterResetPending = true; - HostAdapterResetPendingCount++; - } - else if (InterruptRegister & BusLogic_IncomingMailboxLoaded) - { - /* - Scan through the Incoming Mailboxes in Strict Round Robin - fashion, saving any completed CCBs for further processing. - It is essential that for each CCB and SCSI Command issued, - command completion processing is performed exactly once. - Therefore, only Incoming Mailboxes with completion code - Command Completed Without Error, Command Completed With - Error, or Command Aborted At Host Request are saved for - completion processing. When an Incoming Mailbox has a - completion code of Aborted Command Not Found, the CCB had - already completed or been aborted before the current Abort - request was processed, and so completion processing has - already occurred and no further action should be taken. - */ - BusLogic_IncomingMailbox_T *NextIncomingMailbox = - HostAdapter->NextIncomingMailbox; - BusLogic_CompletionCode_T MailboxCompletionCode; - while ((MailboxCompletionCode = - NextIncomingMailbox->CompletionCode) != - BusLogic_IncomingMailboxFree) - { - BusLogic_CCB_T *CCB = NextIncomingMailbox->CCB; - if (MailboxCompletionCode != BusLogic_AbortedCommandNotFound) - if (CCB->Status == BusLogic_CCB_Active) - { - /* - Mark this CCB as completed and add it to the end - of the list of completed CCBs. - */ - CCB->Status = BusLogic_CCB_Completed; - CCB->MailboxCompletionCode = MailboxCompletionCode; - CCB->Next = NULL; - if (FirstCompletedCCB == NULL) - { - FirstCompletedCCB = CCB; - LastCompletedCCB = CCB; - } - else - { - LastCompletedCCB->Next = CCB; - LastCompletedCCB = CCB; - } - HostAdapter->QueuedOperationCount[CCB->TargetID]--; - } - else - { - /* - If a CCB ever appears in an Incoming Mailbox and - is not marked as status Active, then there is - most likely a bug in the Host Adapter firmware. - */ - printk("scsi%d: Illegal CCB #%d status %d in " - "Incoming Mailbox\n", HostAdapter->HostNumber, - CCB->SerialNumber, CCB->Status); - } - else printk("scsi%d: Aborted CCB #%d to Target %d " - "Not Found\n", HostAdapter->HostNumber, - CCB->SerialNumber, CCB->TargetID); - NextIncomingMailbox->CompletionCode = - BusLogic_IncomingMailboxFree; - if (++NextIncomingMailbox > HostAdapter->LastIncomingMailbox) - NextIncomingMailbox = HostAdapter->FirstIncomingMailbox; - } - HostAdapter->NextIncomingMailbox = NextIncomingMailbox; - } - else if (InterruptRegister & BusLogic_CommandComplete) - HostAdapter->HostAdapterCommandCompleted = true; - } - /* - Release exclusive access to Host Adapter. - */ - BusLogic_UnlockHostAdapterID(HostAdapter); - } - /* - Enable interrupts while the completed CCBs are processed. - */ - sti(); - /* - Iterate over the Host Adapters performing any pending Host Adapter Resets. - */ - if (HostAdapterResetPendingCount > 0) - for (HostAdapter = BusLogic_RegisteredHostAdapters; - HostAdapter != NULL; - HostAdapter = HostAdapter->Next) - if (HostAdapter->HostAdapterResetPending) - { - BusLogic_ResetHostAdapter(HostAdapter, NULL); - HostAdapter->HostAdapterResetPending = false; - scsi_mark_host_bus_reset(HostAdapter->SCSI_Host); - } - /* - Iterate over the completed CCBs setting the SCSI Command Result Codes, - deallocating the CCBs, and calling the Completion Routines. - */ - while (FirstCompletedCCB != NULL) - { - BusLogic_CCB_T *CCB = FirstCompletedCCB; - SCSI_Command_T *Command = CCB->Command; - FirstCompletedCCB = FirstCompletedCCB->Next; - HostAdapter = CCB->HostAdapter; - /* - Bus Device Reset CCBs have the Command field non-NULL only when a Bus - Device Reset was requested for a command that was not currently active - in the Host Adapter, and hence would not have its Completion Routine - called otherwise. - */ - if (CCB->Opcode == BusLogic_SCSIBusDeviceReset) - { - printk("scsi%d: Bus Device Reset CCB #%d to Target %d Completed\n", - HostAdapter->HostNumber, CCB->SerialNumber, CCB->TargetID); - if (Command != NULL) Command->result = DID_RESET << 16; - } - else - /* - Translate the Mailbox Completion Code, Host Adapter Status, and - Target Device Status into a SCSI Subsystem Result Code. - */ - switch (CCB->MailboxCompletionCode) - { - case BusLogic_IncomingMailboxFree: - case BusLogic_AbortedCommandNotFound: - printk("scsi%d: CCB #%d to Target %d Impossible State\n", - HostAdapter->HostNumber, CCB->SerialNumber, CCB->TargetID); - break; - case BusLogic_CommandCompletedWithoutError: - HostAdapter->CommandSuccessfulFlag[CCB->TargetID] = true; - Command->result = DID_OK << 16; - break; - case BusLogic_CommandAbortedAtHostRequest: - printk("scsi%d: CCB #%d to Target %d Aborted\n", - HostAdapter->HostNumber, CCB->SerialNumber, CCB->TargetID); - Command->result = DID_ABORT << 16; - break; - case BusLogic_CommandCompletedWithError: - Command->result = - BusLogic_ComputeResultCode(CCB->HostAdapterStatus, - CCB->TargetDeviceStatus); - if (BusLogic_GlobalOptions & BusLogic_TraceErrors) - if (CCB->HostAdapterStatus != BusLogic_SCSISelectionTimeout) - { - int i; - printk("scsi%d: CCB #%d Target %d: Result %X " - "Host Adapter Status %02X Target Status %02X\n", - HostAdapter->HostNumber, CCB->SerialNumber, - CCB->TargetID, Command->result, - CCB->HostAdapterStatus, CCB->TargetDeviceStatus); - printk("scsi%d: CDB ", HostAdapter->HostNumber); - for (i = 0; i < CCB->CDB_Length; i++) - printk(" %02X", CCB->CDB[i]); - printk("\n"); - printk("scsi%d: Sense ", HostAdapter->HostNumber); - for (i = 0; i < CCB->SenseDataLength; i++) - printk(" %02X", (*CCB->SenseDataPointer)[i]); - printk("\n"); - } - break; - } - /* - Place CCB back on the Host Adapter's free list. - */ - BusLogic_DeallocateCCB(CCB); - /* - Call the SCSI Command Completion Routine if appropriate. - */ - if (Command != NULL) Command->scsi_done(Command); - } -} - - -/* - BusLogic_WriteOutgoingMailbox places CCB and Action Code into an Outgoing - Mailbox for execution by Host Adapter. -*/ - -static boolean BusLogic_WriteOutgoingMailbox(BusLogic_HostAdapter_T - *HostAdapter, - BusLogic_ActionCode_T ActionCode, - BusLogic_CCB_T *CCB) -{ - BusLogic_OutgoingMailbox_T *NextOutgoingMailbox; - boolean Result = false; - BusLogic_LockHostAdapter(HostAdapter); - NextOutgoingMailbox = HostAdapter->NextOutgoingMailbox; - if (NextOutgoingMailbox->ActionCode == BusLogic_OutgoingMailboxFree) - { - CCB->Status = BusLogic_CCB_Active; - /* - The CCB field must be written before the Action Code field since - the Host Adapter is operating asynchronously and the locking code - does not protect against simultaneous access by the Host Adapter. - */ - NextOutgoingMailbox->CCB = CCB; - NextOutgoingMailbox->ActionCode = ActionCode; - BusLogic_StartMailboxScan(HostAdapter); - if (++NextOutgoingMailbox > HostAdapter->LastOutgoingMailbox) - NextOutgoingMailbox = HostAdapter->FirstOutgoingMailbox; - HostAdapter->NextOutgoingMailbox = NextOutgoingMailbox; - if (ActionCode == BusLogic_MailboxStartCommand) - HostAdapter->QueuedOperationCount[CCB->TargetID]++; - Result = true; - } - BusLogic_UnlockHostAdapter(HostAdapter); - return Result; -} - - -/* - BusLogic_QueueCommand creates a CCB for Command and places it into an - Outgoing Mailbox for execution by the associated Host Adapter. -*/ - -int BusLogic_QueueCommand(SCSI_Command_T *Command, - void (*CompletionRoutine)(SCSI_Command_T *)) -{ - BusLogic_HostAdapter_T *HostAdapter = - (BusLogic_HostAdapter_T *) Command->host->hostdata; - unsigned char *CDB = Command->cmnd; - unsigned char CDB_Length = Command->cmd_len; - unsigned char TargetID = Command->target; - unsigned char LogicalUnit = Command->lun; - void *BufferPointer = Command->request_buffer; - int BufferLength = Command->request_bufflen; - int SegmentCount = Command->use_sg; - BusLogic_CCB_T *CCB; - long EnableTQ; - /* - SCSI REQUEST_SENSE commands will be executed automatically by the Host - Adapter for any errors, so they should not be executed explicitly unless - the Sense Data is zero indicating that no error occurred. - */ - if (CDB[0] == REQUEST_SENSE && Command->sense_buffer[0] != 0) - { - Command->result = DID_OK << 16; - CompletionRoutine(Command); - return 0; - } - /* - Allocate a CCB from the Host Adapter's free list. If there are none - available and memory allocation fails, return a result code of Bus Busy - so that this Command will be retried. - */ - CCB = BusLogic_AllocateCCB(HostAdapter); - if (CCB == NULL) - { - Command->result = DID_BUS_BUSY << 16; - CompletionRoutine(Command); - return 0; - } - /* - Initialize the fields in the BusLogic Command Control Block (CCB). - */ - if (SegmentCount == 0) - { - CCB->Opcode = BusLogic_InitiatorCCB; - CCB->DataLength = BufferLength; - CCB->DataPointer = BufferPointer; - } - else - { - SCSI_ScatterList_T *ScatterList = (SCSI_ScatterList_T *) BufferPointer; - int Segment; - CCB->Opcode = BusLogic_InitiatorCCB_ScatterGather; - CCB->DataLength = SegmentCount * sizeof(BusLogic_ScatterGatherSegment_T); - CCB->DataPointer = CCB->ScatterGatherList; - for (Segment = 0; Segment < SegmentCount; Segment++) - { - CCB->ScatterGatherList[Segment].SegmentByteCount = - ScatterList[Segment].length; - CCB->ScatterGatherList[Segment].SegmentDataPointer = - ScatterList[Segment].address; - } - } - switch (CDB[0]) - { - case READ_6: - case READ_10: - CCB->DataDirection = BusLogic_DataInLengthChecked; - HostAdapter->ReadWriteOperationCount[TargetID]++; - break; - case WRITE_6: - case WRITE_10: - CCB->DataDirection = BusLogic_DataOutLengthChecked; - HostAdapter->ReadWriteOperationCount[TargetID]++; - break; - default: - CCB->DataDirection = BusLogic_UncheckedDataTransfer; - break; - } - CCB->CDB_Length = CDB_Length; - CCB->SenseDataLength = sizeof(Command->sense_buffer); - CCB->HostAdapterStatus = 0; - CCB->TargetDeviceStatus = 0; - CCB->TargetID = TargetID; - CCB->LogicalUnit = LogicalUnit; - /* - For Wide SCSI Host Adapters, Wide Mode CCBs are used to support more than - 8 Logical Units per Target, and this requires setting the overloaded - TagEnable field to Logical Unit bit 5. - */ - if (HostAdapter->HostWideSCSI) - { - CCB->TagEnable = LogicalUnit >> 5; - CCB->WideModeTagEnable = false; - } - else CCB->TagEnable = false; - /* - BusLogic recommends that after a Reset the first couple of commands that - are sent to a Target be sent in a non Tagged Queue fashion so that the Host - Adapter and Target can establish Synchronous Transfer before Queue Tag - messages can interfere with the Synchronous Negotiation message. By - waiting to enable tagged Queuing until after the first 16 read/write - commands have been sent, it is assured that the Tagged Queuing message - will not occur while the partition table is printed. - */ - if ((HostAdapter->TaggedQueuingPermitted & (1 << TargetID)) && - Command->device->tagged_supported && - (EnableTQ = HostAdapter->ReadWriteOperationCount[TargetID] - 16) >= 0) - { - BusLogic_QueueTag_T QueueTag = BusLogic_SimpleQueueTag; - unsigned long CurrentTime = jiffies; - if (EnableTQ == 0) - printk("scsi%d: Tagged Queuing now active for Target %d\n", - HostAdapter->HostNumber, TargetID); - /* - When using Tagged Queuing with Simple Queue Tags, it appears that disk - drive controllers do not guarantee that a queued command will not - remain in a disconnected state indefinitely if commands that read or - write nearer the head position continue to arrive without interruption. - Therefore, for each Target Device this driver keeps track of the last - time either the queue was empty or an Ordered Queue Tag was issued. If - more than 2 seconds have elapsed since this last sequence point, this - command will be issued with an Ordered Queue Tag rather than a Simple - Queue Tag, which forces the Target Device to complete all previously - queued commands before this command may be executed. - */ - if (HostAdapter->QueuedOperationCount[TargetID] == 0) - HostAdapter->LastSequencePoint[TargetID] = CurrentTime; - else if (CurrentTime - HostAdapter->LastSequencePoint[TargetID] > 2*HZ) - { - HostAdapter->LastSequencePoint[TargetID] = CurrentTime; - QueueTag = BusLogic_OrderedQueueTag; - } - if (HostAdapter->HostWideSCSI) - { - CCB->WideModeTagEnable = true; - CCB->WideModeQueueTag = QueueTag; - } - else - { - CCB->TagEnable = true; - CCB->QueueTag = QueueTag; - } - } - memcpy(CCB->CDB, CDB, CDB_Length); - CCB->SenseDataPointer = (SCSI_SenseData_T *) &Command->sense_buffer; - CCB->Command = Command; - Command->scsi_done = CompletionRoutine; - /* - Place the CCB in an Outgoing Mailbox. If there are no Outgoing - Mailboxes available, return a result code of Bus Busy so that this - Command will be retried. - */ - if (!(BusLogic_WriteOutgoingMailbox(HostAdapter, - BusLogic_MailboxStartCommand, CCB))) - { - printk("scsi%d: cannot write Outgoing Mailbox\n", - HostAdapter->HostNumber); - BusLogic_DeallocateCCB(CCB); - Command->result = DID_BUS_BUSY << 16; - CompletionRoutine(Command); - } - return 0; -} - - -/* - BusLogic_AbortCommand aborts Command if possible. -*/ - -int BusLogic_AbortCommand(SCSI_Command_T *Command) -{ - BusLogic_HostAdapter_T *HostAdapter = - (BusLogic_HostAdapter_T *) Command->host->hostdata; - unsigned long CommandPID = Command->pid; - unsigned char InterruptRegister; - BusLogic_CCB_T *CCB; - int Result; - /* - If the Host Adapter has posted an interrupt but the Interrupt Handler - has not been called for some reason (i.e. the interrupt was lost), try - calling the Interrupt Handler directly to process the commands that - have been completed. - */ - InterruptRegister = BusLogic_ReadInterruptRegister(HostAdapter); - if (InterruptRegister & BusLogic_InterruptValid) - { - unsigned long ProcessorFlags; - printk("scsi%d: Recovering Lost/Delayed Interrupt for IRQ Channel %d\n", - HostAdapter->HostNumber, HostAdapter->IRQ_Channel); - save_flags(ProcessorFlags); - cli(); - BusLogic_InterruptHandler(HostAdapter->IRQ_Channel, NULL); - restore_flags(ProcessorFlags); - return SCSI_ABORT_SNOOZE; - } - /* - Find the CCB to be aborted if possible. - */ - BusLogic_LockHostAdapter(HostAdapter); - for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll) - if (CCB->Command == Command) break; - BusLogic_UnlockHostAdapter(HostAdapter); - if (CCB == NULL) - { - printk("scsi%d: Unable to Abort Command to Target %d - No CCB Found\n", - HostAdapter->HostNumber, Command->target); - return SCSI_ABORT_NOT_RUNNING; - } - /* - Briefly pause to see if this command will complete. - */ - printk("scsi%d: Pausing briefly to see if CCB #%d " - "to Target %d will complete\n", - HostAdapter->HostNumber, CCB->SerialNumber, CCB->TargetID); - BusLogic_Delay(2); - /* - If this CCB is still Active and still refers to the same Command, then - actually aborting this Command is necessary. - */ - BusLogic_LockHostAdapter(HostAdapter); - Result = SCSI_ABORT_NOT_RUNNING; - if (CCB->Status == BusLogic_CCB_Active && - CCB->Command == Command && Command->pid == CommandPID) - { - /* - Attempt to abort this CCB. - */ - if (BusLogic_WriteOutgoingMailbox(HostAdapter, - BusLogic_MailboxAbortCommand, CCB)) - { - printk("scsi%d: Aborting CCB #%d to Target %d\n", - HostAdapter->HostNumber, CCB->SerialNumber, CCB->TargetID); - Result = SCSI_ABORT_PENDING; - } - else - { - printk("scsi%d: Unable to Abort CCB #%d to Target %d - " - "No Outgoing Mailboxes\n", HostAdapter->HostNumber, - CCB->SerialNumber, CCB->TargetID); - Result = SCSI_ABORT_BUSY; - } - } - else printk("scsi%d: CCB #%d to Target %d completed\n", - HostAdapter->HostNumber, CCB->SerialNumber, CCB->TargetID); - BusLogic_UnlockHostAdapter(HostAdapter); - return Result; -} - - -/* - BusLogic_ResetHostAdapter resets Host Adapter if possible, marking all - currently executing SCSI commands as having been reset, as well as - the specified Command if non-NULL. -*/ - -static int BusLogic_ResetHostAdapter(BusLogic_HostAdapter_T *HostAdapter, - SCSI_Command_T *Command) -{ - BusLogic_CCB_T *CCB; - if (Command == NULL) - printk("scsi%d: Resetting %s due to SCSI Reset State Interrupt\n", - HostAdapter->HostNumber, HostAdapter->BoardName); - else printk("scsi%d: Resetting %s due to Target %d\n", - HostAdapter->HostNumber, HostAdapter->BoardName, Command->target); - /* - Attempt to Reset and Reinitialize the Host Adapter. - */ - BusLogic_LockHostAdapter(HostAdapter); - if (!(BusLogic_HardResetHostAdapter(HostAdapter) && - BusLogic_InitializeHostAdapter(HostAdapter))) - { - printk("scsi%d: Resetting %s Failed\n", - HostAdapter->HostNumber, HostAdapter->BoardName); - BusLogic_UnlockHostAdapter(HostAdapter); - return SCSI_RESET_ERROR; - } - BusLogic_UnlockHostAdapter(HostAdapter); - /* - Wait a few seconds between the Host Adapter Hard Reset which initiates - a SCSI Bus Reset and issuing any SCSI commands. Some SCSI devices get - confused if they receive SCSI commands too soon after a SCSI Bus Reset. - */ - BusLogic_Delay(HostAdapter->BusSettleTime); - /* - Mark all currently executing CCBs as having been reset. - */ - BusLogic_LockHostAdapter(HostAdapter); - for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll) - if (CCB->Status == BusLogic_CCB_Active) - { - CCB->Status = BusLogic_CCB_Reset; - if (CCB->Command == Command) - { - CCB->Command = NULL; - /* - Disable Tagged Queuing if it was active for this Target Device. - */ - if (((HostAdapter->HostWideSCSI && CCB->WideModeTagEnable) || - (!HostAdapter->HostWideSCSI && CCB->TagEnable)) && - (HostAdapter->TaggedQueuingPermitted & (1 << CCB->TargetID))) - { - HostAdapter->TaggedQueuingPermitted &= ~(1 << CCB->TargetID); - printk("scsi%d: Tagged Queuing now disabled for Target %d\n", - HostAdapter->HostNumber, CCB->TargetID); - } - } - } - BusLogic_UnlockHostAdapter(HostAdapter); - /* - Perform completion processing for the Command being Reset. - */ - if (Command != NULL) - { - Command->result = DID_RESET << 16; - Command->scsi_done(Command); - } - /* - Perform completion processing for any other active CCBs. - */ - for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll) - if (CCB->Status == BusLogic_CCB_Reset) - { - Command = CCB->Command; - BusLogic_DeallocateCCB(CCB); - if (Command != NULL) - { - Command->result = DID_RESET << 16; - Command->scsi_done(Command); - } - } - return SCSI_RESET_SUCCESS | SCSI_RESET_BUS_RESET; -} - - -/* - BusLogic_BusDeviceReset sends a Bus Device Reset to the Target - associated with Command. -*/ - -static int BusLogic_BusDeviceReset(BusLogic_HostAdapter_T *HostAdapter, - SCSI_Command_T *Command) -{ - BusLogic_CCB_T *CCB = BusLogic_AllocateCCB(HostAdapter), *XCCB; - unsigned char TargetID = Command->target; - /* - If sending a Bus Device Reset is impossible, attempt a full Host - Adapter Hard Reset and SCSI Bus Reset. - */ - if (CCB == NULL) - return BusLogic_ResetHostAdapter(HostAdapter, Command); - printk("scsi%d: Sending Bus Device Reset CCB #%d to Target %d\n", - HostAdapter->HostNumber, CCB->SerialNumber, TargetID); - CCB->Opcode = BusLogic_SCSIBusDeviceReset; - CCB->TargetID = TargetID; - CCB->Command = Command; - /* - If there is a currently executing CCB in the Host Adapter for this Command, - then an Incoming Mailbox entry will be made with a completion code of - BusLogic_HostAdapterAssertedBusDeviceReset. Otherwise, the CCB's Command - field will be left pointing to the Command so that the interrupt for the - completion of the Bus Device Reset can call the Completion Routine for the - Command. - */ - BusLogic_LockHostAdapter(HostAdapter); - for (XCCB = HostAdapter->All_CCBs; XCCB != NULL; XCCB = XCCB->NextAll) - if (XCCB->Command == Command && XCCB->Status == BusLogic_CCB_Active) - { - CCB->Command = NULL; - /* - Disable Tagged Queuing if it was active for this Target Device. - */ - if (((HostAdapter->HostWideSCSI && XCCB->WideModeTagEnable) || - (!HostAdapter->HostWideSCSI && XCCB->TagEnable)) && - (HostAdapter->TaggedQueuingPermitted & (1 << TargetID))) - { - HostAdapter->TaggedQueuingPermitted &= ~(1 << TargetID); - printk("scsi%d: Tagged Queuing now disabled for Target %d\n", - HostAdapter->HostNumber, TargetID); - } - break; - } - BusLogic_UnlockHostAdapter(HostAdapter); - /* - Attempt to write an Outgoing Mailbox with the Bus Device Reset CCB. - If sending a Bus Device Reset is impossible, attempt a full Host - Adapter Hard Reset and SCSI Bus Reset. - */ - if (!(BusLogic_WriteOutgoingMailbox(HostAdapter, - BusLogic_MailboxStartCommand, CCB))) - { - printk("scsi%d: cannot write Outgoing Mailbox for Bus Device Reset\n", - HostAdapter->HostNumber); - BusLogic_DeallocateCCB(CCB); - return BusLogic_ResetHostAdapter(HostAdapter, Command); - } - HostAdapter->ReadWriteOperationCount[TargetID] = 0; - HostAdapter->QueuedOperationCount[TargetID] = 0; - return SCSI_RESET_PENDING; -} - - -/* - BusLogic_ResetCommand takes appropriate action to reset Command. -*/ - -int BusLogic_ResetCommand(SCSI_Command_T *Command) -{ - BusLogic_HostAdapter_T *HostAdapter = - (BusLogic_HostAdapter_T *) Command->host->hostdata; - unsigned char TargetID = Command->target; - unsigned char ErrorRecoveryOption = - HostAdapter->ErrorRecoveryOption[TargetID]; - if (ErrorRecoveryOption == BusLogic_ErrorRecoveryDefault) - if (Command->host->suggest_bus_reset) - ErrorRecoveryOption = BusLogic_ErrorRecoveryHardReset; - else ErrorRecoveryOption = BusLogic_ErrorRecoveryBusDeviceReset; - switch (ErrorRecoveryOption) - { - case BusLogic_ErrorRecoveryHardReset: - return BusLogic_ResetHostAdapter(HostAdapter, Command); - case BusLogic_ErrorRecoveryBusDeviceReset: - if (HostAdapter->CommandSuccessfulFlag[TargetID]) - { - HostAdapter->CommandSuccessfulFlag[TargetID] = false; - return BusLogic_BusDeviceReset(HostAdapter, Command); - } - else return BusLogic_ResetHostAdapter(HostAdapter, Command); - } - printk("scsi%d: Error Recovery for Target %d Suppressed\n", - HostAdapter->HostNumber, TargetID); - return SCSI_RESET_PUNT; -} - - -/* - BusLogic_BIOSDiskParameters returns the Heads/Sectors/Cylinders BIOS Disk - Parameters for Disk. The default disk geometry is 64 heads, 32 sectors, and - the appropriate number of cylinders so as not to exceed drive capacity. In - order for disks equal to or larger than 1 GB to be addressable by the BIOS - without exceeding the BIOS limitation of 1024 cylinders, Extended Translation - may be enabled in AutoSCSI on "C" Series boards or by a dip switch setting - on older boards. With Extended Translation enabled, drives between 1 GB - inclusive and 2 GB exclusive are given a disk geometry of 128 heads and 32 - sectors, and drives between 2 GB inclusive and 8 GB exclusive are given a - disk geometry of 255 heads and 63 sectors. On "C" Series boards the firmware - can be queried for the precise translation in effect for each drive - individually, but there is really no need to do so since we know the total - capacity of the drive and whether Extended Translation is enabled, hence we - can deduce the BIOS disk geometry that must be in effect. -*/ - -int BusLogic_BIOSDiskParameters(SCSI_Disk_T *Disk, KernelDevice_T Device, - int *Parameters) -{ - BusLogic_HostAdapter_T *HostAdapter = - (BusLogic_HostAdapter_T *) Disk->device->host->hostdata; - BIOS_DiskParameters_T *DiskParameters = (BIOS_DiskParameters_T *) Parameters; - if (HostAdapter->ExtendedTranslation && - Disk->capacity >= 2*1024*1024 /* 1 GB in 512 byte sectors */) - if (Disk->capacity >= 4*1024*1024 /* 2 GB in 512 byte sectors */) - { - DiskParameters->Heads = 255; - DiskParameters->Sectors = 63; - } - else - { - DiskParameters->Heads = 128; - DiskParameters->Sectors = 32; - } - else - { - DiskParameters->Heads = 64; - DiskParameters->Sectors = 32; - } - DiskParameters->Cylinders = - Disk->capacity / (DiskParameters->Heads * DiskParameters->Sectors); - return 0; -} - - -/* - BusLogic_Setup handles processing of Kernel Command Line Arguments. - - For the BusLogic driver, a kernel command line entry comprises the driver - identifier "BusLogic=" optionally followed by a comma-separated sequence of - integers and then optionally followed by a comma-separated sequence of - strings. Each command line entry applies to one BusLogic Host Adapter. - Multiple command line entries may be used in systems which contain multiple - BusLogic Host Adapters. - - The first integer specified is the I/O Address at which the Host Adapter is - located. If unspecified, it defaults to 0 which means to apply this entry to - the first BusLogic Host Adapter found during the default probe sequence. If - any I/O Address parameters are provided on the command line, then the default - probe sequence is omitted. - - The second integer specified is the number of Concurrent Commands per Logical - Unit to allow for Target Devices on the Host Adapter. If unspecified, it - defaults to 0 which means to use the value of BusLogic_Concurrency for - non-ISA Host Adapters, or BusLogic_Concurrency_ISA for ISA Host Adapters. - - The third integer specified is the Bus Settle Time in seconds. This is - the amount of time to wait between a Host Adapter Hard Reset which initiates - a SCSI Bus Reset and issuing any SCSI commands. If unspecified, it defaults - to 0 which means to use the value of BusLogic_DefaultBusSettleTime. - - The fourth integer specified is the Local Options. If unspecified, it - defaults to 0. Note that Local Options are only applied to a specific Host - Adapter. - - The fifth integer specified is the Global Options. If unspecified, it - defaults to 0. Note that Global Options are applied across all Host - Adapters. - - The string options are used to provide control over Tagged Queuing and Error - Recovery. If both Tagged Queuing and Error Recovery strings are provided, the - Tagged Queuing specification string must come first. - - The Tagged Queuing specification begins with "TQ:" and allows for explicitly - specifying whether Tagged Queuing is permitted on Target Devices that support - it. The following specification options are available: - - TQ:Default Tagged Queuing will be permitted based on the firmware - version of the BusLogic Host Adapter and based on - whether the Concurrency value allows queuing multiple - commands. - - TQ:Enable Tagged Queuing will be enabled for all Target Devices - on this Host Adapter overriding any limitation that - would otherwise be imposed based on the Host Adapter - firmware version. - - TQ:Disable Tagged Queuing will be disabled for all Target Devices - on this Host Adapter. - - TQ:<Per-Target-Spec> Tagged Queuing will be controlled individually for each - Target Device. <Per-Target-Spec> is a sequence of "Y", - "N", and "X" characters. "Y" enabled Tagged Queuing, - "N" disables Tagged Queuing, and "X" accepts the - default based on the firmware version. The first - character refers to Target 0, the second to Target 1, - and so on; if the sequence of "Y", "N", and "X" - characters does not cover all the Target Devices, - unspecified characters are assumed to be "X". - - Note that explicitly requesting Tagged Queuing may lead to problems; this - facility is provided primarily to allow disabling Tagged Queuing on Target - Devices that do not implement it correctly. - - The Error Recovery specification begins with "ER:" and allows for explicitly - specifying the Error Recovery action to be performed when ResetCommand is - called due to a SCSI Command failing to complete successfully. The following - specification options are available: - - ER:Default Error Recovery will select between the Hard Reset and - Bus Device Reset options based on the recommendation - of the SCSI Subsystem. - - ER:HardReset Error Recovery will initiate a Host Adapter Hard Reset - which also causes a SCSI Bus Reset. - - ER:BusDeviceReset Error Recovery will send a Bus Device Reset message to - the individual Target Device causing the error. If - Error Recovery is again initiated for this Target - Device and no SCSI Command to this Target Device has - completed successfully since the Bus Device Reset - message was sent, then a Hard Reset will be attempted. - - ER:None Error Recovery will be suppressed. This option should - only be selected if a SCSI Bus Reset or Bus Device - Reset will cause the Target Device to fail completely - and unrecoverably. - - ER:<Per-Target-Spec> Error Recovery will be controlled individually for each - Target Device. <Per-Target-Spec> is a sequence of "D", - "H", "B", and "N" characters. "D" selects Default, "H" - selects Hard Reset, "B" selects Bus Device Reset, and - "N" selects None. The first character refers to Target - 0, the second to Target 1, and so on; if the sequence - of "D", "H", "B", and "N" characters does not cover all - the Target Devices, unspecified characters are assumed - to be "D". -*/ - -void BusLogic_Setup(char *Strings, int *Integers) -{ - BusLogic_CommandLineEntry_T *CommandLineEntry = - &BusLogic_CommandLineEntries[BusLogic_CommandLineEntryCount++]; - static int ProbeListIndex = 0; - int IntegerCount = Integers[0], TargetID, i; - CommandLineEntry->IO_Address = 0; - CommandLineEntry->Concurrency = 0; - CommandLineEntry->BusSettleTime = 0; - CommandLineEntry->LocalOptions = 0; - CommandLineEntry->TaggedQueuingPermitted = 0; - CommandLineEntry->TaggedQueuingPermittedMask = 0; - memset(CommandLineEntry->ErrorRecoveryOption, - BusLogic_ErrorRecoveryDefault, - sizeof(CommandLineEntry->ErrorRecoveryOption)); - if (IntegerCount > 5) - printk("BusLogic: Unexpected Command Line Integers ignored\n"); - if (IntegerCount >= 1) - { - unsigned short IO_Address = Integers[1]; - if (IO_Address > 0) - { - for (i = 0; ; i++) - if (BusLogic_IO_StandardAddresses[i] == 0) - { - printk("BusLogic: Invalid Command Line Entry " - "(illegal I/O Address 0x%X)\n", IO_Address); - return; - } - else if (i < ProbeListIndex && - IO_Address == BusLogic_IO_AddressProbeList[i]) - { - printk("BusLogic: Invalid Command Line Entry " - "(duplicate I/O Address 0x%X)\n", IO_Address); - return; - } - else if (IO_Address >= 0x1000 || - IO_Address == BusLogic_IO_StandardAddresses[i]) break; - BusLogic_IO_AddressProbeList[ProbeListIndex++] = IO_Address; - BusLogic_IO_AddressProbeList[ProbeListIndex] = 0; - } - CommandLineEntry->IO_Address = IO_Address; - } - if (IntegerCount >= 2) - { - unsigned short Concurrency = Integers[2]; - if (Concurrency > BusLogic_MailboxCount) - { - printk("BusLogic: Invalid Command Line Entry " - "(illegal Concurrency %d)\n", Concurrency); - return; - } - CommandLineEntry->Concurrency = Concurrency; - } - if (IntegerCount >= 3) - CommandLineEntry->BusSettleTime = Integers[3]; - if (IntegerCount >= 4) - CommandLineEntry->LocalOptions = Integers[4]; - if (IntegerCount >= 5) - BusLogic_GlobalOptions |= Integers[5]; - if (!(BusLogic_CommandLineEntryCount == 0 || ProbeListIndex == 0 || - BusLogic_CommandLineEntryCount == ProbeListIndex)) - { - printk("BusLogic: Invalid Command Line Entry " - "(all or no I/O Addresses must be specified)\n"); - return; - } - if (Strings == NULL) return; - if (strncmp(Strings, "TQ:", 3) == 0) - { - Strings += 3; - if (strncmp(Strings, "Default", 7) == 0) - Strings += 7; - else if (strncmp(Strings, "Enable", 6) == 0) - { - Strings += 6; - CommandLineEntry->TaggedQueuingPermitted = 0xFFFF; - CommandLineEntry->TaggedQueuingPermittedMask = 0xFFFF; - } - else if (strncmp(Strings, "Disable", 7) == 0) - { - Strings += 7; - CommandLineEntry->TaggedQueuingPermitted = 0x0000; - CommandLineEntry->TaggedQueuingPermittedMask = 0xFFFF; - } - else - for (TargetID = 0; TargetID < BusLogic_MaxTargetIDs; TargetID++) - switch (*Strings++) - { - case 'Y': - CommandLineEntry->TaggedQueuingPermitted |= 1 << TargetID; - CommandLineEntry->TaggedQueuingPermittedMask |= 1 << TargetID; - break; - case 'N': - CommandLineEntry->TaggedQueuingPermittedMask |= 1 << TargetID; - break; - case 'X': - break; - default: - Strings--; - TargetID = BusLogic_MaxTargetIDs; - break; - } - } - if (*Strings == ',') Strings++; - if (strncmp(Strings, "ER:", 3) == 0) - { - Strings += 3; - if (strncmp(Strings, "Default", 7) == 0) - Strings += 7; - else if (strncmp(Strings, "HardReset", 9) == 0) - { - Strings += 9; - memset(CommandLineEntry->ErrorRecoveryOption, - BusLogic_ErrorRecoveryHardReset, - sizeof(CommandLineEntry->ErrorRecoveryOption)); - } - else if (strncmp(Strings, "BusDeviceReset", 14) == 0) - { - Strings += 14; - memset(CommandLineEntry->ErrorRecoveryOption, - BusLogic_ErrorRecoveryBusDeviceReset, - sizeof(CommandLineEntry->ErrorRecoveryOption)); - } - else if (strncmp(Strings, "None", 4) == 0) - { - Strings += 4; - memset(CommandLineEntry->ErrorRecoveryOption, - BusLogic_ErrorRecoveryNone, - sizeof(CommandLineEntry->ErrorRecoveryOption)); - } - else - for (TargetID = 0; TargetID < BusLogic_MaxTargetIDs; TargetID++) - switch (*Strings++) - { - case 'D': - CommandLineEntry->ErrorRecoveryOption[TargetID] = - BusLogic_ErrorRecoveryDefault; - break; - case 'H': - CommandLineEntry->ErrorRecoveryOption[TargetID] = - BusLogic_ErrorRecoveryHardReset; - break; - case 'B': - CommandLineEntry->ErrorRecoveryOption[TargetID] = - BusLogic_ErrorRecoveryBusDeviceReset; - break; - case 'N': - CommandLineEntry->ErrorRecoveryOption[TargetID] = - BusLogic_ErrorRecoveryNone; - break; - default: - Strings--; - TargetID = BusLogic_MaxTargetIDs; - break; - } - } - if (*Strings != '\0') - printk("BusLogic: Unexpected Command Line String '%s' ignored\n", Strings); -} - - -/* - Include Module support if requested. -*/ - - -#ifdef MODULE - -SCSI_Host_Template_T driver_template = BUSLOGIC; - -#include "scsi_module.c" - -#endif diff --git a/i386/i386at/gpl/linux/scsi/BusLogic.h b/i386/i386at/gpl/linux/scsi/BusLogic.h deleted file mode 100644 index 69048e9f..00000000 --- a/i386/i386at/gpl/linux/scsi/BusLogic.h +++ /dev/null @@ -1,977 +0,0 @@ -/* - - Linux Driver for BusLogic MultiMaster SCSI Host Adapters - - Copyright 1995 by Leonard N. Zubkoff <lnz@dandelion.com> - - See BusLogic.c for licensing information. - -*/ - - -/* - Define types for some of the structures that interface with the rest - of the Linux Kernel and SCSI Subsystem. -*/ - -typedef struct pt_regs Registers_T; -typedef Scsi_Host_Template SCSI_Host_Template_T; -typedef struct Scsi_Host SCSI_Host_T; -typedef struct scsi_disk SCSI_Disk_T; -typedef struct scsi_cmnd SCSI_Command_T; -typedef struct scatterlist SCSI_ScatterList_T; -typedef kdev_t KernelDevice_T; - - -/* - Define prototypes for the BusLogic Driver Interface Functions. -*/ - -const char *BusLogic_DriverInfo(SCSI_Host_T *); -int BusLogic_DetectHostAdapter(SCSI_Host_Template_T *); -int BusLogic_ReleaseHostAdapter(SCSI_Host_T *); -int BusLogic_QueueCommand(SCSI_Command_T *, - void (*CompletionRoutine)(SCSI_Command_T *)); -int BusLogic_AbortCommand(SCSI_Command_T *); -int BusLogic_ResetCommand(SCSI_Command_T *); -int BusLogic_BIOSDiskParameters(SCSI_Disk_T *, KernelDevice_T, int *); - - -/* - Define the BusLogic SCSI Host Template structure. -*/ - -#define BUSLOGIC \ - { NULL, /* Next */ \ - NULL, /* Usage Count Pointer */ \ - NULL, /* /proc Directory Entry */ \ - NULL, /* /proc Info Function */ \ - "BusLogic", /* Driver Name */ \ - BusLogic_DetectHostAdapter, /* Detect Host Adapter */ \ - BusLogic_ReleaseHostAdapter, /* Release Host Adapter */ \ - BusLogic_DriverInfo, /* Driver Info Function */ \ - NULL, /* Command Function */ \ - BusLogic_QueueCommand, /* Queue Command Function */ \ - BusLogic_AbortCommand, /* Abort Command Function */ \ - BusLogic_ResetCommand, /* Reset Command Function */ \ - NULL, /* Slave Attach Function */ \ - BusLogic_BIOSDiskParameters, /* Disk BIOS Parameters */ \ - 0, /* Can Queue */ \ - 0, /* This ID */ \ - 0, /* Scatter/Gather Table Size */ \ - 0, /* SCSI Commands per LUN */ \ - 0, /* Present */ \ - 1, /* Default Unchecked ISA DMA */ \ - ENABLE_CLUSTERING } /* Enable Clustering */ - - -/* - BusLogic_DriverVersion protects the private portion of this file. -*/ - -#ifdef BusLogic_DriverVersion - - -/* - Define the maximum number of BusLogic Host Adapters that are supported. -*/ - -#define BusLogic_MaxHostAdapters 10 - - -/* - Define the maximum number of I/O Addresses that may be probed. -*/ - -#define BusLogic_IO_MaxProbeAddresses 16 - - -/* - Define the maximum number of Target IDs supported by this driver. -*/ - -#define BusLogic_MaxTargetIDs 16 - - -/* - Define the number of Incoming and Outgoing Mailboxes used by this driver. - The maximum possible value is 255, since the MailboxCount parameter to the - Initialize Extended Mailbox command is limited to a single byte. -*/ - -#define BusLogic_MailboxCount 64 - - -/* - Define the number of Command Control Blocks (CCBs) to create during - initialization for each Host Adapter. Additional CCBs will be allocated - if necessary as commands are queued. -*/ - -#define BusLogic_InitialCCBs 32 - - -/* - Define the maximum number of Scatter/Gather Segments used by this driver. - For maximum performance, it is important that this limit be at least as - large as the maximum single request generated by the routine make_request. -*/ - -#define BusLogic_ScatterGatherLimit 128 - - -/* - Define the default number of Concurrent Commands per Logical Unit to allow - for Target Devices depending on whether or not ISA bounce buffers are - required. -*/ - -#define BusLogic_Concurrency 7 -#define BusLogic_Concurrency_BB 1 - - -/* - Define the default amount of time in seconds to wait between a Host Adapter - Hard Reset which initiates a SCSI Bus Reset and issuing any SCSI commands. - Some SCSI devices get confused if they receive SCSI commands too soon after - a SCSI Bus Reset. -*/ - -#define BusLogic_DefaultBusSettleTime 2 - - -/* - Define the possible Local Options. -*/ - -#define BusLogic_InhibitTargetInquiry 1 - - -/* - Define the possible Global Options. -*/ - -#define BusLogic_TraceProbe 1 -#define BusLogic_TraceHardReset 2 -#define BusLogic_TraceConfiguration 4 -#define BusLogic_TraceErrors 8 - - -/* - Define the possible Error Recovery Options. -*/ - -#define BusLogic_ErrorRecoveryDefault 0 -#define BusLogic_ErrorRecoveryHardReset 1 -#define BusLogic_ErrorRecoveryBusDeviceReset 2 -#define BusLogic_ErrorRecoveryNone 3 - -static char - *BusLogic_ErrorRecoveryOptions[] = - { "Default", "Hard Reset", "Bus Device Reset", "None" }, - *BusLogic_ErrorRecoveryOptions2[] = - { "D", "H", "B", "N" }; - - -/* - Define a boolean data type. -*/ - -#define false 0 -#define true 1 -typedef unsigned char boolean; - - -/* - Define the BusLogic SCSI Host Adapter I/O Register Offsets. -*/ - -#define BusLogic_IO_PortCount 4 /* I/O Registers */ -#define BusLogic_ControlRegister 0 /* WO register */ -#define BusLogic_StatusRegister 0 /* RO register */ -#define BusLogic_CommandParameterRegister 1 /* WO register */ -#define BusLogic_DataInRegister 1 /* RO register */ -#define BusLogic_InterruptRegister 2 /* RO register */ -#define BusLogic_GeometryRegister 3 /* RO, undocumented */ - - -/* - Define the bits in the write-only Control Register. -*/ - -#define BusLogic_ReservedCR 0x0F -#define BusLogic_SCSIBusReset 0x10 -#define BusLogic_InterruptReset 0x20 -#define BusLogic_SoftReset 0x40 -#define BusLogic_HardReset 0x80 - - -/* - Define the bits in the read-only Status Register. -*/ - -#define BusLogic_CommandInvalid 0x01 -#define BusLogic_ReservedSR 0x02 -#define BusLogic_DataInRegisterReady 0x04 -#define BusLogic_CommandParameterRegisterBusy 0x08 -#define BusLogic_HostAdapterReady 0x10 -#define BusLogic_InitializationRequired 0x20 -#define BusLogic_DiagnosticFailure 0x40 -#define BusLogic_DiagnosticActive 0x80 - - -/* - Define the bits in the read-only Interrupt Register. -*/ - -#define BusLogic_IncomingMailboxLoaded 0x01 -#define BusLogic_OutgoingMailboxAvailable 0x02 -#define BusLogic_CommandComplete 0x04 -#define BusLogic_SCSIResetState 0x08 -#define BusLogic_ReservedIR 0x70 -#define BusLogic_InterruptValid 0x80 - - -/* - Define the bits in the undocumented read-only Geometry Register. -*/ - -#define BusLogic_Drive0Geometry 0x03 -#define BusLogic_Drive1Geometry 0x0C -#define BusLogic_ReservedGR 0x70 -#define BusLogic_ExtendedTranslationEnabled 0x80 - - -/* - Define the BusLogic SCSI Host Adapter Command Register Operation Codes. -*/ - -typedef enum -{ - BusLogic_TestCommandCompleteInterrupt = 0x00, /* documented */ - BusLogic_InitializeMailbox = 0x01, /* documented */ - BusLogic_StartMailboxCommand = 0x02, /* documented */ - BusLogic_StartBIOSCommand = 0x03, /* documented */ - BusLogic_InquireBoardID = 0x04, /* documented */ - BusLogic_EnableOutgoingMailboxAvailableIRQ = 0x05, /* documented */ - BusLogic_SetSCSISelectionTimeout = 0x06, /* documented */ - BusLogic_SetPreemptTimeOnBus = 0x07, /* documented */ - BusLogic_SetTimeOffBus = 0x08, /* ISA Bus only */ - BusLogic_SetBusTransferRate = 0x09, /* ISA Bus only */ - BusLogic_InquireInstalledDevicesID0to7 = 0x0A, /* documented */ - BusLogic_InquireConfiguration = 0x0B, /* documented */ - BusLogic_SetTargetMode = 0x0C, /* now undocumented */ - BusLogic_InquireSetupInformation = 0x0D, /* documented */ - BusLogic_WriteAdapterLocalRAM = 0x1A, /* documented */ - BusLogic_ReadAdapterLocalRAM = 0x1B, /* documented */ - BusLogic_WriteBusMasterChipFIFO = 0x1C, /* documented */ - BusLogic_ReadBusMasterChipFIFO = 0x1D, /* documented */ - BusLogic_EchoCommandData = 0x1F, /* documented */ - BusLogic_HostAdapterDiagnostic = 0x20, /* documented */ - BusLogic_SetAdapterOptions = 0x21, /* documented */ - BusLogic_InquireInstalledDevicesID8to15 = 0x23, /* Wide only */ - BusLogic_InitializeExtendedMailbox = 0x81, /* documented */ - BusLogic_InquireFirmwareVersion3rdDigit = 0x84, /* undocumented */ - BusLogic_InquireFirmwareVersionLetter = 0x85, /* undocumented */ - BusLogic_InquireBoardModelNumber = 0x8B, /* undocumented */ - BusLogic_InquireSynchronousPeriod = 0x8C, /* undocumented */ - BusLogic_InquireExtendedSetupInformation = 0x8D, /* documented */ - BusLogic_EnableStrictRoundRobinMode = 0x8F, /* documented */ - BusLogic_ModifyIOAddress = 0x95, /* PCI only */ - BusLogic_EnableWideModeCCB = 0x96 /* Wide only */ -} -BusLogic_OperationCode_T; - - -/* - Define the Inquire Board ID reply structure. -*/ - -typedef struct BusLogic_BoardID -{ - unsigned char BoardType; - unsigned char CustomFeatures; - unsigned char FirmwareVersion1stDigit; - unsigned char FirmwareVersion2ndDigit; -} -BusLogic_BoardID_T; - - -/* - Define the Inquire Installed Devices ID 0 to 7 and Inquire Installed - Devices ID 8 to 15 reply type. For each Target ID, a byte is returned - where bit 0 set indicates that Logical Unit 0 exists, bit 1 set indicates - that Logical Unit 1 exists, and so on. -*/ - -typedef unsigned char BusLogic_InstalledDevices8_T[8]; - -typedef unsigned char BusLogic_InstalledDevices_T[BusLogic_MaxTargetIDs]; - - -/* - Define the Inquire Configuration reply structure. -*/ - -typedef struct BusLogic_Configuration -{ - unsigned char :5; /* Byte 0: DMA Channel */ - boolean DMA_Channel5:1; - boolean DMA_Channel6:1; - boolean DMA_Channel7:1; - boolean IRQ_Channel9:1; /* Byte 1: IRQ Channel */ - boolean IRQ_Channel10:1; - boolean IRQ_Channel11:1; - boolean IRQ_Channel12:1; - unsigned char :1; - boolean IRQ_Channel14:1; - boolean IRQ_Channel15:1; - unsigned char :1; - unsigned char HostAdapterID:4; /* Byte 2: Host Adapter ID */ - unsigned char :4; -} -BusLogic_Configuration_T; - - -/* - Define the Inquire Setup Information reply structure. -*/ - -typedef struct BusLogic_SynchronousValue -{ - unsigned char Offset:4; - unsigned char TransferPeriod:3; - boolean Synchronous:1; -} -BusLogic_SynchronousValue_T; - -typedef BusLogic_SynchronousValue_T - BusLogic_SynchronousValues8_T[8]; - -typedef BusLogic_SynchronousValue_T - BusLogic_SynchronousValues_T[BusLogic_MaxTargetIDs]; - -typedef struct BusLogic_SetupInformation -{ - boolean SynchronousInitiationEnabled:1; /* Byte 0 */ - boolean ParityCheckEnabled:1; - unsigned char :6; - unsigned char BusTransferRate; /* Byte 1 */ - unsigned char PreemptTimeOnBus; /* Byte 2 */ - unsigned char TimeOffBus; /* Byte 3 */ - unsigned char MailboxCount; /* Byte 4 */ - unsigned char MailboxAddress[3]; /* Bytes 5-7 */ - BusLogic_SynchronousValues8_T SynchronousValuesID0to7; /* Bytes 8-15 */ - unsigned char DisconnectPermittedID0to7; /* Byte 16 */ - unsigned char Signature; /* Byte 17 */ - unsigned char CharacterD; /* Byte 18 */ - unsigned char BusLetter; /* Byte 19 */ - unsigned char :8; /* Byte 20 */ - unsigned char :8; /* Byte 21 */ - BusLogic_SynchronousValues8_T SynchronousValuesID8to15; /* Bytes 22-29 */ - unsigned char DisconnectPermittedID8to15; /* Byte 30 */ -} -BusLogic_SetupInformation_T; - - -/* - Define the Initialize Extended Mailbox request structure. -*/ - -typedef struct BusLogic_ExtendedMailboxRequest -{ - unsigned char MailboxCount; - void *BaseMailboxAddress __attribute__ ((packed)); -} -BusLogic_ExtendedMailboxRequest_T; - - -/* - Define the Inquire Firmware Version 3rd Digit reply type. -*/ - -typedef unsigned char BusLogic_FirmwareVersion3rdDigit_T; - - -/* - Define the Inquire Firmware Version Letter reply type. -*/ - -typedef unsigned char BusLogic_FirmwareVersionLetter_T; - - -/* - Define the Inquire Board Model Number reply type. -*/ - -typedef unsigned char BusLogic_BoardModelNumber_T[5]; - - -/* - Define the Inquire Synchronous Period reply type. For each Target ID, a byte - is returned which represents the Synchronous Transfer Period in units of 10 - nanoseconds. -*/ - -typedef unsigned char BusLogic_SynchronousPeriod_T[BusLogic_MaxTargetIDs]; - - -/* - Define the Inquire Extended Setup Information reply structure. -*/ - -typedef struct BusLogic_ExtendedSetupInformation -{ - unsigned char BusType; /* Byte 0 */ - unsigned char BIOS_Address; /* Byte 1 */ - unsigned short ScatterGatherLimit; /* Bytes 2-3 */ - unsigned char MailboxCount; /* Byte 4 */ - void *BaseMailboxAddress __attribute__ ((packed)); /* Bytes 5-8 */ - struct { unsigned char :6; /* Byte 9 */ - boolean LevelSensitiveInterrupts:1; - unsigned char :1; } Misc; - unsigned char FirmwareRevision[3]; /* Bytes 10-12 */ - boolean HostWideSCSI:1; /* Byte 13 Bit 0 */ - boolean HostDifferentialSCSI:1; /* Byte 13 Bit 1 */ - unsigned char :6; -} -BusLogic_ExtendedSetupInformation_T; - - -/* - Define the Enable Strict Round Robin Mode request type. -*/ - -#define BusLogic_AggressiveRoundRobinMode 0x00 -#define BusLogic_StrictRoundRobinMode 0x01 - -typedef unsigned char BusLogic_RoundRobinModeRequest_T; - - -/* - Define the Modify I/O Address request type. On PCI Host Adapters, the - Modify I/O Address command allows modification of the ISA compatible I/O - Address that the Host Adapter responds to; it does not affect the PCI - compliant I/O Address assigned at system initialization. -*/ - -#define BusLogic_ModifyIO_330 0x00 -#define BusLogic_ModifyIO_334 0x01 -#define BusLogic_ModifyIO_230 0x02 -#define BusLogic_ModifyIO_234 0x03 -#define BusLogic_ModifyIO_130 0x04 -#define BusLogic_ModifyIO_134 0x05 -#define BusLogic_ModifyIO_Disable 0x06 -#define BusLogic_ModifyIO_Disable2 0x07 - -typedef unsigned char BusLogic_ModifyIOAddressRequest_T; - - -/* - Define the Enable Wide Mode SCSI CCB request type. Wide Mode CCBs are - necessary to support more than 8 Logical Units per Target. -*/ - -#define BusLogic_NormalModeCCB 0x00 -#define BusLogic_WideModeCCB 0x01 - -typedef unsigned char BusLogic_WideModeCCBRequest_T; - - -/* - Define the Requested Reply Length type used by the Inquire Setup Information, - Inquire Board Model Number, Inquire Synchronous Period, and Inquire Extended - Setup Information commands. -*/ - -typedef unsigned char BusLogic_RequestedReplyLength_T; - - -/* - Define a Lock data structure. Until a true symmetric multiprocessing kernel - is available, locking is implemented as saving the processor flags and - disabling interrupts, and unlocking restores the saved processor flags. -*/ - -typedef unsigned long BusLogic_Lock_T; - - -/* - Define the Outgoing Mailbox Action Codes. -*/ - -typedef enum -{ - BusLogic_OutgoingMailboxFree = 0, - BusLogic_MailboxStartCommand = 1, - BusLogic_MailboxAbortCommand = 2 -} -BusLogic_ActionCode_T; - - -/* - Define the Incoming Mailbox Completion Codes. -*/ - -typedef enum -{ - BusLogic_IncomingMailboxFree = 0, - BusLogic_CommandCompletedWithoutError = 1, - BusLogic_CommandAbortedAtHostRequest = 2, - BusLogic_AbortedCommandNotFound = 3, - BusLogic_CommandCompletedWithError = 4 -} -BusLogic_CompletionCode_T; - - -/* - Define the Command Control Block (CCB) Opcodes. -*/ - -typedef enum -{ - BusLogic_InitiatorCCB = 0x00, - BusLogic_TargetCCB = 0x01, - BusLogic_InitiatorCCB_ScatterGather = 0x02, - BusLogic_InitiatorCCB_ResidualDataLength = 0x03, - BusLogic_InitiatorCCB_ScatterGatherResidual = 0x04, - BusLogic_SCSIBusDeviceReset = 0x81 -} -BusLogic_CCB_Opcode_T; - - -/* - Define the CCB Data Direction Codes. -*/ - -typedef enum -{ - BusLogic_UncheckedDataTransfer = 0x00, - BusLogic_DataInLengthChecked = 0x01, - BusLogic_DataOutLengthChecked = 0x02, - BusLogic_NoDataTransfer = 0x03 -} -BusLogic_DataDirection_T; - - -/* - Define the Host Adapter Status Codes. -*/ - -typedef enum -{ - BusLogic_CommandCompletedNormally = 0x00, - BusLogic_LinkedCommandCompleted = 0x0A, - BusLogic_LinkedCommandCompletedWithFlag = 0x0B, - BusLogic_SCSISelectionTimeout = 0x11, - BusLogic_DataOverUnderRun = 0x12, - BusLogic_UnexpectedBusFree = 0x13, - BusLogic_InvalidBusPhaseRequested = 0x14, - BusLogic_InvalidOutgoingMailboxActionCode = 0x15, - BusLogic_InvalidCommandOperationCode = 0x16, - BusLogic_LinkedCCBhasInvalidLUN = 0x17, - BusLogic_InvalidCommandParameter = 0x1A, - BusLogic_AutoRequestSenseFailed = 0x1B, - BusLogic_TaggedQueuingMessageRejected = 0x1C, - BusLogic_UnsupportedMessageReceived = 0x1D, - BusLogic_HostAdapterHardwareFailed = 0x20, - BusLogic_TargetFailedResponseToATN = 0x21, - BusLogic_HostAdapterAssertedRST = 0x22, - BusLogic_OtherDeviceAssertedRST = 0x23, - BusLogic_TargetDeviceReconnectedImproperly = 0x24, - BusLogic_HostAdapterAssertedBusDeviceReset = 0x25, - BusLogic_AbortQueueGenerated = 0x26, - BusLogic_HostAdapterSoftwareError = 0x27, - BusLogic_HostAdapterHardwareTimeoutError = 0x30, - BusLogic_SCSIParityErrorDetected = 0x34 -} -BusLogic_HostAdapterStatus_T; - - -/* - Define the SCSI Target Device Status Codes. -*/ - -typedef enum -{ - BusLogic_OperationGood = 0x00, - BusLogic_CheckCondition = 0x02, - BusLogic_DeviceBusy = 0x08 -} -BusLogic_TargetDeviceStatus_T; - - -/* - Define the Queue Tag Codes. -*/ - -typedef enum -{ - BusLogic_SimpleQueueTag = 0x00, - BusLogic_HeadOfQueueTag = 0x01, - BusLogic_OrderedQueueTag = 0x02, - BusLogic_ReservedQT = 0x03 -} -BusLogic_QueueTag_T; - - -/* - Define the SCSI Command Descriptor Block (CDB). -*/ - -#define BusLogic_CDB_MaxLength 12 - -typedef unsigned char SCSI_CDB_T[BusLogic_CDB_MaxLength]; - - -/* - Define the SCSI Sense Data. -*/ - -#define BusLogic_SenseDataMaxLength 255 - -typedef unsigned char SCSI_SenseData_T[BusLogic_SenseDataMaxLength]; - - -/* - Define the Scatter/Gather Segment structure required by the Host Adapter - Firmware Interface. -*/ - -typedef struct BusLogic_ScatterGatherSegment -{ - unsigned long SegmentByteCount; - void *SegmentDataPointer; -} -BusLogic_ScatterGatherSegment_T; - - -/* - Define the 32 Bit Mode Command Control Block (CCB) structure. The first 40 - bytes are defined by the Host Adapter Firmware Interface. The remaining - components are defined by the Linux BusLogic Driver. Wide Mode CCBs differ - from standard 32 Bit Mode CCBs only in having the TagEnable and QueueTag - fields moved from byte 17 to byte 1, and the Logical Unit field in byte 17 - expanded to 6 bits; unfortunately, using a union of structs containing - enumeration type bitfields to provide both definitions leads to packing - problems, so the following definition is used which requires setting - TagEnable to Logical Unit bit 5 in Wide Mode CCBs. -*/ - -typedef struct BusLogic_CCB -{ - /* - BusLogic Host Adapter Firmware Portion. - */ - BusLogic_CCB_Opcode_T Opcode:8; /* Byte 0 */ - unsigned char :3; /* Byte 1 Bits 0-2 */ - BusLogic_DataDirection_T DataDirection:2; /* Byte 1 Bits 3-4 */ - boolean WideModeTagEnable:1; /* Byte 1 Bit 5 */ - BusLogic_QueueTag_T WideModeQueueTag:2; /* Byte 1 Bits 6-7 */ - unsigned char CDB_Length; /* Byte 2 */ - unsigned char SenseDataLength; /* Byte 3 */ - unsigned long DataLength; /* Bytes 4-7 */ - void *DataPointer; /* Bytes 8-11 */ - unsigned char :8; /* Byte 12 */ - unsigned char :8; /* Byte 13 */ - BusLogic_HostAdapterStatus_T HostAdapterStatus:8; /* Byte 14 */ - BusLogic_TargetDeviceStatus_T TargetDeviceStatus:8; /* Byte 15 */ - unsigned char TargetID; /* Byte 16 */ - unsigned char LogicalUnit:5; /* Byte 17 Bits 0-4 */ - boolean TagEnable:1; /* Byte 17 Bit 5 */ - BusLogic_QueueTag_T QueueTag:2; /* Byte 17 Bits 6-7 */ - SCSI_CDB_T CDB; /* Bytes 18-29 */ - unsigned char :8; /* Byte 30 */ - unsigned char :8; /* Byte 31 */ - unsigned long :32; /* Bytes 32-35 */ - SCSI_SenseData_T *SenseDataPointer; /* Bytes 36-39 */ - /* - BusLogic Linux Driver Portion. - */ - struct BusLogic_HostAdapter *HostAdapter; - SCSI_Command_T *Command; - enum { BusLogic_CCB_Free = 0, - BusLogic_CCB_Active = 1, - BusLogic_CCB_Completed = 2, - BusLogic_CCB_Reset = 3 } Status; - BusLogic_CompletionCode_T MailboxCompletionCode; - unsigned int SerialNumber; - struct BusLogic_CCB *Next; - struct BusLogic_CCB *NextAll; - BusLogic_ScatterGatherSegment_T - ScatterGatherList[BusLogic_ScatterGatherLimit]; -} -BusLogic_CCB_T; - - -/* - Define the 32 Bit Mode Outgoing Mailbox structure. -*/ - -typedef struct BusLogic_OutgoingMailbox -{ - BusLogic_CCB_T *CCB; - unsigned long :24; - BusLogic_ActionCode_T ActionCode:8; -} -BusLogic_OutgoingMailbox_T; - - -/* - Define the 32 Bit Mode Incoming Mailbox structure. -*/ - -typedef struct BusLogic_IncomingMailbox -{ - BusLogic_CCB_T *CCB; - BusLogic_HostAdapterStatus_T HostAdapterStatus:8; - BusLogic_TargetDeviceStatus_T TargetDeviceStatus:8; - unsigned char :8; - BusLogic_CompletionCode_T CompletionCode:8; -} -BusLogic_IncomingMailbox_T; - - -/* - Define the possible Bus Types. -*/ - -typedef enum -{ - BusLogic_Unknown_Bus = 0, - BusLogic_ISA_Bus = 1, - BusLogic_MCA_Bus = 2, - BusLogic_EISA_Bus = 3, - BusLogic_VESA_Bus = 4, - BusLogic_PCI_Bus = 5 -} -BusLogic_BusType_T; - -static char - *BusLogic_BusNames[] = - { "Unknown", "ISA", "MCA", "EISA", "VESA", "PCI" }; - - -/* - Define the Linux BusLogic Driver Command Line Entry structure. -*/ - -typedef struct BusLogic_CommandLineEntry -{ - unsigned short IO_Address; - unsigned short Concurrency; - unsigned short BusSettleTime; - unsigned short LocalOptions; - unsigned short TaggedQueuingPermitted; - unsigned short TaggedQueuingPermittedMask; - unsigned char ErrorRecoveryOption[BusLogic_MaxTargetIDs]; -} -BusLogic_CommandLineEntry_T; - - -/* - Define the Linux BusLogic Driver Host Adapter structure. -*/ - -typedef struct BusLogic_HostAdapter -{ - SCSI_Host_T *SCSI_Host; - unsigned char HostNumber; - unsigned char ModelName[9]; - unsigned char FirmwareVersion[6]; - unsigned char BoardName[18]; - unsigned char InterruptLabel[62]; - unsigned short IO_Address; - unsigned char IRQ_Channel; - unsigned char DMA_Channel; - unsigned char SCSI_ID; - BusLogic_BusType_T BusType:3; - boolean IRQ_ChannelAcquired:1; - boolean DMA_ChannelAcquired:1; - boolean SynchronousInitiation:1; - boolean ParityChecking:1; - boolean ExtendedTranslation:1; - boolean LevelSensitiveInterrupts:1; - boolean HostWideSCSI:1; - boolean HostDifferentialSCSI:1; - boolean HostAdapterResetPending:1; - boolean BounceBuffersRequired:1; - volatile boolean HostAdapterCommandCompleted:1; - unsigned short HostAdapterScatterGatherLimit; - unsigned short DriverScatterGatherLimit; - unsigned short MaxTargetIDs; - unsigned short MaxLogicalUnits; - unsigned short Concurrency; - unsigned short BusSettleTime; - unsigned short LocalOptions; - unsigned short DisconnectPermitted; - unsigned short TaggedQueuingPermitted; - unsigned long BIOS_Address; - BusLogic_InstalledDevices_T InstalledDevices; - BusLogic_SynchronousValues_T SynchronousValues; - BusLogic_SynchronousPeriod_T SynchronousPeriod; - BusLogic_Lock_T Lock; - struct BusLogic_HostAdapter *Next; - BusLogic_CommandLineEntry_T *CommandLineEntry; - BusLogic_CCB_T *All_CCBs; - BusLogic_CCB_T *Free_CCBs; - unsigned char ErrorRecoveryOption[BusLogic_MaxTargetIDs]; - unsigned char CommandSuccessfulFlag[BusLogic_MaxTargetIDs]; - unsigned long ReadWriteOperationCount[BusLogic_MaxTargetIDs]; - unsigned char QueuedOperationCount[BusLogic_MaxTargetIDs]; - unsigned long LastSequencePoint[BusLogic_MaxTargetIDs]; - BusLogic_OutgoingMailbox_T *FirstOutgoingMailbox; - BusLogic_OutgoingMailbox_T *LastOutgoingMailbox; - BusLogic_OutgoingMailbox_T *NextOutgoingMailbox; - BusLogic_IncomingMailbox_T *FirstIncomingMailbox; - BusLogic_IncomingMailbox_T *LastIncomingMailbox; - BusLogic_IncomingMailbox_T *NextIncomingMailbox; - BusLogic_OutgoingMailbox_T OutgoingMailboxes[BusLogic_MailboxCount]; - BusLogic_IncomingMailbox_T IncomingMailboxes[BusLogic_MailboxCount]; -} -BusLogic_HostAdapter_T; - - -/* - Define a symbolic structure for the BIOS Disk Parameters. -*/ - -typedef struct BIOS_DiskParameters -{ - int Heads; - int Sectors; - int Cylinders; -} -BIOS_DiskParameters_T; - - -/* - BusLogic_LockHostAdapter acquires exclusive access to Host Adapter. -*/ - -static inline -void BusLogic_LockHostAdapter(BusLogic_HostAdapter_T *HostAdapter) -{ - save_flags(HostAdapter->Lock); - cli(); -} - - -/* - BusLogic_UnlockHostAdapter releases exclusive access to Host Adapter. -*/ - -static inline -void BusLogic_UnlockHostAdapter(BusLogic_HostAdapter_T *HostAdapter) -{ - restore_flags(HostAdapter->Lock); -} - - -/* - BusLogic_LockHostAdapterID acquires exclusive access to Host Adapter, - but is only called when interrupts are disabled. -*/ - -static inline -void BusLogic_LockHostAdapterID(BusLogic_HostAdapter_T *HostAdapter) -{ -} - - -/* - BusLogic_UnlockHostAdapterID releases exclusive access to Host Adapter, - but is only called when interrupts are disabled. -*/ - -static inline -void BusLogic_UnlockHostAdapterID(BusLogic_HostAdapter_T *HostAdapter) -{ -} - - -/* - Define functions to provide an abstraction for reading and writing the - Host Adapter I/O Registers. -*/ - -static inline -void BusLogic_WriteControlRegister(BusLogic_HostAdapter_T *HostAdapter, - unsigned char Value) -{ - outb(Value, HostAdapter->IO_Address + BusLogic_ControlRegister); -} - -static inline -unsigned char BusLogic_ReadStatusRegister(BusLogic_HostAdapter_T *HostAdapter) -{ - return inb(HostAdapter->IO_Address + BusLogic_StatusRegister); -} - -static inline -void BusLogic_WriteCommandParameterRegister(BusLogic_HostAdapter_T *HostAdapter, - unsigned char Value) -{ - outb(Value, HostAdapter->IO_Address + BusLogic_CommandParameterRegister); -} - -static inline -unsigned char BusLogic_ReadDataInRegister(BusLogic_HostAdapter_T *HostAdapter) -{ - return inb(HostAdapter->IO_Address + BusLogic_DataInRegister); -} - -static inline -unsigned char BusLogic_ReadInterruptRegister(BusLogic_HostAdapter_T - *HostAdapter) -{ - return inb(HostAdapter->IO_Address + BusLogic_InterruptRegister); -} - -static inline -unsigned char BusLogic_ReadGeometryRegister(BusLogic_HostAdapter_T *HostAdapter) -{ - return inb(HostAdapter->IO_Address + BusLogic_GeometryRegister); -} - - -/* - BusLogic_StartMailboxScan issues a Start Mailbox Scan command, which - notifies the Host Adapter that an entry has been made in an Outgoing - Mailbox. -*/ - -static inline -void BusLogic_StartMailboxScan(BusLogic_HostAdapter_T *HostAdapter) -{ - BusLogic_WriteCommandParameterRegister(HostAdapter, - BusLogic_StartMailboxCommand); -} - - -/* - BusLogic_Delay waits for Seconds to elapse. -*/ - -static inline void BusLogic_Delay(int Seconds) -{ - unsigned long TimeoutJiffies = jiffies + Seconds * HZ; - unsigned long ProcessorFlags; - save_flags(ProcessorFlags); - sti(); - while (jiffies < TimeoutJiffies) ; - restore_flags(ProcessorFlags); -} - - -/* - Define prototypes for the forward referenced BusLogic Driver - Internal Functions. -*/ - -static void BusLogic_InterruptHandler(int, Registers_T *); -static int BusLogic_ResetHostAdapter(BusLogic_HostAdapter_T *, - SCSI_Command_T *); - - -#endif /* BusLogic_DriverVersion */ diff --git a/i386/i386at/gpl/linux/scsi/NCR5380.h b/i386/i386at/gpl/linux/scsi/NCR5380.h deleted file mode 100644 index 3a121810..00000000 --- a/i386/i386at/gpl/linux/scsi/NCR5380.h +++ /dev/null @@ -1,363 +0,0 @@ -/* - * NCR 5380 defines - * - * Copyright 1993, Drew Eckhardt - * Visionary Computing - * (Unix consulting and custom programming) - * drew@colorado.edu - * +1 (303) 666-5836 - * - * DISTRIBUTION RELEASE 6 - * - * For more information, please consult - * - * NCR 5380 Family - * SCSI Protocol Controller - * Databook - * NCR Microelectronics - * 1635 Aeroplaza Drive - * Colorado Springs, CO 80916 - * 1+ (719) 578-3400 - * 1+ (800) 334-5454 - */ - -/* - * $Log: NCR5380.h,v $ - * Revision 1.1.1.1 1996/10/30 01:39:59 thomas - * Imported from UK22 - * - * Revision 1.1 1996/03/25 20:25:09 goel - * Linux driver merge. - * - */ - -#ifndef NCR5380_H -#define NCR5380_H - -#define NCR5380_PUBLIC_RELEASE 6 -#define NCR53C400_PUBLIC_RELEASE 2 - -#define NDEBUG_ARBITRATION 0x1 -#define NDEBUG_AUTOSENSE 0x2 -#define NDEBUG_DMA 0x4 -#define NDEBUG_HANDSHAKE 0x8 -#define NDEBUG_INFORMATION 0x10 -#define NDEBUG_INIT 0x20 -#define NDEBUG_INTR 0x40 -#define NDEBUG_LINKED 0x80 -#define NDEBUG_MAIN 0x100 -#define NDEBUG_NO_DATAOUT 0x200 -#define NDEBUG_NO_WRITE 0x400 -#define NDEBUG_PIO 0x800 -#define NDEBUG_PSEUDO_DMA 0x1000 -#define NDEBUG_QUEUES 0x2000 -#define NDEBUG_RESELECTION 0x4000 -#define NDEBUG_SELECTION 0x8000 -#define NDEBUG_USLEEP 0x10000 -#define NDEBUG_LAST_BYTE_SENT 0x20000 -#define NDEBUG_RESTART_SELECT 0x40000 -#define NDEBUG_EXTENDED 0x80000 -#define NDEBUG_C400_PREAD 0x100000 -#define NDEBUG_C400_PWRITE 0x200000 -#define NDEBUG_LISTS 0x400000 - -/* - * The contents of the OUTPUT DATA register are asserted on the bus when - * either arbitration is occurring or the phase-indicating signals ( - * IO, CD, MSG) in the TARGET COMMAND register and the ASSERT DATA - * bit in the INITIATOR COMMAND register is set. - */ - -#define OUTPUT_DATA_REG 0 /* wo DATA lines on SCSI bus */ -#define CURRENT_SCSI_DATA_REG 0 /* ro same */ - -#define INITIATOR_COMMAND_REG 1 /* rw */ -#define ICR_ASSERT_RST 0x80 /* rw Set to assert RST */ -#define ICR_ARBITRATION_PROGRESS 0x40 /* ro Indicates arbitration complete */ -#define ICR_TRI_STATE 0x40 /* wo Set to tri-state drivers */ -#define ICR_ARBITRATION_LOST 0x20 /* ro Indicates arbitration lost */ -#define ICR_DIFF_ENABLE 0x20 /* wo Set to enable diff. drivers */ -#define ICR_ASSERT_ACK 0x10 /* rw ini Set to assert ACK */ -#define ICR_ASSERT_BSY 0x08 /* rw Set to assert BSY */ -#define ICR_ASSERT_SEL 0x04 /* rw Set to assert SEL */ -#define ICR_ASSERT_ATN 0x02 /* rw Set to assert ATN */ -#define ICR_ASSERT_DATA 0x01 /* rw SCSI_DATA_REG is asserted */ - -#ifdef DIFFERENTIAL -#define ICR_BASE ICR_DIFF_ENABLE -#else -#define ICR_BASE 0 -#endif - -#define MODE_REG 2 -/* - * Note : BLOCK_DMA code will keep DRQ asserted for the duration of the - * transfer, causing the chip to hog the bus. You probably don't want - * this. - */ -#define MR_BLOCK_DMA_MODE 0x80 /* rw block mode DMA */ -#define MR_TARGET 0x40 /* rw target mode */ -#define MR_ENABLE_PAR_CHECK 0x20 /* rw enable parity checking */ -#define MR_ENABLE_PAR_INTR 0x10 /* rw enable bad parity interrupt */ -#define MR_ENABLE_EOP_INTR 0x08 /* rw enable eop interrupt */ -#define MR_MONITOR_BSY 0x04 /* rw enable int on unexpected bsy fail */ -#define MR_DMA_MODE 0x02 /* rw DMA / pseudo DMA mode */ -#define MR_ARBITRATE 0x01 /* rw start arbitration */ - -#ifdef PARITY -#define MR_BASE MR_ENABLE_PAR_CHECK -#else -#define MR_BASE 0 -#endif - -#define TARGET_COMMAND_REG 3 -#define TCR_LAST_BYTE_SENT 0x80 /* ro DMA done */ -#define TCR_ASSERT_REQ 0x08 /* tgt rw assert REQ */ -#define TCR_ASSERT_MSG 0x04 /* tgt rw assert MSG */ -#define TCR_ASSERT_CD 0x02 /* tgt rw assert CD */ -#define TCR_ASSERT_IO 0x01 /* tgt rw assert IO */ - -#define STATUS_REG 4 /* ro */ -/* - * Note : a set bit indicates an active signal, driven by us or another - * device. - */ -#define SR_RST 0x80 -#define SR_BSY 0x40 -#define SR_REQ 0x20 -#define SR_MSG 0x10 -#define SR_CD 0x08 -#define SR_IO 0x04 -#define SR_SEL 0x02 -#define SR_DBP 0x01 - -/* - * Setting a bit in this register will cause an interrupt to be generated when - * BSY is false and SEL true and this bit is asserted on the bus. - */ -#define SELECT_ENABLE_REG 4 /* wo */ - -#define BUS_AND_STATUS_REG 5 /* ro */ -#define BASR_END_DMA_TRANSFER 0x80 /* ro set on end of transfer */ -#define BASR_DRQ 0x40 /* ro mirror of DRQ pin */ -#define BASR_PARITY_ERROR 0x20 /* ro parity error detected */ -#define BASR_IRQ 0x10 /* ro mirror of IRQ pin */ -#define BASR_PHASE_MATCH 0x08 /* ro Set when MSG CD IO match TCR */ -#define BASR_BUSY_ERROR 0x04 /* ro Unexpected change to inactive state */ -#define BASR_ATN 0x02 /* ro BUS status */ -#define BASR_ACK 0x01 /* ro BUS status */ - -/* Write any value to this register to start a DMA send */ -#define START_DMA_SEND_REG 5 /* wo */ - -/* - * Used in DMA transfer mode, data is latched from the SCSI bus on - * the falling edge of REQ (ini) or ACK (tgt) - */ -#define INPUT_DATA_REG 6 /* ro */ - -/* Write any value to this register to start a DMA receive */ -#define START_DMA_TARGET_RECEIVE_REG 6 /* wo */ - -/* Read this register to clear interrupt conditions */ -#define RESET_PARITY_INTERRUPT_REG 7 /* ro */ - -/* Write any value to this register to start an ini mode DMA receive */ -#define START_DMA_INITIATOR_RECEIVE_REG 7 /* wo */ - -#define C400_CONTROL_STATUS_REG NCR53C400_register_offset-8 /* rw */ - -#define CSR_RESET 0x80 /* wo Resets 53c400 */ -#define CSR_53C80_REG 0x80 /* ro 5380 registers busy */ -#define CSR_TRANS_DIR 0x40 /* rw Data transfer direction */ -#define CSR_SCSI_BUFF_INTR 0x20 /* rw Enable int on transfer ready */ -#define CSR_53C80_INTR 0x10 /* rw Enable 53c80 interrupts */ -#define CSR_SHARED_INTR 0x08 /* rw Interrupt sharing */ -#define CSR_HOST_BUF_NOT_RDY 0x04 /* ro Is Host buffer ready */ -#define CSR_SCSI_BUF_RDY 0x02 /* ro SCSI buffer read */ -#define CSR_GATED_53C80_IRQ 0x01 /* ro Last block xferred */ - -#if 0 -#define CSR_BASE CSR_SCSI_BUFF_INTR | CSR_53C80_INTR -#else -#define CSR_BASE CSR_53C80_INTR -#endif - -/* Number of 128-byte blocks to be transferred */ -#define C400_BLOCK_COUNTER_REG NCR53C400_register_offset-7 /* rw */ - -/* Resume transfer after disconnect */ -#define C400_RESUME_TRANSFER_REG NCR53C400_register_offset-6 /* wo */ - -/* Access to host buffer stack */ -#define C400_HOST_BUFFER NCR53C400_register_offset-4 /* rw */ - - -/* Note : PHASE_* macros are based on the values of the STATUS register */ -#define PHASE_MASK (SR_MSG | SR_CD | SR_IO) - -#define PHASE_DATAOUT 0 -#define PHASE_DATAIN SR_IO -#define PHASE_CMDOUT SR_CD -#define PHASE_STATIN (SR_CD | SR_IO) -#define PHASE_MSGOUT (SR_MSG | SR_CD) -#define PHASE_MSGIN (SR_MSG | SR_CD | SR_IO) -#define PHASE_UNKNOWN 0xff - -/* - * Convert status register phase to something we can use to set phase in - * the target register so we can get phase mismatch interrupts on DMA - * transfers. - */ - -#define PHASE_SR_TO_TCR(phase) ((phase) >> 2) - -/* - * The internal should_disconnect() function returns these based on the - * expected length of a disconnect if a device supports disconnect/ - * reconnect. - */ - -#define DISCONNECT_NONE 0 -#define DISCONNECT_TIME_TO_DATA 1 -#define DISCONNECT_LONG 2 - -/* - * These are "special" values for the tag parameter passed to NCR5380_select. - */ - -#define TAG_NEXT -1 /* Use next free tag */ -#define TAG_NONE -2 /* - * Establish I_T_L nexus instead of I_T_L_Q - * even on SCSI-II devices. - */ - -/* - * These are "special" values for the irq and dma_channel fields of the - * Scsi_Host structure - */ - -#define IRQ_NONE 255 -#define DMA_NONE 255 -#define IRQ_AUTO 254 -#define DMA_AUTO 254 - -#define FLAG_HAS_LAST_BYTE_SENT 1 /* NCR53c81 or better */ -#define FLAG_CHECK_LAST_BYTE_SENT 2 /* Only test once */ -#define FLAG_NCR53C400 4 /* NCR53c400 */ -#define FLAG_NO_PSEUDO_DMA 8 /* Inhibit DMA */ - -#ifndef ASM -struct NCR5380_hostdata { - NCR5380_implementation_fields; /* implementation specific */ - unsigned char id_mask, id_higher_mask; /* 1 << id, all bits greater */ - unsigned char targets_present; /* targets we have connected - to, so we can call a select - failure a retryable condition */ - volatile unsigned char busy[8]; /* index = target, bit = lun */ -#if defined(REAL_DMA) || defined(REAL_DMA_POLL) - volatile int dma_len; /* requested length of DMA */ -#endif - volatile unsigned char last_message; /* last message OUT */ - volatile Scsi_Cmnd *connected; /* currently connected command */ - volatile Scsi_Cmnd *issue_queue; /* waiting to be issued */ - volatile Scsi_Cmnd *disconnected_queue; /* waiting for reconnect */ - volatile int restart_select; /* we have disconnected, - used to restart - NCR5380_select() */ - volatile unsigned aborted:1; /* flag, says aborted */ - int flags; -#ifdef USLEEP - unsigned long time_expires; /* in jiffies, set prior to sleeping */ - struct Scsi_Host *next_timer; -#endif -}; - -#ifdef __KERNEL__ -static struct Scsi_Host *first_instance; /* linked list of 5380's */ - -#if defined(AUTOPROBE_IRQ) -static int NCR5380_probe_irq (struct Scsi_Host *instance, int possible); -#endif -static void NCR5380_init (struct Scsi_Host *instance, int flags); -static void NCR5380_information_transfer (struct Scsi_Host *instance); -static void NCR5380_intr (int irq, struct pt_regs * regs); -static void NCR5380_main (void); -static void NCR5380_print_options (struct Scsi_Host *instance); -static void NCR5380_print_phase (struct Scsi_Host *instance); -static void NCR5380_print (struct Scsi_Host *instance); -#ifndef NCR5380_abort -static -#endif -int NCR5380_abort (Scsi_Cmnd *cmd); -#ifndef NCR5380_reset -static -#endif -int NCR5380_reset (Scsi_Cmnd *cmd); -#ifndef NCR5380_queue_command -static -#endif -int NCR5380_queue_command (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)); - - -static void NCR5380_reselect (struct Scsi_Host *instance); -static int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag); -#if defined(PSEUDO_DMA) || defined(REAL_DMA) || defined(REAL_DMA_POLL) -static int NCR5380_transfer_dma (struct Scsi_Host *instance, - unsigned char *phase, int *count, unsigned char **data); -#endif -static int NCR5380_transfer_pio (struct Scsi_Host *instance, - unsigned char *phase, int *count, unsigned char **data); - -#if (defined(REAL_DMA) || defined(REAL_DMA_POLL)) && defined(i386) -static __inline__ int NCR5380_i386_dma_setup (struct Scsi_Host *instance, - unsigned char *ptr, unsigned int count, unsigned char mode) { - unsigned limit; - - if (instance->dma_channel <=3) { - if (count > 65536) - count = 65536; - limit = 65536 - (((unsigned) ptr) & 0xFFFF); - } else { - if (count > 65536 * 2) - count = 65536 * 2; - limit = 65536* 2 - (((unsigned) ptr) & 0x1FFFF); - } - - if (count > limit) count = limit; - - if ((count & 1) || (((unsigned) ptr) & 1)) - panic ("scsi%d : attempted unaligned DMA transfer\n", instance->host_no); - cli(); - disable_dma(instance->dma_channel); - clear_dma_ff(instance->dma_channel); - set_dma_addr(instance->dma_channel, (unsigned int) ptr); - set_dma_count(instance->dma_channel, count); - set_dma_mode(instance->dma_channel, mode); - enable_dma(instance->dma_channel); - sti(); - return count; -} - -static __inline__ int NCR5380_i386_dma_write_setup (struct Scsi_Host *instance, - unsigned char *src, unsigned int count) { - return NCR5380_i386_dma_setup (instance, src, count, DMA_MODE_WRITE); -} - -static __inline__ int NCR5380_i386_dma_read_setup (struct Scsi_Host *instance, - unsigned char *src, unsigned int count) { - return NCR5380_i386_dma_setup (instance, src, count, DMA_MODE_READ); -} - -static __inline__ int NCR5380_i386_dma_residual (struct Scsi_Host *instance) { - register int tmp; - cli(); - clear_dma_ff(instance->dma_channel); - tmp = get_dma_residue(instance->dma_channel); - sti(); - return tmp; -} -#endif /* defined(REAL_DMA) && defined(i386) */ -#endif __KERNEL_ -#endif /* ndef ASM */ -#endif /* NCR5380_H */ diff --git a/i386/i386at/gpl/linux/scsi/NCR5380.src b/i386/i386at/gpl/linux/scsi/NCR5380.src deleted file mode 100644 index 64beb813..00000000 --- a/i386/i386at/gpl/linux/scsi/NCR5380.src +++ /dev/null @@ -1,3035 +0,0 @@ -#ifndef NDEBUG -#define NDEBUG (NDEBUG_RESTART_SELECT | NDEBUG_ABORT) -#endif -/* - * NCR 5380 generic driver routines. These should make it *trivial* - * to implement 5380 SCSI drivers under Linux with a non-trantor - * architecture. - * - * Note that these routines also work with NR53c400 family chips. - * - * Copyright 1993, Drew Eckhardt - * Visionary Computing - * (Unix and Linux consulting and custom programming) - * drew@colorado.edu - * +1 (303) 666-5836 - * - * DISTRIBUTION RELEASE 6. - * - * For more information, please consult - * - * NCR 5380 Family - * SCSI Protocol Controller - * Databook - * - * NCR Microelectronics - * 1635 Aeroplaza Drive - * Colorado Springs, CO 80916 - * 1+ (719) 578-3400 - * 1+ (800) 334-5454 - */ - -/* - * $Log: NCR5380.src,v $ - * Revision 1.1.1.1 1996/10/30 01:39:59 thomas - * Imported from UK22 - * -# Revision 1.1 1996/03/25 20:25:10 goel -# Linux driver merge. -# - * Revision 1.5 1994/01/19 09:14:57 drew - * Fixed udelay() hack that was being used on DATAOUT phases - * instead of a proper wait for the final handshake. - * - * Revision 1.4 1994/01/19 06:44:25 drew - * *** empty log message *** - * - * Revision 1.3 1994/01/19 05:24:40 drew - * Added support for TCR LAST_BYTE_SENT bit. - * - * Revision 1.2 1994/01/15 06:14:11 drew - * REAL DMA support, bug fixes. - * - * Revision 1.1 1994/01/15 06:00:54 drew - * Initial revision - * - */ - -/* - * Further development / testing that should be done : - * 1. Cleanup the NCR5380_transfer_dma function and DMA operation complete - * code so that everything does the same thing that's done at the - * end of a pseudo-DMA read operation. - * - * 2. Fix REAL_DMA (interrupt driven, polled works fine) - - * basically, transfer size needs to be reduced by one - * and the last byte read as is done with PSEUDO_DMA. - * - * 3. Test USLEEP code - * - * 4. Test SCSI-II tagged queueing (I have no devices which support - * tagged queueing) - * - * 5. Test linked command handling code after Eric is ready with - * the high level code. - */ - -#if (NDEBUG & NDEBUG_LISTS) -#define LIST(x,y) {printk("LINE:%d Adding %p to %p\n", __LINE__, (void*)(x), (void*)(y)); if ((x)==(y)) udelay(5); } -#define REMOVE(w,x,y,z) {printk("LINE:%d Removing: %p->%p %p->%p \n", __LINE__, (void*)(w), (void*)(x), (void*)(y), (void*)(z)); if ((x)==(y)) udelay(5); } -#else -#define LIST(x,y) -#define REMOVE(w,x,y,z) -#endif - -#ifndef notyet -#undef LINKED -#undef USLEEP -#undef REAL_DMA -#endif - -#ifdef REAL_DMA_POLL -#undef READ_OVERRUNS -#define READ_OVERRUNS -#endif - -/* - * Design - * Issues : - * - * The other Linux SCSI drivers were written when Linux was Intel PC-only, - * and specifically for each board rather than each chip. This makes their - * adaptation to platforms like the Mac (Some of which use NCR5380's) - * more difficult than it has to be. - * - * Also, many of the SCSI drivers were written before the command queuing - * routines were implemented, meaning their implementations of queued - * commands were hacked on rather than designed in from the start. - * - * When I designed the Linux SCSI drivers I figured that - * while having two different SCSI boards in a system might be useful - * for debugging things, two of the same type wouldn't be used. - * Well, I was wrong and a number of users have mailed me about running - * multiple high-performance SCSI boards in a server. - * - * Finally, when I get questions from users, I have no idea what - * revision of my driver they are running. - * - * This driver attempts to address these problems : - * This is a generic 5380 driver. To use it on a different platform, - * one simply writes appropriate system specific macros (ie, data - * transfer - some PC's will use the I/O bus, 68K's must use - * memory mapped) and drops this file in their 'C' wrapper. - * - * As far as command queueing, two queues are maintained for - * each 5380 in the system - commands that haven't been issued yet, - * and commands that are currently executing. This means that an - * unlimited number of commands may be queued, letting - * more commands propagate from the higher driver levels giving higher - * throughput. Note that both I_T_L and I_T_L_Q nexuses are supported, - * allowing multiple commands to propagate all the way to a SCSI-II device - * while a command is already executing. - * - * To solve the multiple-boards-in-the-same-system problem, - * there is a separate instance structure for each instance - * of a 5380 in the system. So, multiple NCR5380 drivers will - * be able to coexist with appropriate changes to the high level - * SCSI code. - * - * A NCR5380_PUBLIC_REVISION macro is provided, with the release - * number (updated for each public release) printed by the - * NCR5380_print_options command, which should be called from the - * wrapper detect function, so that I know what release of the driver - * users are using. - * - * Issues specific to the NCR5380 : - * - * When used in a PIO or pseudo-dma mode, the NCR5380 is a braindead - * piece of hardware that requires you to sit in a loop polling for - * the REQ signal as long as you are connected. Some devices are - * brain dead (ie, many TEXEL CD ROM drives) and won't disconnect - * while doing long seek operations. - * - * The workaround for this is to keep track of devices that have - * disconnected. If the device hasn't disconnected, for commands that - * should disconnect, we do something like - * - * while (!REQ is asserted) { sleep for N usecs; poll for M usecs } - * - * Some tweaking of N and M needs to be done. An algorithm based - * on "time to data" would give the best results as long as short time - * to datas (ie, on the same track) were considered, however these - * broken devices are the exception rather than the rule and I'd rather - * spend my time optimizing for the normal case. - * - * Architecture : - * - * At the heart of the design is a coroutine, NCR5380_main, - * which is started when not running by the interrupt handler, - * timer, and queue command function. It attempts to establish - * I_T_L or I_T_L_Q nexuses by removing the commands from the - * issue queue and calling NCR5380_select() if a nexus - * is not established. - * - * Once a nexus is established, the NCR5380_information_transfer() - * phase goes through the various phases as instructed by the target. - * if the target goes into MSG IN and sends a DISCONNECT message, - * the command structure is placed into the per instance disconnected - * queue, and NCR5380_main tries to find more work. If USLEEP - * was defined, and the target is idle for too long, the system - * will try to sleep. - * - * If a command has disconnected, eventually an interrupt will trigger, - * calling NCR5380_intr() which will in turn call NCR5380_reselect - * to reestablish a nexus. This will run main if necessary. - * - * On command termination, the done function will be called as - * appropriate. - * - * SCSI pointers are maintained in the SCp field of SCSI command - * structures, being initialized after the command is connected - * in NCR5380_select, and set as appropriate in NCR5380_information_transfer. - * Note that in violation of the standard, an implicit SAVE POINTERS operation - * is done, since some BROKEN disks fail to issue an explicit SAVE POINTERS. - */ - -/* - * Using this file : - * This file a skeleton Linux SCSI driver for the NCR 5380 series - * of chips. To use it, you write a architecture specific functions - * and macros and include this file in your driver. - * - * These macros control options : - * AUTOPROBE_IRQ - if defined, the NCR5380_probe_irq() function will be - * defined. - * - * AUTOSENSE - if defined, REQUEST SENSE will be performed automatically - * for commands that return with a CHECK CONDITION status. - * - * DIFFERENTIAL - if defined, NCR53c81 chips will use external differential - * transceivers. - * - * LIMIT_TRANSFERSIZE - if defined, limit the pseudo-dma transfers to 512 - * bytes at a time. Since interrupts are disabled by default during - * these transfers, we might need this to give reasonable interrupt - * service time if the transfer size gets too large. - * - * LINKED - if defined, linked commands are supported. - * - * PSEUDO_DMA - if defined, PSEUDO DMA is used during the data transfer phases. - * - * REAL_DMA - if defined, REAL DMA is used during the data transfer phases. - * - * REAL_DMA_POLL - if defined, REAL DMA is used but the driver doesn't - * rely on phase mismatch and EOP interrupts to determine end - * of phase. - * - * SCSI2 - if defined, SCSI-2 tagged queuing is used where possible - * - * UNSAFE - leave interrupts enabled during pseudo-DMA transfers. You - * only really want to use this if you're having a problem with - * dropped characters during high speed communications, and even - * then, you're going to be better off twiddling with transfersize - * in the high level code. - * - * USLEEP - if defined, on devices that aren't disconnecting from the - * bus, we will go to sleep so that the CPU can get real work done - * when we run a command that won't complete immediately. - * - * Note that if USLEEP is defined, NCR5380_TIMER *must* also be - * defined. - * - * Defaults for these will be provided if USLEEP is defined, although - * the user may want to adjust these to allocate CPU resources to - * the SCSI driver or "real" code. - * - * USLEEP_SLEEP - amount of time, in jiffies, to sleep - * - * USLEEP_POLL - amount of time, in jiffies, to poll - * - * These macros MUST be defined : - * NCR5380_local_declare() - declare any local variables needed for your transfer - * routines. - * - * NCR5380_setup(instance) - initialize any local variables needed from a given - * instance of the host adapter for NCR5380_{read,write,pread,pwrite} - * - * NCR5380_read(register) - read from the specified register - * - * NCR5380_write(register, value) - write to the specific register - * - * NCR5380_implementation_fields - additional fields needed for this - * specific implementation of the NCR5380 - * - * Either real DMA *or* pseudo DMA may be implemented - * REAL functions : - * NCR5380_REAL_DMA should be defined if real DMA is to be used. - * Note that the DMA setup functions should return the number of bytes - * that they were able to program the controller for. - * - * Also note that generic i386/PC versions of these macros are - * available as NCR5380_i386_dma_write_setup, - * NCR5380_i386_dma_read_setup, and NCR5380_i386_dma_residual. - * - * NCR5380_dma_write_setup(instance, src, count) - initialize - * NCR5380_dma_read_setup(instance, dst, count) - initialize - * NCR5380_dma_residual(instance); - residual count - * - * PSEUDO functions : - * NCR5380_pwrite(instance, src, count) - * NCR5380_pread(instance, dst, count); - * - * If nothing specific to this implementation needs doing (ie, with external - * hardware), you must also define - * - * NCR5380_queue_command - * NCR5380_reset - * NCR5380_abort - * - * to be the global entry points into the specific driver, ie - * #define NCR5380_queue_command t128_queue_command. - * - * If this is not done, the routines will be defined as static functions - * with the NCR5380* names and the user must provide a globally - * accessible wrapper function. - * - * The generic driver is initialized by calling NCR5380_init(instance), - * after setting the appropriate host specific fields and ID. If the - * driver wishes to autoprobe for an IRQ line, the NCR5380_probe_irq(instance, - * possible) function may be used. Before the specific driver initialization - * code finishes, NCR5380_print_options should be called. - */ - -static int do_abort (struct Scsi_Host *host); -static void do_reset (struct Scsi_Host *host); -static struct Scsi_Host *first_instance = NULL; -static Scsi_Host_Template *the_template = NULL; - -/* - * Function : void initialize_SCp(Scsi_Cmnd *cmd) - * - * Purpose : initialize the saved data pointers for cmd to point to the - * start of the buffer. - * - * Inputs : cmd - Scsi_Cmnd structure to have pointers reset. - */ - -static __inline__ void initialize_SCp(Scsi_Cmnd *cmd) { - /* - * Initialize the Scsi Pointer field so that all of the commands in the - * various queues are valid. - */ - - if (cmd->use_sg) { - cmd->SCp.buffer = (struct scatterlist *) cmd->buffer; - cmd->SCp.buffers_residual = cmd->use_sg - 1; - cmd->SCp.ptr = (char *) cmd->SCp.buffer->address; - cmd->SCp.this_residual = cmd->SCp.buffer->length; - } else { - cmd->SCp.buffer = NULL; - cmd->SCp.buffers_residual = 0; - cmd->SCp.ptr = (char *) cmd->request_buffer; - cmd->SCp.this_residual = cmd->request_bufflen; - } -} - -#include <linux/delay.h> - -#ifdef NDEBUG -static struct { - unsigned char mask; - const char * name;} -signals[] = {{ SR_DBP, "PARITY"}, { SR_RST, "RST" }, { SR_BSY, "BSY" }, - { SR_REQ, "REQ" }, { SR_MSG, "MSG" }, { SR_CD, "CD" }, { SR_IO, "IO" }, - { SR_SEL, "SEL" }, {0, NULL}}, -basrs[] = {{BASR_ATN, "ATN"}, {BASR_ACK, "ACK"}, {0, NULL}}, -icrs[] = {{ICR_ASSERT_RST, "ASSERT RST"},{ICR_ASSERT_ACK, "ASSERT ACK"}, - {ICR_ASSERT_BSY, "ASSERT BSY"}, {ICR_ASSERT_SEL, "ASSERT SEL"}, - {ICR_ASSERT_ATN, "ASSERT ATN"}, {ICR_ASSERT_DATA, "ASSERT DATA"}, - {0, NULL}}, -mrs[] = {{MR_BLOCK_DMA_MODE, "MODE BLOCK DMA"}, {MR_TARGET, "MODE TARGET"}, - {MR_ENABLE_PAR_CHECK, "MODE PARITY CHECK"}, {MR_ENABLE_PAR_INTR, - "MODE PARITY INTR"}, {MR_MONITOR_BSY, "MODE MONITOR BSY"}, - {MR_DMA_MODE, "MODE DMA"}, {MR_ARBITRATE, "MODE ARBITRATION"}, - {0, NULL}}; - -/* - * Function : void NCR5380_print(struct Scsi_Host *instance) - * - * Purpose : print the SCSI bus signals for debugging purposes - * - * Input : instance - which NCR5380 - */ - -static void NCR5380_print(struct Scsi_Host *instance) { - NCR5380_local_declare(); - unsigned char status, data, basr, mr, icr, i; - NCR5380_setup(instance); - cli(); - data = NCR5380_read(CURRENT_SCSI_DATA_REG); - status = NCR5380_read(STATUS_REG); - mr = NCR5380_read(MODE_REG); - icr = NCR5380_read(INITIATOR_COMMAND_REG); - basr = NCR5380_read(BUS_AND_STATUS_REG); - sti(); - printk("STATUS_REG: %02x ", status); - for (i = 0; signals[i].mask ; ++i) - if (status & signals[i].mask) - printk(",%s", signals[i].name); - printk("\nBASR: %02x ", basr); - for (i = 0; basrs[i].mask ; ++i) - if (basr & basrs[i].mask) - printk(",%s", basrs[i].name); - printk("\nICR: %02x ", icr); - for (i = 0; icrs[i].mask; ++i) - if (icr & icrs[i].mask) - printk(",%s", icrs[i].name); - printk("\nMODE: %02x ", mr); - for (i = 0; mrs[i].mask; ++i) - if (mr & mrs[i].mask) - printk(",%s", mrs[i].name); - printk("\n"); -} - -static struct { - unsigned char value; - const char *name; -} phases[] = { -{PHASE_DATAOUT, "DATAOUT"}, {PHASE_DATAIN, "DATAIN"}, {PHASE_CMDOUT, "CMDOUT"}, -{PHASE_STATIN, "STATIN"}, {PHASE_MSGOUT, "MSGOUT"}, {PHASE_MSGIN, "MSGIN"}, -{PHASE_UNKNOWN, "UNKNOWN"}}; - -/* - * Function : void NCR5380_print_phase(struct Scsi_Host *instance) - * - * Purpose : print the current SCSI phase for debugging purposes - * - * Input : instance - which NCR5380 - */ - -static void NCR5380_print_phase(struct Scsi_Host *instance) { - NCR5380_local_declare(); - unsigned char status; - int i; - NCR5380_setup(instance); - - status = NCR5380_read(STATUS_REG); - if (!(status & SR_REQ)) - printk("scsi%d : REQ not asserted, phase unknown.\n", - instance->host_no); - else { - for (i = 0; (phases[i].value != PHASE_UNKNOWN) && - (phases[i].value != (status & PHASE_MASK)); ++i); - printk("scsi%d : phase %s\n", instance->host_no, phases[i].name); - } -} -#endif - -/* - * We need to have our coroutine active given these constraints : - * 1. The mutex flag, main_running, can only be set when the main - * routine can actually process data, otherwise SCSI commands - * will never get issued. - * - * 2. NCR5380_main() shouldn't be called before it has exited, because - * other drivers have had kernel stack overflows in similar - * situations. - * - * 3. We don't want to inline NCR5380_main() because of space concerns, - * even though it is only called in two places. - * - * So, the solution is to set the mutex in an inline wrapper for the - * main coroutine, and have the main coroutine exit with interrupts - * disabled after the final search through the queues so that no race - * conditions are possible. - */ - -static volatile int main_running = 0; - -/* - * Function : run_main(void) - * - * Purpose : insure that the coroutine is running and will process our - * request. main_running is checked/set here (in an inline function) - * rather than in NCR5380_main itself to reduce the chances of stack - * overflow. - * - */ - -static __inline__ void run_main(void) { - cli(); - if (!main_running) { - main_running = 1; - NCR5380_main(); - /* - * main_running is cleared in NCR5380_main once it can't do - * more work, and NCR5380_main exits with interrupts disabled. - */ - sti(); - } else - sti(); -} - -#ifdef USLEEP -#ifndef NCR5380_TIMER -#error "NCR5380_TIMER must be defined so that this type of NCR5380 driver gets a unique timer." -#endif - -/* - * These need tweaking, and would probably work best as per-device - * flags initialized differently for disk, tape, cd, etc devices. - * People with broken devices are free to experiment as to what gives - * the best results for them. - * - * USLEEP_SLEEP should be a minimum seek time. - * - * USLEEP_POLL should be a maximum rotational latency. - */ -#ifndef USLEEP_SLEEP -/* 20 ms (reasonable hard disk speed) */ -#define USLEEP_SLEEP 2 -#endif -/* 300 RPM (floppy speed) */ -#ifndef USLEEP_POLL -#define USLEEP_POLL 20 -#endif - -static struct Scsi_Host * expires_first = NULL; - -/* - * Function : int should_disconnect (unsigned char cmd) - * - * Purpose : decide weather a command would normally disconnect or - * not, since if it won't disconnect we should go to sleep. - * - * Input : cmd - opcode of SCSI command - * - * Returns : DISCONNECT_LONG if we should disconnect for a really long - * time (ie always, sleep, look for REQ active, sleep), - * DISCONNECT_TIME_TO_DATA if we would only disconnect for a normal - * time-to-data delay, DISCONNECT_NONE if this command would return - * immediately. - * - * Future sleep algorithms based on time to data can exploit - * something like this so they can differentiate between "normal" - * (ie, read, write, seek) and unusual commands (ie, * format). - * - * Note : We don't deal with commands that handle an immediate disconnect, - * - */ - -static int should_disconnect (unsigned char cmd) { - switch (cmd) { - case READ_6: - case WRITE_6: - case SEEK_6: - case READ_10: - case WRITE_10: - case SEEK_10: - return DISCONNECT_TIME_TO_DATA; - case FORMAT_UNIT: - case SEARCH_HIGH: - case SEARCH_LOW: - case SEARCH_EQUAL: - return DISCONNECT_LONG; - default: - return DISCONNECT_NONE; - } -} - -/* - * Assumes instance->time_expires has been set in higher level code. - */ - -static int NCR5380_set_timer (struct Scsi_Host *instance) { - struct Scsi_Host *tmp, **prev; - - cli(); - if (((struct NCR5380_hostdata *) (instance->host_data))->next_timer) { - sti(); - return -1; - } - - for (prev = &expires_first, tmp = expires_first; tmp; - prev = &(((struct NCR5380_hostdata *) tmp->host_data)->next_timer), - tmp = ((struct NCR5380_hostdata *) tmp->host_data)->next_timer) - if (instance->time_expires < tmp->time_expires) - break; - - instance->next_timer = tmp; - *prev = instance; - timer_table[NCR5380_TIMER].expires = expires_first->time_expires; - timer_active |= 1 << NCR5380_TIMER; - sti(); - return 0; -} - -/* Doing something about unwanted reentrancy here might be useful */ -void NCR5380_timer_fn(void) { - struct Scsi_Host *instance; - cli(); - for (; expires_first && expires_first->time_expires >= jiffies; ) { - instance = ((NCR5380_hostdata *) expires_first->host_data)-> - expires_next; - ((NCR5380_hostdata *) expires_first->host_data)->expires_next = - NULL; - ((NCR5380_hostdata *) expires_first->host_data)->time_expires = - 0; - expires_first = instance; - } - - if (expires_first) { - timer_table[NCR5380_TIMER].expires = ((NCR5380_hostdata *) - expires_first->host_data)->time_expires; - timer_active |= (1 << NCR5380_TIMER); - } else { - timer_table[NCR5380_TIMER].expires = 0; - timer_active &= ~(1 << MCR5380_TIMER); - } - sti(); - - run_main(); -} -#endif /* def USLEEP */ - -static void NCR5380_all_init (void) { - static int done = 0; - if (!done) { -#if (NDEBUG & NDEBUG_INIT) - printk("scsi : NCR5380_all_init()\n"); -#endif - done = 1; -#ifdef USLEEP - timer_table[NCR5380_TIMER].expires = 0; - timer_table[NCR5380_TIMER].fn = NCR5380_timer_fn; -#endif - } -} - -#ifdef AUTOPROBE_IRQ -/* - * Function : int NCR5380_probe_irq (struct Scsi_Host *instance, int possible) - * - * Purpose : autoprobe for the IRQ line used by the NCR5380. - * - * Inputs : instance - pointer to this instance of the NCR5380 driver, - * possible - bitmask of permissible interrupts. - * - * Returns : number of the IRQ selected, IRQ_NONE if no interrupt fired. - * - * XXX no effort is made to deal with spurious interrupts. - */ - - -static int probe_irq; -static void probe_intr (int irq, struct pt_regs * regs) { - probe_irq = irq; -}; - -static int NCR5380_probe_irq (struct Scsi_Host *instance, int possible) { - NCR5380_local_declare(); - struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) - instance->hostdata; - unsigned long timeout; - int trying_irqs, i, mask; - NCR5380_setup(instance); - - for (trying_irqs = i = 0, mask = 1; i < 16; ++i, mask <<= 1) - if ((mask & possible) && (request_irq(i, &probe_intr, SA_INTERRUPT, "NCR-probe") - == 0)) - trying_irqs |= mask; - - timeout = jiffies + 25; - probe_irq = IRQ_NONE; - -/* - * A interrupt is triggered whenever BSY = false, SEL = true - * and a bit set in the SELECT_ENABLE_REG is asserted on the - * SCSI bus. - * - * Note that the bus is only driven when the phase control signals - * (I/O, C/D, and MSG) match those in the TCR, so we must reset that - * to zero. - */ - - NCR5380_write(TARGET_COMMAND_REG, 0); - NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); - NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask); - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA | - ICR_ASSERT_SEL); - - while (probe_irq == IRQ_NONE && jiffies < timeout) - barrier(); - - NCR5380_write(SELECT_ENABLE_REG, 0); - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - - for (i = 0, mask = 1; i < 16; ++i, mask <<= 1) - if (trying_irqs & mask) - free_irq(i); - - return probe_irq; -} -#endif /* AUTOPROBE_IRQ */ - -/* - * Function : void NCR58380_print_options (struct Scsi_Host *instance) - * - * Purpose : called by probe code indicating the NCR5380 driver - * options that were selected. - * - * Inputs : instance, pointer to this instance. Unused. - */ - -static void NCR5380_print_options (struct Scsi_Host *instance) { - printk(" generic options" -#ifdef AUTOPROBE_IRQ - " AUTOPROBE_IRQ" -#endif -#ifdef AUTOSENSE - " AUTOSENSE" -#endif -#ifdef DIFFERENTIAL - " DIFFERENTIAL" -#endif -#ifdef REAL_DMA - " REAL DMA" -#endif -#ifdef REAL_DMA_POLL - " REAL DMA POLL" -#endif -#ifdef PARITY - " PARITY" -#endif -#ifdef PSEUDO_DMA - " PSEUDO DMA" -#endif -#ifdef SCSI2 - " SCSI-2" -#endif -#ifdef UNSAFE - " UNSAFE " -#endif - ); -#ifdef USLEEP - printk(" USLEEP, USLEEP_POLL=%d USLEEP_SLEEP=%d", USLEEP_POLL, USLEEP_SLEEP); -#endif - printk(" generic release=%d", NCR5380_PUBLIC_RELEASE); - if (((struct NCR5380_hostdata *)instance->hostdata)->flags & FLAG_NCR53C400) { - printk(" ncr53c400 release=%d", NCR53C400_PUBLIC_RELEASE); - } -} - -/* - * Function : void NCR5380_print_status (struct Scsi_Host *instance) - * - * Purpose : print commands in the various queues, called from - * NCR5380_abort and NCR5380_debug to aid debugging. - * - * Inputs : instance, pointer to this instance. - */ - -static void NCR5380_print_status (struct Scsi_Host *instance) { - struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) - instance->hostdata; - Scsi_Cmnd *ptr; - - - printk("NCR5380 : coroutine is%s running.\n", - main_running ? "" : "n't"); - -#ifdef NDEBUG - NCR5380_print (instance); - NCR5380_print_phase (instance); -#endif - - cli(); - if (!hostdata->connected) { - printk ("scsi%d: no currently connected command\n", - instance->host_no); - } else { - print_Scsi_Cmnd ((Scsi_Cmnd *) hostdata->connected); - } - - printk ("scsi%d: issue_queue\n", instance->host_no); - - for (ptr = (Scsi_Cmnd *) hostdata->issue_queue; ptr; - ptr = (Scsi_Cmnd *) ptr->host_scribble) - print_Scsi_Cmnd (ptr); - - printk ("scsi%d: disconnected_queue\n", instance->host_no); - - for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr; - ptr = (Scsi_Cmnd *) ptr->host_scribble) - print_Scsi_Cmnd (ptr); - - sti(); -} - - -/* - * Function : void NCR5380_init (struct Scsi_Host *instance, flags) - * - * Purpose : initializes *instance and corresponding 5380 chip, - * with flags OR'd into the initial flags value. - * - * Inputs : instance - instantiation of the 5380 driver. - * - * Notes : I assume that the host, hostno, and id bits have been - * set correctly. I don't care about the irq and other fields. - * - */ - -static void NCR5380_init (struct Scsi_Host *instance, int flags) { - NCR5380_local_declare(); - int i, pass; - unsigned long timeout; - struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) - instance->hostdata; - - /* - * On NCR53C400 boards, NCR5380 registers are mapped 8 past - * the base address. - */ - -#ifdef NCR53C400 - if (flags & FLAG_NCR53C400) - instance->NCR5380_instance_name += NCR53C400_address_adjust; -#endif - - NCR5380_setup(instance); - - NCR5380_all_init(); - - hostdata->aborted = 0; - hostdata->id_mask = 1 << instance->this_id; - for (i = hostdata->id_mask; i <= 0x80; i <<= 1) - if (i > hostdata->id_mask) - hostdata->id_higher_mask |= i; - for (i = 0; i < 8; ++i) - hostdata->busy[i] = 0; -#ifdef REAL_DMA - hostdata->dmalen = 0; -#endif - hostdata->targets_present = 0; - hostdata->connected = NULL; - hostdata->issue_queue = NULL; - hostdata->disconnected_queue = NULL; - - /* The CHECK code seems to break the 53C400. Will check it later maybe */ - if (flags & FLAG_NCR53C400) - hostdata->flags = FLAG_HAS_LAST_BYTE_SENT | flags; - else - hostdata->flags = FLAG_CHECK_LAST_BYTE_SENT | flags; - - if (!the_template) { - the_template = instance->hostt; - first_instance = instance; - } - - -#ifdef USLEEP - hostdata->time_expires = 0; - hostdata->next_timer = NULL; -#endif - -#ifndef AUTOSENSE - if ((instance->cmd_per_lun > 1) || instance->can_queue > 1)) - printk("scsi%d : WARNING : support for multiple outstanding commands enabled\n" - " without AUTOSENSE option, contingent allegiance conditions may\n" - " be incorrectly cleared.\n", instance->host_no); -#endif /* def AUTOSENSE */ - - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - NCR5380_write(MODE_REG, MR_BASE); - NCR5380_write(TARGET_COMMAND_REG, 0); - NCR5380_write(SELECT_ENABLE_REG, 0); - -#ifdef NCR53C400 - if (hostdata->flags & FLAG_NCR53C400) { - NCR5380_write(C400_CONTROL_STATUS_REG, CSR_BASE); - } -#endif - - /* - * Detect and correct bus wedge problems. - * - * If the system crashed, it may have crashed in a state - * where a SCSI command was still executing, and the - * SCSI bus is not in a BUS FREE STATE. - * - * If this is the case, we'll try to abort the currently - * established nexus which we know nothing about, and that - * failing, do a hard reset of the SCSI bus - */ - - for (pass = 1; (NCR5380_read(STATUS_REG) & SR_BSY) && - pass <= 6 ; ++pass) { - switch (pass) { - case 1: - case 3: - case 5: - printk("scsi%d: SCSI bus busy, waiting up to five seconds\n", - instance->host_no); - timeout = jiffies + 500; - while (jiffies < timeout && (NCR5380_read(STATUS_REG) & SR_BSY)); - break; - case 2: - printk("scsi%d: bus busy, attempting abort\n", - instance->host_no); - do_abort (instance); - break; - case 4: - printk("scsi%d: bus busy, attempting reset\n", - instance->host_no); - do_reset (instance); - break; - case 6: - printk("scsi%d: bus locked solid or invalid override\n", - instance->host_no); - } - } -} - -/* - * Function : int NCR5380_queue_command (Scsi_Cmnd *cmd, - * void (*done)(Scsi_Cmnd *)) - * - * Purpose : enqueues a SCSI command - * - * Inputs : cmd - SCSI command, done - function called on completion, with - * a pointer to the command descriptor. - * - * Returns : 0 - * - * Side effects : - * cmd is added to the per instance issue_queue, with minor - * twiddling done to the host specific fields of cmd. If the - * main coroutine is not running, it is restarted. - * - */ - -/* Only make static if a wrapper function is used */ -#ifndef NCR5380_queue_command -static -#endif -int NCR5380_queue_command (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) { - struct Scsi_Host *instance = cmd->host; - struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) - instance->hostdata; - Scsi_Cmnd *tmp; - -#if (NDEBUG & NDEBUG_NO_WRITE) - switch (cmd->cmnd[0]) { - case WRITE: - case WRITE_10: - printk("scsi%d : WRITE attempted with NO_WRITE debugging flag set\n", - instance->host_no); - cmd->result = (DID_ERROR << 16); - done(cmd); - return 0; - } -#endif /* (NDEBUG & NDEBUG_NO_WRITE) */ - - - /* - * We use the host_scribble field as a pointer to the next command - * in a queue - */ - - cmd->host_scribble = NULL; - cmd->scsi_done = done; - - cmd->result = 0; - - - /* - * Insert the cmd into the issue queue. Note that REQUEST SENSE - * commands are added to the head of the queue since any command will - * clear the contingent allegiance condition that exists and the - * sense data is only guaranteed to be valid while the condition exists. - */ - - cli(); - if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) { - LIST(cmd, hostdata->issue_queue); - cmd->host_scribble = (unsigned char *) hostdata->issue_queue; - hostdata->issue_queue = cmd; - } else { - for (tmp = (Scsi_Cmnd *) hostdata->issue_queue; tmp->host_scribble; - tmp = (Scsi_Cmnd *) tmp->host_scribble); - LIST(cmd, tmp); - tmp->host_scribble = (unsigned char *) cmd; - } -#if (NDEBUG & NDEBUG_QUEUES) - printk("scsi%d : command added to %s of queue\n", instance->host_no, - (cmd->cmnd[0] == REQUEST_SENSE) ? "head" : "tail"); -#endif - -/* Run the coroutine if it isn't already running. */ - run_main(); - return 0; -} - -/* - * Function : NCR5380_main (void) - * - * Purpose : NCR5380_main is a coroutine that runs as long as more work can - * be done on the NCR5380 host adapters in a system. Both - * NCR5380_queue_command() and NCR5380_intr() will try to start it - * in case it is not running. - * - * NOTE : NCR5380_main exits with interrupts *disabled*, the caller should - * reenable them. This prevents reentrancy and kernel stack overflow. - */ - -static void NCR5380_main (void) { - Scsi_Cmnd *tmp, *prev; - struct Scsi_Host *instance; - struct NCR5380_hostdata *hostdata; - int done; - - /* - * We run (with interrupts disabled) until we're sure that none of - * the host adapters have anything that can be done, at which point - * we set main_running to 0 and exit. - * - * Interrupts are enabled before doing various other internal - * instructions, after we've decided that we need to run through - * the loop again. - * - * this should prevent any race conditions. - */ - - do { - cli(); /* Freeze request queues */ - done = 1; - for (instance = first_instance; instance && - instance->hostt == the_template; instance=instance->next) { - hostdata = (struct NCR5380_hostdata *) instance->hostdata; - cli(); - if (!hostdata->connected) { -#if (NDEBUG & NDEBUG_MAIN) - printk("scsi%d : not connected\n", instance->host_no); -#endif - /* - * Search through the issue_queue for a command destined - * for a target that's not busy. - */ -#if (NDEBUG & NDEBUG_LISTS) - for (tmp= (Scsi_Cmnd *) hostdata->issue_queue, prev=NULL; tmp && (tmp != prev); prev=tmp, tmp=(Scsi_Cmnd*)tmp->host_scribble) - ; - /*printk("%p ", tmp);*/ - if ((tmp == prev) && tmp) printk(" LOOP\n");/* else printk("\n");*/ -#endif - for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, - prev = NULL; tmp; prev = tmp, tmp = (Scsi_Cmnd *) - tmp->host_scribble) { - -#if (NDEBUG & NDEBUG_LISTS) - if (prev != tmp) - printk("MAIN tmp=%p target=%d busy=%d lun=%d\n", tmp, tmp->target, hostdata->busy[tmp->target], tmp->lun); -#endif - /* When we find one, remove it from the issue queue. */ - if (!(hostdata->busy[tmp->target] & (1 << tmp->lun))) { - if (prev) { - REMOVE(prev,prev->host_scribble,tmp,tmp->host_scribble); - prev->host_scribble = tmp->host_scribble; - } else { - REMOVE(-1,hostdata->issue_queue,tmp,tmp->host_scribble); - hostdata->issue_queue = (Scsi_Cmnd *) tmp->host_scribble; - } - tmp->host_scribble = NULL; - - /* reenable interrupts after finding one */ - sti(); - - /* - * Attempt to establish an I_T_L nexus here. - * On success, instance->hostdata->connected is set. - * On failure, we must add the command back to the - * issue queue so we can keep trying. - */ -#if (NDEBUG & (NDEBUG_MAIN | NDEBUG_QUEUES)) - printk("scsi%d : main() : command for target %d lun %d removed from issue_queue\n", - instance->host_no, tmp->target, tmp->lun); -#endif - - /* - * A successful selection is defined as one that - * leaves us with the command connected and - * in hostdata->connected, OR has terminated the - * command. - * - * With successfull commands, we fall through - * and see if we can do an information transfer, - * with failures we will restart. - */ - - if (!NCR5380_select(instance, tmp, - /* - * REQUEST SENSE commands are issued without tagged - * queueing, even on SCSI-II devices because the - * contingent allegiance condition exists for the - * entire unit. - */ - (tmp->cmnd[0] == REQUEST_SENSE) ? TAG_NONE : - TAG_NEXT)) { - break; - } else { - cli(); - LIST(tmp, hostdata->issue_queue); - tmp->host_scribble = (unsigned char *) - hostdata->issue_queue; - hostdata->issue_queue = tmp; - done = 0; - sti(); -#if (NDEBUG & (NDEBUG_MAIN | NDEBUG_QUEUES)) - printk("scsi%d : main(): select() failed, returned to issue_queue\n", - instance->host_no); -#endif - } - } /* if target/lun is not busy */ - } /* for */ - } /* if (!hostdata->connected) */ - - if (hostdata->connected -#ifdef REAL_DMA - && !hostdata->dmalen -#endif -#ifdef USLEEP - && (!hostdata->time_expires || hostdata->time_expires >= jiffies) -#endif - ) { - sti(); -#if (NDEBUG & NDEBUG_MAIN) - printk("scsi%d : main() : performing information transfer\n", - instance->host_no); -#endif - NCR5380_information_transfer(instance); -#if (NDEBUG & NDEBUG_MAIN) - printk("scsi%d : main() : done set false\n", instance->host_no); -#endif - done = 0; - } else - break; - } /* for instance */ - } while (!done); - main_running = 0; -} - -/* - * Function : void NCR5380_intr (int irq) - * - * Purpose : handle interrupts, reestablishing I_T_L or I_T_L_Q nexuses - * from the disconnected queue, and restarting NCR5380_main() - * as required. - * - * Inputs : int irq, irq that caused this interrupt. - * - */ - -static void NCR5380_intr (int irq, struct pt_regs * regs) { - NCR5380_local_declare(); - struct Scsi_Host *instance; - int done; - unsigned char basr; -#if (NDEBUG & NDEBUG_INTR) - printk("scsi : NCR5380 irq %d triggered\n", irq); -#endif - do { - done = 1; - for (instance = first_instance; instance && (instance->hostt == - the_template); instance = instance->next) - if (instance->irq == irq) { - - /* Look for pending interrupts */ - NCR5380_setup(instance); - basr = NCR5380_read(BUS_AND_STATUS_REG); - /* XXX dispatch to appropriate routine if found and done=0 */ - if (basr & BASR_IRQ) { -#if (NDEBUG & NDEBUG_INTR) - NCR5380_print(instance); -#endif - if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == - (SR_SEL | SR_IO)) { - done = 0; - sti(); -#if (NDEBUG & NDEBUG_INTR) - printk("scsi%d : SEL interrupt\n", instance->host_no); -#endif - NCR5380_reselect(instance); - (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG); - } else if (basr & BASR_PARITY_ERROR) { -#if (NDEBUG & NDEBUG_INTR) - printk("scsi%d : PARITY interrupt\n", instance->host_no); -#endif - (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG); - } else if ((NCR5380_read(STATUS_REG) & SR_RST) == SR_RST) { -#if (NDEBUG & NDEBUG_INTR) - printk("scsi%d : RESET interrupt\n", instance->host_no); -#endif - (void)NCR5380_read(RESET_PARITY_INTERRUPT_REG); - } else { -/* - * XXX the rest of the interrupt conditions should *only* occur during a - * DMA transfer, which I haven't gotten around to fixing yet. - */ - -#if defined(REAL_DMA) - /* - * We should only get PHASE MISMATCH and EOP interrupts - * if we have DMA enabled, so do a sanity check based on - * the current setting of the MODE register. - */ - - if ((NCR5380_read(MODE_REG) & MR_DMA) && ((basr & - BASR_END_DMA_TRANSFER) || - !(basr & BASR_PHASE_MATCH))) { - int transfered; - - if (!hostdata->connected) - panic("scsi%d : received end of DMA interrupt with no connected cmd\n", - instance->hostno); - - transfered = (hostdata->dmalen - NCR5380_dma_residual(instance)); - hostdata->connected->SCp.this_residual -= transferred; - hostdata->connected->SCp.ptr += transferred; - hostdata->dmalen = 0; - - (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG); -#if NCR_TIMEOUT - { - unsigned long timeout = jiffies + NCR_TIMEOUT; - - while (NCR5380_read(BUS_AND_STATUS_REG) & BASR_ACK - && jiffies < timeout) - ; - if (jiffies >= timeout) - printk("scsi%d: timeout at NCR5380.c:%d\n", - host->host_no, __LINE__); - } -#else /* NCR_TIMEOUT */ - while (NCR5380_read(BUS_AND_STATUS_REG) & BASR_ACK); -#endif - - NCR5380_write(MODE_REG, MR_BASE); - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - } -#else -#if (NDEBUG & NDEBUG_INTR) - printk("scsi : unknown interrupt, BASR 0x%X, MR 0x%X, SR 0x%x\n", basr, NCR5380_read(MODE_REG), NCR5380_read(STATUS_REG)); -#endif - (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG); -#endif - } - } /* if BASR_IRQ */ - if (!done) - run_main(); - } /* if (instance->irq == irq) */ - } while (!done); -} - -/* - * Function : int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, - * int tag); - * - * Purpose : establishes I_T_L or I_T_L_Q nexus for new or existing command, - * including ARBITRATION, SELECTION, and initial message out for - * IDENTIFY and queue messages. - * - * Inputs : instance - instantiation of the 5380 driver on which this - * target lives, cmd - SCSI command to execute, tag - set to TAG_NEXT for - * new tag, TAG_NONE for untagged queueing, otherwise set to the tag for - * the command that is presently connected. - * - * Returns : -1 if selection could not execute for some reason, - * 0 if selection succeeded or failed because the target - * did not respond. - * - * Side effects : - * If bus busy, arbitration failed, etc, NCR5380_select() will exit - * with registers as they should have been on entry - ie - * SELECT_ENABLE will be set appropriately, the NCR5380 - * will cease to drive any SCSI bus signals. - * - * If successful : I_T_L or I_T_L_Q nexus will be established, - * instance->connected will be set to cmd. - * SELECT interrupt will be disabled. - * - * If failed (no target) : cmd->scsi_done() will be called, and the - * cmd->result host byte set to DID_BAD_TARGET. - */ - -static int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, - int tag) { - NCR5380_local_declare(); - struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata*) - instance->hostdata; - unsigned char tmp[3], phase; - unsigned char *data; - int len; - unsigned long timeout; - NCR5380_setup(instance); - - hostdata->restart_select = 0; -#if defined (NDEBUG) && (NDEBUG & NDEBUG_ARBITRATION) - NCR5380_print(instance); - printk("scsi%d : starting arbitration, id = %d\n", instance->host_no, - instance->this_id); -#endif - cli(); - - /* - * Set the phase bits to 0, otherwise the NCR5380 won't drive the - * data bus during SELECTION. - */ - - NCR5380_write(TARGET_COMMAND_REG, 0); - - - /* - * Start arbitration. - */ - - NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask); - NCR5380_write(MODE_REG, MR_ARBITRATE); - - sti(); - - /* Wait for arbitration logic to complete */ -#if NCR_TIMEOUT - { - unsigned long timeout = jiffies + 2*NCR_TIMEOUT; - - while (!(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS) - && jiffies < timeout) - ; - if (jiffies >= timeout) - { - printk("scsi: arbitration timeout at %d\n", __LINE__); - NCR5380_write(MODE_REG, MR_BASE); - NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); - return -1; - } - } -#else /* NCR_TIMEOUT */ - while (!(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS)); -#endif - -#if (NDEBUG & NDEBUG_ARBITRATION) - printk("scsi%d : arbitration complete\n", instance->host_no); -/* Avoid GCC 2.4.5 asm needs to many reloads error */ - __asm__("nop"); -#endif - - /* - * The arbitration delay is 2.2us, but this is a minimum and there is - * no maximum so we can safely sleep for ceil(2.2) usecs to accommodate - * the integral nature of udelay(). - * - */ - - udelay(3); - - /* Check for lost arbitration */ - if ((NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) || - (NCR5380_read(CURRENT_SCSI_DATA_REG) & hostdata->id_higher_mask) || - (NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST)) { - NCR5380_write(MODE_REG, MR_BASE); -#if (NDEBUG & NDEBUG_ARBITRATION) - printk("scsi%d : lost arbitration, deasserting MR_ARBITRATE\n", - instance->host_no); -#endif - return -1; - } - - - - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_SEL); - - if (NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) { - NCR5380_write(MODE_REG, MR_BASE); - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); -#if (NDEBUG & NDEBUG_ARBITRATION) - printk("scsi%d : lost arbitration, deasserting ICR_ASSERT_SEL\n", - instance->host_no); -#endif - return -1; - } - - /* - * Again, bus clear + bus settle time is 1.2us, however, this is - * a minimum so we'll udelay ceil(1.2) - */ - - udelay(2); - -#if (NDEBUG & NDEBUG_ARBITRATION) - printk("scsi%d : won arbitration\n", instance->host_no); -#endif - - - /* - * Now that we have won arbitration, start Selection process, asserting - * the host and target ID's on the SCSI bus. - */ - - NCR5380_write(OUTPUT_DATA_REG, (hostdata->id_mask | (1 << cmd->target))); - - /* - * Raise ATN while SEL is true before BSY goes false from arbitration, - * since this is the only way to guarantee that we'll get a MESSAGE OUT - * phase immediately after selection. - */ - - NCR5380_write(INITIATOR_COMMAND_REG, (ICR_BASE | ICR_ASSERT_BSY | - ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_SEL )); - NCR5380_write(MODE_REG, MR_BASE); - - /* - * Reselect interrupts must be turned off prior to the dropping of BSY, - * otherwise we will trigger an interrupt. - */ - NCR5380_write(SELECT_ENABLE_REG, 0); - - /* - * The initiator shall then wait at least two deskew delays and release - * the BSY signal. - */ - udelay(1); /* wingel -- wait two bus deskew delay >2*45ns */ - - /* Reset BSY */ - NCR5380_write(INITIATOR_COMMAND_REG, (ICR_BASE | ICR_ASSERT_DATA | - ICR_ASSERT_ATN | ICR_ASSERT_SEL)); - - /* - * Something weird happens when we cease to drive BSY - looks - * like the board/chip is letting us do another read before the - * appropriate propagation delay has expired, and we're confusing - * a BSY signal from ourselves as the target's response to SELECTION. - * - * A small delay (the 'C++' frontend breaks the pipeline with an - * unnecessary jump, making it work on my 386-33/Trantor T128, the - * tighter 'C' code breaks and requires this) solves the problem - - * the 1 us delay is arbitrary, and only used because this delay will - * be the same on other platforms and since it works here, it should - * work there. - * - * wingel suggests that this could be due to failing to wait - * one deskew delay. - */ - - udelay(1); - -#if (NDEBUG & NDEBUG_SELECTION) - printk("scsi%d : selecting target %d\n", instance->host_no, cmd->target); -#endif - - /* - * The SCSI specification calls for a 250 ms timeout for the actual - * selection. - */ - - timeout = jiffies + 25; - - /* - * XXX very interesting - we're seeing a bounce where the BSY we - * asserted is being reflected / still asserted (propagation delay?) - * and it's detecting as true. Sigh. - */ - - while ((jiffies < timeout) && !(NCR5380_read(STATUS_REG) & - (SR_BSY | SR_IO))); - - if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == - (SR_SEL | SR_IO)) { - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - NCR5380_reselect(instance); - printk ("scsi%d : reselection after won arbitration?\n", - instance->host_no); - NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); - return -1; - } - - /* - * No less than two deskew delays after the initiator detects the - * BSY signal is true, it shall release the SEL signal and may - * change the DATA BUS. -wingel - */ - - udelay(1); - - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN); - - if (!(NCR5380_read(STATUS_REG) & SR_BSY)) { - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - if (hostdata->targets_present & (1 << cmd->target)) { - printk("scsi%d : weirdness\n", instance->host_no); - if (hostdata->restart_select) - printk("\trestart select\n"); -#ifdef NDEBUG - NCR5380_print (instance); -#endif - NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); - return -1; - } - cmd->result = DID_BAD_TARGET << 16; - cmd->scsi_done(cmd); - NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); -#if (NDEBUG & NDEBUG_SELECTION) - printk("scsi%d : target did not respond within 250ms\n", - instance->host_no); -#endif - NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); - return 0; - } - - hostdata->targets_present |= (1 << cmd->target); - - /* - * Since we followed the SCSI spec, and raised ATN while SEL - * was true but before BSY was false during selection, the information - * transfer phase should be a MESSAGE OUT phase so that we can send the - * IDENTIFY message. - * - * If SCSI-II tagged queuing is enabled, we also send a SIMPLE_QUEUE_TAG - * message (2 bytes) with a tag ID that we increment with every command - * until it wraps back to 0. - * - * XXX - it turns out that there are some broken SCSI-II devices, - * which claim to support tagged queuing but fail when more than - * some number of commands are issued at once. - */ - - /* Wait for start of REQ/ACK handshake */ -#ifdef NCR_TIMEOUT - { - unsigned long timeout = jiffies + NCR_TIMEOUT; - - while (!(NCR5380_read(STATUS_REG) & SR_REQ) && jiffies < timeout); - - if (jiffies >= timeout) { - printk("scsi%d: timeout at NCR5380.c:%d\n", __LINE__); - NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); - return -1; - } - } -#else /* NCR_TIMEOUT */ - while (!(NCR5380_read(STATUS_REG) & SR_REQ)); -#endif /* def NCR_TIMEOUT */ - -#if (NDEBUG & NDEBUG_SELECTION) - printk("scsi%d : target %d selected, going into MESSAGE OUT phase.\n", - instance->host_no, cmd->target); -#endif - tmp[0] = IDENTIFY(((instance->irq == IRQ_NONE) ? 0 : 1), cmd->lun); -#ifdef SCSI2 - if (cmd->device->tagged_queue && (tag != TAG_NONE)) { - tmp[1] = SIMPLE_QUEUE_TAG; - if (tag == TAG_NEXT) { - /* 0 is TAG_NONE, used to imply no tag for this command */ - if (cmd->device->current_tag == 0) - cmd->device->current_tag = 1; - - cmd->tag = cmd->device->current_tag; - cmd->device->current_tag++; - } else - cmd->tag = (unsigned char) tag; - - tmp[2] = cmd->tag; - hostdata->last_message = SIMPLE_QUEUE_TAG; - len = 3; - } else -#endif /* def SCSI2 */ - { - len = 1; - cmd->tag=0; - } - - /* Send message(s) */ - data = tmp; - phase = PHASE_MSGOUT; - NCR5380_transfer_pio(instance, &phase, &len, &data); -#if (NDEBUG & NDEBUG_SELECTION) - printk("scsi%d : nexus established.\n", instance->host_no); -#endif - /* XXX need to handle errors here */ - hostdata->connected = cmd; -#ifdef SCSI2 - if (!cmd->device->tagged_queue) -#endif - hostdata->busy[cmd->target] |= (1 << cmd->lun); - - initialize_SCp(cmd); - - - return 0; -} - -/* - * Function : int NCR5380_transfer_pio (struct Scsi_Host *instance, - * unsigned char *phase, int *count, unsigned char **data) - * - * Purpose : transfers data in given phase using polled I/O - * - * Inputs : instance - instance of driver, *phase - pointer to - * what phase is expected, *count - pointer to number of - * bytes to transfer, **data - pointer to data pointer. - * - * Returns : -1 when different phase is entered without transferring - * maximum number of bytes, 0 if all bytes or transfered or exit - * is in same phase. - * - * Also, *phase, *count, *data are modified in place. - * - * XXX Note : handling for bus free may be useful. - */ - -/* - * Note : this code is not as quick as it could be, however it - * IS 100% reliable, and for the actual data transfer where speed - * counts, we will always do a pseudo DMA or DMA transfer. - */ - -static int NCR5380_transfer_pio (struct Scsi_Host *instance, - unsigned char *phase, int *count, unsigned char **data) { - NCR5380_local_declare(); - register unsigned char p = *phase, tmp; - register int c = *count; - register unsigned char *d = *data; - NCR5380_setup(instance); - -#if (NDEBUG & NDEBUG_PIO) - if (!(p & SR_IO)) - printk("scsi%d : pio write %d bytes\n", instance->host_no, c); - else - printk("scsi%d : pio read %d bytes\n", instance->host_no, c); -#endif - - /* - * The NCR5380 chip will only drive the SCSI bus when the - * phase specified in the appropriate bits of the TARGET COMMAND - * REGISTER match the STATUS REGISTER - */ - - NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p)); - - do { - /* - * Wait for assertion of REQ, after which the phase bits will be - * valid - */ - while (!((tmp = NCR5380_read(STATUS_REG)) & SR_REQ)); - -#if (NDEBUG & NDEBUG_HANDSHAKE) - printk("scsi%d : REQ detected\n", instance->host_no); -#endif - - /* Check for phase mismatch */ - if ((tmp & PHASE_MASK) != p) { -#if (NDEBUG & NDEBUG_PIO) - printk("scsi%d : phase mismatch\n", instance->host_no); - NCR5380_print_phase(instance); -#endif - break; - } - - /* Do actual transfer from SCSI bus to / from memory */ - if (!(p & SR_IO)) - NCR5380_write(OUTPUT_DATA_REG, *d); - else - *d = NCR5380_read(CURRENT_SCSI_DATA_REG); - - ++d; - - /* - * The SCSI standard suggests that in MSGOUT phase, the initiator - * should drop ATN on the last byte of the message phase - * after REQ has been asserted for the handshake but before - * the initiator raises ACK. - */ - - if (!(p & SR_IO)) { - if (!((p & SR_MSG) && c > 1)) { - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | - ICR_ASSERT_DATA); -#if (NDEBUG & NDEBUG_PIO) - NCR5380_print(instance); -#endif - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | - ICR_ASSERT_DATA | ICR_ASSERT_ACK); - } else { - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | - ICR_ASSERT_DATA | ICR_ASSERT_ATN); -#if (NDEBUG & NDEBUG_PIO) - NCR5380_print(instance); -#endif - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | - ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_ACK); - } - } else { -#if (NDEBUG & NDEBUG_PIO) - NCR5380_print(instance); -#endif - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ACK); - } - - while (NCR5380_read(STATUS_REG) & SR_REQ); - -#if (NDEBUG & NDEBUG_HANDSHAKE) - printk("scsi%d : req false, handshake complete\n", instance->host_no); -#endif - -/* - * We have several special cases to consider during REQ/ACK handshaking : - * 1. We were in MSGOUT phase, and we are on the last byte of the - * message. ATN must be dropped as ACK is dropped. - * - * 2. We are in a MSGIN phase, and we are on the last byte of the - * message. We must exit with ACK asserted, so that the calling - * code may raise ATN before dropping ACK to reject the message. - * - * 3. ACK and ATN are clear and the target may proceed as normal. - */ - if (!(p == PHASE_MSGIN && c == 1)) { - if (p == PHASE_MSGOUT && c > 1) - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN); - else - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - } - } while (--c); - -#if (NDEBUG & NDEBUG_PIO) - printk("scsi%d : residual %d\n", instance->host_no, c); -#endif - - *count = c; - *data = d; - tmp = NCR5380_read(STATUS_REG); - if (tmp & SR_REQ) - *phase = tmp & PHASE_MASK; - else - *phase = PHASE_UNKNOWN; - - if (!c || (*phase == p)) - return 0; - else - return -1; -} - -static void do_reset (struct Scsi_Host *host) { - NCR5380_local_declare(); - NCR5380_setup(host); - - cli(); - NCR5380_write(TARGET_COMMAND_REG, - PHASE_SR_TO_TCR(NCR5380_read(STATUS_REG) & PHASE_MASK)); - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST); - udelay(25); - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - sti(); -} - -/* - * Function : do_abort (Scsi_Host *host) - * - * Purpose : abort the currently established nexus. Should only be - * called from a routine which can drop into a - * - * Returns : 0 on success, -1 on failure. - */ - -static int do_abort (struct Scsi_Host *host) { - NCR5380_local_declare(); - unsigned char tmp, *msgptr, phase; - int len; - NCR5380_setup(host); - - - /* Request message out phase */ - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN); - - /* - * Wait for the target to indicate a valid phase by asserting - * REQ. Once this happens, we'll have either a MSGOUT phase - * and can immediately send the ABORT message, or we'll have some - * other phase and will have to source/sink data. - * - * We really don't care what value was on the bus or what value - * the target see's, so we just handshake. - */ - - while (!(tmp = NCR5380_read(STATUS_REG)) & SR_REQ); - - NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp)); - - if ((tmp & PHASE_MASK) != PHASE_MSGOUT) { - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN | - ICR_ASSERT_ACK); - while (NCR5380_read(STATUS_REG) & SR_REQ); - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN); - } - - tmp = ABORT; - msgptr = &tmp; - len = 1; - phase = PHASE_MSGOUT; - NCR5380_transfer_pio (host, &phase, &len, &msgptr); - - /* - * If we got here, and the command completed successfully, - * we're about to go into bus free state. - */ - - return len ? -1 : 0; -} - -#if defined(REAL_DMA) || defined(PSEUDO_DMA) || defined (REAL_DMA_POLL) -/* - * Function : int NCR5380_transfer_dma (struct Scsi_Host *instance, - * unsigned char *phase, int *count, unsigned char **data) - * - * Purpose : transfers data in given phase using either real - * or pseudo DMA. - * - * Inputs : instance - instance of driver, *phase - pointer to - * what phase is expected, *count - pointer to number of - * bytes to transfer, **data - pointer to data pointer. - * - * Returns : -1 when different phase is entered without transferring - * maximum number of bytes, 0 if all bytes or transfered or exit - * is in same phase. - * - * Also, *phase, *count, *data are modified in place. - * - */ - - -static int NCR5380_transfer_dma (struct Scsi_Host *instance, - unsigned char *phase, int *count, unsigned char **data) { - NCR5380_local_declare(); - register int c = *count; - register unsigned char p = *phase; - register unsigned char *d = *data; - unsigned char tmp; - int foo; -#if defined(REAL_DMA_POLL) - int cnt, toPIO; - unsigned char saved_data = 0, overrun = 0, residue; -#endif - - struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) - instance->hostdata; - - NCR5380_setup(instance); - - if ((tmp = (NCR5380_read(STATUS_REG) & PHASE_MASK)) != p) { - *phase = tmp; - return -1; - } -#if defined(REAL_DMA) || defined(REAL_DMA_POLL) -#ifdef READ_OVERRUNS - if (p & SR_IO) { - c -= 2; - } -#endif -#if (NDEBUG & NDEBUG_DMA) - printk("scsi%d : initializing DMA channel %d for %s, %d bytes %s %0x\n", - instance->host_no, instance->dma_channel, (p & SR_IO) ? "reading" : - "writing", c, (p & SR_IO) ? "to" : "from", (unsigned) d); -#endif - hostdata->dma_len = (p & SR_IO) ? - NCR5380_dma_read_setup(instance, d, c) : - NCR5380_dma_write_setup(instance, d, c); -#endif - - NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p)); - -#ifdef REAL_DMA - NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_ENABLE_EOP_INTR | MR_MONITOR_BSY); -#elif defined(REAL_DMA_POLL) - NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE); -#else - /* - * Note : on my sample board, watch-dog timeouts occurred when interrupts - * were not disabled for the duration of a single DMA transfer, from - * before the setting of DMA mode to after transfer of the last byte. - */ - -#if defined(PSEUDO_DMA) && !defined(UNSAFE) - cli(); -#endif - /* KLL May need eop and parity in 53c400 */ - if (hostdata->flags & FLAG_NCR53C400) - NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_ENABLE_PAR_CHECK - | MR_ENABLE_PAR_INTR | MR_ENABLE_EOP_INTR | MR_DMA_MODE - | MR_MONITOR_BSY); - else - NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE); -#endif /* def REAL_DMA */ - -#if (NDEBUG & NDEBUG_DMA) & 0 - printk("scsi%d : mode reg = 0x%X\n", instance->host_no, NCR5380_read(MODE_REG)); -#endif - -/* - * FOO stuff. For some UNAPPARENT reason, I'm getting - * watchdog timers fired on bootup for NO APPARENT REASON, meaning it's - * probably a timing problem. - * - * Since this is the only place I have back-to-back writes, perhaps this - * is the problem? - */ - - if (p & SR_IO) { -#ifndef FOO - udelay(1); -#endif - NCR5380_write(START_DMA_INITIATOR_RECEIVE_REG, 0); - } else { -#ifndef FOO - udelay(1); -#endif - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA); -#ifndef FOO - udelay(1); -#endif - NCR5380_write(START_DMA_SEND_REG, 0); -#ifndef FOO - udelay(1); -#endif - } - -#if defined(REAL_DMA_POLL) - do { - tmp = NCR5380_read(BUS_AND_STATUS_REG); - } while ((tmp & BASR_PHASE_MATCH) && !(tmp & (BASR_BUSY_ERROR | - BASR_END_DMA_TRANSFER))); - -/* - At this point, either we've completed DMA, or we have a phase mismatch, - or we've unexpectedly lost BUSY (which is a real error). - - For write DMAs, we want to wait until the last byte has been - transferred out over the bus before we turn off DMA mode. Alas, there - seems to be no terribly good way of doing this on a 5380 under all - conditions. For non-scatter-gather operations, we can wait until REQ - and ACK both go false, or until a phase mismatch occurs. Gather-writes - are nastier, since the device will be expecting more data than we - are prepared to send it, and REQ will remain asserted. On a 53C8[01] we - could test LAST BIT SENT to assure transfer (I imagine this is precisely - why this signal was added to the newer chips) but on the older 538[01] - this signal does not exist. The workaround for this lack is a watchdog; - we bail out of the wait-loop after a modest amount of wait-time if - the usual exit conditions are not met. Not a terribly clean or - correct solution :-% - - Reads are equally tricky due to a nasty characteristic of the NCR5380. - If the chip is in DMA mode for an READ, it will respond to a target's - REQ by latching the SCSI data into the INPUT DATA register and asserting - ACK, even if it has _already_ been notified by the DMA controller that - the current DMA transfer has completed! If the NCR5380 is then taken - out of DMA mode, this already-acknowledged byte is lost. - - This is not a problem for "one DMA transfer per command" reads, because - the situation will never arise... either all of the data is DMA'ed - properly, or the target switches to MESSAGE IN phase to signal a - disconnection (either operation bringing the DMA to a clean halt). - However, in order to handle scatter-reads, we must work around the - problem. The chosen fix is to DMA N-2 bytes, then check for the - condition before taking the NCR5380 out of DMA mode. One or two extra - bytes are transferred via PIO as necessary to fill out the original - request. -*/ - - if (p & SR_IO) { -#ifdef READ_OVERRUNS - udelay(10); - if (((NCR5380_read(BUS_AND_STATUS_REG) & (BASR_PHASE_MATCH|BASR_ACK)) == - (BASR_PHASE_MATCH | BASR_ACK))) { - saved_data = NCR5380_read(INPUT_DATA_REGISTER); - overrun = 1; - } -#endif - } else { - int limit = 100; - while (((tmp = NCR5380_read(BUS_AND_STATUS_REG)) & BASR_ACK) || - (NCR5380_read(STATUS_REG) & SR_REQ)) { - if (!(tmp & BASR_PHASE_MATCH)) break; - if (--limit < 0) break; - } - } - - -#if (NDEBUG & NDEBUG_DMA) - printk("scsi%d : polled DMA transfer complete, basr 0x%X, sr 0x%X\n", - instance->host_no, tmp, NCR5380_read(STATUS_REG)); -#endif - - NCR5380_write(MODE_REG, MR_BASE); - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - - residue = NCR5380_dma_residual(instance); - c -= residue; - *count -= c; - *data += c; - *phase = NCR5380_read(STATUS_REG) & PHASE_MASK; - -#ifdef READ_OVERRUNS - if (*phase == p && (p & SR_IO) && residue == 0) { - if (overrun) { -#if (NDEBUG & NDEBUG_DMA) - printk("Got an input overrun, using saved byte\n"); -#endif - **data = saved_data; - *data += 1; - *count -= 1; - cnt = toPIO = 1; - } else { - printk("No overrun??\n"); - cnt = toPIO = 2; - } -#if (NDEBUG & NDEBUG_DMA) - printk("Doing %d-byte PIO to 0x%X\n", cnt, *data); -#endif - NCR5380_transfer_pio(instance, phase, &cnt, data); - *count -= toPIO - cnt; - } -#endif - -#if (NDEBUG & NDEBUG_DMA) - printk("Return with data ptr = 0x%X, count %d, last 0x%X, next 0x%X\n", - *data, *count, *(*data+*count-1), *(*data+*count)); -#endif - return 0; - -#elif defined(REAL_DMA) - return 0; -#else /* defined(REAL_DMA_POLL) */ - if (p & SR_IO) { - int diff = 1; - if (hostdata->flags & FLAG_NCR53C400) { - diff=0; - } - - if (!(foo = NCR5380_pread(instance, d, c - diff))) { - /* - * We can't disable DMA mode after successfully transferring - * what we plan to be the last byte, since that would open up - * a race condition where if the target asserted REQ before - * we got the DMA mode reset, the NCR5380 would have latched - * an additional byte into the INPUT DATA register and we'd - * have dropped it. - * - * The workaround was to transfer one fewer bytes than we - * intended to with the pseudo-DMA read function, wait for - * the chip to latch the last byte, read it, and then disable - * pseudo-DMA mode. - * - * After REQ is asserted, the NCR5380 asserts DRQ and ACK. - * REQ is deasserted when ACK is asserted, and not reasserted - * until ACK goes false. Since the NCR5380 won't lower ACK - * until DACK is asserted, which won't happen unless we twiddle - * the DMA port or we take the NCR5380 out of DMA mode, we - * can guarantee that we won't handshake another extra - * byte. - */ - - if (!(hostdata->flags & FLAG_NCR53C400)) { - while (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ)); - /* Wait for clean handshake */ - while (NCR5380_read(STATUS_REG) & SR_REQ); - d[c - 1] = NCR5380_read(INPUT_DATA_REG); - } - } - } else { - int timeout; -#if (NDEBUG & NDEBUG_C400_PWRITE) - printk("About to pwrite %d bytes\n", c); -#endif - if (!(foo = NCR5380_pwrite(instance, d, c))) { - /* - * Wait for the last byte to be sent. If REQ is being asserted for - * the byte we're interested, we'll ACK it and it will go false. - */ - if (!(hostdata->flags & FLAG_HAS_LAST_BYTE_SENT)) { - timeout = 20000; -#if 1 -#if 1 - while (!(NCR5380_read(BUS_AND_STATUS_REG) & - BASR_DRQ) && (NCR5380_read(BUS_AND_STATUS_REG) & - BASR_PHASE_MATCH)); -#else - if (NCR5380_read(STATUS_REG) & SR_REQ) { - for (; timeout && - !(NCR5380_read(BUS_AND_STATUS_REG) & BASR_ACK); - --timeout); - for (; timeout && (NCR5380_read(STATUS_REG) & SR_REQ); - --timeout); - } -#endif - - -#if (NDEBUG & NDEBUG_LAST_BYTE_SENT) - if (!timeout) - printk("scsi%d : timed out on last byte\n", - instance->host_no); -#endif - - - if (hostdata->flags & FLAG_CHECK_LAST_BYTE_SENT) { - hostdata->flags &= ~FLAG_CHECK_LAST_BYTE_SENT; - if (NCR5380_read(TARGET_COMMAND_REG) & TCR_LAST_BYTE_SENT) { - hostdata->flags |= FLAG_HAS_LAST_BYTE_SENT; -#if (NDEBUG & NDEBUG_LAST_BYTE_SENT) - printk("scsi%d : last bit sent works\n", - instance->host_no); -#endif - } - } - } else { -#if (NDEBUG & NDEBUG_C400_PWRITE) - printk("Waiting for LASTBYTE\n"); -#endif - while (!(NCR5380_read(TARGET_COMMAND_REG) & TCR_LAST_BYTE_SENT)); -#if (NDEBUG & NDEBUG_C400_PWRITE) - printk("Got LASTBYTE\n"); -#endif - } -#else - udelay (5); -#endif - } - } - - NCR5380_write(MODE_REG, MR_BASE); - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - - if ((!(p & SR_IO)) && (hostdata->flags & FLAG_NCR53C400)) { -#if (NDEBUG & NDEBUG_C400_PWRITE) - printk("53C400w: Checking for IRQ\n"); -#endif - if (NCR5380_read(BUS_AND_STATUS_REG) & BASR_IRQ) { -#if (NDEBUG & NDEBUG_C400_PWRITE) - printk("53C400w: got it, reading reset interupt reg\n"); -#endif - NCR5380_read(RESET_PARITY_INTERRUPT_REG); - } else { - printk("53C400w: IRQ NOT THERE!\n"); - } - } - - *data = d + c; - *count = 0; - *phase = (NCR5380_read(STATUS_REG & PHASE_MASK)); -#if 0 - NCR5380_print_phase(instance); -#endif -#if defined(PSEUDO_DMA) && !defined(UNSAFE) - sti(); -#endif /* defined(REAL_DMA_POLL) */ - return foo; -#endif /* def REAL_DMA */ -} -#endif /* defined(REAL_DMA) | defined(PSEUDO_DMA) */ - -/* - * Function : NCR5380_information_transfer (struct Scsi_Host *instance) - * - * Purpose : run through the various SCSI phases and do as the target - * directs us to. Operates on the currently connected command, - * instance->connected. - * - * Inputs : instance, instance for which we are doing commands - * - * Side effects : SCSI things happen, the disconnected queue will be - * modified if a command disconnects, *instance->connected will - * change. - * - * XXX Note : we need to watch for bus free or a reset condition here - * to recover from an unexpected bus free condition. - */ - -static void NCR5380_information_transfer (struct Scsi_Host *instance) { - NCR5380_local_declare(); - struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) - instance->hostdata; - unsigned char msgout = NOP; - int sink = 0; - int len; -#if defined(PSEUDO_DMA) || defined(REAL_DMA_POLL) - int transfersize; -#endif - unsigned char *data; - unsigned char phase, tmp, extended_msg[10], old_phase=0xff; - Scsi_Cmnd *cmd = (Scsi_Cmnd *) hostdata->connected; - NCR5380_setup(instance); - - while (1) { - tmp = NCR5380_read(STATUS_REG); - /* We only have a valid SCSI phase when REQ is asserted */ - if (tmp & SR_REQ) { - phase = (tmp & PHASE_MASK); - if (phase != old_phase) { - old_phase = phase; -#if (NDEBUG & NDEBUG_INFORMATION) - NCR5380_print_phase(instance); -#endif - } - - if (sink && (phase != PHASE_MSGOUT)) { - NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp)); - - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN | - ICR_ASSERT_ACK); - while (NCR5380_read(STATUS_REG) & SR_REQ); - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | - ICR_ASSERT_ATN); - sink = 0; - continue; - } - - switch (phase) { - case PHASE_DATAIN: - case PHASE_DATAOUT: -#if (NDEBUG & NDEBUG_NO_DATAOUT) - printk("scsi%d : NDEBUG_NO_DATAOUT set, attempted DATAOUT aborted\n", - instance->host_no); - sink = 1; - do_abort(instance); - cmd->result = DID_ERROR << 16; - cmd->done(cmd); - return; -#endif - /* - * If there is no room left in the current buffer in the - * scatter-gather list, move onto the next one. - */ - - if (!cmd->SCp.this_residual && cmd->SCp.buffers_residual) { - ++cmd->SCp.buffer; - --cmd->SCp.buffers_residual; - cmd->SCp.this_residual = cmd->SCp.buffer->length; - cmd->SCp.ptr = cmd->SCp.buffer->address; -#if (NDEBUG & NDEBUG_INFORMATION) - printk("scsi%d : %d bytes and %d buffers left\n", - instance->host_no, cmd->SCp.this_residual, - cmd->SCp.buffers_residual); -#endif - } - - /* - * The preferred transfer method is going to be - * PSEUDO-DMA for systems that are strictly PIO, - * since we can let the hardware do the handshaking. - * - * For this to work, we need to know the transfersize - * ahead of time, since the pseudo-DMA code will sit - * in an unconditional loop. - */ - -#if defined(PSEUDO_DMA) || defined(REAL_DMA_POLL) - /* KLL - * PSEUDO_DMA is defined here. If this is the g_NCR5380 - * driver then it will always be defined, so the - * FLAG_NO_PSEUDO_DMA is used to inhibit PDMA in the base - * NCR5380 case. I think this is a fairly clean solution. - * We supplement these 2 if's with the flag. - */ -#ifdef NCR5380_dma_xfer_len - if (!cmd->device->borken && - !(hostdata->flags & FLAG_NO_PSEUDO_DMA) && - (transfersize = NCR5380_dma_xfer_len(instance, cmd)) != 0) { -#else - transfersize = cmd->transfersize; - -#ifdef LIMIT_TRANSFERSIZE /* If we have problems with interrupt service */ - if( transfersize > 512 ) - transfersize = 512; -#endif /* LIMIT_TRANSFERSIZE */ - - if (!cmd->device->borken && transfersize && - !(hostdata->flags & FLAG_NO_PSEUDO_DMA) && - cmd->SCp.this_residual && !(cmd->SCp.this_residual % - transfersize)) { -#endif - len = transfersize; - if (NCR5380_transfer_dma(instance, &phase, - &len, (unsigned char **) &cmd->SCp.ptr)) { - /* - * If the watchdog timer fires, all future accesses to this - * device will use the polled-IO. - */ - printk("scsi%d : switching target %d lun %d to slow handshake\n", - instance->host_no, cmd->target, cmd->lun); - cmd->device->borken = 1; - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | - ICR_ASSERT_ATN); - sink = 1; - do_abort(instance); - cmd->result = DID_ERROR << 16; - cmd->done(cmd); - /* XXX - need to source or sink data here, as appropriate */ - } else - cmd->SCp.this_residual -= transfersize - len; - } else -#endif /* defined(PSEUDO_DMA) || defined(REAL_DMA_POLL) */ - NCR5380_transfer_pio(instance, &phase, - (int *) &cmd->SCp.this_residual, (unsigned char **) - &cmd->SCp.ptr); - break; - case PHASE_MSGIN: - len = 1; - data = &tmp; - NCR5380_transfer_pio(instance, &phase, &len, &data); - cmd->SCp.Message = tmp; - - switch (tmp) { - /* - * Linking lets us reduce the time required to get the - * next command out to the device, hopefully this will - * mean we don't waste another revolution due to the delays - * required by ARBITRATION and another SELECTION. - * - * In the current implementation proposal, low level drivers - * merely have to start the next command, pointed to by - * next_link, done() is called as with unlinked commands. - */ -#ifdef LINKED - case LINKED_CMD_COMPLETE: - case LINKED_FLG_CMD_COMPLETE: - /* Accept message by clearing ACK */ - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - -#if (NDEBUG & NDEBUG_LINKED) - printk("scsi%d : target %d lun %d linked command complete.\n", - instance->host_no, cmd->target, cmd->lun); -#endif - /* - * Sanity check : A linked command should only terminate with - * one of these messages if there are more linked commands - * available. - */ - - if (!cmd->next_link) { - printk("scsi%d : target %d lun %d linked command complete, no next_link\n" - instance->host_no, cmd->target, cmd->lun); - sink = 1; - do_abort (instance); - return; - } - - initialize_SCp(cmd->next_link); - /* The next command is still part of this process */ - cmd->next_link->tag = cmd->tag; - cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8); -#if (NDEBUG & NDEBUG_LINKED) - printk("scsi%d : target %d lun %d linked request done, calling scsi_done().\n", - instance->host_no, cmd->target, cmd->lun); -#endif - cmd->scsi_done(cmd); - cmd = hostdata->connected; - break; -#endif /* def LINKED */ - case ABORT: - case COMMAND_COMPLETE: - /* Accept message by clearing ACK */ - sink = 1; - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - hostdata->connected = NULL; -#if (NDEBUG & NDEBUG_QUEUES) - printk("scsi%d : command for target %d, lun %d completed\n", - instance->host_no, cmd->target, cmd->lun); -#endif - hostdata->busy[cmd->target] &= ~(1 << cmd->lun); - - /* - * I'm not sure what the correct thing to do here is : - * - * If the command that just executed is NOT a request - * sense, the obvious thing to do is to set the result - * code to the values of the stored parameters. - * - * If it was a REQUEST SENSE command, we need some way - * to differentiate between the failure code of the original - * and the failure code of the REQUEST sense - the obvious - * case is success, where we fall through and leave the result - * code unchanged. - * - * The non-obvious place is where the REQUEST SENSE failed - */ - - if (cmd->cmnd[0] != REQUEST_SENSE) - cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8); - else if (cmd->SCp.Status != GOOD) - cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16); - -#ifdef AUTOSENSE - if ((cmd->cmnd[0] != REQUEST_SENSE) && - (cmd->SCp.Status == CHECK_CONDITION)) { -#if (NDEBUG & NDEBUG_AUTOSENSE) - printk("scsi%d : performing request sense\n", - instance->host_no); -#endif - cmd->cmnd[0] = REQUEST_SENSE; - cmd->cmnd[1] &= 0xe0; - cmd->cmnd[2] = 0; - cmd->cmnd[3] = 0; - cmd->cmnd[4] = sizeof(cmd->sense_buffer); - cmd->cmnd[5] = 0; - - cmd->SCp.buffer = NULL; - cmd->SCp.buffers_residual = 0; - cmd->SCp.ptr = (char *) cmd->sense_buffer; - cmd->SCp.this_residual = sizeof(cmd->sense_buffer); - - cli(); - LIST(cmd,hostdata->issue_queue); - cmd->host_scribble = (unsigned char *) - hostdata->issue_queue; - hostdata->issue_queue = (Scsi_Cmnd *) cmd; - sti(); -#if (NDEBUG & NDEBUG_QUEUES) - printk("scsi%d : REQUEST SENSE added to head of issue queue\n",instance->host_no); -#endif - } else -#endif /* def AUTOSENSE */ - cmd->scsi_done(cmd); - - NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); - /* - * Restore phase bits to 0 so an interrupted selection, - * arbitration can resume. - */ - NCR5380_write(TARGET_COMMAND_REG, 0); - - while ((NCR5380_read(STATUS_REG) & SR_BSY) && !hostdata->connected) - barrier(); - return; - case MESSAGE_REJECT: - /* Accept message by clearing ACK */ - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - switch (hostdata->last_message) { - case HEAD_OF_QUEUE_TAG: - case ORDERED_QUEUE_TAG: - case SIMPLE_QUEUE_TAG: - cmd->device->tagged_queue = 0; - hostdata->busy[cmd->target] |= (1 << cmd->lun); - break; - default: - break; - } - case DISCONNECT: - /* Accept message by clearing ACK */ - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - cmd->device->disconnect = 1; - cli(); - LIST(cmd,hostdata->disconnected_queue); - cmd->host_scribble = (unsigned char *) - hostdata->disconnected_queue; - hostdata->connected = NULL; - hostdata->disconnected_queue = cmd; - sti(); -#if (NDEBUG & NDEBUG_QUEUES) - printk("scsi%d : command for target %d lun %d was moved from connected to" - " the disconnected_queue\n", instance->host_no, - cmd->target, cmd->lun); -#endif - /* - * Restore phase bits to 0 so an interrupted selection, - * arbitration can resume. - */ - NCR5380_write(TARGET_COMMAND_REG, 0); - - /* Enable reselect interrupts */ - NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); - /* Wait for bus free to avoid nasty timeouts */ - while ((NCR5380_read(STATUS_REG) & SR_BSY) && !hostdata->connected) - barrier(); -#if 0 - NCR5380_print_status(instance); -#endif - return; - /* - * The SCSI data pointer is *IMPLICITLY* saved on a disconnect - * operation, in violation of the SCSI spec so we can safely - * ignore SAVE/RESTORE pointers calls. - * - * Unfortunately, some disks violate the SCSI spec and - * don't issue the required SAVE_POINTERS message before - * disconnecting, and we have to break spec to remain - * compatible. - */ - case SAVE_POINTERS: - case RESTORE_POINTERS: - /* Accept message by clearing ACK */ - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - break; - case EXTENDED_MESSAGE: -/* - * Extended messages are sent in the following format : - * Byte - * 0 EXTENDED_MESSAGE == 1 - * 1 length (includes one byte for code, doesn't - * include first two bytes) - * 2 code - * 3..length+1 arguments - * - * Start the extended message buffer with the EXTENDED_MESSAGE - * byte, since print_msg() wants the whole thing. - */ - extended_msg[0] = EXTENDED_MESSAGE; - /* Accept first byte by clearing ACK */ - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - -#if (NDEBUG & NDEBUG_EXTENDED) - printk("scsi%d : receiving extended message\n", - instance->host_no); -#endif - - len = 2; - data = extended_msg + 1; - phase = PHASE_MSGIN; - NCR5380_transfer_pio(instance, &phase, &len, &data); - -#if (NDEBUG & NDEBUG_EXTENDED) - printk("scsi%d : length=%d, code=0x%02x\n", - instance->host_no, (int) extended_msg[1], - (int) extended_msg[2]); -#endif - - if (!len && extended_msg[1] <= - (sizeof (extended_msg) - 1)) { - /* Accept third byte by clearing ACK */ - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - len = extended_msg[1] - 1; - data = extended_msg + 3; - phase = PHASE_MSGIN; - - NCR5380_transfer_pio(instance, &phase, &len, &data); - -#if (NDEBUG & NDEBUG_EXTENDED) - printk("scsi%d : message received, residual %d\n", - instance->host_no, len); -#endif - - switch (extended_msg[2]) { - case EXTENDED_SDTR: - case EXTENDED_WDTR: - case EXTENDED_MODIFY_DATA_POINTER: - case EXTENDED_EXTENDED_IDENTIFY: - tmp = 0; - } - } else if (len) { - printk("scsi%d: error receiving extended message\n", - instance->host_no); - tmp = 0; - } else { - printk("scsi%d: extended message code %02x length %d is too long\n", - instance->host_no, extended_msg[2], extended_msg[1]); - tmp = 0; - } - /* Fall through to reject message */ - - /* - * If we get something weird that we aren't expecting, - * reject it. - */ - default: - if (!tmp) { - printk("scsi%d: rejecting message ", instance->host_no); - print_msg (extended_msg); - printk("\n"); - } else if (tmp != EXTENDED_MESSAGE) - printk("scsi%d: rejecting unknown message %02x from target %d, lun %d\n", - instance->host_no, tmp, cmd->target, cmd->lun); - else - printk("scsi%d: rejecting unknown extended message code %02x, length %d from target %d, lun %d\n", - instance->host_no, extended_msg[1], extended_msg[0], cmd->target, cmd->lun); - - msgout = MESSAGE_REJECT; - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | - ICR_ASSERT_ATN); - break; - } /* switch (tmp) */ - break; - case PHASE_MSGOUT: - len = 1; - data = &msgout; - hostdata->last_message = msgout; - NCR5380_transfer_pio(instance, &phase, &len, &data); - if (msgout == ABORT) { - hostdata->busy[cmd->target] &= ~(1 << cmd->lun); - hostdata->connected = NULL; - cmd->result = DID_ERROR << 16; - cmd->scsi_done(cmd); - NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); - return; - } - msgout = NOP; - break; - case PHASE_CMDOUT: - len = cmd->cmd_len; - data = cmd->cmnd; - /* - * XXX for performance reasons, on machines with a - * PSEUDO-DMA architecture we should probably - * use the dma transfer function. - */ - NCR5380_transfer_pio(instance, &phase, &len, - &data); -#ifdef USLEEP - if (!disconnect && should_disconnect(cmd->cmnd[0])) { - hostdata->time_expires = jiffies + USLEEP_SLEEP; -#if (NDEBUG & NDEBUG_USLEEP) - printk("scsi%d : issued command, sleeping until %ul\n", instance->host_no, - hostdata->time_expires); -#endif - NCR5380_set_timer (instance); - return; - } -#endif /* def USLEEP */ - break; - case PHASE_STATIN: - len = 1; - data = &tmp; - NCR5380_transfer_pio(instance, &phase, &len, &data); - cmd->SCp.Status = tmp; - break; - default: - printk("scsi%d : unknown phase\n", instance->host_no); -#ifdef NDEBUG - NCR5380_print(instance); -#endif - } /* switch(phase) */ - } /* if (tmp * SR_REQ) */ -#ifdef USLEEP - else { - if (!disconnect && hostdata->time_expires && jiffies > - hostdata->time_expires) { - hostdata->time_expires = jiffies + USLEEP_SLEEP; -#if (NDEBUG & NDEBUG_USLEEP) - printk("scsi%d : poll timed out, sleeping until %ul\n", instance->host_no, - hostdata->time_expires); -#endif - NCR5380_set_timer (instance); - return; - } - } -#endif - } /* while (1) */ -} - -/* - * Function : void NCR5380_reselect (struct Scsi_Host *instance) - * - * Purpose : does reselection, initializing the instance->connected - * field to point to the Scsi_Cmnd for which the I_T_L or I_T_L_Q - * nexus has been reestablished, - * - * Inputs : instance - this instance of the NCR5380. - * - */ - - -static void NCR5380_reselect (struct Scsi_Host *instance) { - NCR5380_local_declare(); - struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) - instance->hostdata; - unsigned char target_mask; - unsigned char lun, phase; - int len; -#ifdef SCSI2 - unsigned char tag; -#endif - unsigned char msg[3]; - unsigned char *data; - Scsi_Cmnd *tmp = NULL, *prev; - int abort = 0; - NCR5380_setup(instance); - - /* - * Disable arbitration, etc. since the host adapter obviously - * lost, and tell an interrupted NCR5380_select() to restart. - */ - - NCR5380_write(MODE_REG, MR_BASE); - hostdata->restart_select = 1; - - target_mask = NCR5380_read(CURRENT_SCSI_DATA_REG) & ~(hostdata->id_mask); - -#if (NDEBUG & NDEBUG_RESELECTION) - printk("scsi%d : reselect\n", instance->host_no); -#endif - - /* - * At this point, we have detected that our SCSI ID is on the bus, - * SEL is true and BSY was false for at least one bus settle delay - * (400 ns). - * - * We must assert BSY ourselves, until the target drops the SEL - * signal. - */ - - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_BSY); - - while (NCR5380_read(STATUS_REG) & SR_SEL); - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - - /* - * Wait for target to go into MSGIN. - */ - - while (!(NCR5380_read(STATUS_REG) & SR_REQ)); - - len = 1; - data = msg; - phase = PHASE_MSGIN; - NCR5380_transfer_pio(instance, &phase, &len, &data); - - - if (!msg[0] & 0x80) { - printk("scsi%d : expecting IDENTIFY message, got ", - instance->host_no); - print_msg(msg); - abort = 1; - } else { - /* Accept message by clearing ACK */ - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - lun = (msg[0] & 0x07); - - /* - * We need to add code for SCSI-II to track which devices have - * I_T_L_Q nexuses established, and which have simple I_T_L - * nexuses so we can chose to do additional data transfer. - */ - -#ifdef SCSI2 -#error "SCSI-II tagged queueing is not supported yet" -#endif - - /* - * Find the command corresponding to the I_T_L or I_T_L_Q nexus we - * just reestablished, and remove it from the disconnected queue. - */ - - - for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue, prev = NULL; - tmp; prev = tmp, tmp = (Scsi_Cmnd *) tmp->host_scribble) - if ((target_mask == (1 << tmp->target)) && (lun == tmp->lun) -#ifdef SCSI2 - && (tag == tmp->tag) -#endif -) { - if (prev) { - REMOVE(prev,prev->host_scribble,tmp,tmp->host_scribble); - prev->host_scribble = tmp->host_scribble; - } else { - REMOVE(-1,hostdata->disconnected_queue,tmp,tmp->host_scribble); - hostdata->disconnected_queue = (Scsi_Cmnd *) tmp->host_scribble; - } - tmp->host_scribble = NULL; - break; - } - - if (!tmp) { -#ifdef SCSI2 - printk("scsi%d : warning : target bitmask %02x lun %d tag %d not in disconnect_queue.\n", - instance->host_no, target_mask, lun, tag); -#else - printk("scsi%d : warning : target bitmask %02x lun %d not in disconnect_queue.\n", - instance->host_no, target_mask, lun); -#endif - /* - * Since we have an established nexus that we can't do anything with, - * we must abort it. - */ - abort = 1; - } - } - - if (abort) { - do_abort (instance); - } else { - hostdata->connected = tmp; -#if (NDEBUG & NDEBUG_RESELECTION) - printk("scsi%d : nexus established, target = %d, lun = %d, tag = %d\n", - instance->host_no, tmp->target, tmp->lun, tmp->tag); -#endif - } -} - -/* - * Function : void NCR5380_dma_complete (struct Scsi_Host *instance) - * - * Purpose : called by interrupt handler when DMA finishes or a phase - * mismatch occurs (which would finish the DMA transfer). - * - * Inputs : instance - this instance of the NCR5380. - * - * Returns : pointer to the Scsi_Cmnd structure for which the I_T_L - * nexus has been reestablished, on failure NULL is returned. - */ - -#ifdef REAL_DMA -static void NCR5380_dma_complete (NCR5380_instance *instance) { - NCR5380_local_declare(); - struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata * - instance->hostdata); - int transferred; - NCR5380_setup(instance); - - /* - * XXX this might not be right. - * - * Wait for final byte to transfer, ie wait for ACK to go false. - * - * We should use the Last Byte Sent bit, unfortunately this is - * not available on the 5380/5381 (only the various CMOS chips) - */ - - while (NCR5380_read(BUS_AND_STATUS_REG) & BASR_ACK); - - NCR5380_write(MODE_REG, MR_BASE); - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - - /* - * The only places we should see a phase mismatch and have to send - * data from the same set of pointers will be the data transfer - * phases. So, residual, requested length are only important here. - */ - - if (!(hostdata->connected->SCp.phase & SR_CD)) { - transferred = instance->dmalen - NCR5380_dma_residual(); - hostdata->connected->SCp.this_residual -= transferred; - hostdata->connected->SCp.ptr += transferred; - } -} -#endif /* def REAL_DMA */ - -/* - * Function : int NCR5380_abort (Scsi_Cmnd *cmd) - * - * Purpose : abort a command - * - * Inputs : cmd - the Scsi_Cmnd to abort, code - code to set the - * host byte of the result field to, if zero DID_ABORTED is - * used. - * - * Returns : 0 - success, -1 on failure. - * - * XXX - there is no way to abort the command that is currently - * connected, you have to wait for it to complete. If this is - * a problem, we could implement longjmp() / setjmp(), setjmp() - * called where the loop started in NCR5380_main(). - */ - -#ifndef NCR5380_abort -static -#endif -int NCR5380_abort (Scsi_Cmnd *cmd) { - NCR5380_local_declare(); - struct Scsi_Host *instance = cmd->host; - struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) - instance->hostdata; - Scsi_Cmnd *tmp, **prev; - - printk("scsi%d : aborting command\n", instance->host_no); - print_Scsi_Cmnd (cmd); - - NCR5380_print_status (instance); - - printk("scsi%d : aborting command\n", instance->host_no); - print_Scsi_Cmnd (cmd); - - NCR5380_print_status (instance); - - cli(); - NCR5380_setup(instance); - -#if (NDEBUG & NDEBUG_ABORT) - printk("scsi%d : abort called\n", instance->host_no); - printk(" basr 0x%X, sr 0x%X\n", - NCR5380_read(BUS_AND_STATUS_REG), NCR5380_read(STATUS_REG)); -#endif - -#if 0 -/* - * Case 1 : If the command is the currently executing command, - * we'll set the aborted flag and return control so that - * information transfer routine can exit cleanly. - */ - - if (hostdata->connected == cmd) { -#if (NDEBUG & NDEBUG_ABORT) - printk("scsi%d : aborting connected command\n", instance->host_no); -#endif - hostdata->aborted = 1; -/* - * We should perform BSY checking, and make sure we haven't slipped - * into BUS FREE. - */ - - NCR5380_write(INITIATOR_COMMAND_REG, ICR_ASSERT_ATN); -/* - * Since we can't change phases until we've completed the current - * handshake, we have to source or sink a byte of data if the current - * phase is not MSGOUT. - */ - -/* - * Return control to the executing NCR drive so we can clear the - * aborted flag and get back into our main loop. - */ - - return 0; - } -#endif - -/* - * Case 2 : If the command hasn't been issued yet, we simply remove it - * from the issue queue. - */ -#if (NDEBUG & NDEBUG_ABORT) - /* KLL */ - printk("scsi%d : abort going into loop.\n", instance->host_no); -#endif - for (prev = (Scsi_Cmnd **) &(hostdata->issue_queue), - tmp = (Scsi_Cmnd *) hostdata->issue_queue; - tmp; prev = (Scsi_Cmnd **) &(tmp->host_scribble), tmp = - (Scsi_Cmnd *) tmp->host_scribble) - if (cmd == tmp) { - REMOVE(5,*prev,tmp,tmp->host_scribble); - (*prev) = (Scsi_Cmnd *) tmp->host_scribble; - tmp->host_scribble = NULL; - tmp->result = DID_ABORT << 16; - sti(); -#if (NDEBUG & NDEBUG_ABORT) - printk("scsi%d : abort removed command from issue queue.\n", - instance->host_no); -#endif - tmp->done(tmp); - return SCSI_ABORT_SUCCESS; - } -#if (NDEBUG & NDEBUG_ABORT) - /* KLL */ - else if (prev == tmp) printk("scsi%d : LOOP\n", instance->host_no); -#endif - -/* - * Case 3 : If any commands are connected, we're going to fail the abort - * and let the high level SCSI driver retry at a later time or - * issue a reset. - * - * Timeouts, and therefore aborted commands, will be highly unlikely - * and handling them cleanly in this situation would make the common - * case of noresets less efficient, and would pollute our code. So, - * we fail. - */ - - if (hostdata->connected) { - sti(); -#if (NDEBUG & NDEBUG_ABORT) - printk("scsi%d : abort failed, command connected.\n", instance->host_no); -#endif - return SCSI_ABORT_NOT_RUNNING; - } - -/* - * Case 4: If the command is currently disconnected from the bus, and - * there are no connected commands, we reconnect the I_T_L or - * I_T_L_Q nexus associated with it, go into message out, and send - * an abort message. - * - * This case is especially ugly. In order to reestablish the nexus, we - * need to call NCR5380_select(). The easiest way to implement this - * function was to abort if the bus was busy, and let the interrupt - * handler triggered on the SEL for reselect take care of lost arbitrations - * where necessary, meaning interrupts need to be enabled. - * - * When interrupts are enabled, the queues may change - so we - * can't remove it from the disconnected queue before selecting it - * because that could cause a failure in hashing the nexus if that - * device reselected. - * - * Since the queues may change, we can't use the pointers from when we - * first locate it. - * - * So, we must first locate the command, and if NCR5380_select() - * succeeds, then issue the abort, relocate the command and remove - * it from the disconnected queue. - */ - - for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue; tmp; - tmp = (Scsi_Cmnd *) tmp->host_scribble) - if (cmd == tmp) { - sti(); -#if (NDEBUG & NDEBUG_ABORT) - printk("scsi%d : aborting disconnected command.\n", instance->host_no); -#endif - - if (NCR5380_select (instance, cmd, (int) cmd->tag)) - return SCSI_ABORT_BUSY; - -#if (NDEBUG & NDEBUG_ABORT) - printk("scsi%d : nexus reestablished.\n", instance->host_no); -#endif - - do_abort (instance); - - cli(); - for (prev = (Scsi_Cmnd **) &(hostdata->disconnected_queue), - tmp = (Scsi_Cmnd *) hostdata->disconnected_queue; - tmp; prev = (Scsi_Cmnd **) &(tmp->host_scribble), tmp = - (Scsi_Cmnd *) tmp->host_scribble) - if (cmd == tmp) { - REMOVE(5,*prev,tmp,tmp->host_scribble); - *prev = (Scsi_Cmnd *) tmp->host_scribble; - tmp->host_scribble = NULL; - tmp->result = DID_ABORT << 16; - sti(); - tmp->done(tmp); - return SCSI_ABORT_SUCCESS; - } - } - -/* - * Case 5 : If we reached this point, the command was not found in any of - * the queues. - * - * We probably reached this point because of an unlikely race condition - * between the command completing successfully and the abortion code, - * so we won't panic, but we will notify the user in case something really - * broke. - */ - - sti(); - printk("scsi%d : warning : SCSI command probably completed successfully\n" - " before abortion\n", instance->host_no); - return SCSI_ABORT_NOT_RUNNING; -} - - -/* - * Function : int NCR5380_reset (Scsi_Cmnd *cmd) - * - * Purpose : reset the SCSI bus. - * - * Returns : SCSI_RESET_WAKEUP - * - */ - -#ifndef NCR5380_reset -static -#endif -int NCR5380_reset (Scsi_Cmnd *cmd) { - NCR5380_local_declare(); - NCR5380_setup(cmd->host); - - NCR5380_print_status (cmd->host); - do_reset (cmd->host); - - return SCSI_RESET_WAKEUP; -} - diff --git a/i386/i386at/gpl/linux/scsi/NCR53c406a.c b/i386/i386at/gpl/linux/scsi/NCR53c406a.c deleted file mode 100644 index 3105b1bb..00000000 --- a/i386/i386at/gpl/linux/scsi/NCR53c406a.c +++ /dev/null @@ -1,1079 +0,0 @@ -/* - * NCR53c406.c - * Low-level SCSI driver for NCR53c406a chip. - * Copyright (C) 1994, 1995, 1996 Normunds Saumanis (normunds@fi.ibm.com) - * - * LILO command line usage: ncr53c406a=<PORTBASE>[,<IRQ>[,<FASTPIO>]] - * Specify IRQ = 0 for non-interrupt driven mode. - * FASTPIO = 1 for fast pio mode, 0 for slow mode. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - */ - -#define NCR53C406A_DEBUG 0 -#define VERBOSE_NCR53C406A_DEBUG 0 - -/* Set this to 1 for PIO mode (recommended) or to 0 for DMA mode */ -#define USE_PIO 1 - -#define USE_BIOS 0 -/* #define BIOS_ADDR 0xD8000 */ /* define this if autoprobe fails */ -/* #define PORT_BASE 0x330 */ /* define this if autoprobe fails */ -/* #define IRQ_LEV 0 */ /* define this if autoprobe fails */ -#define DMA_CHAN 5 /* this is ignored if DMA is disabled */ - -/* Set this to 0 if you encounter kernel lockups while transferring - * data in PIO mode */ -#define USE_FAST_PIO 1 - -/* ============= End of user configurable parameters ============= */ - -#include <linux/module.h> - -#include <linux/errno.h> -#include <linux/ioport.h> -#include <linux/sched.h> -#include <linux/interrupt.h> -#include <linux/proc_fs.h> -#include <linux/stat.h> -#include <asm/io.h> -#include <asm/dma.h> -#include <asm/bitops.h> -#include <asm/irq.h> - -#include <linux/blk.h> -#include "scsi.h" -#include "hosts.h" -#include "sd.h" - -#include "NCR53c406a.h" - -/* ============================================================= */ - -#define WATCHDOG 5000000 - -#define SYNC_MODE 0 /* Synchrounous transfer mode */ - -#if DEBUG -#undef NCR53C406A_DEBUG -#define NCR53C406A_DEBUG 1 -#endif - -#if USE_PIO -#define USE_DMA 0 -#else -#define USE_DMA 1 -#endif - -/* Default configuration */ -#define C1_IMG 0x07 /* ID=7 */ -#define C2_IMG 0x48 /* FE SCSI2 */ -#if USE_DMA -#define C3_IMG 0x21 /* CDB TE */ -#else -#define C3_IMG 0x20 /* CDB */ -#endif -#define C4_IMG 0x04 /* ANE */ -#define C5_IMG 0xb6 /* AA PI SIE POL */ - -#define REG0 (outb(C4_IMG, CONFIG4)) -#define REG1 (outb(C5_IMG, CONFIG5)) - -#if NCR53C406A_DEBUG -#define DEB(x) x -#else -#define DEB(x) -#endif - -#if VERBOSE_NCR53C406A_DEBUG -#define VDEB(x) x -#else -#define VDEB(x) -#endif - -#define LOAD_DMA_COUNT(count) \ - outb(count & 0xff, TC_LSB); \ - outb((count >> 8) & 0xff, TC_MSB); \ - outb((count >> 16) & 0xff, TC_HIGH); - -/* Chip commands */ -#define DMA_OP 0x80 - -#define SCSI_NOP 0x00 -#define FLUSH_FIFO 0x01 -#define CHIP_RESET 0x02 -#define SCSI_RESET 0x03 -#define RESELECT 0x40 -#define SELECT_NO_ATN 0x41 -#define SELECT_ATN 0x42 -#define SELECT_ATN_STOP 0x43 -#define ENABLE_SEL 0x44 -#define DISABLE_SEL 0x45 -#define SELECT_ATN3 0x46 -#define RESELECT3 0x47 -#define TRANSFER_INFO 0x10 -#define INIT_CMD_COMPLETE 0x11 -#define MSG_ACCEPT 0x12 -#define TRANSFER_PAD 0x18 -#define SET_ATN 0x1a -#define RESET_ATN 0x1b -#define SEND_MSG 0x20 -#define SEND_STATUS 0x21 -#define SEND_DATA 0x22 -#define DISCONN_SEQ 0x23 -#define TERMINATE_SEQ 0x24 -#define TARG_CMD_COMPLETE 0x25 -#define DISCONN 0x27 -#define RECV_MSG 0x28 -#define RECV_CMD 0x29 -#define RECV_DATA 0x2a -#define RECV_CMD_SEQ 0x2b -#define TARGET_ABORT_DMA 0x04 - -/*----------------------------------------------------------------*/ -/* the following will set the monitor border color (useful to find - where something crashed or gets stuck at */ -/* 1 = blue - 2 = green - 3 = cyan - 4 = red - 5 = magenta - 6 = yellow - 7 = white -*/ - -#if NCR53C406A_DEBUG -#define rtrc(i) {inb(0x3da);outb(0x31,0x3c0);outb((i),0x3c0);} -#else -#define rtrc(i) {} -#endif -/*----------------------------------------------------------------*/ - -enum Phase { - idle, - data_out, - data_in, - command_ph, - status_ph, - message_out, - message_in -}; - -/* Static function prototypes */ -static void NCR53c406a_intr(int, struct pt_regs *); -static void internal_done(Scsi_Cmnd *); -static void wait_intr(void); -static void chip_init(void); -static void calc_port_addr(void); -#ifndef IRQ_LEV -static int irq_probe(void); -#endif - -/* ================================================================= */ - -#if USE_BIOS -static void *bios_base = (void *)0; -#endif - -#if PORT_BASE -static int port_base = PORT_BASE; -#else -static int port_base = 0; -#endif - -#if IRQ_LEV -static int irq_level = IRQ_LEV; -#else -static int irq_level = -1; /* 0 is 'no irq', so use -1 for 'uninitialized'*/ -#endif - -#if USE_DMA -static int dma_chan = 0; -#endif - -#if USE_PIO -static int fast_pio = USE_FAST_PIO; -#endif - -static Scsi_Cmnd *current_SC = NULL; -static volatile int internal_done_flag = 0; -static volatile int internal_done_errcode = 0; -static char info_msg[256]; - -struct proc_dir_entry proc_scsi_NCR53c406a = { - PROC_SCSI_NCR53C406A, 7, "NCR53c406a", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; -/* ================================================================= */ - -/* possible BIOS locations */ -#if USE_BIOS -static void *addresses[] = { - (void *)0xd8000, - (void *)0xc8000 -}; -#define ADDRESS_COUNT (sizeof( addresses ) / sizeof( unsigned )) -#endif USE_BIOS - -/* possible i/o port addresses */ -static unsigned short ports[] = { 0x230, 0x330 }; -#define PORT_COUNT (sizeof( ports ) / sizeof( unsigned short )) - -/* possible interrupt channels */ -static unsigned short intrs[] = { 10, 11, 12, 15 }; -#define INTR_COUNT (sizeof( intrs ) / sizeof( unsigned short )) - -/* signatures for NCR 53c406a based controllers */ -#if USE_BIOS -struct signature { - char *signature; - int sig_offset; - int sig_length; -} signatures[] = { - /* 1 2 3 4 5 6 */ - /* 123456789012345678901234567890123456789012345678901234567890 */ - { "Copyright (C) Acculogic, Inc.\r\n2.8M Diskette Extension Bios ver 4.04.03 03/01/1993", 61, 82 }, -}; -#define SIGNATURE_COUNT (sizeof( signatures ) / sizeof( struct signature )) -#endif USE_BIOS - -/* ============================================================ */ - -/* Control Register Set 0 */ -static int TC_LSB; /* transfer counter lsb */ -static int TC_MSB; /* transfer counter msb */ -static int SCSI_FIFO; /* scsi fifo register */ -static int CMD_REG; /* command register */ -static int STAT_REG; /* status register */ -static int DEST_ID; /* selection/reselection bus id */ -static int INT_REG; /* interrupt status register */ -static int SRTIMOUT; /* select/reselect timeout reg */ -static int SEQ_REG; /* sequence step register */ -static int SYNCPRD; /* synchronous transfer period */ -static int FIFO_FLAGS; /* indicates # of bytes in fifo */ -static int SYNCOFF; /* synchronous offset register */ -static int CONFIG1; /* configuration register */ -static int CLKCONV; /* clock conversion reg */ -/*static int TESTREG;*/ /* test mode register */ -static int CONFIG2; /* Configuration 2 Register */ -static int CONFIG3; /* Configuration 3 Register */ -static int CONFIG4; /* Configuration 4 Register */ -static int TC_HIGH; /* Transfer Counter High */ -/*static int FIFO_BOTTOM;*/ /* Reserve FIFO byte register */ - -/* Control Register Set 1 */ -/*static int JUMPER_SENSE;*/ /* Jumper sense port reg (r/w) */ -/*static int SRAM_PTR;*/ /* SRAM address pointer reg (r/w) */ -/*static int SRAM_DATA;*/ /* SRAM data register (r/w) */ -static int PIO_FIFO; /* PIO FIFO registers (r/w) */ -/*static int PIO_FIFO1;*/ /* */ -/*static int PIO_FIFO2;*/ /* */ -/*static int PIO_FIFO3;*/ /* */ -static int PIO_STATUS; /* PIO status (r/w) */ -/*static int ATA_CMD;*/ /* ATA command/status reg (r/w) */ -/*static int ATA_ERR;*/ /* ATA features/error register (r/w)*/ -static int PIO_FLAG; /* PIO flag interrupt enable (r/w) */ -static int CONFIG5; /* Configuration 5 register (r/w) */ -/*static int SIGNATURE;*/ /* Signature Register (r) */ -/*static int CONFIG6;*/ /* Configuration 6 register (r) */ - -/* ============================================================== */ - -#if USE_DMA -static __inline__ int -NCR53c406a_dma_setup (unsigned char *ptr, - unsigned int count, - unsigned char mode) { - unsigned limit; - unsigned long flags = 0; - - VDEB(printk("dma: before count=%d ", count)); - if (dma_chan <=3) { - if (count > 65536) - count = 65536; - limit = 65536 - (((unsigned) ptr) & 0xFFFF); - } else { - if (count > (65536<<1)) - count = (65536<<1); - limit = (65536<<1) - (((unsigned) ptr) & 0x1FFFF); - } - - if (count > limit) count = limit; - - VDEB(printk("after count=%d\n", count)); - if ((count & 1) || (((unsigned) ptr) & 1)) - panic ("NCR53c406a: attempted unaligned DMA transfer\n"); - - save_flags(flags); - cli(); - disable_dma(dma_chan); - clear_dma_ff(dma_chan); - set_dma_addr(dma_chan, (long) ptr); - set_dma_count(dma_chan, count); - set_dma_mode(dma_chan, mode); - enable_dma(dma_chan); - restore_flags(flags); - - return count; -} - -static __inline__ int -NCR53c406a_dma_write(unsigned char *src, unsigned int count) { - return NCR53c406a_dma_setup (src, count, DMA_MODE_WRITE); -} - -static __inline__ int -NCR53c406a_dma_read(unsigned char *src, unsigned int count) { - return NCR53c406a_dma_setup (src, count, DMA_MODE_READ); -} - -static __inline__ int -NCR53c406a_dma_residual (void) { - register int tmp; - unsigned long flags = 0; - save_flags(flags); - cli(); - clear_dma_ff(dma_chan); - tmp = get_dma_residue(dma_chan); - restore_flags(flags); - - return tmp; -} -#endif USE_DMA - -#if USE_PIO -static __inline__ int NCR53c406a_pio_read(unsigned char *request, - unsigned int reqlen) -{ - int i; - int len; /* current scsi fifo size */ - unsigned long flags = 0; - - REG1; - while (reqlen) { - i = inb(PIO_STATUS); - /* VDEB(printk("pio_status=%x\n", i)); */ - if (i & 0x80) - return 0; - - switch( i & 0x1e ) { - default: - case 0x10: - len=0; break; - case 0x0: - len=1; break; - case 0x8: - len=42; break; - case 0xc: - len=84; break; - case 0xe: - len=128; break; - } - - if ((i & 0x40) && len == 0) { /* fifo empty and interrupt occured */ - return 0; - } - - if (len) { - if( len > reqlen ) - len = reqlen; - - save_flags(flags); - cli(); - if( fast_pio && len > 3 ) { - insl(PIO_FIFO,request,len>>2); - request += len & 0xfc; - reqlen -= len & 0xfc; - } - else { - while(len--) { - *request++ = inb(PIO_FIFO); - reqlen--; - } - } - restore_flags(flags); - } - } - return 0; -} - -static __inline__ int NCR53c406a_pio_write(unsigned char *request, - unsigned int reqlen) -{ - int i = 0; - int len; /* current scsi fifo size */ - unsigned long flags = 0; - - REG1; - while (reqlen && !(i&0x40)) { - i = inb(PIO_STATUS); - /* VDEB(printk("pio_status=%x\n", i)); */ - if (i & 0x80) /* error */ - return 0; - - switch( i & 0x1e ) { - case 0x10: - len=128; break; - case 0x0: - len=84; break; - case 0x8: - len=42; break; - case 0xc: - len=1; break; - default: - case 0xe: - len=0; break; - } - - if (len) { - if( len > reqlen ) - len = reqlen; - - save_flags(flags); - cli(); - if( fast_pio && len > 3 ) { - outsl(PIO_FIFO,request,len>>2); - request += len & 0xfc; - reqlen -= len & 0xfc; - } - else { - while(len--) { - outb(*request++, PIO_FIFO); - reqlen--; - } - } - restore_flags(flags); - } - } - return 0; -} -#endif USE_PIO - -int -NCR53c406a_detect(Scsi_Host_Template * tpnt){ - struct Scsi_Host *shpnt; -#ifndef PORT_BASE - int i; -#endif - -#if USE_BIOS - int ii, jj; - bios_base = 0; - /* look for a valid signature */ - for( ii=0; ii < ADDRESS_COUNT && !bios_base; ii++) - for( jj=0; (jj < SIGNATURE_COUNT) && !bios_base; jj++) - if(!memcmp((void *) addresses[ii]+signatures[jj].sig_offset, - (void *) signatures[jj].signature, - (int) signatures[jj].sig_length)) - bios_base=addresses[ii]; - - if(!bios_base){ - printk("NCR53c406a: BIOS signature not found\n"); - return 0; - } - - DEB(printk("NCR53c406a BIOS found at %X\n", (unsigned int) bios_base);); -#endif USE_BIOS - -#ifdef PORT_BASE - if (check_region(port_base, 0x10)) /* ports already snatched */ - port_base = 0; - -#else /* autodetect */ - if (port_base) { /* LILO override */ - if (check_region(port_base, 0x10)) - port_base = 0; - } - else { - for(i=0; i<PORT_COUNT && !port_base; i++){ - if(check_region(ports[i], 0x10)){ - DEB(printk("NCR53c406a: port %x in use\n", ports[i])); - } - else { - VDEB(printk("NCR53c406a: port %x available\n", ports[i])); - outb(C5_IMG, ports[i] + 0x0d); /* reg set 1 */ - if( (inb(ports[i] + 0x0e) ^ inb(ports[i] + 0x0e)) == 7 - && (inb(ports[i] + 0x0e) ^ inb(ports[i] + 0x0e)) == 7 - && (inb(ports[i] + 0x0e) & 0xf8) == 0x58 ) { - VDEB(printk("NCR53c406a: Sig register valid\n")); - VDEB(printk("port_base=%x\n", port_base)); - port_base = ports[i]; - } - } - } - } -#endif PORT_BASE - - if(!port_base){ /* no ports found */ - printk("NCR53c406a: no available ports found\n"); - return 0; - } - - DEB(printk("NCR53c406a detected\n")); - - calc_port_addr(); - chip_init(); - -#ifndef IRQ_LEV - if (irq_level < 0) { /* LILO override if >= 0*/ - irq_level=irq_probe(); - if (irq_level < 0) { /* Trouble */ - printk("NCR53c406a: IRQ problem, irq_level=%d, giving up\n", irq_level); - return 0; - } - } -#endif - - DEB(printk("NCR53c406a: using port_base %x\n", port_base)); - request_region(port_base, 0x10, "NCR53c406a"); - - if(irq_level > 0) { - if(request_irq(irq_level, NCR53c406a_intr, 0, "NCR53c406a")){ - printk("NCR53c406a: unable to allocate IRQ %d\n", irq_level); - return 0; - } - tpnt->can_queue = 1; - DEB(printk("NCR53c406a: allocated IRQ %d\n", irq_level)); - } - else if (irq_level == 0) { - tpnt->can_queue = 0; - DEB(printk("NCR53c406a: No interrupts detected\n")); -#if USE_DMA - printk("NCR53c406a: No interrupts found and DMA mode defined. Giving up.\n"); - return 0; -#endif USE_DMA - } - else { - DEB(printk("NCR53c406a: Shouldn't get here!\n")); - return 0; - } - -#if USE_DMA - dma_chan = DMA_CHAN; - if(request_dma(dma_chan, "NCR53c406a") != 0){ - printk("NCR53c406a: unable to allocate DMA channel %d\n", dma_chan); - return 0; - } - - DEB(printk("Allocated DMA channel %d\n", dma_chan)); -#endif USE_DMA - - tpnt->present = 1; - tpnt->proc_dir = &proc_scsi_NCR53c406a; - - shpnt = scsi_register(tpnt, 0); - shpnt->irq = irq_level; - shpnt->io_port = port_base; - shpnt->n_io_port = 0x10; -#if USE_DMA - shpnt->dma = dma_chan; -#endif - -#if USE_DMA - sprintf(info_msg, "NCR53c406a at 0x%x, IRQ %d, DMA channel %d.", - port_base, irq_level, dma_chan); -#else - sprintf(info_msg, "NCR53c406a at 0x%x, IRQ %d, %s PIO mode.", - port_base, irq_level, fast_pio ? "fast" : "slow"); -#endif - - return (tpnt->present); -} - -/* called from init/main.c */ -void NCR53c406a_setup(char *str, int *ints) -{ - static size_t setup_idx = 0; - size_t i; - - DEB(printk("NCR53c406a: Setup called\n");); - - if (setup_idx >= PORT_COUNT - 1) { - printk("NCR53c406a: Setup called too many times. Bad LILO params?\n"); - return; - } - if (ints[0] < 1 || ints[0] > 3) { - printk("NCR53c406a: Malformed command line\n"); - printk("NCR53c406a: Usage: ncr53c406a=<PORTBASE>[,<IRQ>[,<FASTPIO>]]\n"); - return; - } - for (i = 0; i < PORT_COUNT && !port_base; i++) - if (ports[i] == ints[1]) { - port_base = ints[1]; - DEB(printk("NCR53c406a: Specified port_base 0x%X\n", port_base);) - } - if (!port_base) { - printk("NCR53c406a: Invalid PORTBASE 0x%X specified\n", ints[1]); - return; - } - - if (ints[0] > 1) { - if (ints[2] == 0) { - irq_level = 0; - DEB(printk("NCR53c406a: Specified irq %d\n", irq_level);) - } - else - for (i = 0; i < INTR_COUNT && irq_level < 0; i++) - if (intrs[i] == ints[2]) { - irq_level = ints[2]; - DEB(printk("NCR53c406a: Specified irq %d\n", port_base);) - } - if (irq_level < 0) - printk("NCR53c406a: Invalid IRQ %d specified\n", ints[2]); - } - - if (ints[0] > 2) - fast_pio = ints[3]; - - DEB(printk("NCR53c406a: port_base=0x%X, irq=%d, fast_pio=%d\n", - port_base, irq_level, fast_pio);) -} - -const char* -NCR53c406a_info(struct Scsi_Host *SChost){ - DEB(printk("NCR53c406a_info called\n")); - return (info_msg); -} - -static void internal_done(Scsi_Cmnd *SCpnt) { - internal_done_errcode = SCpnt->result; - ++internal_done_flag; -} - - -static void wait_intr() { - int i = jiffies + WATCHDOG; - - while(i>jiffies && !(inb(STAT_REG)&0xe0)) /* wait for a pseudo-interrupt */ - barrier(); - - if (i <= jiffies) { /* Timed out */ - rtrc(0); - current_SC->result = DID_TIME_OUT << 16; - current_SC->SCp.phase = idle; - current_SC->scsi_done(current_SC); - return; - } - - NCR53c406a_intr(0, NULL); -} - -int NCR53c406a_command(Scsi_Cmnd *SCpnt){ - DEB(printk("NCR53c406a_command called\n")); - NCR53c406a_queue(SCpnt, internal_done); - if(irq_level) - while (!internal_done_flag); - else /* interrupts not supported */ - while (!internal_done_flag) - wait_intr(); - - internal_done_flag = 0; - return internal_done_errcode; -} - - -int -NCR53c406a_queue(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)){ - int i; - unsigned long flags = 0; - - VDEB(printk("NCR53c406a_queue called\n")); - DEB(printk("cmd=%02x, cmd_len=%02x, target=%02x, lun=%02x, bufflen=%d\n", - SCpnt->cmnd[0], - SCpnt->cmd_len, - SCpnt->target, - SCpnt->lun, - SCpnt->request_bufflen)); - -#if 0 - VDEB(for(i=0; i<SCpnt->cmd_len; i++) - printk("cmd[%d]=%02x ", i, SCpnt->cmnd[i])); - VDEB(printk("\n")); -#endif - - current_SC = SCpnt; - current_SC->scsi_done = done; - current_SC->SCp.phase = command_ph; - current_SC->SCp.Status = 0; - current_SC->SCp.Message = 0; - - save_flags(flags); - cli(); - REG0; - outb(SCpnt->target, DEST_ID); /* set destination */ - outb(FLUSH_FIFO, CMD_REG); /* reset the fifos */ - - for(i=0; i<SCpnt->cmd_len; i++){ - outb(SCpnt->cmnd[i], SCSI_FIFO); - } - outb(SELECT_NO_ATN, CMD_REG); - restore_flags(flags); - - rtrc(1); - return 0; -} - -int -NCR53c406a_abort(Scsi_Cmnd *SCpnt){ - DEB(printk("NCR53c406a_abort called\n")); - return SCSI_ABORT_SNOOZE; /* Don't know how to abort */ -} - -int -NCR53c406a_reset(Scsi_Cmnd *SCpnt){ - DEB(printk("NCR53c406a_reset called\n")); - outb(C4_IMG, CONFIG4); /* Select reg set 0 */ - outb(CHIP_RESET, CMD_REG); - outb(SCSI_NOP, CMD_REG); /* required after reset */ - outb(SCSI_RESET, CMD_REG); - chip_init(); - - rtrc(2); - if (irq_level) - return SCSI_RESET_PENDING; /* should get an interrupt */ - else - return SCSI_RESET_WAKEUP; /* won't get any interrupts */ -} - -int -NCR53c406a_biosparm(Scsi_Disk *disk, kdev_t dev, int* info_array){ - int size; - - DEB(printk("NCR53c406a_biosparm called\n")); - - size = disk->capacity; - info_array[0] = 64; /* heads */ - info_array[1] = 32; /* sectors */ - info_array[2] = size>>11; /* cylinders */ - if (info_array[2] > 1024) { /* big disk */ - info_array[0] = 255; - info_array[1] = 63; - info_array[2] = size / (255*63); - } - return 0; - } - - static void -NCR53c406a_intr(int unused, struct pt_regs *regs){ - DEB(unsigned char fifo_size;) - DEB(unsigned char seq_reg;) - unsigned char status, int_reg; - unsigned long flags = 0; -#if USE_PIO - unsigned char pio_status; - struct scatterlist *sglist; - unsigned int sgcount; -#endif - - VDEB(printk("NCR53c406a_intr called\n")); - - save_flags(flags); - cli(); -#if USE_PIO - REG1; - pio_status = inb(PIO_STATUS); -#endif - REG0; - status = inb(STAT_REG); - DEB(seq_reg = inb(SEQ_REG)); - int_reg = inb(INT_REG); - DEB(fifo_size = inb(FIFO_FLAGS) & 0x1f); - restore_flags(flags); - -#if NCR53C406A_DEBUG - printk("status=%02x, seq_reg=%02x, int_reg=%02x, fifo_size=%02x", - status, seq_reg, int_reg, fifo_size); -#if (USE_DMA) - printk("\n"); -#else - printk(", pio=%02x\n", pio_status); -#endif USE_DMA -#endif NCR53C406A_DEBUG - - if(int_reg & 0x80){ /* SCSI reset intr */ - rtrc(3); - DEB(printk("NCR53c406a: reset intr received\n")); - current_SC->SCp.phase = idle; - current_SC->result = DID_RESET << 16; - current_SC->scsi_done(current_SC); - return; - } - -#if USE_PIO - if(pio_status & 0x80) { - printk("NCR53C406A: Warning: PIO error!\n"); - current_SC->SCp.phase = idle; - current_SC->result = DID_ERROR << 16; - current_SC->scsi_done(current_SC); - return; - } -#endif USE_PIO - - if(status & 0x20) { /* Parity error */ - printk("NCR53c406a: Warning: parity error!\n"); - current_SC->SCp.phase = idle; - current_SC->result = DID_PARITY << 16; - current_SC->scsi_done(current_SC); - return; - } - - if(status & 0x40) { /* Gross error */ - printk("NCR53c406a: Warning: gross error!\n"); - current_SC->SCp.phase = idle; - current_SC->result = DID_ERROR << 16; - current_SC->scsi_done(current_SC); - return; - } - - if(int_reg & 0x20){ /* Disconnect */ - DEB(printk("NCR53c406a: disconnect intr received\n")); - if(current_SC->SCp.phase != message_in){ /* Unexpected disconnect */ - current_SC->result = DID_NO_CONNECT << 16; - } - else{ /* Command complete, return status and message */ - current_SC->result = (current_SC->SCp.Status & 0xff) - | ((current_SC->SCp.Message & 0xff) << 8) | (DID_OK << 16); - } - - rtrc(0); - current_SC->SCp.phase = idle; - current_SC->scsi_done( current_SC ); - return; - } - - switch(status & 0x07){ /* scsi phase */ - case 0x00: /* DATA-OUT */ - if(int_reg & 0x10){ /* Target requesting info transfer */ - rtrc(5); - current_SC->SCp.phase = data_out; - VDEB(printk("NCR53c406a: Data-Out phase\n")); - outb(FLUSH_FIFO, CMD_REG); - LOAD_DMA_COUNT(current_SC->request_bufflen); /* Max transfer size */ -#if USE_DMA /* No s/g support for DMA */ - NCR53c406a_dma_write(current_SC->request_buffer, - current_SC->request_bufflen); -#endif USE_DMA - outb(TRANSFER_INFO | DMA_OP, CMD_REG); -#if USE_PIO - if (!current_SC->use_sg) /* Don't use scatter-gather */ - NCR53c406a_pio_write(current_SC->request_buffer, - current_SC->request_bufflen); - else { /* use scatter-gather */ - sgcount = current_SC->use_sg; - sglist = current_SC->request_buffer; - while( sgcount-- ) { - NCR53c406a_pio_write(sglist->address, sglist->length); - sglist++; - } - } - REG0; -#endif USE_PIO - } - break; - - case 0x01: /* DATA-IN */ - if(int_reg & 0x10){ /* Target requesting info transfer */ - rtrc(6); - current_SC->SCp.phase = data_in; - VDEB(printk("NCR53c406a: Data-In phase\n")); - outb(FLUSH_FIFO, CMD_REG); - LOAD_DMA_COUNT(current_SC->request_bufflen); /* Max transfer size */ -#if USE_DMA /* No s/g support for DMA */ - NCR53c406a_dma_read(current_SC->request_buffer, - current_SC->request_bufflen); -#endif USE_DMA - outb(TRANSFER_INFO | DMA_OP, CMD_REG); -#if USE_PIO - if (!current_SC->use_sg) /* Don't use scatter-gather */ - NCR53c406a_pio_read(current_SC->request_buffer, - current_SC->request_bufflen); - else { /* Use scatter-gather */ - sgcount = current_SC->use_sg; - sglist = current_SC->request_buffer; - while( sgcount-- ) { - NCR53c406a_pio_read(sglist->address, sglist->length); - sglist++; - } - } - REG0; -#endif USE_PIO - } - break; - - case 0x02: /* COMMAND */ - current_SC->SCp.phase = command_ph; - printk("NCR53c406a: Warning: Unknown interupt occured in command phase!\n"); - break; - - case 0x03: /* STATUS */ - rtrc(7); - current_SC->SCp.phase = status_ph; - VDEB(printk("NCR53c406a: Status phase\n")); - outb(FLUSH_FIFO, CMD_REG); - outb(INIT_CMD_COMPLETE, CMD_REG); - break; - - case 0x04: /* Reserved */ - case 0x05: /* Reserved */ - printk("NCR53c406a: WARNING: Reserved phase!!!\n"); - break; - - case 0x06: /* MESSAGE-OUT */ - DEB(printk("NCR53c406a: Message-Out phase\n")); - current_SC->SCp.phase = message_out; - outb(SET_ATN, CMD_REG); /* Reject the message */ - outb(MSG_ACCEPT, CMD_REG); - break; - - case 0x07: /* MESSAGE-IN */ - rtrc(4); - VDEB(printk("NCR53c406a: Message-In phase\n")); - current_SC->SCp.phase = message_in; - - current_SC->SCp.Status = inb(SCSI_FIFO); - current_SC->SCp.Message = inb(SCSI_FIFO); - - VDEB(printk("SCSI FIFO size=%d\n", inb(FIFO_FLAGS) & 0x1f)); - DEB(printk("Status = %02x Message = %02x\n", - current_SC->SCp.Status, current_SC->SCp.Message)); - - if(current_SC->SCp.Message == SAVE_POINTERS || - current_SC->SCp.Message == DISCONNECT) { - outb(SET_ATN, CMD_REG); /* Reject message */ - DEB(printk("Discarding SAVE_POINTERS message\n")); - } - outb(MSG_ACCEPT, CMD_REG); - break; - } -} - -#ifndef IRQ_LEV -static int irq_probe() -{ - int irqs, irq; - int i; - - inb(INT_REG); /* clear the interrupt register */ - sti(); - irqs = probe_irq_on(); - - /* Invalid command will cause an interrupt */ - REG0; - outb(0xff, CMD_REG); - - /* Wait for the interrupt to occur */ - i = jiffies + WATCHDOG; - while(i > jiffies && !(inb(STAT_REG) & 0x80)) - barrier(); - if (i <= jiffies) { /* Timed out, must be hardware trouble */ - probe_irq_off(irqs); - return -1; - } - - irq = probe_irq_off(irqs); - - /* Kick the chip */ - outb(CHIP_RESET, CMD_REG); - outb(SCSI_NOP, CMD_REG); - chip_init(); - - return irq; -} -#endif IRQ_LEV - -static void chip_init() -{ - REG1; -#if USE_DMA - outb(0x00, PIO_STATUS); -#else /* USE_PIO */ - outb(0x01, PIO_STATUS); -#endif - outb(0x00, PIO_FLAG); - - outb(C4_IMG, CONFIG4); /* REG0; */ - outb(C3_IMG, CONFIG3); - outb(C2_IMG, CONFIG2); - outb(C1_IMG, CONFIG1); - - outb(0x05, CLKCONV); /* clock conversion factor */ - outb(0x9C, SRTIMOUT); /* Selection timeout */ - outb(0x05, SYNCPRD); /* Synchronous transfer period */ - outb(SYNC_MODE, SYNCOFF); /* synchronous mode */ -} - -void calc_port_addr() -{ - /* Control Register Set 0 */ - TC_LSB = (port_base+0x00); - TC_MSB = (port_base+0x01); - SCSI_FIFO = (port_base+0x02); - CMD_REG = (port_base+0x03); - STAT_REG = (port_base+0x04); - DEST_ID = (port_base+0x04); - INT_REG = (port_base+0x05); - SRTIMOUT = (port_base+0x05); - SEQ_REG = (port_base+0x06); - SYNCPRD = (port_base+0x06); - FIFO_FLAGS = (port_base+0x07); - SYNCOFF = (port_base+0x07); - CONFIG1 = (port_base+0x08); - CLKCONV = (port_base+0x09); - /* TESTREG = (port_base+0x0A); */ - CONFIG2 = (port_base+0x0B); - CONFIG3 = (port_base+0x0C); - CONFIG4 = (port_base+0x0D); - TC_HIGH = (port_base+0x0E); - /* FIFO_BOTTOM = (port_base+0x0F); */ - - /* Control Register Set 1 */ - /* JUMPER_SENSE = (port_base+0x00);*/ - /* SRAM_PTR = (port_base+0x01);*/ - /* SRAM_DATA = (port_base+0x02);*/ - PIO_FIFO = (port_base+0x04); - /* PIO_FIFO1 = (port_base+0x05);*/ - /* PIO_FIFO2 = (port_base+0x06);*/ - /* PIO_FIFO3 = (port_base+0x07);*/ - PIO_STATUS = (port_base+0x08); - /* ATA_CMD = (port_base+0x09);*/ - /* ATA_ERR = (port_base+0x0A);*/ - PIO_FLAG = (port_base+0x0B); - CONFIG5 = (port_base+0x0D); - /* SIGNATURE = (port_base+0x0E);*/ - /* CONFIG6 = (port_base+0x0F);*/ -} - -#ifdef MODULE -/* Eventually this will go into an include file, but this will be later */ -Scsi_Host_Template driver_template = NCR53c406a; - -#include "scsi_module.c" -#endif - -/* - * Overrides for Emacs so that we get a uniform tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 4 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -4 - * c-argdecl-indent: 4 - * c-label-offset: -4 - * c-continued-statement-offset: 4 - * c-continued-brace-offset: 0 - * indent-tabs-mode: nil - * tab-width: 8 - * End: - */ diff --git a/i386/i386at/gpl/linux/scsi/NCR53c406a.h b/i386/i386at/gpl/linux/scsi/NCR53c406a.h deleted file mode 100644 index dcb48870..00000000 --- a/i386/i386at/gpl/linux/scsi/NCR53c406a.h +++ /dev/null @@ -1,83 +0,0 @@ -#ifndef _NCR53C406A_H -#define _NCR53C406A_H - -/* - * NCR53c406a.h - * - * Copyright (C) 1994 Normunds Saumanis (normunds@rx.tech.swh.lv) - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - */ - -#ifndef NULL -#define NULL 0 -#endif - -/* NOTE: scatter-gather support only works in PIO mode. - * Use SG_NONE if DMA mode is enabled! - */ -#define NCR53c406a { \ - NULL /* next */, \ - NULL /* usage count */, \ - &proc_scsi_NCR53c406a /* proc_dir */, \ - NULL /* proc_info */, \ - "NCR53c406a" /* name */, \ - NCR53c406a_detect /* detect */, \ - NULL /* release */, \ - NCR53c406a_info /* info */, \ - NCR53c406a_command /* command */, \ - NCR53c406a_queue /* queuecommand */, \ - NCR53c406a_abort /* abort */, \ - NCR53c406a_reset /* reset */, \ - NULL /* slave_attach */, \ - NCR53c406a_biosparm /* biosparm */, \ - 1 /* can_queue */, \ - 7 /* SCSI ID of the chip */, \ - 32 /*SG_ALL*/ /*SG_NONE*/, \ - 1 /* commands per lun */, \ - 0 /* number of boards in system */, \ - 1 /* unchecked_isa_dma */, \ - ENABLE_CLUSTERING \ -} - -extern struct proc_dir_entry proc_scsi_NCR53c406a; - -int NCR53c406a_detect(Scsi_Host_Template *); -const char* NCR53c406a_info(struct Scsi_Host *); - -int NCR53c406a_command(Scsi_Cmnd *); -int NCR53c406a_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); -int NCR53c406a_abort(Scsi_Cmnd *); -int NCR53c406a_reset(Scsi_Cmnd *); -int NCR53c406a_biosparm(Disk *, kdev_t, int []); - -#endif /* _NCR53C406A_H */ - -/* - * Overrides for Emacs so that we get a uniform tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 4 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -4 - * c-argdecl-indent: 4 - * c-label-offset: -4 - * c-continued-statement-offset: 4 - * c-continued-brace-offset: 0 - * indent-tabs-mode: nil - * tab-width: 8 - * End: - */ - diff --git a/i386/i386at/gpl/linux/scsi/advansys.c b/i386/i386at/gpl/linux/scsi/advansys.c deleted file mode 100644 index 3f8efe3d..00000000 --- a/i386/i386at/gpl/linux/scsi/advansys.c +++ /dev/null @@ -1,9061 +0,0 @@ -/* $Id: advansys.c,v 1.1.1.1 1997/02/25 21:27:45 thomas Exp $ */ -/* - * advansys.c - Linux Host Driver for AdvanSys SCSI Adapters - * - * Copyright (c) 1995-1996 Advanced System Products, Inc. - * All Rights Reserved. - * - * This driver may be modified and freely distributed provided that - * the above copyright message and this comment are included in the - * distribution. The latest version of this driver is available at - * the AdvanSys FTP and BBS sites listed below. - * - * Please send questions, comments, bug reports to: - * bobf@advansys.com (Bob Frey) - */ - -/* The driver has been tested with Linux 1.2.1 and 1.3.57 kernels. */ -#define ASC_VERSION "1.2" /* AdvanSys Driver Version */ - -/* - - Documentation for the AdvanSys Driver - - A. Adapters Supported by this Driver - B. Linux 1.2.X - Directions for Adding the AdvanSys Driver - C. Linux 1.3.X - Directions for Adding the AdvanSys Driver - D. Source Comments - E. Driver Compile Time Options and Debugging - F. Driver LILO Option - G. Release History - H. Known Problems or Issues - I. Credits - J. AdvanSys Contact Information - - - A. Adapters Supported by this Driver - - AdvanSys (Advanced System Products, Inc.) manufactures the following - Bus-Mastering SCSI-2 Host Adapters for the ISA, EISA, VL, and PCI - buses. This Linux driver supports all of these adapters. - - The CDB counts below indicate the number of SCSI CDB (Command - Descriptor Block) requests that can be stored in the RISC chip - cache and board LRAM. The driver detect routine will display the - number of CDBs available for each adapter detected. This value - can be lowered in the BIOS by changing the 'Host Queue Size' - adapter setting. - - Connectivity Products: - ABP920 - Bus-Master PCI 16 CDB - ABP930 - Bus-Master PCI 16 CDB - ABP5140 - Bus-Master PnP ISA 16 CDB - - Single Channel Products: - ABP542 - Bus-Master ISA 240 CDB - ABP5150 - Bus-Master ISA 240 CDB * - ABP742 - Bus-Master EISA 240 CDB - ABP842 - Bus-Master VL 240 CDB - ABP940 - Bus-Master PCI 240 CDB - - Dual Channel Products: - ABP950 - Dual Channel Bus-Master PCI 240 CDB Per Channel - ABP852 - Dual Channel Bus-Master VL 240 CDB Per Channel - ABP752 - Dual Channel Bus-Master EISA 240 CDB Per Channel - - * This board is shipped by HP with the 4020i CD-R drive. It has - no BIOS so it cannot control a boot device, but it can control - any secondary devices. - - B. Linux 1.2.X - Directions for Adding the AdvanSys Driver - - There are two source files: advansys.h and advansys.c. Copy - both of these files to the directory /usr/src/linux/drivers/scsi. - - 1. Add the following line to /usr/src/linux/arch/i386/config.in - after "comment 'SCSI low-level drivers'": - - bool 'AdvanSys SCSI support' CONFIG_SCSI_ADVANSYS y - - 2. Add the following lines to /usr/src/linux/drivers/scsi/hosts.c - after "#include "hosts.h"": - - #ifdef CONFIG_SCSI_ADVANSYS - #include "advansys.h" - #endif - - and after "static Scsi_Host_Template builtin_scsi_hosts[] =": - - #ifdef CONFIG_SCSI_ADVANSYS - ADVANSYS, - #endif - - 3. Add the following lines to /usr/src/linux/drivers/scsi/Makefile: - - ifdef CONFIG_SCSI_ADVANSYS - SCSI_SRCS := $(SCSI_SRCS) advansys.c - SCSI_OBJS := $(SCSI_OBJS) advansys.o - else - SCSI_MODULE_OBJS := $(SCSI_MODULE_OBJS) advansys.o - endif - - 4. (Optional) If you would like to enable the LILO command line - and /etc/lilo.conf 'advansys' option, make the following changes. - This option can be used to disable I/O port scanning or to limit - I/O port scanning to specific addresses. Refer to the 'Driver - LILO Option' section below. Add the following lines to - /usr/src/linux/init/main.c in the prototype section: - - extern void advansys_setup(char *str, int *ints); - - and add the following lines to the bootsetups[] array. - - #ifdef CONFIG_SCSI_ADVANSYS - { "advansys=", advansys_setup }, - #endif - - 5. If you have the HP 4020i CD-R driver and Linux 1.2.X you should - add a fix to the CD-ROM target driver. This fix will allow - you to mount CDs with the iso9660 file system. Linux 1.3.X - already has this fix. In the file /usr/src/linux/drivers/scsi/sr.c - and function get_sectorsize() after the line: - - if(scsi_CDs[i].sector_size == 0) scsi_CDs[i].sector_size = 2048; - - add the following line: - - if(scsi_CDs[i].sector_size == 2340) scsi_CDs[i].sector_size = 2048; - - 6. In the directory /usr/src/linux run 'make config' to configure - the AdvanSys driver, then run 'make vmlinux' or 'make zlilo' to - make the kernel. If the AdvanSys driver is not configured, then - a loadable module can be built by running 'make modules' and - 'make modules_install'. Use 'insmod' and 'rmmod' to install - and remove advansys.o. - - C. Linux 1.3.X - Directions for Adding the AdvanSys Driver - - There are two source files: advansys.h and advansys.c. Copy - both of these files to the directory /usr/src/linux/drivers/scsi. - - 1. Add the following line to /usr/src/linux/drivers/scsi/Config.in - after "comment 'SCSI low-level drivers'": - - dep_tristate 'AdvanSys SCSI support' CONFIG_SCSI_ADVANSYS $CONFIG_SCSI - - 2. Add the following lines to /usr/src/linux/drivers/scsi/hosts.c - after "#include "hosts.h"": - - #ifdef CONFIG_SCSI_ADVANSYS - #include "advansys.h" - #endif - - and after "static Scsi_Host_Template builtin_scsi_hosts[] =": - - #ifdef CONFIG_SCSI_ADVANSYS - ADVANSYS, - #endif - - 3. Add the following lines to /usr/src/linux/drivers/scsi/Makefile: - - ifeq ($(CONFIG_SCSI_ADVANSYS),y) - L_OBJS += advansys.o - else - ifeq ($(CONFIG_SCSI_ADVANSYS),m) - M_OBJS += advansys.o - endif - endif - - 4. Add the following line to /usr/src/linux/include/linux/proc_fs.h - in the enum scsi_directory_inos array: - - PROC_SCSI_ADVANSYS, - - 5. (Optional) If you would like to enable the LILO command line - and /etc/lilo.conf 'advansys' option, make the following changes. - This option can be used to disable I/O port scanning or to limit - I/O port scanning to specific addresses. Refer to the 'Driver - LILO Option' section below. Add the following lines to - /usr/src/linux/init/main.c in the prototype section: - - extern void advansys_setup(char *str, int *ints); - - and add the following lines to the bootsetups[] array. - - #ifdef CONFIG_SCSI_ADVANSYS - { "advansys=", advansys_setup }, - #endif - - 6. In the directory /usr/src/linux run 'make config' to configure - the AdvanSys driver, then run 'make vmlinux' or 'make zlilo' to - make the kernel. If the AdvanSys driver is not configured, then - a loadable module can be built by running 'make modules' and - 'make modules_install'. Use 'insmod' and 'rmmod' to install - and remove advansys.o. - - D. Source Comments - - 1. Use tab stops set to 4 for the source files. For vi use 'se tabstops=4'. - - 2. This driver should be maintained in multiple files. But to make - it easier to include with Linux and to follow Linux conventions, - the whole driver is maintained in the source files advansys.h and - advansys.c. In this file logical sections of the driver begin with - a comment that contains '---'. The following are the logical sections - of the driver below. - - --- Linux Version - --- Linux Include Files - --- Driver Options - --- Asc Library Constants and Macros - --- Debugging Header - --- Driver Constants - --- Driver Macros - --- Driver Structures - --- Driver Data - --- Driver Function Prototypes - --- Linux 'Scsi_Host_Template' and advansys_setup() Functions - --- Loadable Driver Support - --- Miscellaneous Driver Functions - --- Functions Required by the Asc Library - --- Tracing and Debugging Functions - --- Asc Library Functions - - 3. The string 'XXX' is used to flag code that needs to be re-written - or that contains a problem that needs to be addressed. - - 4. I have stripped comments from and reformatted the source for the - Asc Library which is included in this file. I haven't done this - to obfuscate the code. Actually I have done this to deobfuscate - the code. The Asc Library source can be found under the following - headings. - - --- Asc Library Constants and Macros - --- Asc Library Functions - - E. Driver Compile Time Options and Debugging - - In this source file the following constants can be defined. They are - defined in the source below. Both of these options are enabled by - default. - - 1. ADVANSYS_DEBUG - enable for debugging and assertions - - The amount of debugging output can be controlled with the global - variable 'asc_dbglvl'. The higher the number the more output. By - default the debug level is 0. - - If the driver is loaded at boot time and the LILO Driver Option - is included in the system, the debug level can be changed by - specifying a 5th (ASC_NUM_BOARD_SUPPORTED + 1) I/O Port. The - first three hex digits of the pseudo I/O Port must be set to - 'deb' and the fourth hex digit specifies the debug level: 0 - F. - The following command line will look for an adapter at 0x330 - and set the debug level to 2. - - linux advansys=0x330,0x0,0x0,0x0,0xdeb2 - - If the driver is built as a loadable module this variable can be - defined when the driver is loaded. The following insmod command - will set the debug level to one. - - insmod advansys.o asc_dbglvl=1 - - - Debugging Message Levels: - 0: Errors Only - 1: High-Level Tracing - 2-N: Verbose Tracing - - I don't know the approved way for turning on printk()s to the - console. Here's a program I use to do this. Debug output is - logged in /var/adm/messages. - - main() - { - syscall(103, 7, 0, 0); - } - - I found that increasing LOG_BUF_LEN to 40960 in kernel/printk.c - prevents most level 1 debug messages from being lost. - - 2. ADVANSYS_STATS - enable statistics and tracing - - For Linux 1.2.X if ADVANSYS_STATS_1_2_PRINT is defined every - 10,000 I/O operations the driver will print statistics to the - console. This value can be changed by modifying the constant - used in advansys_queuecommand(). ADVANSYS_STATS_1_2_PRINT is - off by default. - - For Linux 1.3.X statistics can be accessed by reading the - /proc/scsi/advansys/[0-9] files. - - Note: these statistics are currently maintained on a global driver - basis and not per board. - - F. Driver LILO Option - - If init/main.c is modified as described in the 'Directions for Adding - the AdvanSys Driver to Linux' section (B.4.) above, the driver will - recognize the 'advansys' LILO command line and /etc/lilo.conf option. - This option can be used to either disable I/O port scanning or to limit - scanning to 1 - 4 I/O ports. Regardless of the option setting EISA and - PCI boards will still be searched for and detected. This option only - affects searching for ISA and VL boards. - - Examples: - 1. Eliminate I/O port scanning: - boot: linux advansys= - or - boot: linux advansys=0x0 - 2. Limit I/O port scanning to one I/O port: - boot: linux advansys=0x110 - 3. Limit I/O port scanning to four I/O ports: - boot: linux advansys=0x110,0x210,0x230,0x330 - - For a loadable module the same effect can be achieved by setting - the 'asc_iopflag' variable and 'asc_ioport' array when loading - the driver, e.g. - - insmod advansys.o asc_iopflag=1 asc_ioport=0x110,0x330 - - If ADVANSYS_DEBUG is defined a 5th (ASC_NUM_BOARD_SUPPORTED + 1) - I/O Port may be added to specify the driver debug level. Refer to - the 'Driver Compile Time Options and Debugging' section above for - more information. - - G. Release History - - 12/23/95 BETA-1.0: - First Release - - 12/28/95 BETA-1.1: - 1. Prevent advansys_detect() from being called twice. - 2. Add LILO 0xdeb[0-f] option to set 'asc_dbglvl'. - - 1/12/96 1.2: - 1. Prevent re-entrancy in the interrupt handler which - resulted in the driver hanging Linux. - 2. Fix problem that prevented ABP-940 cards from being - recognized on some PCI motherboards. - 3. Add support for the ABP-5140 PnP ISA card. - 4. Fix check condition return status. - 5. Add conditionally compiled code for Linux 1.3.X. - - H. Known Problems or Issues - - 1. The setting for 'cmd_per_lun' needs to be changed. It is currently - less then what the AdvanSys boards can queue. Because the target and - mid-level Linux drivers base memory allocation on 'cmd_per_lun' (as - well as 'sg_tablesize') memory use gets out of hand with a large - 'cmd_per_lun'. 'cmd_per_lun' should be per device instead of per - adapter. When the driver is compiled as a loadable module both - 'cmd_per_lun' and 'sg_tablesize' are tuned down to try to prevent - memory allocation errors. - - 2. For the first scsi command sent to a device the driver increases - the timeout value. This gives the driver more time to perform - its own initialization for the board and each device. The timeout - value is only changed on the first scsi command for each device - and never thereafter. - - I. Credits - - Nathan Hartwell (mage@cdc3.cdc.net) provided the directions and - and basis for the Linux 1.3.X changes which were included in the - 1.2 release. - - J. AdvanSys Contact Information - - Mail: Advanced System Products, Inc. - 1150 Ringwood Court - San Jose, CA 95131 USA - Operator: 1-408-383-9400 - FAX: 1-408-383-9612 - Tech Support: 1-800-525-7440 - BBS: 1-408-383-9540 (9600,N,8,1) - Interactive FAX: 1-408-383-9753 - Customer Direct Sales: 1-800-883-1099 - Tech Support E-Mail: support@advansys.com - Linux Support E-Mail: bobf@advansys.com - FTP Site: ftp.advansys.com (login: anonymous) - Web Site: http://www.advansys.com - -*/ - - -/* - * --- Linux Version - */ - -/* - * The driver can be used in Linux 1.2.X or 1.3.X. - */ -#if !defined(LINUX_1_2) && !defined(LINUX_1_3) -#ifndef LINUX_VERSION_CODE -#include <linux/version.h> -#endif /* LINUX_VERSION_CODE */ -#if LINUX_VERSION_CODE > 65536 + 3 * 256 -#define LINUX_1_3 -#else /* LINUX_VERSION_CODE */ -#define LINUX_1_2 -#endif /* LINUX_VERSION_CODE */ -#endif /* !defined(LINUX_1_2) && !defined(LINUX_1_3) */ - - -/* - * --- Linux Include Files - */ - -#ifdef MODULE -#ifdef LINUX_1_3 -#include <linux/autoconf.h> -#endif /* LINUX_1_3 */ -#include <linux/module.h> -#endif /* MODULE */ -#include <linux/string.h> -#include <linux/sched.h> -#include <linux/kernel.h> -#include <linux/head.h> -#include <linux/types.h> -#include <linux/ioport.h> -#include <linux/delay.h> -#include <linux/malloc.h> -#include <linux/config.h> -#ifdef LINUX_1_3 -#include <linux/proc_fs.h> -#endif /* LINUX_1_3 */ -#include <asm/io.h> -#include <asm/system.h> -#include <asm/dma.h> -#ifdef LINUX_1_2 -#include "../block/blk.h" -#else /* LINUX_1_3 */ -#include <linux/blk.h> -#include <linux/stat.h> -#endif /* LINUX_1_3 */ -#include "scsi.h" -#include "hosts.h" -#include "sd.h" -#include "advansys.h" - - -/* - * --- Driver Options - */ -#define ADVANSYS_DEBUG /* Enable for debugging and assertions. */ -#define ADVANSYS_STATS /* Enable for statistics and tracing. */ -#ifdef LINUX_1_2 -#undef ADVANSYS_STATS_1_2_PRINT /* Enable to print statistics to console. */ -#endif /* LINUX_1_2 */ - - -/* - * --- Asc Library Constants and Macros - */ - -#define ASC_LIB_VERSION_MAJOR 1 -#define ASC_LIB_VERSION_MINOR 16 -#define ASC_LIB_SERIAL_NUMBER 53 - -typedef unsigned char uchar; -typedef unsigned char BYTE; -typedef unsigned short WORD; -typedef unsigned long DWORD; - -typedef int BOOL; - -#ifndef NULL -#define NULL (0) -#endif - -#ifndef TRUE -#define TRUE (1) -#endif - -#ifndef FALSE -#define FALSE (0) -#endif - -#define REG register - -#define rchar REG char -#define rshort REG short -#define rint REG int -#define rlong REG long - -#define ruchar REG uchar -#define rushort REG ushort -#define ruint REG uint -#define rulong REG ulong - -#define NULLPTR ( void *)0 -#define FNULLPTR ( void dosfar *)0UL -#define EOF (-1) -#define EOS '\0' -#define ERR (-1) -#define UB_ERR (uchar)(0xFF) -#define UW_ERR (uint)(0xFFFF) -#define UL_ERR (ulong)(0xFFFFFFFFUL) - -#define iseven_word( val ) ( ( ( ( uint )val) & ( uint )0x0001 ) == 0 ) -#define isodd_word( val ) ( ( ( ( uint )val) & ( uint )0x0001 ) != 0 ) -#define toeven_word( val ) ( ( ( uint )val ) & ( uint )0xFFFE ) - -#define biton( val, bits ) ((( uint )( val >> bits ) & (uint)0x0001 ) != 0 ) -#define bitoff( val, bits ) ((( uint )( val >> bits ) & (uint)0x0001 ) == 0 ) -#define lbiton( val, bits ) ((( ulong )( val >> bits ) & (ulong)0x00000001UL ) != 0 ) -#define lbitoff( val, bits ) ((( ulong )( val >> bits ) & (ulong)0x00000001UL ) == 0 ) - -#define absh( val ) ( ( val ) < 0 ? -( val ) : ( val ) ) - -#define swapbyte( ch ) ( ( ( (ch) << 4 ) | ( (ch) >> 4 ) ) ) - -#ifndef GBYTE -#define GBYTE (0x40000000UL) -#endif - -#ifndef MBYTE -#define MBYTE (0x100000UL) -#endif - -#ifndef KBYTE -#define KBYTE (0x400) -#endif - -#define HI_BYTE(x) ( *( ( BYTE *)(&x)+1 ) ) -#define LO_BYTE(x) ( *( ( BYTE *)&x ) ) - -#define HI_WORD(x) ( *( ( WORD *)(&x)+1 ) ) -#define LO_WORD(x) ( *( ( WORD *)&x ) ) - -#ifndef MAKEWORD -#define MAKEWORD(lo, hi) ((WORD) (((WORD) lo) | ((WORD) hi << 8))) -#endif - -#ifndef MAKELONG -#define MAKELONG(lo, hi) ((DWORD) (((DWORD) lo) | ((DWORD) hi << 16))) -#endif - -#define SwapWords(dWord) ((DWORD) ((dWord >> 16) | (dWord << 16))) -#define SwapBytes(word) ((WORD) ((word >> 8) | (word << 8))) - -#define BigToLittle(dWord) \ - ((DWORD) (SwapWords(MAKELONG(SwapBytes(LO_WORD(dWord)), SwapBytes(HI_WORD(dWord)))))) -#define LittleToBig(dWord) BigToLittle(dWord) - -#define Lptr -#define dosfar -#define far -#define PortAddr unsigned short -#define Ptr2Func ulong - -#define inp(port) inb(port) -#define inpw(port) inw(port) -#define outp(port, byte) outb((byte), (port)) -#define outpw(port, word) outw((word), (port)) - -#define ASC_MAX_SG_QUEUE 5 -#define ASC_MAX_SG_LIST (1 + ((ASC_SG_LIST_PER_Q) * (ASC_MAX_SG_QUEUE))) - -#define CC_INIT_INQ_DISPLAY FALSE - -#define CC_CLEAR_LRAM_SRB_PTR FALSE -#define CC_VERIFY_LRAM_COPY FALSE - -#define CC_DEBUG_SG_LIST FALSE -#define CC_FAST_STRING_IO FALSE - -#define CC_WRITE_IO_COUNT FALSE -#define CC_CLEAR_DMA_REMAIN FALSE - -#define CC_DISABLE_PCI_PARITY_INT TRUE - -#define CC_LINK_BUSY_Q FALSE - -#define CC_TARGET_MODE FALSE - -#define CC_SCAM FALSE - -#define CC_LITTLE_ENDIAN_HOST TRUE - -#ifndef CC_TEST_LRAM_ENDIAN - -#if CC_LITTLE_ENDIAN_HOST -#define CC_TEST_LRAM_ENDIAN FALSE -#else -#define CC_TEST_LRAM_ENDIAN TRUE -#endif - -#endif - -#define CC_STRUCT_ALIGNED TRUE - -#define CC_MEMORY_MAPPED_IO FALSE - -#ifndef CC_TARGET_MODE -#define CC_TARGET_MODE FALSE -#endif - -#ifndef CC_STRUCT_ALIGNED -#define CC_STRUCT_ALIGNED FALSE -#endif - -#ifndef CC_LITTLE_ENDIAN_HOST -#define CC_LITTLE_ENDIAN_HOST TRUE -#endif - -#if !CC_LITTLE_ENDIAN_HOST - -#ifndef CC_TEST_LRAM_ENDIAN -#define CC_TEST_LRAM_ENDIAN TRUE -#endif - -#endif - -#ifndef CC_MEMORY_MAPPED_IO -#define CC_MEMORY_MAPPED_IO FALSE -#endif - -#ifndef CC_WRITE_IO_COUNT -#define CC_WRITE_IO_COUNT FALSE -#endif - -#ifndef CC_CLEAR_DMA_REMAIN -#define CC_CLEAR_DMA_REMAIN FALSE -#endif - -#define ASC_CS_TYPE unsigned short - -#ifndef asc_ptr_type -#define asc_ptr_type -#endif - -#ifndef CC_SCAM -#define CC_SCAM FALSE -#endif - -#ifndef ASC_GET_PTR2FUNC -#define ASC_GET_PTR2FUNC( fun ) ( Ptr2Func )( fun ) -#endif - -#define FLIP_BYTE_NIBBLE( x ) ( ((x<<4)& 0xFF) | (x>>4) ) - -#define ASC_IS_ISA (0x0001) -#define ASC_IS_ISAPNP (0x0081) -#define ASC_IS_EISA (0x0002) -#define ASC_IS_PCI (0x0004) -#define ASC_IS_PCMCIA (0x0008) -#define ASC_IS_PNP (0x0010) -#define ASC_IS_MCA (0x0020) -#define ASC_IS_VL (0x0040) - -#define ASC_ISA_PNP_PORT_ADDR (0x279) -#define ASC_ISA_PNP_PORT_WRITE (ASC_ISA_PNP_PORT_ADDR+0x800) - -#define ASC_IS_WIDESCSI_16 (0x0100) -#define ASC_IS_WIDESCSI_32 (0x0200) - -#define ASC_IS_BIG_ENDIAN (0x8000) - -#define ASC_CHIP_MIN_VER_VL (0x01) -#define ASC_CHIP_MAX_VER_VL (0x07) - -#define ASC_CHIP_MIN_VER_PCI (0x09) -#define ASC_CHIP_MAX_VER_PCI (0x0F) -#define ASC_CHIP_VER_PCI_BIT (0x08) - -#define ASC_CHIP_MIN_VER_ISA (0x11) -#define ASC_CHIP_MIN_VER_ISA_PNP (0x21) -#define ASC_CHIP_MAX_VER_ISA (0x27) -#define ASC_CHIP_VER_ISA_BIT (0x30) -#define ASC_CHIP_VER_ISAPNP_BIT (0x20) - -#define ASC_CHIP_VER_ASYN_BUG (0x21) - -#define ASC_CHIP_MIN_VER_EISA (0x41) -#define ASC_CHIP_MAX_VER_EISA (0x47) -#define ASC_CHIP_VER_EISA_BIT (0x40) - -#define ASC_MAX_VL_DMA_ADDR (0x07FFFFFFL) -#define ASC_MAX_VL_DMA_COUNT (0x07FFFFFFL) - -#define ASC_MAX_PCI_DMA_ADDR (0xFFFFFFFFL) -#define ASC_MAX_PCI_DMA_COUNT (0xFFFFFFFFL) - -#define ASC_MAX_ISA_DMA_ADDR (0x00FFFFFFL) -#define ASC_MAX_ISA_DMA_COUNT (0x00FFFFFFL) - -#define ASC_MAX_EISA_DMA_ADDR (0x07FFFFFFL) -#define ASC_MAX_EISA_DMA_COUNT (0x07FFFFFFL) - -#if !CC_STRUCT_ALIGNED - -#define DvcGetQinfo( iop_base, s_addr, outbuf, words) \ - AscMemWordCopyFromLram( iop_base, s_addr, outbuf, words) - -#define DvcPutScsiQ( iop_base, s_addr, outbuf, words) \ - AscMemWordCopyToLram( iop_base, s_addr, outbuf, words) - -#endif - -#define ASC_SCSI_ID_BITS 3 -#define ASC_SCSI_TIX_TYPE uchar -#define ASC_ALL_DEVICE_BIT_SET 0xFF - -#ifdef ASC_WIDESCSI_16 - -#undef ASC_SCSI_ID_BITS -#define ASC_SCSI_ID_BITS 4 -#define ASC_ALL_DEVICE_BIT_SET 0xFFFF - -#endif - -#ifdef ASC_WIDESCSI_32 - -#undef ASC_SCSI_ID_BITS -#define ASC_SCSI_ID_BITS 5 -#define ASC_ALL_DEVICE_BIT_SET 0xFFFFFFFFL - -#endif - -#if ASC_SCSI_ID_BITS == 3 - -#define ASC_SCSI_BIT_ID_TYPE uchar -#define ASC_MAX_TID 7 -#define ASC_MAX_LUN 7 -#define ASC_SCSI_WIDTH_BIT_SET 0xFF - -#elif ASC_SCSI_ID_BITS == 4 - -#define ASC_SCSI_BIT_ID_TYPE ushort -#define ASC_MAX_TID 15 -#define ASC_MAX_LUN 7 -#define ASC_SCSI_WIDTH_BIT_SET 0xFFFF - -#elif ASC_SCSI_ID_BITS == 5 - -#define ASC_SCSI_BIT_ID_TYPE ulong -#define ASC_MAX_TID 31 -#define ASC_MAX_LUN 7 -#define ASC_SCSI_WIDTH_BIT_SET 0xFFFFFFFF - -#else - -#error ASC_SCSI_ID_BITS definition is wrong - -#endif - -#define ASC_MAX_SENSE_LEN 32 -#define ASC_MIN_SENSE_LEN 14 - -#define ASC_MAX_CDB_LEN 12 - -#define SCSICMD_TestUnitReady 0x00 -#define SCSICMD_Rewind 0x01 -#define SCSICMD_Rezero 0x01 -#define SCSICMD_RequestSense 0x03 -#define SCSICMD_Format 0x04 -#define SCSICMD_FormatUnit 0x04 -#define SCSICMD_Read6 0x08 -#define SCSICMD_Write6 0x0A -#define SCSICMD_Seek6 0x0B -#define SCSICMD_Inquiry 0x12 -#define SCSICMD_Verify6 0x13 -#define SCSICMD_ModeSelect6 0x15 -#define SCSICMD_ModeSense6 0x1A - -#define SCSICMD_StartStopUnit 0x1B -#define SCSICMD_LoadUnloadTape 0x1B -#define SCSICMD_ReadCapacity 0x25 -#define SCSICMD_Read10 0x28 -#define SCSICMD_Write10 0x2A -#define SCSICMD_Seek10 0x2B -#define SCSICMD_Erase10 0x2C -#define SCSICMD_WriteAndVerify10 0x2E -#define SCSICMD_Verify10 0x2F - -#define SCSICMD_ModeSelect10 0x55 -#define SCSICMD_ModeSense10 0x5A - -#define SCSI_TYPE_DASD 0x00 -#define SCSI_TYPE_SASD 0x01 -#define SCSI_TYPE_PRN 0x02 -#define SCSI_TYPE_PROC 0x03 - -#define SCSI_TYPE_WORM 0x04 -#define SCSI_TYPE_CDROM 0x05 -#define SCSI_TYPE_SCANNER 0x06 -#define SCSI_TYPE_OPTMEM 0x07 -#define SCSI_TYPE_MED_CHG 0x08 -#define SCSI_TYPE_COMM 0x09 -#define SCSI_TYPE_UNKNOWN 0x1F -#define SCSI_TYPE_NO_DVC 0xFF - -#define ASC_SCSIDIR_NOCHK 0x00 - -#define ASC_SCSIDIR_T2H 0x08 - -#define ASC_SCSIDIR_H2T 0x10 - -#define ASC_SCSIDIR_NODATA 0x18 - -#define SCSI_SENKEY_NO_SENSE 0x00 -#define SCSI_SENKEY_UNDEFINED 0x01 -#define SCSI_SENKEY_NOT_READY 0x02 -#define SCSI_SENKEY_MEDIUM_ERR 0x03 -#define SCSI_SENKEY_HW_ERR 0x04 -#define SCSI_SENKEY_ILLEGAL 0x05 -#define SCSI_SENKEY_ATTENSION 0x06 -#define SCSI_SENKEY_PROTECTED 0x07 -#define SCSI_SENKEY_BLANK 0x08 -#define SCSI_SENKEY_V_UNIQUE 0x09 -#define SCSI_SENKEY_CPY_ABORT 0x0A -#define SCSI_SENKEY_ABORT 0x0B -#define SCSI_SENKEY_EQUAL 0x0C -#define SCSI_SENKEY_VOL_OVERFLOW 0x0D -#define SCSI_SENKEY_MISCOMP 0x0E -#define SCSI_SENKEY_RESERVED 0x0F - -#define ASC_SRB_HOST( x ) ( ( uchar )( ( uchar )( x ) >> 4 ) ) -#define ASC_SRB_TID( x ) ( ( uchar )( ( uchar )( x ) & ( uchar )0x0F ) ) - -#define ASC_SRB_LUN( x ) ( ( uchar )( ( uint )( x ) >> 13 ) ) - -#define PUT_CDB1( x ) ( ( uchar )( ( uint )( x ) >> 8 ) ) - -#define SS_GOOD 0x00 -#define SS_CHK_CONDITION 0x02 -#define SS_CONDITION_MET 0x04 -#define SS_TARGET_BUSY 0x08 -#define SS_INTERMID 0x10 -#define SS_INTERMID_COND_MET 0x14 - -#define SS_RSERV_CONFLICT 0x18 -#define SS_CMD_TERMINATED 0x22 - -#define SS_QUEUE_FULL 0x28 - -#define MS_CMD_DONE 0x00 -#define MS_EXTEND 0x01 -#define MS_SDTR_LEN 0x03 -#define MS_SDTR_CODE 0x01 - -#define M1_SAVE_DATA_PTR 0x02 -#define M1_RESTORE_PTRS 0x03 -#define M1_DISCONNECT 0x04 -#define M1_INIT_DETECTED_ERR 0x05 -#define M1_ABORT 0x06 -#define M1_MSG_REJECT 0x07 -#define M1_NO_OP 0x08 -#define M1_MSG_PARITY_ERR 0x09 -#define M1_LINK_CMD_DONE 0x0A -#define M1_LINK_CMD_DONE_WFLAG 0x0B -#define M1_BUS_DVC_RESET 0x0C -#define M1_ABORT_TAG 0x0D -#define M1_CLR_QUEUE 0x0E -#define M1_INIT_RECOVERY 0x0F -#define M1_RELEASE_RECOVERY 0x10 -#define M1_KILL_IO_PROC 0x11 - -#define M2_QTAG_MSG_SIMPLE 0x20 -#define M2_QTAG_MSG_HEAD 0x21 -#define M2_QTAG_MSG_ORDERED 0x22 -#define M2_IGNORE_WIDE_RESIDUE 0x23 - -typedef struct { - uchar peri_dvc_type:5; - uchar peri_qualifier:3; -} ASC_SCSI_INQ0; - -typedef struct { - uchar dvc_type_modifier:7; - uchar rmb:1; -} ASC_SCSI_INQ1; - -typedef struct { - uchar ansi_apr_ver:3; - uchar ecma_ver:3; - uchar iso_ver:2; -} ASC_SCSI_INQ2; - -typedef struct { - uchar rsp_data_fmt:4; - - uchar res:2; - uchar TemIOP:1; - uchar aenc:1; -} ASC_SCSI_INQ3; - -typedef struct { - uchar StfRe:1; - uchar CmdQue:1; - uchar Reserved:1; - uchar Linked:1; - uchar Sync:1; - uchar WBus16:1; - uchar WBus32:1; - uchar RelAdr:1; -} ASC_SCSI_INQ7; - -typedef struct { - ASC_SCSI_INQ0 byte0; - ASC_SCSI_INQ1 byte1; - ASC_SCSI_INQ2 byte2; - ASC_SCSI_INQ3 byte3; - uchar add_len; - uchar res1; - uchar res2; - ASC_SCSI_INQ7 byte7; - uchar vendor_id[8]; - uchar product_id[16]; - uchar product_rev_level[4]; -} ASC_SCSI_INQUIRY; - -typedef struct asc_req_sense { - uchar err_code:7; - uchar info_valid:1; - uchar segment_no; - uchar sense_key:4; - uchar reserved_bit:1; - uchar sense_ILI:1; - uchar sense_EOM:1; - uchar file_mark:1; - uchar info1[4]; - uchar add_sense_len; - uchar cmd_sp_info[4]; - uchar asc; - uchar ascq; - - uchar fruc; - uchar sks_byte0:7; - uchar sks_valid:1; - uchar sks_bytes[2]; - uchar notused[2]; - uchar ex_sense_code; - uchar info2[4]; -} ASC_REQ_SENSE; - -#define ASC_SG_LIST_PER_Q 7 - -#define QS_FREE 0x00 -#define QS_READY 0x01 -#define QS_DISC1 0x02 -#define QS_DISC2 0x04 -#define QS_BUSY 0x08 - -#define QS_ABORTED 0x40 -#define QS_DONE 0x80 - -#define QC_NO_CALLBACK 0x01 - -#define QC_SG_SWAP_QUEUE 0x02 -#define QC_SG_HEAD 0x04 -#define QC_DATA_IN 0x08 -#define QC_DATA_OUT 0x10 - -#define QC_URGENT 0x20 -#define QC_MSG_OUT 0x40 -#define QC_REQ_SENSE 0x80 - -#define QCSG_SG_XFER_LIST 0x02 -#define QCSG_SG_XFER_MORE 0x04 -#define QCSG_SG_XFER_END 0x08 - -#define QD_IN_PROGRESS 0x00 -#define QD_NO_ERROR 0x01 -#define QD_ABORTED_BY_HOST 0x02 -#define QD_WITH_ERROR 0x04 -#define QD_INVALID_REQUEST 0x80 -#define QD_INVALID_HOST_NUM 0x81 -#define QD_INVALID_DEVICE 0x82 -#define QD_ERR_INTERNAL 0xFF - -#define QHSTA_NO_ERROR 0x00 -#define QHSTA_M_SEL_TIMEOUT 0x11 -#define QHSTA_M_DATA_OVER_RUN 0x12 -#define QHSTA_M_DATA_UNDER_RUN 0x12 -#define QHSTA_M_UNEXPECTED_BUS_FREE 0x13 -#define QHSTA_M_BAD_BUS_PHASE_SEQ 0x14 - -#define QHSTA_D_QDONE_SG_LIST_CORRUPTED 0x21 -#define QHSTA_D_ASC_DVC_ERROR_CODE_SET 0x22 -#define QHSTA_D_HOST_ABORT_FAILED 0x23 -#define QHSTA_D_EXE_SCSI_Q_FAILED 0x24 -#define QHSTA_D_EXE_SCSI_Q_BUSY_TIMEOUT 0x25 - -#define QHSTA_D_ASPI_NO_BUF_POOL 0x26 - -#define QHSTA_M_WTM_TIMEOUT 0x41 -#define QHSTA_M_BAD_CMPL_STATUS_IN 0x42 -#define QHSTA_M_NO_AUTO_REQ_SENSE 0x43 -#define QHSTA_M_AUTO_REQ_SENSE_FAIL 0x44 -#define QHSTA_M_TARGET_STATUS_BUSY 0x45 -#define QHSTA_M_BAD_TAG_CODE 0x46 - -#define QHSTA_M_BAD_QUEUE_FULL_OR_BUSY 0x47 - -#define QHSTA_D_LRAM_CMP_ERROR 0x81 -#define QHSTA_M_MICRO_CODE_ERROR_HALT 0xA1 - -#define ASC_FLAG_SCSIQ_REQ 0x01 -#define ASC_FLAG_BIOS_SCSIQ_REQ 0x02 -#define ASC_FLAG_BIOS_ASYNC_IO 0x04 -#define ASC_FLAG_SRB_LINEAR_ADDR 0x08 - -#define ASC_FLAG_WIN16 0x10 -#define ASC_FLAG_WIN32 0x20 - -#define ASC_FLAG_DOS_VM_CALLBACK 0x80 - -#define ASC_TAG_FLAG_ADD_ONE_BYTE 0x10 -#define ASC_TAG_FLAG_ISAPNP_ADD_BYTES 0x40 - -#define ASC_SCSIQ_CPY_BEG 4 -#define ASC_SCSIQ_SGHD_CPY_BEG 2 - -#define ASC_SCSIQ_B_FWD 0 -#define ASC_SCSIQ_B_BWD 1 - -#define ASC_SCSIQ_B_STATUS 2 -#define ASC_SCSIQ_B_QNO 3 - -#define ASC_SCSIQ_B_CNTL 4 -#define ASC_SCSIQ_B_SG_QUEUE_CNT 5 - -#define ASC_SCSIQ_D_DATA_ADDR 8 -#define ASC_SCSIQ_D_DATA_CNT 12 -#define ASC_SCSIQ_B_SENSE_LEN 20 -#define ASC_SCSIQ_DONE_INFO_BEG 22 -#define ASC_SCSIQ_D_SRBPTR 22 -#define ASC_SCSIQ_B_TARGET_IX 26 -#define ASC_SCSIQ_B_CDB_LEN 28 -#define ASC_SCSIQ_B_TAG_CODE 29 -#define ASC_SCSIQ_W_VM_ID 30 -#define ASC_SCSIQ_DONE_STATUS 32 -#define ASC_SCSIQ_HOST_STATUS 33 -#define ASC_SCSIQ_SCSI_STATUS 34 -#define ASC_SCSIQ_CDB_BEG 36 -#define ASC_SCSIQ_DW_REMAIN_XFER_ADDR 56 -#define ASC_SCSIQ_DW_REMAIN_XFER_CNT 60 -#define ASC_SCSIQ_B_SG_WK_QP 49 -#define ASC_SCSIQ_B_SG_WK_IX 50 -#define ASC_SCSIQ_W_REQ_COUNT 52 -#define ASC_SCSIQ_B_LIST_CNT 6 -#define ASC_SCSIQ_B_CUR_LIST_CNT 7 - -#define ASC_SGQ_B_SG_CNTL 4 -#define ASC_SGQ_B_SG_HEAD_QP 5 -#define ASC_SGQ_B_SG_LIST_CNT 6 -#define ASC_SGQ_B_SG_CUR_LIST_CNT 7 -#define ASC_SGQ_LIST_BEG 8 - -#define ASC_DEF_SCSI1_QNG 2 -#define ASC_MAX_SCSI1_QNG 2 -#define ASC_DEF_SCSI2_QNG 16 -#define ASC_MAX_SCSI2_QNG 32 - -#define ASC_TAG_CODE_MASK 0x23 - -#define ASC_STOP_REQ_RISC_STOP 0x01 - -#define ASC_STOP_ACK_RISC_STOP 0x03 - -#define ASC_STOP_CLEAN_UP_BUSY_Q 0x10 -#define ASC_STOP_CLEAN_UP_DISC_Q 0x20 -#define ASC_STOP_HOST_REQ_RISC_HALT 0x40 -#define ASC_STOP_SEND_INT_TO_HOST 0x80 - -#define ASC_TIDLUN_TO_IX( tid, lun ) ( ASC_SCSI_TIX_TYPE )( (tid) + ((lun)<<ASC_SCSI_ID_BITS) ) - -#define ASC_TID_TO_TARGET_ID( tid ) ( ASC_SCSI_BIT_ID_TYPE )( 0x01 << (tid) ) -#define ASC_TIX_TO_TARGET_ID( tix ) ( 0x01 << ( (tix) & ASC_MAX_TID ) ) -#define ASC_TIX_TO_TID( tix ) ( (tix) & ASC_MAX_TID ) -#define ASC_TID_TO_TIX( tid ) ( (tid) & ASC_MAX_TID ) -#define ASC_TIX_TO_LUN( tix ) ( ( (tix) >> ASC_SCSI_ID_BITS ) & ASC_MAX_LUN ) - -#define ASC_QNO_TO_QADDR( q_no ) ( (ASC_QADR_BEG)+( ( int )(q_no) << 6 ) ) - -typedef struct asc_scisq_1 { - uchar status; - uchar q_no; - uchar cntl; - uchar sg_queue_cnt; - - uchar target_id; - uchar target_lun; - - ulong data_addr; - ulong data_cnt; - ulong sense_addr; - uchar sense_len; - uchar user_def; -} ASC_SCSIQ_1; - -typedef struct asc_scisq_2 { - ulong srb_ptr; - uchar target_ix; - - uchar flag; - uchar cdb_len; - uchar tag_code; - - ushort vm_id; -} ASC_SCSIQ_2; - -typedef struct asc_scsiq_3 { - uchar done_stat; - uchar host_stat; - uchar scsi_stat; - uchar scsi_msg; -} ASC_SCSIQ_3; - -typedef struct asc_scsiq_4 { - uchar cdb[ASC_MAX_CDB_LEN]; - uchar y_first_sg_list_qp; - uchar y_working_sg_qp; - uchar y_working_sg_ix; - uchar y_cntl; - ushort x_req_count; - ushort x_reconnect_rtn; - ulong x_saved_data_addr; - ulong x_saved_data_cnt; -} ASC_SCSIQ_4; - -typedef struct asc_q_done_info { - ASC_SCSIQ_2 d2; - ASC_SCSIQ_3 d3; - uchar q_status; - uchar q_no; - uchar cntl; - uchar sense_len; - uchar user_def; - uchar res; - ulong remain_bytes; -} ASC_QDONE_INFO; - -typedef struct asc_sg_list { - ulong addr; - ulong bytes; -} ASC_SG_LIST; - -typedef struct asc_sg_head { - uchar entry_cnt; - - uchar queue_cnt; - - uchar entry_to_copy; - uchar res; - ASC_SG_LIST sg_list[ASC_MAX_SG_LIST]; -} ASC_SG_HEAD; - -#define ASC_MIN_SG_LIST 2 - -typedef struct asc_min_sg_head { - uchar entry_cnt; - - uchar queue_cnt; - - uchar entry_to_copy; - uchar res; - ASC_SG_LIST sg_list[ASC_MIN_SG_LIST]; -} ASC_MIN_SG_HEAD; - -#define QCX_SORT (0x0001) -#define QCX_COALEASE (0x0002) - -#if CC_LINK_BUSY_Q -typedef struct asc_ext_scsi_q { - ulong lba; - ushort lba_len; - struct asc_scsi_q dosfar *next; - struct asc_scsi_q dosfar *join; - ushort cntl; - ushort buffer_id; - uchar q_required; - uchar res; -} ASC_EXT_SCSI_Q; - -#endif - -typedef struct asc_scsi_q { - ASC_SCSIQ_1 q1; - ASC_SCSIQ_2 q2; - uchar dosfar *cdbptr; - - ASC_SG_HEAD dosfar *sg_head; - -#if CC_LINK_BUSY_Q - ASC_EXT_SCSI_Q ext; -#endif - -} ASC_SCSI_Q; - -typedef struct asc_scsi_req_q { - ASC_SCSIQ_1 r1; - ASC_SCSIQ_2 r2; - uchar dosfar *cdbptr; - ASC_SG_HEAD dosfar *sg_head; - -#if CC_LINK_BUSY_Q - ASC_EXT_SCSI_Q ext; -#endif - - uchar dosfar *sense_ptr; - - ASC_SCSIQ_3 r3; - uchar cdb[ASC_MAX_CDB_LEN]; - uchar sense[ASC_MIN_SENSE_LEN]; -} ASC_SCSI_REQ_Q; - -typedef struct asc_risc_q { - uchar fwd; - uchar bwd; - ASC_SCSIQ_1 i1; - ASC_SCSIQ_2 i2; - ASC_SCSIQ_3 i3; - ASC_SCSIQ_4 i4; -} ASC_RISC_Q; - -typedef struct asc_sg_list_q { - - uchar seq_no; - uchar q_no; - uchar cntl; - uchar sg_head_qp; - uchar sg_list_cnt; - uchar sg_cur_list_cnt; - -} ASC_SG_LIST_Q; - -typedef struct asc_risc_sg_list_q { - uchar fwd; - uchar bwd; - ASC_SG_LIST_Q sg; - ASC_SG_LIST sg_list[7]; -} ASC_RISC_SG_LIST_Q; - -#define ASC_EXE_SCSI_IO_MAX_IDLE_LOOP 0x1000000UL -#define ASC_EXE_SCSI_IO_MAX_WAIT_LOOP 1024 - -#define ASCQ_ERR_NO_ERROR 0 -#define ASCQ_ERR_IO_NOT_FOUND 1 -#define ASCQ_ERR_LOCAL_MEM 2 -#define ASCQ_ERR_CHKSUM 3 -#define ASCQ_ERR_START_CHIP 4 -#define ASCQ_ERR_INT_TARGET_ID 5 -#define ASCQ_ERR_INT_LOCAL_MEM 6 -#define ASCQ_ERR_HALT_RISC 7 -#define ASCQ_ERR_GET_ASPI_ENTRY 8 -#define ASCQ_ERR_CLOSE_ASPI 9 -#define ASCQ_ERR_HOST_INQUIRY 0x0A -#define ASCQ_ERR_SAVED_SRB_BAD 0x0B -#define ASCQ_ERR_QCNTL_SG_LIST 0x0C -#define ASCQ_ERR_Q_STATUS 0x0D -#define ASCQ_ERR_WR_SCSIQ 0x0E -#define ASCQ_ERR_PC_ADDR 0x0F -#define ASCQ_ERR_SYN_OFFSET 0x10 -#define ASCQ_ERR_SYN_XFER_TIME 0x11 -#define ASCQ_ERR_LOCK_DMA 0x12 -#define ASCQ_ERR_UNLOCK_DMA 0x13 -#define ASCQ_ERR_VDS_CHK_INSTALL 0x14 -#define ASCQ_ERR_MICRO_CODE_HALT 0x15 -#define ASCQ_ERR_SET_LRAM_ADDR 0x16 -#define ASCQ_ERR_CUR_QNG 0x17 -#define ASCQ_ERR_SG_Q_LINKS 0x18 -#define ASCQ_ERR_SCSIQ_PTR 0x19 -#define ASCQ_ERR_ISR_RE_ENTRY 0x1A -#define ASCQ_ERR_CRITICAL_RE_ENTRY 0x1B -#define ASCQ_ERR_ISR_ON_CRITICAL 0x1C -#define ASCQ_ERR_SG_LIST_ODD_ADDRESS 0x1D -#define ASCQ_ERR_XFER_ADDRESS_TOO_BIG 0x1E -#define ASCQ_ERR_SCSIQ_NULL_PTR 0x1F -#define ASCQ_ERR_SCSIQ_BAD_NEXT_PTR 0x20 -#define ASCQ_ERR_GET_NUM_OF_FREE_Q 0x21 -#define ASCQ_ERR_SEND_SCSI_Q 0x22 -#define ASCQ_ERR_HOST_REQ_RISC_HALT 0x23 -#define ASCQ_ERR_RESET_SDTR 0x24 - -#define ASC_WARN_NO_ERROR 0x0000 -#define ASC_WARN_IO_PORT_ROTATE 0x0001 -#define ASC_WARN_EEPROM_CHKSUM 0x0002 -#define ASC_WARN_IRQ_MODIFIED 0x0004 -#define ASC_WARN_AUTO_CONFIG 0x0008 -#define ASC_WARN_CMD_QNG_CONFLICT 0x0010 - -#define ASC_WARN_EEPROM_RECOVER 0x0020 -#define ASC_WARN_CFG_MSW_RECOVER 0x0040 - -#define ASC_IERR_WRITE_EEPROM 0x0001 -#define ASC_IERR_MCODE_CHKSUM 0x0002 -#define ASC_IERR_SET_PC_ADDR 0x0004 -#define ASC_IERR_START_STOP_CHIP 0x0008 - -#define ASC_IERR_IRQ_NO 0x0010 - -#define ASC_IERR_SET_IRQ_NO 0x0020 -#define ASC_IERR_CHIP_VERSION 0x0040 -#define ASC_IERR_SET_SCSI_ID 0x0080 -#define ASC_IERR_GET_PHY_ADDR 0x0100 -#define ASC_IERR_BAD_SIGNATURE 0x0200 -#define ASC_IERR_NO_BUS_TYPE 0x0400 -#define ASC_IERR_SCAM 0x0800 -#define ASC_IERR_SET_SDTR 0x1000 -#define ASC_IERR_RW_LRAM 0x8000 - -#define ASC_DEF_IRQ_NO 10 -#define ASC_MAX_IRQ_NO 15 -#define ASC_MIN_IRQ_NO 10 - -#define ASC_MIN_REMAIN_Q (0x02) -#define ASC_DEF_MAX_TOTAL_QNG (0x40) - -#define ASC_MIN_TAG_Q_PER_DVC (0x04) -#define ASC_DEF_TAG_Q_PER_DVC (0x04) - -#define ASC_MIN_FREE_Q ASC_MIN_REMAIN_Q - -#define ASC_MIN_TOTAL_QNG (( ASC_MAX_SG_QUEUE )+( ASC_MIN_FREE_Q )) - -#define ASC_MAX_TOTAL_QNG 240 -#define ASC_MAX_PCI_INRAM_TOTAL_QNG 20 - -#define ASC_MAX_INRAM_TAG_QNG 16 - -typedef struct asc_dvc_cfg { - ASC_SCSI_BIT_ID_TYPE can_tagged_qng; - - ASC_SCSI_BIT_ID_TYPE cmd_qng_enabled; - ASC_SCSI_BIT_ID_TYPE disc_enable; - uchar res; - uchar chip_scsi_id:4; - - uchar isa_dma_speed:4; - - uchar isa_dma_channel; - uchar chip_version; - ushort pci_device_id; - ushort lib_serial_no; - ushort lib_version; - ushort mcode_date; - ushort mcode_version; - uchar sdtr_data[ASC_MAX_TID + 1]; - uchar max_tag_qng[ASC_MAX_TID + 1]; - uchar dosfar *overrun_buf; - -} ASC_DVC_CFG; - -#define ASC_DEF_DVC_CNTL 0xFFFF -#define ASC_DEF_CHIP_SCSI_ID 7 -#define ASC_DEF_ISA_DMA_SPEED 4 - -#define ASC_INIT_STATE_NULL 0x0000 -#define ASC_INIT_STATE_BEG_GET_CFG 0x0001 -#define ASC_INIT_STATE_END_GET_CFG 0x0002 -#define ASC_INIT_STATE_BEG_SET_CFG 0x0004 -#define ASC_INIT_STATE_END_SET_CFG 0x0008 -#define ASC_INIT_STATE_BEG_LOAD_MC 0x0010 -#define ASC_INIT_STATE_END_LOAD_MC 0x0020 -#define ASC_INIT_STATE_BEG_INQUIRY 0x0040 -#define ASC_INIT_STATE_END_INQUIRY 0x0080 -#define ASC_INIT_RESET_SCSI_DONE 0x0100 - -#define ASC_PCI_DEVICE_ID_REV_A 0x1100 -#define ASC_PCI_DEVICE_ID_REV_B 0x1200 - -#define ASC_BUG_FIX_ADD_ONE_BYTE 0x0001 - -#define ASYN_SDTR_DATA_FIX_PCI_REV_AB 0x41 - -#define ASC_MIN_TAGGED_CMD 7 - -typedef struct asc_dvc_var { - PortAddr iop_base; - ushort err_code; - ushort dvc_cntl; - ushort bug_fix_cntl; - ushort bus_type; - Ptr2Func isr_callback; - Ptr2Func exe_callback; - - ASC_SCSI_BIT_ID_TYPE init_sdtr; - - ASC_SCSI_BIT_ID_TYPE sdtr_done; - - ASC_SCSI_BIT_ID_TYPE use_tagged_qng; - - ASC_SCSI_BIT_ID_TYPE unit_not_ready; - - ASC_SCSI_BIT_ID_TYPE queue_full_or_busy; - - ASC_SCSI_BIT_ID_TYPE start_motor; - uchar scsi_reset_wait; - uchar chip_no; - - char is_in_int; - uchar max_total_qng; - - uchar cur_total_qng; - - uchar in_critical_cnt; - - uchar irq_no; - uchar last_q_shortage; - - ushort init_state; - uchar cur_dvc_qng[ASC_MAX_TID + 1]; - uchar max_dvc_qng[ASC_MAX_TID + 1]; - - ASC_SCSI_Q dosfar *scsiq_busy_head[ASC_MAX_TID + 1]; - ASC_SCSI_Q dosfar *scsiq_busy_tail[ASC_MAX_TID + 1]; - - ulong int_count; - ulong req_count; - ulong busy_count; - - ASC_DVC_CFG dosfar *cfg; - Ptr2Func saved_ptr2func; - ulong reserved2; - ulong reserved3; - ulong max_dma_count; - ASC_SCSI_BIT_ID_TYPE no_scam; - ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer; -} ASC_DVC_VAR; - -typedef int (dosfar * ASC_ISR_CALLBACK) (ASC_DVC_VAR asc_ptr_type *, ASC_QDONE_INFO dosfar *); -typedef int (dosfar * ASC_EXE_CALLBACK) (ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_Q dosfar *); - -typedef struct asc_dvc_inq_info { - uchar type[ASC_MAX_TID + 1][ASC_MAX_LUN + 1]; -} ASC_DVC_INQ_INFO; - -typedef struct asc_cap_info { - ulong lba; - ulong blk_size; -} ASC_CAP_INFO; - -typedef struct asc_cap_info_array { - ASC_CAP_INFO cap_info[ASC_MAX_TID + 1][ASC_MAX_LUN + 1]; -} ASC_CAP_INFO_ARRAY; - -#define ASC_IOADR_TABLE_MAX_IX 11 -#define ASC_IOADR_GAP 0x10 -#define ASC_SEARCH_IOP_GAP 0x10 -#define ASC_MIN_IOP_ADDR ( PortAddr )0x0100 -#define ASC_MAX_IOP_ADDR ( PortAddr )0x3F0 - -#define ASC_IOADR_1 ( PortAddr )0x0110 -#define ASC_IOADR_2 ( PortAddr )0x0130 -#define ASC_IOADR_3 ( PortAddr )0x0150 -#define ASC_IOADR_4 ( PortAddr )0x0190 -#define ASC_IOADR_5 ( PortAddr )0x0210 -#define ASC_IOADR_6 ( PortAddr )0x0230 -#define ASC_IOADR_7 ( PortAddr )0x0250 -#define ASC_IOADR_8 ( PortAddr )0x0330 -#define ASC_IOADR_DEF ASC_IOADR_8 - -#define ASC_SYN_XFER_NO 8 -#define ASC_MAX_SDTR_PERIOD_INDEX 7 -#define ASC_SYN_MAX_OFFSET 0x0F -#define ASC_DEF_SDTR_OFFSET 0x0F -#define ASC_DEF_SDTR_INDEX 0x00 - -#define SYN_XFER_NS_0 25 -#define SYN_XFER_NS_1 30 -#define SYN_XFER_NS_2 35 -#define SYN_XFER_NS_3 40 -#define SYN_XFER_NS_4 50 -#define SYN_XFER_NS_5 60 -#define SYN_XFER_NS_6 70 -#define SYN_XFER_NS_7 85 - -#define ASC_SDTR_PERIOD_IX_MIN 7 - -#define SYN_XMSG_WLEN 3 - -typedef struct sdtr_xmsg { - uchar msg_type; - uchar msg_len; - uchar msg_req; - uchar xfer_period; - uchar req_ack_offset; - uchar res; -} SDTR_XMSG; - -#define ASC_MCNTL_NO_SEL_TIMEOUT ( ushort )0x0001 -#define ASC_MCNTL_NULL_TARGET ( ushort )0x0002 - -#define ASC_CNTL_INITIATOR ( ushort )0x0001 -#define ASC_CNTL_BIOS_GT_1GB ( ushort )0x0002 -#define ASC_CNTL_BIOS_GT_2_DISK ( ushort )0x0004 -#define ASC_CNTL_BIOS_REMOVABLE ( ushort )0x0008 -#define ASC_CNTL_NO_SCAM ( ushort )0x0010 -#define ASC_CNTL_NO_PCI_FIX_ASYN_XFER ( ushort )0x0020 - -#define ASC_CNTL_INT_MULTI_Q ( ushort )0x0080 - -#define ASC_CNTL_NO_LUN_SUPPORT ( ushort )0x0040 - -#define ASC_CNTL_NO_VERIFY_COPY ( ushort )0x0100 -#define ASC_CNTL_RESET_SCSI ( ushort )0x0200 -#define ASC_CNTL_INIT_INQUIRY ( ushort )0x0400 -#define ASC_CNTL_INIT_VERBOSE ( ushort )0x0800 - -#define ASC_CNTL_SCSI_PARITY ( ushort )0x1000 -#define ASC_CNTL_BURST_MODE ( ushort )0x2000 - -#define ASC_CNTL_USE_8_IOP_BASE ( ushort )0x4000 - -#define ASC_EEP_DVC_CFG_BEG_VL 2 -#define ASC_EEP_MAX_DVC_ADDR_VL 15 - -#define ASC_EEP_DVC_CFG_BEG 32 -#define ASC_EEP_MAX_DVC_ADDR 45 - -#define ASC_EEP_DEFINED_WORDS 10 -#define ASC_EEP_MAX_ADDR 63 -#define ASC_EEP_RES_WORDS 0 -#define ASC_EEP_MAX_RETRY 20 -#define ASC_MAX_INIT_BUSY_RETRY 8 - -#define ASC_EEP_ISA_PNP_WSIZE 16 - -typedef struct asceep_config { - ushort cfg_lsw; - ushort cfg_msw; - - uchar init_sdtr; - uchar disc_enable; - - uchar use_cmd_qng; - - uchar start_motor; - uchar max_total_qng; - uchar max_tag_qng; - uchar bios_scan; - - uchar power_up_wait; - - uchar no_scam; - uchar chip_scsi_id:4; - - uchar isa_dma_speed:4; - - uchar sdtr_data[ASC_MAX_TID + 1]; - - uchar adapter_info[6]; - - ushort cntl; - - ushort chksum; -} ASCEEP_CONFIG; - -#define ASC_EEP_CMD_READ 0x80 -#define ASC_EEP_CMD_WRITE 0x40 -#define ASC_EEP_CMD_WRITE_ABLE 0x30 -#define ASC_EEP_CMD_WRITE_DISABLE 0x00 - -#define ASC_OVERRUN_BSIZE 0x00000048UL - -#define ASCV_MSGOUT_BEG 0x0000 -#define ASCV_MSGOUT_SDTR_PERIOD (ASCV_MSGOUT_BEG+3) -#define ASCV_MSGOUT_SDTR_OFFSET (ASCV_MSGOUT_BEG+4) - -#define ASCV_MSGIN_BEG (ASCV_MSGOUT_BEG+8) -#define ASCV_MSGIN_SDTR_PERIOD (ASCV_MSGIN_BEG+3) -#define ASCV_MSGIN_SDTR_OFFSET (ASCV_MSGIN_BEG+4) - -#define ASCV_SDTR_DATA_BEG (ASCV_MSGIN_BEG+8) -#define ASCV_SDTR_DONE_BEG (ASCV_SDTR_DATA_BEG+8) -#define ASCV_MAX_DVC_QNG_BEG ( ushort )0x0020 - -#define ASCV_ASCDVC_ERR_CODE_W ( ushort )0x0030 -#define ASCV_MCODE_CHKSUM_W ( ushort )0x0032 -#define ASCV_MCODE_SIZE_W ( ushort )0x0034 -#define ASCV_STOP_CODE_B ( ushort )0x0036 -#define ASCV_DVC_ERR_CODE_B ( ushort )0x0037 - -#define ASCV_OVERRUN_PADDR_D ( ushort )0x0038 -#define ASCV_OVERRUN_BSIZE_D ( ushort )0x003C - -#define ASCV_HALTCODE_W ( ushort )0x0040 -#define ASCV_CHKSUM_W ( ushort )0x0042 -#define ASCV_MC_DATE_W ( ushort )0x0044 -#define ASCV_MC_VER_W ( ushort )0x0046 -#define ASCV_NEXTRDY_B ( ushort )0x0048 -#define ASCV_DONENEXT_B ( ushort )0x0049 -#define ASCV_USE_TAGGED_QNG_B ( ushort )0x004A -#define ASCV_SCSIBUSY_B ( ushort )0x004B -#define ASCV_CDBCNT_B ( ushort )0x004C -#define ASCV_CURCDB_B ( ushort )0x004D -#define ASCV_RCLUN_B ( ushort )0x004E -#define ASCV_BUSY_QHEAD_B ( ushort )0x004F -#define ASCV_DISC1_QHEAD_B ( ushort )0x0050 - -#define ASCV_DISC_ENABLE_B ( ushort )0x0052 -#define ASCV_CAN_TAGGED_QNG_B ( ushort )0x0053 -#define ASCV_HOSTSCSI_ID_B ( ushort )0x0055 -#define ASCV_MCODE_CNTL_B ( ushort )0x0056 -#define ASCV_NULL_TARGET_B ( ushort )0x0057 - -#define ASCV_FREE_Q_HEAD_W ( ushort )0x0058 -#define ASCV_DONE_Q_TAIL_W ( ushort )0x005A -#define ASCV_FREE_Q_HEAD_B ( ushort )(ASCV_FREE_Q_HEAD_W+1) -#define ASCV_DONE_Q_TAIL_B ( ushort )(ASCV_DONE_Q_TAIL_W+1) - -#define ASCV_HOST_FLAG_B ( ushort )0x005D - -#define ASCV_TOTAL_READY_Q_B ( ushort )0x0064 -#define ASCV_VER_SERIAL_B ( ushort )0x0065 -#define ASCV_HALTCODE_SAVED_W ( ushort )0x0066 -#define ASCV_WTM_FLAG_B ( ushort )0x0068 -#define ASCV_RISC_FLAG_B ( ushort )0x006A -#define ASCV_REQ_SG_LIST_QP ( ushort )0x006B - -#define ASC_HOST_FLAG_IN_ISR 0x01 -#define ASC_HOST_FLAG_ACK_INT 0x02 - -#define ASC_RISC_FLAG_GEN_INT 0x01 -#define ASC_RISC_FLAG_REQ_SG_LIST 0x02 - -#define IOP_CTRL (0x0F) -#define IOP_STATUS (0x0E) -#define IOP_INT_ACK IOP_STATUS - -#define IOP_REG_IFC (0x0D) - -#define IOP_SYN_OFFSET (0x0B) -#define IOP_REG_PC (0x0C) -#define IOP_RAM_ADDR (0x0A) -#define IOP_RAM_DATA (0x08) -#define IOP_EEP_DATA (0x06) -#define IOP_EEP_CMD (0x07) - -#define IOP_VERSION (0x03) -#define IOP_CONFIG_HIGH (0x04) -#define IOP_CONFIG_LOW (0x02) -#define IOP_ASPI_ID_LOW (0x01) -#define IOP_ASPI_ID_HIGH (0x00) - -#define IOP_REG_DC1 (0x0E) -#define IOP_REG_DC0 (0x0C) -#define IOP_REG_SB (0x0B) -#define IOP_REG_DA1 (0x0A) -#define IOP_REG_DA0 (0x08) -#define IOP_REG_SC (0x09) -#define IOP_DMA_SPEED (0x07) -#define IOP_REG_FLAG (0x07) -#define IOP_FIFO_H (0x06) -#define IOP_FIFO_L (0x04) -#define IOP_REG_ID (0x05) -#define IOP_REG_QP (0x03) -#define IOP_REG_IH (0x02) -#define IOP_REG_IX (0x01) -#define IOP_REG_AX (0x00) - -#define IFC_REG_LOCK (0x00) -#define IFC_REG_UNLOCK (0x09) - -#define IFC_WR_EN_FILTER (0x10) -#define IFC_RD_NO_EEPROM (0x10) -#define IFC_SLEW_RATE (0x20) -#define IFC_ACT_NEG (0x40) -#define IFC_INP_FILTER (0x80) - -#define IFC_INIT_DEFAULT ( IFC_ACT_NEG | IFC_REG_UNLOCK ) - -#define SC_SEL (0x80) -#define SC_BSY (0x40) -#define SC_ACK (0x20) -#define SC_REQ (0x10) -#define SC_ATN (0x08) -#define SC_IO (0x04) -#define SC_CD (0x02) -#define SC_MSG (0x01) - -#define AscGetVarFreeQHead( port ) AscReadLramWord( port, ASCV_FREE_Q_HEAD_W ) -#define AscGetVarDoneQTail( port ) AscReadLramWord( port, ASCV_DONE_Q_TAIL_W ) -#define AscPutVarFreeQHead( port, val ) AscWriteLramWord( port, ASCV_FREE_Q_HEAD_W, val ) -#define AscPutVarDoneQTail( port, val ) AscWriteLramWord( port, ASCV_DONE_Q_TAIL_W, val ) - -#define AscGetRiscVarFreeQHead( port ) AscReadLramByte( port, ASCV_NEXTRDY_B ) -#define AscGetRiscVarDoneQTail( port ) AscReadLramByte( port, ASCV_DONENEXT_B ) -#define AscPutRiscVarFreeQHead( port, val ) AscWriteLramByte( port, ASCV_NEXTRDY_B, val ) -#define AscPutRiscVarDoneQTail( port, val ) AscWriteLramByte( port, ASCV_DONENEXT_B, val ) - -#define AscGetChipIFC( port ) inp( (port)+IOP_REG_IFC ) -#define AscPutChipIFC( port, data ) outp( (port)+IOP_REG_IFC, data ) - -#define AscGetChipLramAddr( port ) ( ushort )inpw( ( PortAddr )((port)+IOP_RAM_ADDR) ) -#define AscSetChipLramAddr( port, addr ) outpw( ( PortAddr )( (port)+IOP_RAM_ADDR ), addr ) -#define AscPutChipLramData( port, data ) outpw( (port)+IOP_RAM_DATA, data ) -#define AscGetChipLramData( port ) inpw( (port)+IOP_RAM_DATA ) - -#define AscWriteChipSyn( port, data ) outp( (port)+IOP_SYN_OFFSET, data ) -#define AscReadChipSyn( port ) inp( (port)+IOP_SYN_OFFSET ) - -#define AscWriteChipIH( port, data ) outpw( (port)+IOP_REG_IH, data ) -#define AscReadChipIH( port ) inpw( (port)+IOP_REG_IH ) - -#define AscWriteChipScsiID( port, data ) outp( (port)+IOP_REG_ID, data ) -#define AscReadChipScsiID( port ) inp( (port)+IOP_REG_ID ) - -#define AscGetChipDmaSpeed( port ) ( uchar )inp( (port)+IOP_DMA_SPEED ) -#define AscSetChipDmaSpeed( port, data ) outp( (port)+IOP_DMA_SPEED, data ) -#define AscGetChipQP( port ) ( uchar )inp( (port)+IOP_REG_QP ) -#define AscSetPCAddr( port, data ) outpw( (port)+IOP_REG_PC, data ) -#define AscGetPCAddr( port ) inpw( (port)+IOP_REG_PC ) -#define AscGetChipVerNo( port ) ( uchar )inp( (port)+IOP_VERSION ) - -#define AscGetChipEEPCmd( port ) ( uchar )inp( (port)+IOP_EEP_CMD ) -#define AscSetChipEEPCmd( port, data ) outp( (port)+IOP_EEP_CMD, data ) -#define AscGetChipEEPData( port ) inpw( (port)+IOP_EEP_DATA ) -#define AscSetChipEEPData( port, data ) outpw( (port)+IOP_EEP_DATA, data ) - -#define AscGetChipControl( port ) ( uchar )inp( (port)+IOP_CTRL ) -#define AscSetChipControl( port, cc_val ) outp( (port)+IOP_CTRL, cc_val ) - -#define AscGetChipStatus( port ) ( ASC_CS_TYPE )inpw( (port)+IOP_STATUS ) -#define AscSetChipStatus( port, cs_val ) outpw( (port)+IOP_STATUS, cs_val ) - -#define AscGetChipCfgLsw( port ) ( ushort )inpw( (port)+IOP_CONFIG_LOW ) -#define AscGetChipCfgMsw( port ) ( ushort )inpw( (port)+IOP_CONFIG_HIGH ) -#define AscSetChipCfgLsw( port, data ) outpw( (port)+IOP_CONFIG_LOW, data ) -#define AscSetChipCfgMsw( port, data ) outpw( (port)+IOP_CONFIG_HIGH, data ) - -#define AscIsIntPending( port ) ( AscGetChipStatus( port ) & CSW_INT_PENDING ) -#define AscGetChipScsiID( port ) ( ( AscGetChipCfgLsw( port ) >> 8 ) & ASC_MAX_TID ) - -#define ASC_HALT_EXTMSG_IN ( ushort )0x8000 -#define ASC_HALT_CHK_CONDITION ( ushort )0x8100 -#define ASC_HALT_SS_QUEUE_FULL ( ushort )0x8200 -#define ASC_HALT_SDTR_REJECTED ( ushort )0x4000 - -#define ASC_MAX_QNO 0xF8 -#define ASC_DATA_SEC_BEG ( ushort )0x0080 -#define ASC_DATA_SEC_END ( ushort )0x0080 -#define ASC_CODE_SEC_BEG ( ushort )0x0080 -#define ASC_CODE_SEC_END ( ushort )0x0080 -#define ASC_QADR_BEG (0x4000) -#define ASC_QADR_USED ( ushort )( ASC_MAX_QNO * 64 ) -#define ASC_QADR_END ( ushort )0x7FFF -#define ASC_QLAST_ADR ( ushort )0x7FC0 -#define ASC_QBLK_SIZE 0x40 -#define ASC_BIOS_DATA_QBEG 0xF8 - -#define ASC_MIN_ACTIVE_QNO 0x01 - -#define ASC_QLINK_END 0xFF -#define ASC_EEPROM_WORDS 0x10 -#define ASC_MAX_MGS_LEN 0x10 - -#define ASC_BIOS_ADDR_DEF 0xDC00 -#define ASC_BIOS_SIZE 0x3800 -#define ASC_BIOS_RAM_OFF 0x3800 -#define ASC_BIOS_RAM_SIZE 0x800 -#define ASC_BIOS_MIN_ADDR 0xC000 -#define ASC_BIOS_MAX_ADDR 0xEC00 -#define ASC_BIOS_BANK_SIZE 0x0400 - -#define ASC_MCODE_START_ADDR 0x0080 - -#define ASC_CFG0_HOST_INT_ON 0x0020 -#define ASC_CFG0_BIOS_ON 0x0040 -#define ASC_CFG0_VERA_BURST_ON 0x0080 -#define ASC_CFG0_SCSI_PARITY_ON 0x0800 - -#define ASC_CFG1_SCSI_TARGET_ON 0x0080 -#define ASC_CFG1_LRAM_8BITS_ON 0x0800 - -#define ASC_CFG_MSW_CLR_MASK 0xF0C0 - -#define CSW_TEST1 ( ASC_CS_TYPE )0x8000 -#define CSW_AUTO_CONFIG ( ASC_CS_TYPE )0x4000 -#define CSW_RESERVED1 ( ASC_CS_TYPE )0x2000 -#define CSW_IRQ_WRITTEN ( ASC_CS_TYPE )0x1000 -#define CSW_33MHZ_SELECTED ( ASC_CS_TYPE )0x0800 -#define CSW_TEST2 ( ASC_CS_TYPE )0x0400 -#define CSW_TEST3 ( ASC_CS_TYPE )0x0200 -#define CSW_RESERVED2 ( ASC_CS_TYPE )0x0100 -#define CSW_DMA_DONE ( ASC_CS_TYPE )0x0080 -#define CSW_FIFO_RDY ( ASC_CS_TYPE )0x0040 - -#define CSW_EEP_READ_DONE ( ASC_CS_TYPE )0x0020 - -#define CSW_HALTED ( ASC_CS_TYPE )0x0010 -#define CSW_SCSI_RESET_ACTIVE ( ASC_CS_TYPE )0x0008 - -#define CSW_PARITY_ERR ( ASC_CS_TYPE )0x0004 -#define CSW_SCSI_RESET_LATCH ( ASC_CS_TYPE )0x0002 - -#define CSW_INT_PENDING ( ASC_CS_TYPE )0x0001 - -#define CIW_INT_ACK ( ASC_CS_TYPE )0x0100 -#define CIW_TEST1 ( ASC_CS_TYPE )0x0200 -#define CIW_TEST2 ( ASC_CS_TYPE )0x0400 -#define CIW_SEL_33MHZ ( ASC_CS_TYPE )0x0800 - -#define CIW_IRQ_ACT ( ASC_CS_TYPE )0x1000 - -#define CC_CHIP_RESET ( uchar )0x80 -#define CC_SCSI_RESET ( uchar )0x40 -#define CC_HALT ( uchar )0x20 -#define CC_SINGLE_STEP ( uchar )0x10 -#define CC_DMA_ABLE ( uchar )0x08 -#define CC_TEST ( uchar )0x04 -#define CC_BANK_ONE ( uchar )0x02 -#define CC_DIAG ( uchar )0x01 - -#define ASC_1000_ID0W 0x04C1 -#define ASC_1000_ID0W_FIX 0x00C1 -#define ASC_1000_ID1B 0x25 - -#define ASC_EISA_BIG_IOP_GAP (0x1C30-0x0C50) -#define ASC_EISA_SMALL_IOP_GAP (0x0020) -#define ASC_EISA_MIN_IOP_ADDR (0x0C30) -#define ASC_EISA_MAX_IOP_ADDR (0xFC50) -#define ASC_EISA_REV_IOP_MASK (0x0C83) -#define ASC_EISA_PID_IOP_MASK (0x0C80) -#define ASC_EISA_CFG_IOP_MASK (0x0C86) - -#define ASC_GET_EISA_SLOT( iop ) ( PortAddr )( (iop) & 0xF000 ) - -#define ASC_EISA_ID_740 0x01745004UL -#define ASC_EISA_ID_750 0x01755004UL - -#define INS_HALTINT ( ushort )0x6281 -#define INS_HALT ( ushort )0x6280 -#define INS_SINT ( ushort )0x6200 -#define INS_RFLAG_WTM ( ushort )0x7380 - -#define ASC_MC_SAVE_CODE_WSIZE 0x500 -#define ASC_MC_SAVE_DATA_WSIZE 0x40 - -typedef struct asc_mc_saved { - ushort data[ASC_MC_SAVE_DATA_WSIZE]; - ushort code[ASC_MC_SAVE_CODE_WSIZE]; -} ASC_MC_SAVED; - -int AscWriteEEPCmdReg(PortAddr iop_base, uchar cmd_reg); -int AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg); -void AscWaitEEPRead(void); -void AscWaitEEPWrite(void); -ushort AscReadEEPWord(PortAddr, uchar); -ushort AscWriteEEPWord(PortAddr, uchar, ushort); -ushort AscGetEEPConfig(PortAddr, ASCEEP_CONFIG dosfar *, ushort); -int AscSetEEPConfigOnce(PortAddr, ASCEEP_CONFIG dosfar *, ushort); -int AscSetEEPConfig(PortAddr, ASCEEP_CONFIG dosfar *, ushort); -ushort AscEEPSum(PortAddr, uchar, uchar); - -int AscStartChip(PortAddr); -int AscStopChip(PortAddr); -void AscSetChipIH(PortAddr, ushort); -int AscSetRunChipSynRegAtID(PortAddr, uchar, uchar); - -int AscIsChipHalted(PortAddr); - -void AscSetChipCfgDword(PortAddr, ulong); -ulong AscGetChipCfgDword(PortAddr); - -void AscAckInterrupt(PortAddr); -void AscDisableInterrupt(PortAddr); -void AscEnableInterrupt(PortAddr); -void AscSetBank(PortAddr, uchar); -uchar AscGetBank(PortAddr); -int AscResetChipAndScsiBus(PortAddr); -ushort AscGetIsaDmaChannel(PortAddr); -ushort AscSetIsaDmaChannel(PortAddr, ushort); -uchar AscSetIsaDmaSpeed(PortAddr, uchar); -uchar AscGetIsaDmaSpeed(PortAddr); - -uchar AscReadLramByte(PortAddr, ushort); -ushort AscReadLramWord(PortAddr, ushort); -ulong AscReadLramDWord(PortAddr, ushort); -void AscWriteLramWord(PortAddr, ushort, ushort); -void AscWriteLramDWord(PortAddr, ushort, ulong); -void AscWriteLramByte(PortAddr, ushort, uchar); -int AscVerWriteLramDWord(PortAddr, ushort, ulong); -int AscVerWriteLramWord(PortAddr, ushort, ushort); -int AscVerWriteLramByte(PortAddr, ushort, uchar); - -ulong AscMemSumLramWord(PortAddr, ushort, int); -void AscMemWordSetLram(PortAddr, ushort, ushort, int); -void AscMemWordCopyToLram(PortAddr, ushort, ushort dosfar *, int); -void AscMemDWordCopyToLram(PortAddr, ushort, ulong dosfar *, int); -void AscMemWordCopyFromLram(PortAddr, ushort, ushort dosfar *, int); -int AscMemWordCmpToLram(PortAddr, ushort, ushort dosfar *, int); - -ushort AscInitAscDvcVar(ASC_DVC_VAR asc_ptr_type *); -ulong AscLoadMicroCode(PortAddr, ushort, - ushort dosfar *, ushort); -ushort AscInitFromEEP(ASC_DVC_VAR asc_ptr_type *); -ushort AscInitFromAscDvcVar(ASC_DVC_VAR asc_ptr_type *); -ushort AscInitMicroCodeVar(ASC_DVC_VAR asc_ptr_type * asc_dvc); - -void dosfar AscInitPollIsrCallBack(ASC_DVC_VAR asc_ptr_type *, - ASC_QDONE_INFO dosfar *); -int AscTestExternalLram(ASC_DVC_VAR asc_ptr_type *); -ushort AscTestLramEndian(PortAddr); - -uchar AscMsgOutSDTR(PortAddr, uchar, uchar); - -uchar AscCalSDTRData(uchar, uchar); -void AscSetChipSDTR(PortAddr, uchar, uchar); -int AscInitChipAllSynReg(ASC_DVC_VAR asc_ptr_type *, uchar); -uchar AscGetSynPeriodIndex(uchar); -uchar AscSynIndexToPeriod(uchar); -uchar AscAllocFreeQueue(PortAddr, uchar); -uchar AscAllocMultipleFreeQueue(PortAddr, uchar, uchar); -int AscRiscHaltedAbortSRB(ASC_DVC_VAR asc_ptr_type *, ulong); -int AscRiscHaltedAbortTIX(ASC_DVC_VAR asc_ptr_type *, uchar); -int AscRiscHaltedAbortALL(ASC_DVC_VAR asc_ptr_type *); -int AscHostReqRiscHalt(PortAddr); -int AscStopQueueExe(PortAddr); -int AscStartQueueExe(PortAddr); -int AscCleanUpDiscQueue(PortAddr); -int AscCleanUpBusyQueue(PortAddr); -int _AscAbortTidBusyQueue(ASC_DVC_VAR asc_ptr_type *, - ASC_QDONE_INFO dosfar *, uchar); -int _AscAbortSrbBusyQueue(ASC_DVC_VAR asc_ptr_type *, - ASC_QDONE_INFO dosfar *, ulong); -int AscWaitTixISRDone(ASC_DVC_VAR asc_ptr_type *, uchar); -int AscWaitISRDone(ASC_DVC_VAR asc_ptr_type *); -ulong AscGetOnePhyAddr(ASC_DVC_VAR asc_ptr_type *, uchar dosfar *, ulong); - -int AscSendScsiQueue(ASC_DVC_VAR asc_ptr_type * asc_dvc, - ASC_SCSI_Q dosfar * scsiq, - uchar n_q_required); -int AscPutReadyQueue(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_Q dosfar *, uchar); -int AscPutReadySgListQueue(ASC_DVC_VAR asc_ptr_type *, - ASC_SCSI_Q dosfar *, uchar); -int AscAbortScsiIO(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_Q dosfar *); -void AscExeScsiIO(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_Q dosfar *); -int AscSetChipSynRegAtID(PortAddr, uchar, uchar); -int AscSetRunChipSynRegAtID(PortAddr, uchar, uchar); -ushort AscInitLram(ASC_DVC_VAR asc_ptr_type *); -int AscReInitLram(ASC_DVC_VAR asc_ptr_type *); -ushort AscInitQLinkVar(ASC_DVC_VAR asc_ptr_type *); -int AscSetLibErrorCode(ASC_DVC_VAR asc_ptr_type *, ushort); -int _AscWaitQDone(PortAddr, ASC_SCSI_Q dosfar *); - -int AscEnterCritical(void); -void AscLeaveCritical(int); - -int AscIsrChipHalted(ASC_DVC_VAR asc_ptr_type *); -uchar _AscCopyLramScsiDoneQ(PortAddr, ushort, - ASC_QDONE_INFO dosfar *, ulong); -int AscIsrQDone(ASC_DVC_VAR asc_ptr_type *); -ushort AscIsrExeBusyQueue(ASC_DVC_VAR asc_ptr_type *, uchar); -int AscScsiSetupCmdQ(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_REQ_Q dosfar *, - uchar dosfar *, ulong); - -int AscScsiInquiry(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_REQ_Q dosfar *, - uchar dosfar *, int); -int AscScsiTestUnitReady(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_REQ_Q dosfar *); -int AscScsiStartStopUnit(ASC_DVC_VAR asc_ptr_type *, - ASC_SCSI_REQ_Q dosfar *, uchar); -int AscScsiReadCapacity(ASC_DVC_VAR asc_ptr_type *, - ASC_SCSI_REQ_Q dosfar *, - uchar dosfar *); - -ulong dosfar *swapfarbuf4(uchar dosfar *); -int PollQueueDone(ASC_DVC_VAR asc_ptr_type *, - ASC_SCSI_REQ_Q dosfar *, - int); -int PollScsiReadCapacity(ASC_DVC_VAR asc_ptr_type *, - ASC_SCSI_REQ_Q dosfar *, - ASC_CAP_INFO dosfar *); -int PollScsiInquiry(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_REQ_Q dosfar *, - uchar dosfar *, int); -int PollScsiTestUnitReady(ASC_DVC_VAR asc_ptr_type *, - ASC_SCSI_REQ_Q dosfar *); -int PollScsiStartUnit(ASC_DVC_VAR asc_ptr_type *, - ASC_SCSI_REQ_Q dosfar *); -int InitTestUnitReady(ASC_DVC_VAR asc_ptr_type *, - ASC_SCSI_REQ_Q dosfar *); -void AscDispInquiry(uchar, uchar, ASC_SCSI_INQUIRY dosfar *); -int AscPollQDone(ASC_DVC_VAR asc_ptr_type *, - ASC_SCSI_REQ_Q dosfar *, int); - -int AscSetBIOSBank(PortAddr, int, ushort); -int AscSetVlBIOSBank(PortAddr, int); -int AscSetEisaBIOSBank(PortAddr, int); -int AscSetIsaBIOSBank(PortAddr, int); - -int AscIsBiosEnabled(PortAddr, ushort); -void AscResetScsiBus(PortAddr); -void AscClrResetScsiBus(PortAddr); - -void AscSingleStepChip(PortAddr); -uchar AscSetChipScsiID(PortAddr, uchar); -ushort AscGetChipBiosAddress(PortAddr, ushort); -ushort AscSetChipBiosAddress(PortAddr, ushort, ushort); -uchar AscGetChipVersion(PortAddr, ushort); -ushort AscGetChipBusType(PortAddr); - -PortAddr AscSearchIOPortAddr11(PortAddr); -PortAddr AscSearchIOPortAddr100(PortAddr); -int AscFindSignature(PortAddr); -void AscToggleIRQAct(PortAddr); -int AscResetChip(PortAddr); -void AscClrResetChip(PortAddr); - -short itos(ushort, uchar dosfar *, short, short); -int insnchar(uchar dosfar *, short, short, ruchar, short); -void itoh(ushort, ruchar dosfar *); -void btoh(uchar, ruchar dosfar *); -void ltoh(ulong, ruchar dosfar *); -uchar dosfar *todstr(ushort, uchar dosfar *); -uchar dosfar *tohstr(ushort, uchar dosfar *); -uchar dosfar *tobhstr(uchar, uchar dosfar *); -uchar dosfar *tolhstr(ulong, uchar dosfar *); - -void AscSetISAPNPWaitForKey(void); -uchar AscGetChipIRQ(PortAddr, ushort); -uchar AscSetChipIRQ(PortAddr, uchar, ushort); -uchar AscGetChipScsiCtrl(PortAddr); - -ushort AscGetEisaChipCfg(PortAddr); -ushort AscGetEisaChipGpReg(PortAddr); -ushort AscSetEisaChipCfg(PortAddr, ushort); -ushort AscSetEisaChipGpReg(PortAddr, ushort); - -ulong AscGetEisaProductID(PortAddr); -PortAddr AscSearchIOPortAddrEISA(PortAddr); - -int AscPollQTailSync(PortAddr); -int AscPollQHeadSync(PortAddr); -int AscWaitQTailSync(PortAddr); - -int _AscRestoreMicroCode(PortAddr, ASC_MC_SAVED dosfar *); - -int AscSCAM(ASC_DVC_VAR asc_ptr_type *); - -ushort SwapByteOfWord(ushort word_val); -ulong SwapWordOfDWord(ulong dword_val); -ulong AdjEndianDword(ulong dword_val); - -int AscAdjEndianScsiQ(ASC_SCSI_Q dosfar *); -int AscAdjEndianQDoneInfo(ASC_QDONE_INFO dosfar *); - -extern int DvcEnterCritical(void); -extern void DvcLeaveCritical(int); - -extern void DvcInPortWords(PortAddr, ushort dosfar *, int); -extern void DvcOutPortWords(PortAddr, ushort dosfar *, int); -extern void DvcOutPortDWords(PortAddr, ulong dosfar *, int); - -extern void DvcSleepMilliSecond(ulong); -extern void DvcDisplayString(uchar dosfar *); -extern ulong DvcGetPhyAddr(uchar dosfar * buf_addr, ulong buf_len); -extern ulong DvcGetSGList(ASC_DVC_VAR asc_ptr_type *, uchar dosfar *, ulong, - ASC_SG_HEAD dosfar *); - -extern void DvcSCAMDelayMS(ulong); -extern int DvcDisableCPUInterrupt(void); -extern void DvcRestoreCPUInterrupt(int); - -void DvcPutScsiQ(PortAddr, ushort, ushort dosfar *, int); -void DvcGetQinfo(PortAddr, ushort, ushort dosfar *, int); - -PortAddr AscSearchIOPortAddr(PortAddr, ushort); -ushort AscInitGetConfig(ASC_DVC_VAR asc_ptr_type *); -ushort AscInitSetConfig(ASC_DVC_VAR asc_ptr_type *); -ushort AscInitAsc1000Driver(ASC_DVC_VAR asc_ptr_type *); -int AscInitScsiTarget(ASC_DVC_VAR asc_ptr_type *, - ASC_DVC_INQ_INFO dosfar *, - uchar dosfar *, - ASC_CAP_INFO_ARRAY dosfar *, - ushort); -int AscInitPollBegin(ASC_DVC_VAR asc_ptr_type *); -int AscInitPollEnd(ASC_DVC_VAR asc_ptr_type *); -int AscInitPollTarget(ASC_DVC_VAR asc_ptr_type *, - ASC_SCSI_REQ_Q dosfar *, - ASC_SCSI_INQUIRY dosfar *, - ASC_CAP_INFO dosfar *); -int AscExeScsiQueue(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_Q dosfar *); - -int AscISR(ASC_DVC_VAR asc_ptr_type *); -void AscISR_AckInterrupt(ASC_DVC_VAR asc_ptr_type *); -int AscISR_CheckQDone(ASC_DVC_VAR asc_ptr_type *, - ASC_QDONE_INFO dosfar *, - uchar dosfar *); - -int AscStartUnit(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_TIX_TYPE); -int AscStopUnit( - ASC_DVC_VAR asc_ptr_type * asc_dvc, - ASC_SCSI_TIX_TYPE target_ix -); - -uint AscGetNumOfFreeQueue(ASC_DVC_VAR asc_ptr_type *, uchar, uchar); -int AscSgListToQueue(int); -int AscQueueToSgList(int); -int AscSetDvcErrorCode(ASC_DVC_VAR asc_ptr_type *, uchar); - -int AscAbortSRB(ASC_DVC_VAR asc_ptr_type *, ulong); -int AscResetDevice(ASC_DVC_VAR asc_ptr_type *, uchar); -int AscResetSB(ASC_DVC_VAR asc_ptr_type *); - -void AscEnableIsaDma(uchar); -void AscDisableIsaDma(uchar); - -ulong AscGetMaxDmaAddress(ushort); -ulong AscGetMaxDmaCount(ushort); - -int AscSaveMicroCode(ASC_DVC_VAR asc_ptr_type *, ASC_MC_SAVED dosfar *); -int AscRestoreOldMicroCode(ASC_DVC_VAR asc_ptr_type *, ASC_MC_SAVED dosfar *); -int AscRestoreNewMicroCode(ASC_DVC_VAR asc_ptr_type *, ASC_MC_SAVED dosfar *); - -/* - * --- Debugging Header - */ - -#ifdef ADVANSYS_DEBUG -#define STATIC -#else /* ADVANSYS_DEBUG */ -#define STATIC static -#endif /* ADVANSYS_DEBUG */ - - -/* - * --- Driver Constants and Macros - */ - -#define ASC_NUM_BOARD_SUPPORTED 4 -#define ASC_NUM_BUS 4 - -/* Reference Scsi_Host hostdata */ -#define ASC_BOARD(host) ((struct asc_board *) &(host)->hostdata) - -#define NO_ISA_DMA 0xff /* No ISA DMA Channel Used */ - -#ifndef min -#define min(a, b) (((a) < (b)) ? (a) : (b)) -#endif /* min */ - -/* Asc Library return codes */ -#define ASC_TRUE 1 -#define ASC_FALSE 0 -#define ASC_NOERROR 1 -#define ASC_BUSY 0 -#define ASC_ERROR (-1) - -/* Scsi_Cmnd function return codes */ -#define STATUS_BYTE(byte) (byte) -#define MSG_BYTE(byte) ((byte) << 8) -#define HOST_BYTE(byte) ((byte) << 16) -#define DRIVER_BYTE(byte) ((byte) << 24) - -/* asc_enqueue() flags */ -#define ASC_FRONT 1 -#define ASC_BACK 2 - -/* PCI configuration declarations */ - -#define ASC_PCI_REV_A_INIT 0x01 -#define ASC_PCI_REV_A_DONE 0x02 -#define ASC_PCI_REV_B_INIT 0x04 -#define ASC_PCI_REV_B_DONE 0x08 - -#define PCI_BASE_CLASS_PREDEFINED 0x00 -#define PCI_BASE_CLASS_MASS_STORAGE 0x01 -#define PCI_BASE_CLASS_NETWORK 0x02 -#define PCI_BASE_CLASS_DISPLAY 0x03 -#define PCI_BASE_CLASS_MULTIMEDIA 0x04 -#define PCI_BASE_CLASS_MEMORY_CONTROLLER 0x05 -#define PCI_BASE_CLASS_BRIDGE_DEVICE 0x06 - -/* MASS STORAGE */ -#define PCI_SUB_CLASS_SCSI_CONTROLLER 0x00 -#define PCI_SUB_CLASS_IDE_CONTROLLER 0x01 -#define PCI_SUB_CLASS_FLOPPY_DISK_CONTROLLER 0x02 -#define PCI_SUB_CLASS_IPI_BUS_CONTROLLER 0x03 -#define PCI_SUB_CLASS_OTHER_MASS_CONTROLLER 0x80 - -/* NETWORK CONTROLLER */ -#define PCI_SUB_CLASS_ETHERNET_CONTROLLER 0x00 -#define PCI_SUB_CLASS_TOKEN_RING_CONTROLLER 0x01 -#define PCI_SUB_CLASS_FDDI_CONTROLLER 0x02 -#define PCI_SUB_CLASS_OTHER_NETWORK_CONTROLLER 0x80 - -/* DISPLAY CONTROLLER */ -#define PCI_SUB_CLASS_VGA_CONTROLLER 0x00 -#define PCI_SUB_CLASS_XGA_CONTROLLER 0x01 -#define PCI_SUB_CLASS_OTHER_DISPLAY_CONTROLLER 0x80 - -/* MULTIMEDIA CONTROLLER */ -#define PCI_SUB_CLASS_VIDEO_DEVICE 0x00 -#define PCI_SUB_CLASS_AUDIO_DEVICE 0x01 -#define PCI_SUB_CLASS_OTHER_MULTIMEDIA_DEVICE 0x80 - -/* MEMORY CONTROLLER */ -#define PCI_SUB_CLASS_RAM_CONTROLLER 0x00 -#define PCI_SUB_CLASS_FLASH_CONTROLLER 0x01 -#define PCI_SUB_CLASS_OTHER_MEMORY_CONTROLLER 0x80 - -/* BRIDGE CONTROLLER */ -#define PCI_SUB_CLASS_HOST_BRIDGE_CONTROLLER 0x00 -#define PCI_SUB_CLASS_ISA_BRIDGE_CONTROLLER 0x01 -#define PCI_SUB_CLASS_EISA_BRIDGE_CONTROLLER 0x02 -#define PCI_SUB_CLASS_MC_BRIDGE_CONTROLLER 0x03 -#define PCI_SUB_CLASS_PCI_TO_PCI_BRIDGE_CONTROLLER 0x04 -#define PCI_SUB_CLASS_PCMCIA_BRIDGE_CONTROLLER 0x05 -#define PCI_SUB_CLASS_OTHER_BRIDGE_CONTROLLER 0x80 - -#define PCI_MAX_SLOT 0x1F -#define PCI_MAX_BUS 0xFF -#define ASC_PCI_VENDORID 0x10CD -#define PCI_IOADDRESS_MASK 0xFFFE - -/* PCI IO Port Addresses to generate special cycle */ - -#define PCI_CONFIG_ADDRESS_MECH1 0x0CF8 -#define PCI_CONFIG_DATA_MECH1 0x0CFC - -#define PCI_CONFIG_FORWARD_REGISTER 0x0CFA /* 0=type 0; 1=type 1; */ - -#define PCI_CONFIG_BUS_NUMBER_MASK 0x00FF0000 -#define PCI_CONFIG_DEVICE_FUNCTION_MASK 0x0000FF00 -#define PCI_CONFIG_REGISTER_NUMBER_MASK 0x000000F8 - -#define PCI_DEVICE_FOUND 0x0000 -#define PCI_DEVICE_NOT_FOUND 0xffff - -#define SUBCLASS_OFFSET 0x0A -#define CLASSCODE_OFFSET 0x0B -#define VENDORID_OFFSET 0x00 -#define DEVICEID_OFFSET 0x02 - -/* - * --- Driver Macros - */ - -#ifndef ADVANSYS_STATS -#define ASC_STATS(counter) -#define ASC_STATS_ADD(counter, count) -#else /* ADVANSYS_STATS */ -#define ASC_STATS(counter) asc_stats.counter++ -#define ASC_STATS_ADD(counter, count) asc_stats.counter += (count) -#endif /* ADVANSYS_STATS */ - -#ifndef ADVANSYS_DEBUG - -#define ASC_DBG(lvl, s) -#define ASC_DBG1(lvl, s, a1) -#define ASC_DBG2(lvl, s, a1, a2) -#define ASC_DBG3(lvl, s, a1, a2, a3) -#define ASC_DBG4(lvl, s, a1, a2, a3, a4) -#define ASC_DBG_PRT_SCSI_HOST(lvl, s) -#define ASC_DBG_PRT_DVC_VAR(lvl, v) -#define ASC_DBG_PRT_DVC_CFG(lvl, c) -#define ASC_DBG_PRT_SCSI_Q(lvl, scsiqp) -#define ASC_DBG_PRT_QDONE_INFO(lvl, qdone) -#define ASC_DBG_PRT_HEX(lvl, name, start, length) -#define ASC_DBG_PRT_CDB(lvl, cdb, len) -#define ASC_DBG_PRT_SENSE(lvl, sense, len) -#define ASC_DBG_PRT_INQUIRY(lvl, inq, len) -#define ASC_ASSERT(a) - -#else /* ADVANSYS_DEBUG */ - -/* - * Debugging Message Levels: - * 0: Errors Only - * 1: High-Level Tracing - * 2-N: Verbose Tracing - */ - -#define ASC_DBG(lvl, s) \ - { \ - if (asc_dbglvl >= (lvl)) { \ - printk(s); \ - } \ - } - -#define ASC_DBG1(lvl, s, a1) \ - { \ - if (asc_dbglvl >= (lvl)) { \ - printk((s), (a1)); \ - } \ - } - -#define ASC_DBG2(lvl, s, a1, a2) \ - { \ - if (asc_dbglvl >= (lvl)) { \ - printk((s), (a1), (a2)); \ - } \ - } - -#define ASC_DBG3(lvl, s, a1, a2, a3) \ - { \ - if (asc_dbglvl >= (lvl)) { \ - printk((s), (a1), (a2), (a3)); \ - } \ - } - -#define ASC_DBG4(lvl, s, a1, a2, a3, a4) \ - { \ - if (asc_dbglvl >= (lvl)) { \ - printk((s), (a1), (a2), (a3), (a4)); \ - } \ - } - -#define ASC_DBG_PRT_SCSI_HOST(lvl, s) \ - { \ - if (asc_dbglvl >= (lvl)) { \ - asc_prt_scsi_host(s); \ - } \ - } - -#define ASC_DBG_PRT_DVC_VAR(lvl, v) \ - { \ - if (asc_dbglvl >= (lvl)) { \ - asc_prt_dvc_var(v); \ - } \ - } - -#define ASC_DBG_PRT_DVC_CFG(lvl, c) \ - { \ - if (asc_dbglvl >= (lvl)) { \ - asc_prt_dvc_cfg(c); \ - } \ - } - -#define ASC_DBG_PRT_SCSI_Q(lvl, scsiqp) \ - { \ - if (asc_dbglvl >= (lvl)) { \ - asc_prt_scsi_q(scsiqp); \ - } \ - } - -#define ASC_DBG_PRT_QDONE_INFO(lvl, qdone) \ - { \ - if (asc_dbglvl >= (lvl)) { \ - asc_prt_qdone_info(qdone); \ - } \ - } - -#define ASC_DBG_PRT_HEX(lvl, name, start, length) \ - { \ - if (asc_dbglvl >= (lvl)) { \ - asc_prt_hex((name), (start), (length)); \ - } \ - } - -#define ASC_DBG_PRT_CDB(lvl, cdb, len) \ - ASC_DBG_PRT_HEX((lvl), "CDB", (uchar *) (cdb), (len)); - -#define ASC_DBG_PRT_SENSE(lvl, sense, len) \ - ASC_DBG_PRT_HEX((lvl), "SENSE", (uchar *) (sense), (len)); - -#define ASC_DBG_PRT_INQUIRY(lvl, inq, len) \ - ASC_DBG_PRT_HEX((lvl), "INQUIRY", (uchar *) (inq), (len)); - -#define ASC_ASSERT(a) \ - { \ - if (!(a)) { \ - printk("ASC_ASSERT() Failure: file %s, line %d\n", \ - __FILE__, __LINE__); \ - } \ - } -#endif /* ADVANSYS_DEBUG */ - - -/* - * --- Driver Structures - */ - -/* - * Structure allocated for each board. - * - * This structure is allocated by scsi_register() at the end - * of the 'Scsi_Host' structure starting at the 'hostdata' - * field. It is guaranteed to be allocated from DMA-able memory. - */ -struct asc_board { - /* Asc Library */ - ASC_DVC_VAR board; /* Board configuration */ - ASC_DVC_CFG cfg; /* Device configuration */ - uchar overrun_buf[ASC_OVERRUN_BSIZE]; - /* Queued Commands */ - ASC_SCSI_BIT_ID_TYPE pending_tidmask; /* Pending command mask */ - Scsi_Cmnd *pending[ASC_MAX_TID]; - /* Target Initialization */ - ASC_SCSI_BIT_ID_TYPE init_tidmask; /* Target initialized mask */ - ASC_SCSI_REQ_Q scsireqq; - ASC_CAP_INFO cap_info; - ASC_SCSI_INQUIRY inquiry; -}; - -/* - * PCI configuration structures - */ -typedef struct _PCI_DATA_ -{ - uchar type; - uchar bus; - uchar slot; - uchar func; - uchar offset; -} PCI_DATA; - -typedef struct _PCI_DEVICE_ -{ - ushort vendorID; - ushort deviceID; - ushort slotNumber; - ushort slotFound; - uchar busNumber; - uchar maxBusNumber; - uchar devFunc; - ushort startSlot; - ushort endSlot; - uchar bridge; - uchar type; -} PCI_DEVICE; - -typedef struct _PCI_CONFIG_SPACE_ -{ - ushort vendorID; - ushort deviceID; - ushort command; - ushort status; - uchar revision; - uchar classCode[3]; - uchar cacheSize; - uchar latencyTimer; - uchar headerType; - uchar bist; - ulong baseAddress[6]; - ushort reserved[4]; - ulong optionRomAddr; - ushort reserved2[4]; - uchar irqLine; - uchar irqPin; - uchar minGnt; - uchar maxLatency; -} PCI_CONFIG_SPACE; - -#ifdef ADVANSYS_STATS -struct asc_stats { - ulong command; /* # calls to advansys_command() */ - ulong queuecommand; /* # calls to advansys_queuecommand() */ - ulong abort; /* # calls to advansys_abort() */ - ulong reset; /* # calls to advansys_reset() */ - ulong biosparam; /* # calls to advansys_biosparam() */ - ulong interrupt; /* # calls to advansys_interrupt() */ - ulong callback; /* # calls asc_isr_callback() */ - ulong cont_cnt; /* # non-scatter-gather I/O requests received */ - ulong cont_xfer; /* contiguous transfer total (512 byte units) */ - ulong sg_cnt; /* # scatter-gather I/O requests received */ - ulong sg_elem; /* scatter-gather element total */ - ulong sg_xfer; /* scatter-gather tranfer total (512 byte units) */ - ulong error; /* # AscExeScsiQueue() ASC_ERROR returns. */ - /* - * Number of times interrupts disabled in advansys_queuecommand() and - * asc_isr_callback(), respectively. For the former indicates how many - * times commands were pending when a new command was received. - */ - ulong cmd_disable; - ulong intr_disable; - /* - * Number of times asc_enqueue() called. Indicates how many ASC_BUSY - * returns have occurred. - */ - ulong enqueue; - ulong dequeue; /* # calls to asc_dequeue(). */ - /* - * Number of times asc_rmqueue() called and the specified command - * was found and removed. - */ - ulong rmqueue; -} asc_stats; -#endif /* ADVANSYS_STATS */ - - -/* - * --- Driver Data - */ - -#ifdef LINUX_1_3 -struct proc_dir_entry proc_scsi_advansys = -{ - PROC_SCSI_ADVANSYS, /* unsigned short low_ino */ - 8, /* unsigned short namelen */ - "advansys", /* const char *name */ - S_IFDIR | S_IRUGO | S_IXUGO, /* mode_t mode */ - 2 /* nlink_t nlink */ -}; -#endif /* LINUX_1_3 */ - -STATIC int asc_board_count; /* Number of boards detected in system. */ -STATIC struct Scsi_Host *asc_host[ASC_NUM_BOARD_SUPPORTED]; -STATIC Scsi_Cmnd *asc_scsi_done; /* Commands needing done function call. */ - -STATIC ushort asc_bus[ASC_NUM_BUS] = { - ASC_IS_ISA, - ASC_IS_VL, - ASC_IS_EISA, - ASC_IS_PCI, -}; - -/* - * Used with the LILO 'advansys' option to eliminate or - * limit I/O port probing at boot time, cf. advansys_setup(). - */ -int asc_iopflag = ASC_FALSE; -int asc_ioport[ASC_NUM_BOARD_SUPPORTED] = { 0, 0, 0, 0 }; - -#ifdef ADVANSYS_DEBUG -char * -asc_bus_name[ASC_NUM_BUS] = { - "ASC_IS_ISA", - "ASC_IS_VL", - "ASC_IS_EISA", - "ASC_IS_PCI", -}; - -int asc_dbglvl = 0; -#endif /* ADVANSYS_DEBUG */ - - -/* - * --- Driver Function Prototypes - * - * advansys.h contains function prototypes for functions global to Linux. - */ - -#ifdef LINUX_1_3 -STATIC int asc_proc_copy(off_t, off_t, char *, int , char *, int); -#endif /* LINUX_1_3 */ -STATIC void advansys_interrupt(int, struct pt_regs *); -STATIC void advansys_command_done(Scsi_Cmnd *); -STATIC int asc_execute_scsi_cmnd(Scsi_Cmnd *); -STATIC void asc_isr_callback(ASC_DVC_VAR *, ASC_QDONE_INFO *); -STATIC void asc_execute_pending(struct Scsi_Host *); -STATIC int asc_init_dev(ASC_DVC_VAR *, Scsi_Cmnd *); -STATIC int asc_srch_pci_dev(PCI_DEVICE *); -STATIC uchar asc_scan_method(PCI_DEVICE *); -STATIC int asc_pci_find_dev(PCI_DEVICE *); -STATIC void asc_get_pci_cfg(PCI_DEVICE *, PCI_CONFIG_SPACE *); -STATIC ushort asc_get_cfg_word(PCI_DATA *); -STATIC uchar asc_get_cfg_byte(PCI_DATA *); -STATIC void asc_enqueue(struct Scsi_Host *, Scsi_Cmnd *, int, int); -STATIC Scsi_Cmnd *asc_dequeue(struct Scsi_Host *, int); -STATIC int asc_rmqueue(struct Scsi_Host *, Scsi_Cmnd *, int); - -/* XXX - Asc Library Routines not supposed to be used directly */ -ushort AscGetChipBiosAddress(PortAddr, ushort); -int AscFindSignature(PortAddr); - -#ifdef ADVANSYS_STATS -STATIC int asc_prt_stats(char *, int); -STATIC int asc_prt_stats_line(char *, int, char *fmt, ...); -#endif /* ADVANSYS_STATS */ -#ifdef ADVANSYS_DEBUG -STATIC void asc_prt_scsi_host(struct Scsi_Host *); -STATIC void asc_prt_dvc_cfg(ASC_DVC_CFG *); -STATIC void asc_prt_dvc_var(ASC_DVC_VAR *); -STATIC void asc_prt_scsi_q(ASC_SCSI_Q *); -STATIC void asc_prt_qdone_info(ASC_QDONE_INFO *); -STATIC void asc_prt_hex(char *f, uchar *, int); -STATIC int interrupts_enabled(void); -#endif /* ADVANSYS_DEBUG */ - - -/* - * --- Linux 'Scsi_Host_Template' and advansys_setup() Functions - */ - -#ifdef LINUX_1_3 -/* - * advansys_proc_info() - /proc/scsi/advansys/[0-ASC_NUM_BOARD_SUPPORTED] - * - * *buffer: I/O buffer - * **start: if inout == FALSE pointer into buffer where user read should start - * offset: current offset into /proc/scsi/advansys file - * length: length of buffer - * hostno: Scsi_Host host_no - * inout: TRUE - user is writing; FALSE - user is reading - * - * Return the number of bytes read from or written to - * /proc/scsi/advansys file. - */ -int -advansys_proc_info(char *buffer, char **start, off_t offset, int length, - int hostno, int inout) -{ - struct Scsi_Host *shp; - int i; - char *cp; - int cplen; - int cnt; - int totcnt; - int leftlen; - char *curbuf; - off_t advoffset; - Scsi_Device *scd; - char prtbuf[480]; /* 6 lines */ - - ASC_DBG(1, "advansys_proc_info: begin\n"); - - /* - * User write not supported. - */ - if (inout == TRUE) { - return(-ENOSYS); - } - - /* - * User read of /proc/scsi/advansys file. - */ - - /* Find the specified board. */ - for (i = 0; i < asc_board_count; i++) { - if (asc_host[i]->host_no == hostno) { - break; - } - } - if (i == asc_board_count) { - return(-ENOENT); - } - shp = asc_host[i]; - - /* Always copy read data to the beginning of the buffer. */ - *start = buffer; - - curbuf = buffer; - advoffset = 0; - totcnt = 0; - leftlen = length; - - /* Get board information. */ - cp = (char *) advansys_info(shp); - strcat(cp, "\n"); - cplen = strlen(cp); - - /* Copy board information. */ - cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); - totcnt += cnt; - leftlen -= cnt; - if (leftlen == 0) { - ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); - return totcnt; - } - advoffset += cplen; - curbuf += cnt; - - /* - * Get and copy information for each device attached to the board. - */ - cp = &prtbuf[0]; - sprintf(cp, "\nDevices attached to SCSI Host %d:\n", shp->host_no); - cplen = strlen(cp); - cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); - totcnt += cnt; - leftlen -= cnt; - if (leftlen == 0) { - ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); - return totcnt; - } - advoffset += cplen; - curbuf += cnt; - - cp = &prtbuf[0]; - for (scd = scsi_devices; scd; scd = scd->next) { - if (scd->host == shp) { - proc_print_scsidevice(scd, cp, &cplen, 0); - cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); - totcnt += cnt; - leftlen -= cnt; - if (leftlen == 0) { - ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); - return totcnt; - } - advoffset += cplen; - curbuf += cnt; - } - } - -#ifdef ADVANSYS_STATS - /* - * prtbuf[] has about 6 lines worth of space. If the statistics ever - * get longer than 6 lines, prtbuf[] should be increased in size. If - * prtbuf[] is too small it will not be overwritten. Instead the user - * just won't get all of the available statistics. - */ - cp = &prtbuf[0]; - cplen = asc_prt_stats(cp, sizeof(prtbuf)); - cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); - totcnt += cnt; - leftlen -= cnt; - if (leftlen == 0) { - ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); - return totcnt; - } - advoffset += cplen; - curbuf += cnt; -#endif /* ADVANSYS_STATS */ - - ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); - - return totcnt; -} -#endif /* LINUX_1_3 */ - - -/* - * advansys_detect() - * - * Detect function for AdvanSys adapters. - * - * Argument is a pointer to the host driver's scsi_hosts entry. - * - * Return number of adapters found. - * - * Note: Because this function is called during system initialization - * it must not call SCSI mid-level functions including scsi_malloc() - * and scsi_free(). - */ -int -advansys_detect(Scsi_Host_Template *tpnt) -{ - static int detect_called = ASC_FALSE; - int iop; - int bus; - struct Scsi_Host *shp; - ASC_DVC_VAR *boardp; - int ioport = 0; - PCI_DEVICE pciDevice; - PCI_CONFIG_SPACE pciConfig; - int ret; - extern PortAddr _asc_def_iop_base[ASC_IOADR_TABLE_MAX_IX]; - - - if (detect_called == ASC_FALSE) { - detect_called = ASC_TRUE; - } else { - printk("AdvanSys SCSI: advansys_detect() mulitple calls ignored\n"); - return 0; - } - - ASC_DBG(1, "advansys_detect: begin\n"); - -#ifdef LINUX_1_3 - tpnt->proc_dir = &proc_scsi_advansys; -#endif /* LINUX_1_3 */ - -#ifdef ADVANSYS_STATS - memset(&asc_stats, 0, sizeof(asc_stats)); -#endif /* ADVANSYS_STATS */ - - asc_board_count = 0; - - /* - * If I/O port probing has been modified, then verify and - * clean-up the 'asc_ioport' list. - */ - if (asc_iopflag == ASC_TRUE) { - for (ioport = 0; ioport < ASC_NUM_BOARD_SUPPORTED; ioport++) { - ASC_DBG2(1, "asdvansys_detect: asc_ioport[%d] %x\n", - ioport, asc_ioport[ioport]); - if (asc_ioport[ioport] != 0) { - for (iop = 0; iop < ASC_IOADR_TABLE_MAX_IX; iop++) { - if (_asc_def_iop_base[iop] == asc_ioport[ioport]) { - break; - } - } - if (iop == ASC_IOADR_TABLE_MAX_IX) { - printk("AdvanSys SCSI: specified I/O Port 0x%X is invalid\n", - asc_ioport[ioport]); - asc_ioport[ioport] = 0; - } - } - } - ioport = 0; - } - - memset(&pciDevice, 0, sizeof(PCI_DEVICE)); - memset(&pciConfig, 0, sizeof(PCI_CONFIG_SPACE)); - pciDevice.maxBusNumber = PCI_MAX_BUS; - pciDevice.endSlot = PCI_MAX_SLOT; - - for (bus = 0; bus < ASC_NUM_BUS; bus++) { - - ASC_DBG2(1, "advansys_detect: bus search type %d (%s)\n", - bus, asc_bus_name[bus]); - iop = 0; - - while (asc_board_count < ASC_NUM_BOARD_SUPPORTED) { - - ASC_DBG1(2, "advansys_detect: asc_board_count %d\n", - asc_board_count); - - switch (asc_bus[bus]) { - case ASC_IS_ISA: - case ASC_IS_VL: - if (asc_iopflag == ASC_FALSE) { - iop = AscSearchIOPortAddr(iop, asc_bus[bus]); - } else { - /* - * ISA and VL I/O port scanning has either been - * eliminated or limited to selected ports on - * the LILO command line, /etc/lilo.conf, or - * by setting variables when the module was loaded. - */ - ASC_DBG(1, "advansys_detect: I/O port scanning modified\n"); - ioport_try_again: - iop = 0; - for (; ioport < ASC_NUM_BOARD_SUPPORTED; ioport++) { - if ((iop = asc_ioport[ioport]) != 0) { - break; - } - } - if (iop) { - ASC_DBG1(1, "advansys_detect: probing I/O port %x...\n", - iop); - if (check_region(iop, ASC_IOADR_GAP) != 0) { - printk("AdvanSys SCSI: specified I/O Port 0x%X is busy\n", iop); - /* Don't try this I/O port twice. */ - asc_ioport[ioport] = 0; - goto ioport_try_again; - } else if (AscFindSignature(iop) == ASC_FALSE) { - printk("AdvanSys SCSI: specified I/O Port 0x%X has no adapter\n", iop); - /* Don't try this I/O port twice. */ - asc_ioport[ioport] = 0; - goto ioport_try_again; - } else { - /* - * If this isn't an ISA board, then it must be - * a VL board. If currently looking an ISA - * board is being looked for then try for - * another ISA board in 'asc_ioport'. - */ - if (asc_bus[bus] == ASC_IS_ISA && - (AscGetChipVersion(iop, ASC_IS_ISA) & - ASC_CHIP_VER_ISA_BIT) == 0) { - /* - * Don't clear 'asc_ioport[ioport]'. Try - * this board again for VL. Increment - * 'ioport' past this board. - */ - ioport++; - goto ioport_try_again; - } - } - /* - * This board appears good, don't try the I/O port - * again by clearing its value. Increment 'ioport' - * for the next iteration. - */ - asc_ioport[ioport++] = 0; - } - } - break; - - case ASC_IS_EISA: - iop = AscSearchIOPortAddr(iop, asc_bus[bus]); - break; - - case ASC_IS_PCI: - if (asc_srch_pci_dev(&pciDevice) != PCI_DEVICE_FOUND) { - iop = 0; - } else { - ASC_DBG2(2, - "advansys_detect: slotFound %d, busNumber %d\n", - pciDevice.slotFound, pciDevice.busNumber); - asc_get_pci_cfg(&pciDevice, &pciConfig); - iop = pciConfig.baseAddress[0] & PCI_IOADDRESS_MASK; - ASC_DBG2(2, "advansys_detect: iop %x, irqLine %d\n", - iop, pciConfig.irqLine); - } - break; - - default: - ASC_DBG(0, "advansys_detect: unknown bus type\n"); - break; - } - ASC_DBG1(1, "advansys_detect: iop %x\n", iop); - - /* - * Adapter not found, try next bus type. - */ - if (iop == 0) { - break; - } - - /* - * Adapter found. - * - * Register the adapter, get its configuration, and - * initialize it. - */ - ASC_DBG(2, "advansys_detect: scsi_register()\n"); - shp = scsi_register(tpnt, sizeof(struct asc_board)); - - /* Save a pointer to the Scsi_host of each found board. */ - asc_host[asc_board_count++] = shp; - - /* Initialize private per board data */ - memset(ASC_BOARD(shp), 0, sizeof(struct asc_board)); - boardp = &ASC_BOARD(shp)->board; - boardp->cfg = &ASC_BOARD(shp)->cfg; - boardp->cfg->overrun_buf = &ASC_BOARD(shp)->overrun_buf[0]; - boardp->iop_base = iop; - - /* - * Set the board bus type and PCI IRQ for AscInitGetConfig(). - */ - boardp->bus_type = asc_bus[bus]; - switch (boardp->bus_type) { - case ASC_IS_ISA: - shp->unchecked_isa_dma = TRUE; - break; - case ASC_IS_EISA: - shp->unchecked_isa_dma = FALSE; - break; - case ASC_IS_VL: - shp->unchecked_isa_dma = FALSE; - break; - case ASC_IS_PCI: - shp->irq = boardp->irq_no = pciConfig.irqLine; - boardp->cfg->pci_device_id = pciConfig.deviceID; - shp->unchecked_isa_dma = FALSE; - break; - default: - ASC_DBG(0, "advansys_detect: unknown adapter type"); - shp->unchecked_isa_dma = TRUE; - break; - } - - /* - * Get the board configuration. AscInitGetConfig() may change - * the board's bus_type value. The asc_bus[bus] value should no - * longer be used. - */ - ASC_DBG(2, "advansys_detect: AscInitGetConfig()\n"); - switch(ret = AscInitGetConfig(boardp)) { - case 0: /* No error */ - break; - case ASC_WARN_IO_PORT_ROTATE: - ASC_DBG(0, "AscInitGetConfig: I/O port address modified\n"); - break; - case ASC_WARN_EEPROM_CHKSUM: - ASC_DBG(0, "AscInitGetConfig: EEPROM checksum error\n"); - break; - case ASC_WARN_IRQ_MODIFIED: - ASC_DBG(0, "AscInitGetConfig: IRQ modified\n"); - break; - case ASC_WARN_CMD_QNG_CONFLICT: - ASC_DBG(0, - "AscInitGetConfig: Tag queuing enabled w/o disconnects\n"); - break; - default: - ASC_DBG1(0, "AscInitGetConfig: Unknown warning: %x\n", ret); - break; - } - if (boardp->err_code != 0) { - ASC_DBG2(0, - "AscInitGetConfig: error: init_state %x, err_code %x\n", - boardp->init_state, boardp->err_code); - scsi_unregister(shp); - asc_board_count--; - continue; - } - - /* - * Modify board configuration. - */ - boardp->isr_callback = (Ptr2Func) asc_isr_callback; - boardp->exe_callback = (Ptr2Func) NULL; - - ASC_DBG(2, "advansys_detect: AscInitSetConfig()\n"); - switch (ret = AscInitSetConfig(boardp)) { - case 0: /* No error. */ - break; - case ASC_WARN_IO_PORT_ROTATE: - ASC_DBG(0, "AscInitSetConfig: I/O port address modified\n"); - break; - case ASC_WARN_EEPROM_CHKSUM: - ASC_DBG(0, "AscInitSetConfig: EEPROM checksum error\n"); - break; - case ASC_WARN_IRQ_MODIFIED: - ASC_DBG(0, "AscInitSetConfig: IRQ modified\n"); - break; - case ASC_WARN_CMD_QNG_CONFLICT: - ASC_DBG(0, "AscInitSetConfig: Tag queuing w/o disconnects\n"); - break; - default: - ASC_DBG1(0, "AscInitSetConfig: Unknown warning: %x\n", ret); - break; - } - if (boardp->err_code != 0) { - ASC_DBG2(0, - "AscInitSetConfig: error: init_state %x, err_code %x\n", - boardp->init_state, boardp->err_code); - scsi_unregister(shp); - asc_board_count--; - continue; - } - - /* - * Finish initializing the 'Scsi_Host' structure. - */ - - /* AscInitSetConfig() will set the IRQ for non-PCI boards. */ - if (boardp->bus_type != ASC_IS_PCI) { - shp->irq = boardp->irq_no; - } - - shp->io_port = boardp->iop_base; - shp->n_io_port = ASC_IOADR_GAP; - shp->this_id = boardp->cfg->chip_scsi_id; - - /* Maximum number of queues this adapter can handle. */ - shp->can_queue = boardp->max_total_qng; - - /* - * XXX - Command queuing limits are maintained per target - * by AdvanSys adapters. Set 'cmd_per_lun' to the minimum - * value of the all the target settings for the adapter. - * - * For now set 'cmd_per_lun' to 'max_total_qng'. This - * value should be adjusted every time a new device is - * found in asc_init_dev(). - * - * XXX - memory allocation is done by the mid-level scsi - * driver based on 'cmd_per_lun'. If 'sg_tablesize' is too large - * allocation failures can occur in scsi_register_host(). - * A 'Scsi_Cmnd' structure is pre-allocated for each command - * also DMA memory is reserved. Set it artificially low for now. - * - * shp->cmd_per_lun = boardp->max_total_qng; - */ -#ifdef MODULE - shp->cmd_per_lun = 1; -#else /* MODULE */ - shp->cmd_per_lun = 4; -#endif /* MODULE */ - ASC_DBG1(1, "advansys_detect: cmd_per_lun: %d\n", shp->cmd_per_lun); - - /* Maximum number of scatter-gather elements adapter can handle. */ - /* - * XXX - memory allocation is done by the mid-level scsi - * driver based on sg_tablesize. If 'sg_tablesize' is too large - * allocation failures can occur in scsi_register_host(). - */ -#ifdef MODULE - shp->sg_tablesize = 8; -#else /* MODULE */ - shp->sg_tablesize = ASC_MAX_SG_LIST; -#endif /* MODULE */ - ASC_DBG1(1, "advansys_detect: sg_tablesize: %d\n", - shp->sg_tablesize); - - /* BIOS start address. */ - shp->base = (char *) ((ulong) AscGetChipBiosAddress( - boardp->iop_base, - boardp->bus_type)); - - /* - * Register Board Resources - I/O Port, DMA, IRQ - */ - - /* Register I/O port range */ - ASC_DBG(2, "advansys_detect: request_region()\n"); - request_region(shp->io_port, shp->n_io_port, "advansys"); - - /* Register DMA channel for ISA bus. */ - if ((boardp->bus_type & ASC_IS_ISA) == 0) { - shp->dma_channel = NO_ISA_DMA; - } else { - shp->dma_channel = boardp->cfg->isa_dma_channel; - if ((ret = request_dma(shp->dma_channel, "advansys")) != 0) { - ASC_DBG2(0, "advansys_detect: request_dma() %d failed %d\n", - shp->dma_channel, ret); - release_region(shp->io_port, shp->n_io_port); - scsi_unregister(shp); - asc_board_count--; - continue; - } - AscEnableIsaDma(shp->dma_channel); - } - - /* Register IRQ Number. */ - ASC_DBG1(2, "advansys_detect: request_irq() %d\n", shp->irq); - if ((ret = request_irq(shp->irq, advansys_interrupt, - SA_INTERRUPT, "advansys")) != 0) { - ASC_DBG1(0, "advansys_detect: request_irq() failed %d\n", ret); - release_region(shp->io_port, shp->n_io_port); - if (shp->dma_channel != NO_ISA_DMA) { - free_dma(shp->dma_channel); - } - scsi_unregister(shp); - asc_board_count--; - continue; - } - - /* - * Initialize board RISC chip and enable interrupts. - */ - ASC_DBG(2, "advansys_detect: AscInitAsc1000Driver()\n"); - if (AscInitAsc1000Driver(boardp)) { - ASC_DBG2(0, - "AscInitAsc1000Driver: error: init_state %x, err_code %x\n", - boardp->init_state, boardp->err_code); - release_region(shp->io_port, shp->n_io_port); - if (shp->dma_channel != NO_ISA_DMA) { - free_dma(shp->dma_channel); - } - free_irq(shp->irq); - scsi_unregister(shp); - asc_board_count--; - continue; - } - ASC_DBG_PRT_SCSI_HOST(2, shp); - } - } - - ASC_DBG1(1, "advansys_detect: done: asc_board_count %d\n", asc_board_count); - return asc_board_count; -} - -/* - * advansys_release() - * - * Release resources allocated for a single AdvanSys adapter. - */ -int -advansys_release(struct Scsi_Host *shp) -{ - ASC_DBG(1, "advansys_release: begin\n"); - free_irq(shp->irq); - if (shp->dma_channel != NO_ISA_DMA) { - ASC_DBG(1, "advansys_release: free_dma()\n"); - free_dma(shp->dma_channel); - } - release_region(shp->io_port, shp->n_io_port); - scsi_unregister(shp); - ASC_DBG(1, "advansys_release: end\n"); - return 0; -} - -/* - * advansys_info() - * - * Return suitable for printing on the console with the argument - * adapter's configuration information. - */ -const char * -advansys_info(struct Scsi_Host *shp) -{ - static char info[128]; - ASC_DVC_VAR *boardp; - char *busname; - - boardp = &ASC_BOARD(shp)->board; - ASC_DBG(1, "advansys_info: begin\n"); - if (boardp->bus_type & ASC_IS_ISA) { - sprintf(info, - "AdvanSys SCSI %s: ISA (%u CDB): BIOS %X, IO %X-%X, IRQ %u, DMA %u", - ASC_VERSION, ASC_BOARD(shp)->board.max_total_qng, - (unsigned) shp->base, shp->io_port, - shp->io_port + (shp->n_io_port - 1), shp->irq, shp->dma_channel); - } else { - switch (boardp->bus_type) { - case ASC_IS_EISA: - busname = "EISA"; - break; - case ASC_IS_VL: - busname = "VL"; - break; - case ASC_IS_PCI: - busname = "PCI"; - break; - default: - busname = "?"; - ASC_DBG1(0, "advansys_info: unknown bus type %d\n", - boardp->bus_type); - break; - } - /* No DMA channel for non-ISA busses. */ - sprintf(info, - "AdvanSys SCSI %s: %s (%u CDB): BIOS %X, IO %X-%X, IRQ %u", - ASC_VERSION, busname, ASC_BOARD(shp)->board.max_total_qng, - (unsigned) shp->base, shp->io_port, - shp->io_port + (shp->n_io_port - 1), shp->irq); - } - ASC_DBG(1, "advansys_info: end\n"); - return info; -} - -/* - * advansys_command() - * - * Polled-I/O. Apparently host driver shouldn't return until - * command is finished. - * - * XXX - Can host driver block here instead of spinning on command status? - */ -int -advansys_command(Scsi_Cmnd *scp) -{ - ASC_DBG1(1, "advansys_command: scp %x\n", (unsigned) scp); - ASC_STATS(command); - scp->SCp.Status = 0; /* Set to a known state */ - advansys_queuecommand(scp, advansys_command_done); - while (scp->SCp.Status == 0) { - continue; - } - ASC_DBG1(1, "advansys_command: result %x\n", scp->result); - return scp->result; -} - -/* - * advansys_queuecommand() - * - * This function always returns 0. Command return status is saved - * in the 'scp' result field. - */ -int -advansys_queuecommand(Scsi_Cmnd *scp, void (*done)(Scsi_Cmnd *)) -{ - struct Scsi_Host *shp; - int flags = 0; - int interrupts_disabled; - - ASC_STATS(queuecommand); - shp = scp->host; - -#ifdef LINUX_1_2 - /* - * For LINUX_1_3, if statistics are enabled they can be accessed - * by reading /proc/scsi/advansys/[0-9]. - */ -#ifdef ADVANSYS_STATS_1_2_PRINT - /* Display statistics every 10000 commands. */ - if ((asc_stats.queuecommand % 10000) == 0) { - printk("\n"); - (void) asc_prt_stats(NULL, 0); - printk("\n"); - } -#endif /* ADVANSYS_STATS_1_2_PRINT */ -#endif /* LINUX_1_2 */ - - /* - * If there are any pending commands for this board before trying - * to execute them, disable interrupts to preserve request ordering. - * - * The typical case will be no pending commands and interrupts - * not disabled. - */ - if (ASC_BOARD(shp)->pending_tidmask == 0) { - interrupts_disabled = ASC_FALSE; - } else { - ASC_STATS(cmd_disable); - /* Disable interrupts */ - interrupts_disabled = ASC_TRUE; - save_flags(flags); - cli(); - ASC_DBG1(1, "advansys_queuecommand: asc_execute_pending() %x\n", - ASC_BOARD(shp)->pending_tidmask); - asc_execute_pending(shp); - } - - /* - * Save the function pointer to Linux mid-level 'done' function and - * execute the command. - */ - scp->scsi_done = done; - if (asc_execute_scsi_cmnd(scp) == ASC_BUSY) { - if (interrupts_disabled == ASC_FALSE) { - save_flags(flags); - cli(); - interrupts_disabled = ASC_TRUE; - } - asc_enqueue(shp, scp, scp->target, ASC_BACK); - } - - if (interrupts_disabled == ASC_TRUE) { - restore_flags(flags); - } - - return 0; -} - -/* - * advansys_abort() - * - * Abort the specified command and reset the device - * associated with the command 'scp'. - */ -int -advansys_abort(Scsi_Cmnd *scp) -{ - ASC_DVC_VAR *boardp; - int flags; - int ret; - - ASC_DBG1(1, "advansys_abort: scp %x\n", (unsigned) scp); - save_flags(flags); - cli(); - ASC_STATS(abort); - if (scp->host == NULL) { - scp->result = HOST_BYTE(DID_ERROR); - ret = SCSI_ABORT_ERROR; - } else if (asc_rmqueue(scp->host, scp, scp->target) == ASC_TRUE) { - scp->result = HOST_BYTE(DID_ABORT); - ret = SCSI_ABORT_SUCCESS; - (void) AscResetDevice(&ASC_BOARD(scp->host)->board, scp->target); - } else { - /* Must enable interrupts for AscAbortSRB() */ - sti(); - boardp = &ASC_BOARD(scp->host)->board; - scp->result = HOST_BYTE(DID_ABORT); - switch (AscAbortSRB(boardp, (ulong) scp)) { - case ASC_TRUE: - /* asc_isr_callback() will be called */ - ASC_DBG(1, "advansys_abort: AscAbortSRB() TRUE\n"); - ret = SCSI_ABORT_PENDING; - break; - case ASC_FALSE: - /* Request has apparently already completed. */ - ASC_DBG(1, "advansys_abort: AscAbortSRB() FALSE\n"); - ret = SCSI_ABORT_NOT_RUNNING; - break; - case ASC_ERROR: - default: - ASC_DBG(1, "advansys_abort: AscAbortSRB() ERROR\n"); - ret = SCSI_ABORT_ERROR; - break; - } - (void) AscResetDevice(boardp, scp->target); - } - restore_flags(flags); - ASC_DBG1(1, "advansys_abort: ret %d\n", ret); - return ret; -} - -/* - * advansys_reset() - * - * Reset all devices and the SCSI bus for the board - * associated with 'scp'. - */ -int -advansys_reset(Scsi_Cmnd *scp) -{ - ASC_DVC_VAR *boardp; - int flags; - Scsi_Cmnd *tscp; - int i; - int ret; - - ASC_DBG1(1, "advansys_reset: %x\n", (unsigned) scp); - save_flags(flags); - cli(); - ASC_STATS(reset); - if (scp->host == NULL) { - scp->result = HOST_BYTE(DID_ERROR); - ret = SCSI_RESET_ERROR; - } else { - /* Remove any pending commands, set DID_RESET, and done them. */ - for (i = 0; i < ASC_MAX_TID; i++) { - while ((tscp = asc_dequeue(scp->host, i)) != NULL) { - tscp->result = HOST_BYTE(DID_RESET); - tscp->scsi_done(tscp); - } - } - /* Must enable interrupts for AscResetSB() */ - sti(); - boardp = &ASC_BOARD(scp->host)->board; - scp->result = HOST_BYTE(DID_RESET); - switch (AscResetSB(boardp)) { - case ASC_TRUE: - ASC_DBG(1, "advansys_abort: AscResetSB() TRUE\n"); - ret = SCSI_RESET_SUCCESS; - break; - case ASC_ERROR: - default: - ASC_DBG(1, "advansys_abort: AscResetSB() ERROR\n"); - ret = SCSI_RESET_ERROR; - break; - } - } - restore_flags(flags); - ASC_DBG1(1, "advansys_reset: ret %d", ret); - return ret; -} - -/* - * advansys_biosparam() - * - * Translate disk drive geometry if the "BIOS greater than 1 GB" - * support is enabled for a drive. - * - * ip (information pointer) is an int array with the following definition: - * ip[0]: heads - * ip[1]: sectors - * ip[2]: cylinders - */ -int -#ifdef LINUX_1_2 -advansys_biosparam(Disk *dp, int dep, int ip[]) -#else /* LINUX_1_3 */ -advansys_biosparam(Disk *dp, kdev_t dep, int ip[]) -#endif /* LINUX_1_3 */ -{ - ASC_DBG(1, "advansys_biosparam: begin\n"); - ASC_STATS(biosparam); - if ((ASC_BOARD(dp->device->host)->board.dvc_cntl & ASC_CNTL_BIOS_GT_1GB) && - dp->capacity > 0x200000) { - ip[0] = 255; - ip[1] = 64; - } else { - ip[0] = 64; - ip[1] = 32; - } - ip[2] = dp->capacity / (ip[0] * ip[1]); - ASC_DBG(1, "advansys_biosparam: end\n"); - return 0; -} - -/* - * advansys_setup() - * - * This function is called from init/main.c at boot time. - * It it passed LILO parameters that can be set from the - * LILO command line or in /etc/lilo.conf. - * - * It is used by the AdvanSys driver to either disable I/O - * port scanning or to limit scanning to 1 - 4 I/O ports. - * Regardless of the option setting EISA and PCI boards - * will still be searched for and detected. This option - * only affects searching for ISA and VL boards. - * - * If ADVANSYS_DEBUG is defined the driver debug level may - * be set using the 5th (ASC_NUM_BOARD_SUPPORTED + 1) I/O Port. - * - * Examples: - * 1. Eliminate I/O port scanning: - * boot: linux advansys= - * or - * boot: linux advansys=0x0 - * 2. Limit I/O port scanning to one I/O port: - * boot: linux advansys=0x110 - * 3. Limit I/O port scanning to four I/O ports: - * boot: linux advansys=0x110,0x210,0x230,0x330 - * 4. If ADVANSYS_DEBUG, limit I/O port scanning to four I/O ports and - * set the driver debug level to 2. - * boot: linux advansys=0x110,0x210,0x230,0x330,0xdeb2 - * - * ints[0] - number of arguments - * ints[1] - first argument - * ints[2] - second argument - * ... - */ -void -advansys_setup(char *str, int *ints) -{ - int i; - - if (asc_iopflag == ASC_TRUE) { - printk("AdvanSys SCSI: 'advansys' LILO option may appear only once\n"); - return; - } - - asc_iopflag = ASC_TRUE; - - if (ints[0] > ASC_NUM_BOARD_SUPPORTED) { -#ifdef ADVANSYS_DEBUG - if ((ints[0] == ASC_NUM_BOARD_SUPPORTED + 1) && - (ints[ASC_NUM_BOARD_SUPPORTED + 1] >> 4 == 0xdeb)) { - asc_dbglvl = ints[ASC_NUM_BOARD_SUPPORTED + 1] & 0xf; - } else { -#endif /* ADVANSYS_DEBUG */ - printk("AdvanSys SCSI: only %d I/O ports accepted\n", - ASC_NUM_BOARD_SUPPORTED); -#ifdef ADVANSYS_DEBUG - } -#endif /* ADVANSYS_DEBUG */ - } - -#ifdef ADVANSYS_DEBUG - ASC_DBG1(1, "advansys_setup: ints[0] %d\n", ints[0]); - for (i = 1; i < ints[0]; i++) { - ASC_DBG2(1, " ints[%d] %x", i, ints[i]); - } - ASC_DBG(1, "\n"); -#endif /* ADVANSYS_DEBUG */ - - for (i = 1; i <= ints[0] && i <= ASC_NUM_BOARD_SUPPORTED; i++) { - asc_ioport[i-1] = ints[i]; - ASC_DBG2(1, "advansys_setup: asc_ioport[%d] %x\n", - i - 1, asc_ioport[i-1]); - } -} - - -/* - * --- Loadable Driver Support - */ - -#ifdef MODULE -Scsi_Host_Template driver_template = ADVANSYS; -# include "scsi_module.c" -#endif /* MODULE */ - - -/* - * --- Miscellaneous Driver Functions - */ - -#ifdef LINUX_1_3 -/* - * asc_proc_copy() - * - * Copy proc information to a read buffer considering the current read - * offset in the file and the remaining space in the read buffer. - */ -STATIC int -asc_proc_copy(off_t advoffset, off_t offset, char *curbuf, int leftlen, - char *cp, int cplen) -{ - int cnt = 0; - - ASC_DBG3(2, "asc_proc_copy: offset %d, advoffset %d, cplen %d\n", - (unsigned) offset, (unsigned) advoffset, cplen); - if (offset <= advoffset) { - /* Read offset below current offset, copy everything. */ - cnt = min(cplen, leftlen); - ASC_DBG3(2, "asc_proc_copy: curbuf %x, cp %x, cnt %d\n", - (unsigned) curbuf, (unsigned) cp, cnt); - memcpy(curbuf, cp, cnt); - } else if (offset < advoffset + cplen) { - /* Read offset within current range, partial copy. */ - cnt = (advoffset + cplen) - offset; - cp = (cp + cplen) - cnt; - cnt = min(cnt, leftlen); - ASC_DBG3(2, "asc_proc_copy: curbuf %x, cp %x, cnt %d\n", - (unsigned) curbuf, (unsigned) cp, cnt); - memcpy(curbuf, cp, cnt); - } - return cnt; -} -#endif /* LINUX_1_3 */ - -/* - * First-level interrupt handler. - */ -STATIC void -advansys_interrupt(int irq, struct pt_regs *regs) -{ - int i; - int flags; - Scsi_Cmnd *scp; - Scsi_Cmnd *tscp; - - /* Disable interrupts, if the aren't already disabled. */ - save_flags(flags); - cli(); - - ASC_DBG(1, "advansys_interrupt: begin\n"); - ASC_STATS(interrupt); - /* - * Check for interrupts on all boards. - * AscISR() will call asc_isr_callback(). - */ - for (i = 0; i < asc_board_count; i++) { - while (AscIsIntPending(asc_host[i]->io_port)) { - ASC_DBG(1, "advansys_interrupt: before AscISR()\n"); - AscISR(&ASC_BOARD(asc_host[i])->board); - } - } - ASC_DBG(1, "advansys_interrupt: end\n"); - - /* - * While interrupts are still disabled save the list of requests that - * need their done function called. After re-enabling interrupts call - * the done function which may re-enable interrupts anyway. - */ - if ((scp = asc_scsi_done) != NULL) { - asc_scsi_done = NULL; - } - - /* Re-enable interrupts, if they were enabled on entry. */ - restore_flags(flags); - - while (scp) { - tscp = (Scsi_Cmnd *) scp->host_scribble; - scp->scsi_done(scp); - scp = tscp; - } - - return; -} - -/* - * Function used only with polled I/O requests that are initiated by - * advansys_command(). - */ -STATIC void -advansys_command_done(Scsi_Cmnd *scp) -{ - ASC_DBG1(1, "advansys_command_done: scp %x\n", (unsigned) scp); - scp->SCp.Status = 1; -} - -/* - * Execute a single 'Scsi_Cmnd'. - * - * The function 'done' is called when the request has been completed. - * - * Scsi_Cmnd: - * - * host - board controlling device - * device - device to send command - * target - target of device - * lun - lun of device - * cmd_len - length of SCSI CDB - * cmnd - buffer for SCSI 8, 10, or 12 byte CDB - * use_sg - if non-zero indicates scatter-gather request with use_sg elements - * - * if (use_sg == 0) - * request_buffer - buffer address for request - * request_bufflen - length of request buffer - * else - * request_buffer - pointer to scatterlist structure - * - * sense_buffer - sense command buffer - * - * result (4 bytes of an int): - * Byte Meaning - * 0 SCSI Status Byte Code - * 1 SCSI One Byte Message Code - * 2 Host Error Code - * 3 Mid-Level Error Code - * - * host driver fields: - * SCp - Scsi_Pointer used for command processing status - * scsi_done - used to save caller's done function - * host_scribble - used for pointer to another Scsi_Cmnd - * - * If this function returns ASC_NOERROR or ASC_ERROR the done - * function has been called. If ASC_BUSY is returned the request - * must be enqueued by the caller and re-tried later. - */ -STATIC int -asc_execute_scsi_cmnd(Scsi_Cmnd *scp) -{ - ASC_DVC_VAR *boardp; - ASC_SCSI_Q scsiq; - ASC_SG_HEAD sghead; - int ret; - - ASC_DBG2(1, "asc_execute_scsi_cmnd: scp %x, done %x\n", - (unsigned) scp, (unsigned) scp->scsi_done); - - boardp = &ASC_BOARD(scp->host)->board; - - /* - * If this is the first command, then initialize the device. If - * no device is found set 'DID_BAD_TARGET' and return. - */ - if ((ASC_BOARD(scp->host)->init_tidmask & - ASC_TIX_TO_TARGET_ID(scp->target)) == 0) { - if (asc_init_dev(boardp, scp) == ASC_FALSE) { - scp->result = HOST_BYTE(DID_BAD_TARGET); - scp->scsi_done(scp); - return ASC_ERROR; - } - ASC_BOARD(scp->host)->init_tidmask |= ASC_TIX_TO_TARGET_ID(scp->target); - } - - memset(&scsiq, 0, sizeof(ASC_SCSI_Q)); - - /* - * Point the ASC_SCSI_Q to the 'Scsi_Cmnd'. - */ - scsiq.q2.srb_ptr = (ulong) scp; - - /* - * Build the ASC_SCSI_Q request. - */ - scsiq.cdbptr = &scp->cmnd[0]; - scsiq.q2.cdb_len = scp->cmd_len; - scsiq.q1.target_id = ASC_TID_TO_TARGET_ID(scp->target); - scsiq.q1.target_lun = scp->lun; - scsiq.q2.target_ix = ASC_TIDLUN_TO_IX(scp->target, scp->lun); - scsiq.q1.sense_addr = (ulong) &scp->sense_buffer[0]; - scsiq.q1.sense_len = sizeof(scp->sense_buffer); - scsiq.q2.tag_code = M2_QTAG_MSG_SIMPLE; - - /* - * Build ASC_SCSI_Q for a contiguous buffer or a scatter-gather - * buffer command. - */ - if (scp->use_sg == 0) { - /* - * CDB request of single contiguous buffer. - */ - ASC_STATS(cont_cnt); - /* request_buffer is already a real address. */ - scsiq.q1.data_addr = (ulong) scp->request_buffer; - scsiq.q1.data_cnt = scp->request_bufflen; - ASC_STATS_ADD(cont_xfer, (scp->request_bufflen + 511) >> 9); - scsiq.q1.sg_queue_cnt = 0; - scsiq.sg_head = NULL; - } else { - /* - * CDB scatter-gather request list. - */ - int sgcnt; - struct scatterlist *slp; - - if (scp->use_sg > ASC_MAX_SG_LIST) { - ASC_DBG2(0, "asc_execute_scsi_cmnd: use_sg %d > %d\n", - scp->use_sg, ASC_MAX_SG_LIST); - scp->result = HOST_BYTE(DID_ERROR); - scp->scsi_done(scp); - return ASC_ERROR; - } - - ASC_STATS(sg_cnt); - - /* - * Allocate a ASC_SG_HEAD structure and set the ASC_SCSI_Q - * to point to it. - */ - memset(&sghead, 0, sizeof(ASC_SG_HEAD)); - - scsiq.q1.cntl |= QC_SG_HEAD; - scsiq.sg_head = &sghead; - scsiq.q1.data_cnt = 0; - scsiq.q1.data_addr = 0; - sghead.entry_cnt = scsiq.q1.sg_queue_cnt = scp->use_sg; - ASC_STATS_ADD(sg_elem, sghead.entry_cnt); - - /* - * Convert scatter-gather list into ASC_SG_HEAD list. - */ - slp = (struct scatterlist *) scp->request_buffer; - for (sgcnt = 0; sgcnt < scp->use_sg; sgcnt++, slp++) { - sghead.sg_list[sgcnt].addr = (ulong) slp->address; - sghead.sg_list[sgcnt].bytes = slp->length; - ASC_STATS_ADD(sg_xfer, (slp->length + 511) >> 9); - } - } - - ASC_DBG_PRT_SCSI_Q(2, &scsiq); - ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len); - - switch (ret = AscExeScsiQueue(boardp, &scsiq)) { - case ASC_NOERROR: - ASC_DBG(1, "asc_execute_scsi_cmnd: AscExeScsiQueue() ASC_NOERROR\n"); - break; - case ASC_BUSY: - /* Caller must enqueue request and retry later. */ - break; - case ASC_ERROR: - ASC_DBG1(0, - "asc_execute_scsi_cmnd: AscExeScsiQueue() ASC_ERROR err_code %x\n", - boardp->err_code); - ASC_STATS(error); - scp->result = HOST_BYTE(DID_ERROR); - scp->scsi_done(scp); - break; - } - - ASC_DBG(1, "asc_execute_scsi_cmnd: end\n"); - return ret; -} - -/* - * asc_isr_callback() - Second Level Interrupt Handler called by AscISR(). - */ -void -asc_isr_callback(ASC_DVC_VAR *boardp, ASC_QDONE_INFO *qdonep) -{ - Scsi_Cmnd *scp; - struct Scsi_Host *shp; - int flags; - Scsi_Cmnd **scpp; - - ASC_ASSERT(interrupts_enabled() == ASC_FALSE); - ASC_DBG2(1, "asc_isr_callback: boardp %x, qdonep %x\n", - (unsigned) boardp, (unsigned) qdonep); - ASC_STATS(callback); - ASC_DBG_PRT_QDONE_INFO(2, qdonep); - - /* - * Get the Scsi_Cmnd structure and Scsi_Host structure for the - * command that has been completed. - */ - scp = (Scsi_Cmnd *) qdonep->d2.srb_ptr; - ASC_DBG1(1, "asc_isr_callback: scp %x\n", (unsigned) scp); - ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len); - - shp = scp->host; - ASC_ASSERT(shp); - ASC_DBG1(1, "asc_isr_callback: shp %x\n", (unsigned) shp); - - /* - * 'qdonep' contains the command's ending status. - */ - switch (qdonep->d3.done_stat) { - case QD_NO_ERROR: - ASC_DBG(2, "asc_isr_callback: QD_NO_ERROR\n"); - switch (qdonep->d3.host_stat) { - case QHSTA_NO_ERROR: - scp->result = 0; - break; - default: - /* QHSTA error occurred */ - scp->result = HOST_BYTE(DID_ERROR); - break; - } - break; - - case QD_WITH_ERROR: - ASC_DBG(2, "asc_isr_callback: QD_WITH_ERROR\n"); - switch (qdonep->d3.host_stat) { - case QHSTA_NO_ERROR: - if (qdonep->d3.scsi_stat == SS_CHK_CONDITION) { - ASC_DBG(2, "asc_isr_callback: SS_CHK_CONDITION\n"); - ASC_DBG_PRT_SENSE(2, scp->sense_buffer, - sizeof(scp->sense_buffer)); - /* - * Note: The status_byte() macro used by target drivers - * defined in scsi.h shifts the status byte returned by - * host drivers right by 1 bit. This is why target drivers - * also use left shifted status byte definitions. For instance - * target drivers use CHECK_CONDITION, defined to 0x1, instead - * of the SCSI defined check condition value of 0x2. - */ - scp->result = DRIVER_BYTE(DRIVER_SENSE) | - STATUS_BYTE(qdonep->d3.scsi_stat); - } else { - scp->result = STATUS_BYTE(qdonep->d3.scsi_stat); - } - break; - - default: - /* QHSTA error occurred */ - ASC_DBG1(2, "asc_isr_callback: host_stat %x\n", - qdonep->d3.host_stat); - scp->result = HOST_BYTE(DID_ERROR) | MSG_BYTE(qdonep->d3.scsi_msg) | - STATUS_BYTE(qdonep->d3.scsi_stat); - break; - } - break; - - case QD_ABORTED_BY_HOST: - ASC_DBG(1, "asc_isr_callback: QD_ABORTED_BY_HOST\n"); - scp->result = HOST_BYTE(DID_ABORT) | MSG_BYTE(qdonep->d3.scsi_msg) | - STATUS_BYTE(qdonep->d3.scsi_stat); - break; - - default: - ASC_DBG1(0, "asc_isr_callback: done_stat %x\n", qdonep->d3.done_stat ); - scp->result = HOST_BYTE(DID_ERROR) | MSG_BYTE(qdonep->d3.scsi_msg) | - STATUS_BYTE(qdonep->d3.scsi_stat); - break; - } - - /* - * Before calling 'scsi_done' for the current 'Scsi_Cmnd' and possibly - * triggering more commands to be issued, try to start any pending - * commands. - */ - if (ASC_BOARD(shp)->pending_tidmask != 0) { - /* - * If there are any pending commands for this board before trying - * to execute them, disable interrupts to preserve request ordering. - */ - ASC_STATS(intr_disable); - save_flags(flags); - cli(); - ASC_DBG1(1, "asc_isr_callback: asc_execute_pending() %x\n", - ASC_BOARD(shp)->pending_tidmask); - asc_execute_pending(shp); - restore_flags(flags); - } - - /* - * Because interrupts may be enabled by the 'Scsi_Cmnd' done function, - * add the command to the end of the global done list. The done function - * for the command will be called in advansys_interrupt(). - */ - for (scpp = &asc_scsi_done; *scpp; - scpp = (Scsi_Cmnd **) &(*scpp)->host_scribble) { - ; - } - *scpp = scp; - scp->host_scribble = NULL; - return; -} - -/* - * Execute as many pending requests as possible for the - * board specified by 'Scsi_Host'. - */ -STATIC void -asc_execute_pending(struct Scsi_Host *shp) -{ - ASC_SCSI_BIT_ID_TYPE scan_tidmask; - Scsi_Cmnd *scp; - int i; - - ASC_ASSERT(interrupts_enabled() == ASC_FALSE); - /* - * Execute pending commands for devices attached to - * the current board in round-robin fashion. - */ - scan_tidmask = ASC_BOARD(shp)->pending_tidmask; - do { - for (i = 0; i < ASC_MAX_TID; i++) { - if (scan_tidmask & ASC_TIX_TO_TARGET_ID(i)) { - if ((scp = asc_dequeue(shp, i)) == NULL) { - scan_tidmask &= ~ASC_TIX_TO_TARGET_ID(i); - } else if (asc_execute_scsi_cmnd(scp) == ASC_BUSY) { - scan_tidmask &= ~ASC_TIX_TO_TARGET_ID(i); - /* Put the request back at front of the list. */ - asc_enqueue(shp, scp, i, ASC_FRONT); - } - } - } - } while (scan_tidmask); - return; -} - -/* - * asc_init_dev() - * - * Perform one-time initialization of a device. - */ -STATIC int -asc_init_dev(ASC_DVC_VAR *boardp, Scsi_Cmnd *scp) -{ - ASC_SCSI_REQ_Q *scsireqq; - ASC_CAP_INFO *cap_info; - ASC_SCSI_INQUIRY *inquiry; - int found; - ASC_SCSI_BIT_ID_TYPE save_use_tagged_qng; - ASC_SCSI_BIT_ID_TYPE save_can_tagged_qng; - int ret; -#ifdef ADVANSYS_DEBUG - ASC_SCSI_BIT_ID_TYPE tidmask; /* target id bit mask: 1 - 128 */ -#endif /* ADVANSYS_DEBUG */ - - ASC_DBG1(1, "asc_init_dev: target %d\n", (unsigned) scp->target); - - /* Return true for the board's target id. */ - if (boardp->cfg->chip_scsi_id == scp->target) { - return ASC_TRUE; - } - - /* - * XXX - Host drivers should not modify the timeout field. - * But on the first command only add some extra time to - * allow the driver to complete its initialization for the - * device. - */ - scp->timeout += 2000; /* Add 5 seconds to the request timeout. */ - - /* Set-up AscInitPollTarget() arguments. */ - scsireqq = &ASC_BOARD(scp->host)->scsireqq; - memset(scsireqq, 0, sizeof(ASC_SCSI_REQ_Q)); - cap_info = &ASC_BOARD(scp->host)->cap_info; - memset(cap_info, 0, sizeof(ASC_CAP_INFO)); - inquiry = &ASC_BOARD(scp->host)->inquiry; - memset(inquiry, 0, sizeof(ASC_SCSI_INQUIRY)); - - /* - * XXX - AscInitPollBegin() re-initializes these fields to - * zero. 'Or' in the new values and restore them before calling - * AscInitPollEnd(). Normally all targets are initialized within - * a call to AscInitPollBegin() and AscInitPollEnd(). - */ - save_use_tagged_qng = boardp->use_tagged_qng; - save_can_tagged_qng = boardp->cfg->can_tagged_qng; - - ASC_DBG(2, "asc_init_dev: AscInitPollBegin()\n"); - if (AscInitPollBegin(boardp)) { - ASC_DBG(0, "asc_init_dev: AscInitPollBegin() failed\n"); - return ASC_FALSE; - } - - scsireqq->sense_ptr = &scsireqq->sense[0]; - scsireqq->r1.sense_len = ASC_MIN_SENSE_LEN; - scsireqq->r1.target_id = ASC_TID_TO_TARGET_ID(scp->target); - scsireqq->r1.target_lun = 0; - scsireqq->r2.target_ix = ASC_TIDLUN_TO_IX(scp->target, 0); - - found = ASC_FALSE; - ASC_DBG(2, "asc_init_dev: AscInitPollTarget()\n"); - switch (ret = AscInitPollTarget(boardp, scsireqq, inquiry, cap_info)) { - case ASC_TRUE: - found = ASC_TRUE; -#ifdef ADVANSYS_DEBUG - tidmask = ASC_TIX_TO_TARGET_ID(scp->target); - ASC_DBG2(1, "asc_init_dev: lba %lu, blk_size %lu\n", - cap_info->lba, cap_info->blk_size); - ASC_DBG1(1, "asc_init_dev: peri_dvc_type %x\n", - inquiry->byte0.peri_dvc_type); - if (boardp->use_tagged_qng & tidmask) { - ASC_DBG1(1, "asc_init_dev: command queuing enabled: %d\n", - boardp->max_dvc_qng[scp->target]); - } else { - ASC_DBG(1, "asc_init_dev: command queuing disabled\n"); - } - if (boardp->init_sdtr & tidmask) { - ASC_DBG(1, "asc_init_dev: synchronous transfers enabled\n"); - } else { - ASC_DBG(1, "asc_init_dev: synchronous transfers disabled\n"); - } - /* Set bit means fix disabled. */ - if (boardp->pci_fix_asyn_xfer & tidmask) { - ASC_DBG(1, "asc_init_dev: synchronous transfer fix disabled\n"); - } else { - ASC_DBG(1, "asc_init_dev: synchronous transfer fix enabled\n"); - } -#endif /* ADVANSYS_DEBUG */ - break; - case ASC_FALSE: - ASC_DBG(1, "asc_init_dev: no device found\n"); - break; - case ASC_ERROR: - ASC_DBG(0, "asc_init_dev: AscInitPollTarget() ASC_ERROR\n"); - break; - default: - ASC_DBG1(0, "asc_init_dev: AscInitPollTarget() unknown ret %d\n", ret); - break; - } - - /* XXX - 'Or' in original tag bits. */ - boardp->use_tagged_qng |= save_use_tagged_qng; - boardp->cfg->can_tagged_qng |= save_can_tagged_qng; - - ASC_DBG(2, "asc_init_dev: AscInitPollEnd()\n"); - AscInitPollEnd(boardp); - -#ifdef ASC_SET_CMD_PER_LUN - /* - * XXX - Refer to the comment in advansys_detect() - * regarding cmd_per_lun. - */ - for (i = 0; i <= ASC_MAX_TID; i++) { - if (boardp->max_dvc_qng[i] < scp->host->cmd_per_lun) { - scp->host->cmd_per_lun = boardp->max_dvc_qng[i]; - } - } -#endif /* ASC_SET_CMD_PER_LUN */ - - return found; -} - -/* - * Search for an AdvanSys PCI device in the PCI configuration space. - */ -STATIC int -asc_srch_pci_dev(PCI_DEVICE *pciDevice) -{ - int ret; - static int scan = 1; - - ASC_DBG(2, "asc_srch_pci_dev: begin\n"); - - if (scan) { - pciDevice->type = asc_scan_method(pciDevice); - scan = 0; - ASC_DBG1(2, "asc_srch_pci_dev: type %d\n", pciDevice->type); - } - ret = asc_pci_find_dev(pciDevice); - ASC_DBG1(2, "asc_srch_pci_dev: asc_pci_find_dev() return %d\n", ret); - if (ret == PCI_DEVICE_FOUND) { - pciDevice->slotNumber = pciDevice->slotFound + 1; - pciDevice->startSlot = pciDevice->slotFound + 1; - } else { - if (pciDevice->bridge > pciDevice->busNumber) { - ASC_DBG2(2, "asc_srch_pci_dev: bridge %x, busNumber %x\n", - pciDevice->bridge, pciDevice->busNumber); - pciDevice->busNumber++; - pciDevice->slotNumber = 0; - pciDevice->startSlot = 0; - pciDevice->endSlot = 0x0f; - ret = asc_srch_pci_dev(pciDevice); - ASC_DBG1(2, "asc_srch_pci_dev recursive call return %d\n", ret); - } - } - ASC_DBG1(2, "asc_srch_pci_dev: return %d\n", ret); - return ret; -} - -/* - * Determine the access method to be used for 'pciDevice'. - */ -STATIC uchar -asc_scan_method(PCI_DEVICE *pciDevice) -{ - ushort data; - PCI_DATA pciData; - uchar type; - uchar slot; - - ASC_DBG(2, "asc_scan_method: begin\n"); - memset(&pciData, 0, sizeof(pciData)); - for (type = 1; type < 3; type++) { - pciData.type = type; - for (slot = 0; slot < PCI_MAX_SLOT; slot++) { - pciData.slot = slot; - data = asc_get_cfg_word(&pciData); - if ((data != 0xFFFF) && (data != 0x0000)) { - ASC_DBG2(4, "asc_scan_method: data %x, type %d\n", data, type); - return (type); - } - } - } - ASC_DBG1(4, "asc_scan_method: type %d\n", type); - return (type); -} - -/* - * Check for an AdvanSys PCI device in 'pciDevice'. - * - * Return PCI_DEVICE_FOUND if found, otherwise return PCI_DEVICE_NOT_FOUND. - */ -STATIC int -asc_pci_find_dev(PCI_DEVICE *pciDevice) -{ - PCI_DATA pciData; - ushort vendorid, deviceid; - uchar classcode, subclass; - uchar lslot; - - ASC_DBG(3, "asc_pci_find_dev: begin\n"); - pciData.type = pciDevice->type; - pciData.bus = pciDevice->busNumber; - pciData.func = pciDevice->devFunc; - lslot = pciDevice->startSlot; - for (; lslot < pciDevice->endSlot; lslot++) { - pciData.slot = lslot; - pciData.offset = VENDORID_OFFSET; - vendorid = asc_get_cfg_word(&pciData); - ASC_DBG1(3, "asc_pci_find_dev: vendorid %x\n", vendorid); - if (vendorid != 0xffff) { - pciData.offset = DEVICEID_OFFSET; - deviceid = asc_get_cfg_word(&pciData); - ASC_DBG1(3, "asc_pci_find_dev: deviceid %x\n", deviceid); - if ((vendorid == ASC_PCI_VENDORID) && - ((deviceid == ASC_PCI_DEVICE_ID_REV_A) || - (deviceid == ASC_PCI_DEVICE_ID_REV_B))) { - pciDevice->slotFound = lslot; - ASC_DBG(3, "asc_pci_find_dev: PCI_DEVICE_FOUND\n"); - return PCI_DEVICE_FOUND; - } else { - pciData.offset = SUBCLASS_OFFSET; - subclass = asc_get_cfg_byte(&pciData); - pciData.offset = CLASSCODE_OFFSET; - classcode = asc_get_cfg_byte(&pciData); - if ((classcode & PCI_BASE_CLASS_BRIDGE_DEVICE) && - (subclass & PCI_SUB_CLASS_PCI_TO_PCI_BRIDGE_CONTROLLER)) { - pciDevice->bridge++; - } - ASC_DBG2(3, "asc_pci_find_dev: subclass %x, classcode %x\n", - subclass, classcode); - } - } - } - return PCI_DEVICE_NOT_FOUND; -} - -/* - * Read PCI configuration data into 'pciConfig'. - */ -STATIC void -asc_get_pci_cfg(PCI_DEVICE *pciDevice, PCI_CONFIG_SPACE *pciConfig) -{ - PCI_DATA pciData; - uchar counter; - uchar *localConfig; - - ASC_DBG1(4, "asc_get_pci_cfg: slot found - %d\n ", - pciDevice->slotFound); - - pciData.type = pciDevice->type; - pciData.bus = pciDevice->busNumber; - pciData.slot = pciDevice->slotFound; - pciData.func = pciDevice->devFunc; - localConfig = (uchar *) pciConfig; - - for (counter = 0; counter < sizeof(PCI_CONFIG_SPACE); counter++) { - pciData.offset = counter; - *localConfig = asc_get_cfg_byte(&pciData); - ASC_DBG1(4, "asc_get_pci_cfg: byte %x\n", *localConfig); - localConfig++; - } - ASC_DBG1(4, "asc_get_pci_cfg: counter %d\n", counter); -} - -/* - * Read a word (16 bits) from the PCI configuration space. - * - * The configuration mechanism is checked for the correct access method. - */ -STATIC ushort -asc_get_cfg_word(PCI_DATA *pciData) -{ - ushort tmp; - ulong address; - ulong lbus = pciData->bus; - ulong lslot = pciData->slot; - ulong lfunc = pciData->func; - uchar t2CFA, t2CF8; - ushort t1CF8, t1CFA, t1CFC, t1CFE; - - ASC_DBG4(4, "asc_get_cfg_word: type %d, bus %lu, slot %lu, func %lu\n", - pciData->type, lbus, lslot, lfunc); - - /* - * check type of configuration mechanism - */ - if (pciData->type == 2) { - /* - * save these registers so we can restore them after we are done - */ - t2CFA = inp(0xCFA); /* save PCI bus register */ - t2CF8 = inp(0xCF8); /* save config space enable register */ - - /* - * go out and write the bus and enable registers - */ - /* set for type 1 cycle, if needed */ - outp(0xCFA, pciData->bus); - /* set the function number */ - outp(0xCF8, 0x10 | (pciData->func << 1)) ; - - /* - * read the configuration space type 2 locations - */ - tmp = (ushort) inpw(0xC000 | ((pciData->slot << 8) + pciData->offset)); - } else { - /* - * type 1 configuration mechanism - * - * save the CONFIG_ADDRESS and CONFIG_DATA register values - */ - t1CFC = inpw(0xCFC); - t1CFE = inpw(0xCFE); - t1CF8 = inpw(0xCF8); - t1CFA = inpw(0xCFA); - - /* - * enable <31>, bus = <23:16>, slot = <15:11>, - * func = <10:8>, reg = <7:2> - */ - address = (ulong) ((lbus << 16) | (lslot << 11) | - (lfunc << 8) | (pciData->offset & 0xFC) | 0x80000000L); - - /* - * write out the address to CONFIG_ADDRESS - */ - outl(address, 0xCF8); - - /* - * read in the word from CONFIG_DATA - */ - tmp = (ushort) ((inl(0xCFC) >> - ((pciData->offset & 2) * 8)) & 0xFFFF); - } - ASC_DBG1(4, "asc_get_cfg_word: config data: %x\n", tmp); - return tmp; -} - -/* - * Reads a byte from the PCI configuration space. - * - * The configuration mechanism is checked for the correct access method. - */ -STATIC uchar -asc_get_cfg_byte(PCI_DATA *pciData) -{ - uchar tmp; - ulong address; - ulong lbus = pciData->bus, lslot = pciData->slot, lfunc = pciData->func; - uchar t2CFA, t2CF8; - ushort t1CF8, t1CFA, t1CFC, t1CFE; - - ASC_DBG1(4, "asc_get_cfg_byte: type: %d\n", pciData->type); - - /* - * check type of configuration mechanism - */ - if (pciData->type == 2) { - /* - * save these registers so we can restore them after we are done - */ - t2CFA = inp(0xCFA); /* save PCI bus register */ - t2CF8 = inp(0xCF8); /* save config space enable register */ - - /* - * go out and write the bus and enable registers - */ - /* set for type 1 cycle, if needed */ - outp(0xCFA, pciData->bus); - /* set the function number */ - outp(0xCF8, 0x10 | (pciData->func << 1)); - - /* - * read the configuration space type 2 locations - */ - tmp = inp(0xC000 | ((pciData->slot << 8) + pciData->offset)); - - /* - * restore the registers used for our transaction - */ - outp(0xCF8, t2CF8); /* restore the enable register */ - outp(0xCFA, t2CFA); /* restore PCI bus register */ - } else { - /* - * type 1 configuration mechanism - * - * save the CONFIG_ADDRESS and CONFIG_DATA register values - */ - t1CFC = inpw(0xCFC); - t1CFE = inpw(0xCFE); - t1CF8 = inpw(0xCF8); - t1CFA = inpw(0xCFA); - - /* - * enable <31>, bus = <23:16>, slot = <15:11>, func = <10:8>, - * reg = <7:2> - */ - address = (ulong) ((lbus << 16) | (lslot << 11) | - (lfunc << 8) | (pciData->offset & 0xFC) | 0x80000000L); - - /* - * write out the address to CONFIG_ADDRESS - */ - outl(address, 0xCF8); - - /* - * read in the word from CONFIG_DATA - */ - tmp = (uchar) ((inl(0xCFC) >> ((pciData->offset & 3) * 8)) & 0xFF); - } - ASC_DBG1(4, "asc_get_cfg_byte: config data: %x\n", tmp); - return tmp; -} - -/* - * Add a 'Scsi_Cmnd' to the end of specified 'Scsi_Host' - * target device pending command list. Set 'pending_tidmask' - * to indicate a command is queued for the device. - * - * 'flag' may be either ASC_FRONT or ASC_BACK. - * - * The 'Scsi_Cmnd' host_scribble field is used as a next pointer. - */ -STATIC void -asc_enqueue(struct Scsi_Host *shp, Scsi_Cmnd *scp, int tid, int flag) -{ - Scsi_Cmnd **scpp; - - ASC_ASSERT(interrupts_enabled() == ASC_FALSE); - ASC_ASSERT(flag == ASC_FRONT || flag == ASC_BACK); - ASC_STATS(enqueue); - if (flag == ASC_FRONT) { - scp->host_scribble = (unsigned char *) ASC_BOARD(shp)->pending[tid]; - ASC_BOARD(shp)->pending[tid] = (Scsi_Cmnd *) scp; - } else { /* ASC_BACK */ - for (scpp = &ASC_BOARD(shp)->pending[tid]; *scpp; - scpp = (Scsi_Cmnd **) &(*scpp)->host_scribble) { - ; - } - *scpp = scp; - scp->host_scribble = NULL; - } - ASC_BOARD(shp)->pending_tidmask |= ASC_TIX_TO_TARGET_ID(tid); -} - -/* - * Return first pending 'Scsi_Cmnd' on the specified 'Scsi_Host' - * for the specified target device. Clear the 'pending_tidmask' - * bit for the device if no more commands are left queued for it. - * - * The 'Scsi_Cmnd' host_scribble field is used as a next pointer. - */ -STATIC Scsi_Cmnd * -asc_dequeue(struct Scsi_Host *shp, int tid) -{ - Scsi_Cmnd *scp; - - ASC_STATS(dequeue); - ASC_ASSERT(interrupts_enabled() == ASC_FALSE); - if ((scp = ASC_BOARD(shp)->pending[tid]) != NULL) { - ASC_BOARD(shp)->pending[tid] = (Scsi_Cmnd *) scp->host_scribble; - } - if (ASC_BOARD(shp)->pending[tid] == NULL) { - ASC_BOARD(shp)->pending_tidmask &= ~ASC_TIX_TO_TARGET_ID(tid); - } - return scp; -} - -/* - * Remove the specified 'Scsi_Cmnd' from the specified 'Scsi_Host' - * for the specified target device. Clear the 'pending_tidmask' - * bit for the device if no more commands are left queued for it. - * - * The 'Scsi_Cmnd' host_scribble field is used as a next pointer. - * - * Return ASC_TRUE if the command was found and removed, otherwise - * return ASC_FALSE if the command was not found. - */ -STATIC int -asc_rmqueue(struct Scsi_Host *shp, Scsi_Cmnd *scp, int tid) -{ - Scsi_Cmnd **scpp; - int ret; - - ASC_ASSERT(interrupts_enabled() == ASC_FALSE); - ret = ASC_FALSE; - for (scpp = &ASC_BOARD(shp)->pending[tid]; - *scpp; scpp = (Scsi_Cmnd **) &(*scpp)->host_scribble) { - if (*scpp == scp) { - *scpp = (Scsi_Cmnd *) scp->host_scribble; - scp->host_scribble = NULL; - ASC_STATS(rmqueue); - ret = ASC_TRUE; - } - } - if (ASC_BOARD(shp)->pending[tid] == NULL) { - ASC_BOARD(shp)->pending_tidmask &= ~ASC_TIX_TO_TARGET_ID(tid); - } - return ret; -} - - -/* - * --- Functions Required by the Asc Library - */ - -/* - * Delay for 'n' milliseconds. Don't use the 'jiffies' - * global variable which is incremented once every 5 ms - * from a timer interrupt, because this function may be - * called when interrupts are disabled. - */ -void -DvcSleepMilliSecond(ulong n) -{ - ulong i; - - ASC_DBG1(4, "DvcSleepMilliSecond: %lu\n", n); - for (i = 0; i < n; i++) { - udelay(1000); - } -} - -void -DvcDisplayString(uchar *s) -{ - printk(s); -} - -int -DvcEnterCritical(void) -{ - int flags; - - save_flags(flags); - cli(); - return flags; -} - -void -DvcLeaveCritical(int flags) -{ - restore_flags(flags); -} - -/* - * Convert a virtual address to a virtual address. - * - * Apparently Linux is loaded V=R (virtual equals real). Just return - * the virtual address. - */ -ulong -DvcGetPhyAddr(uchar *buf_addr, ulong buf_len) -{ - ulong phys_addr; - - phys_addr = (ulong) buf_addr; - return phys_addr; -} - -ulong -DvcGetSGList(ASC_DVC_VAR *asc_dvc_sg, uchar *buf_addr, ulong buf_len, - ASC_SG_HEAD *asc_sg_head_ptr) -{ - ulong buf_size; - - buf_size = buf_len; - asc_sg_head_ptr->entry_cnt = 1; - asc_sg_head_ptr->sg_list[0].addr = (ulong) buf_addr; - asc_sg_head_ptr->sg_list[0].bytes = buf_size; - return buf_size; -} - -/* - * void - * DvcPutScsiQ(PortAddr iop_base, ushort s_addr, ushort *outbuf, int words) - * - * Calling/Exit State: - * none - * - * Description: - * Output an ASC_SCSI_Q structure to the chip - */ -void -DvcPutScsiQ(PortAddr iop_base, ushort s_addr, ushort *outbuf, int words) -{ - int i; - - ASC_DBG_PRT_HEX(2, "DvcPutScsiQ", (uchar *) outbuf, 2 * words); - AscSetChipLramAddr(iop_base, s_addr); - for (i = 0; i < words; i++, outbuf++) { - if (i == 2 || i == 10) { - continue; - } - AscPutChipLramData(iop_base, *outbuf); - } -} - -/* - * void - * DvcGetQinfo(PortAddr iop_base, ushort s_addr, ushort *inbuf, int words) - * - * Calling/Exit State: - * none - * - * Description: - * Input an ASC_QDONE_INFO structure from the chip - */ -void -DvcGetQinfo(PortAddr iop_base, ushort s_addr, ushort *inbuf, int words) -{ - int i; - - AscSetChipLramAddr(iop_base, s_addr); - for (i = 0; i < words; i++, inbuf++) { - if (i == 5) { - continue; - } - *inbuf = AscGetChipLramData(iop_base); - } - ASC_DBG_PRT_HEX(2, "DvcGetQinfo", (uchar *) inbuf, 2 * words); -} - -/* - * void DvcOutPortWords(ushort iop_base, ushort &outbuf, int words) - * - * Calling/Exit State: - * none - * - * Description: - * output a buffer to an i/o port address - */ -void -DvcOutPortWords(ushort iop_base, ushort *outbuf, int words) -{ - int i; - - for (i = 0; i < words; i++, outbuf++) - outpw(iop_base, *outbuf); -} - -/* - * void DvcInPortWords(ushort iop_base, ushort &outbuf, int words) - * - * Calling/Exit State: - * none - * - * Description: - * input a buffer from an i/o port address - */ -void -DvcInPortWords(ushort iop_base, ushort *inbuf, int words) -{ - int i; - - for (i = 0; i < words; i++, inbuf++) - *inbuf = inpw(iop_base); -} - - -/* - * void DvcOutPortDWords(PortAddr port, ulong *pdw, int dwords) - * - * Calling/Exit State: - * none - * - * Description: - * output a buffer of 32-bit integers to an i/o port address in - * 16 bit integer units - */ -void -DvcOutPortDWords(PortAddr port, ulong *pdw, int dwords) -{ - int i; - int words; - ushort *pw; - - pw = (ushort *) pdw; - words = dwords << 1; - for(i = 0; i < words; i++, pw++) { - outpw(port, *pw); - } - return; -} - - -/* - * --- Tracing and Debugging Functions - */ - -#ifdef ADVANSYS_STATS - -#define ASC_PRT_STATS_NEXT() \ - if (cp) { \ - totlen += len; \ - leftlen -= len; \ - if (leftlen == 0) { \ - return totlen; \ - } \ - cp += len; \ - } - -/* - * asc_prt_stats() - * - * Note: no single line should be greater than 160 characters, cf. - * asc_prt_stats_line(). - * - * Return the number of characters copied into 'cp'. No more than - * 'cplen' characters will be copied to 'cp'. - */ -STATIC int -asc_prt_stats(char *cp, int cplen) -{ - struct asc_stats *s; - int leftlen; - int totlen; - int len; - - s = &asc_stats; - leftlen = cplen; - totlen = len = 0; - - len = asc_prt_stats_line(cp, leftlen, -"\nAdvanSys SCSI Host Driver Statistics:\n"); - ASC_PRT_STATS_NEXT(); - - len = asc_prt_stats_line(cp, leftlen, -" command %lu, queuecommand %lu, abort %lu, reset %lu, biosparam %lu,\n", - s->command, s->queuecommand, s->abort, s->reset, s->biosparam); - ASC_PRT_STATS_NEXT(); - - len = asc_prt_stats_line(cp, leftlen, -" interrupt %lu, callback %lu, cmd_disable %lu, intr_disable %lu,\n", - s->interrupt, s->callback, s->cmd_disable, s->intr_disable); - ASC_PRT_STATS_NEXT(); - - len = asc_prt_stats_line(cp, leftlen, -" error %lu, enqueue %lu, dequeue %lu, rmqueue %lu,\n", - s->error, s->enqueue, s->dequeue, s->rmqueue); - ASC_PRT_STATS_NEXT(); - - if (s->cont_cnt > 0) { - len = asc_prt_stats_line(cp, leftlen, -" cont_cnt %lu, cont_xfer %lu: avg_xfer=%lu kb\n", - s->cont_cnt, s->cont_xfer, (s->cont_xfer/2)/s->cont_cnt); - ASC_PRT_STATS_NEXT(); - } - - if (s->sg_cnt > 0) { - len = asc_prt_stats_line(cp, leftlen, -" sg_cnt %lu, sg_elem %lu, sg_xfer %lu: avg_elem=%lu, avg_size=%lu kb\n", - s->sg_cnt, s->sg_elem, s->sg_xfer, - s->sg_elem/s->sg_cnt, (s->sg_xfer/2)/s->sg_cnt); - ASC_PRT_STATS_NEXT(); - } - - return totlen; -} - -/* - * asc_prt_stats_line() - * - * If 'cp' is NULL print to the console, otherwise print to a buffer. - * - * Return 0 if printing to the console, otherwise return the number of - * bytes written to the buffer. - * - * Note: If any single line is greater than 160 bytes the stack - * will be corrupted. 's[]' is defined to be 160 bytes. - */ -int -asc_prt_stats_line(char *buf, int buflen, char *fmt, ...) -{ - va_list args; - int ret; - char s[160]; /* 2 lines */ - - va_start(args, fmt); - ret = vsprintf(s, fmt, args); - if (buf == NULL) { - (void) printk(s); - ret = 0; - } else { - ret = min(buflen, ret); - memcpy(buf, s, ret); - } - va_end(args); - return ret; -} -#endif /* ADVANSYS_STATS */ - -#ifdef ADVANSYS_DEBUG -/* - * asc_prt_scsi_host() - */ -STATIC void -asc_prt_scsi_host(struct Scsi_Host *s) -{ - printk("Scsi_Host at addr %x\n", (unsigned) s); - printk( -" next %x, extra_bytes %u, host_busy %u, host_no %d, last_reset %d,\n", - (unsigned) s->next, s->extra_bytes, s->host_busy, s->host_no, - s->last_reset); - - printk( -" host_wait %x, host_queue %x, hostt %x, block %x,\n", - (unsigned) s->host_wait, (unsigned) s->host_queue, - (unsigned) s->hostt, (unsigned) s->block); - - printk( -" wish_block %d, base %x, io_port %d, n_io_port %d, irq %d, dma_channel %d,\n", - s->wish_block, (unsigned) s->base, s->io_port, s->n_io_port, - s->irq, s->dma_channel); - - printk( -" this_id %d, can_queue %d,\n", s->this_id, s->can_queue); - - printk( -" cmd_per_lun %d, sg_tablesize %d, unchecked_isa_dma %d, loaded_as_module %d\n", - s->cmd_per_lun, s->sg_tablesize, s->unchecked_isa_dma, - s->loaded_as_module); - - printk("hostdata (struct asc_board)\n"); - asc_prt_dvc_var(&ASC_BOARD(s)->board); - asc_prt_dvc_cfg(&ASC_BOARD(s)->cfg); - printk(" overrun_buf %x\n", (unsigned) &ASC_BOARD(s)->overrun_buf[0]); -} - -/* - * asc_prt_dvc_var() - */ -STATIC void -asc_prt_dvc_var(ASC_DVC_VAR *h) -{ - printk("ASC_DVC_VAR at addr %x\n", (unsigned) h); - - printk( -" iop_base %x, err_code %x, dvc_cntl %x, bug_fix_cntl %d,\n", - h->iop_base, h->err_code, h->dvc_cntl, h->bug_fix_cntl); - - printk( -" bus_type %d, isr_callback %x, exe_callback %x, init_sdtr %x,\n", - h->bus_type, (unsigned) h->isr_callback, (unsigned) h->exe_callback, - (unsigned) h->init_sdtr); - - printk( -" sdtr_done %x, use_tagged_qng %x, unit_not_ready %x, chip_no %x,\n", - (unsigned) h->sdtr_done, (unsigned) h->use_tagged_qng, - (unsigned) h->unit_not_ready, (unsigned) h->chip_no); - - printk( -" queue_full_or_busy %x, start_motor %x, scsi_reset_wait %x, irq_no %x,\n", - (unsigned) h->queue_full_or_busy, (unsigned) h->start_motor, - (unsigned) h->scsi_reset_wait, (unsigned) h->irq_no); - - printk( -" is_in_int %x, max_total_qng %x, cur_total_qng %x, in_critical_cnt %x,\n", - (unsigned) h->is_in_int, (unsigned) h->max_total_qng, - (unsigned) h->cur_total_qng, (unsigned) h->in_critical_cnt); - - printk( -" last_q_shortage %x, init_state %x, no_scam %x, pci_fix_asyn_xfer %x,\n", - (unsigned) h->last_q_shortage, (unsigned) h->init_state, - (unsigned) h->no_scam, (unsigned) h->pci_fix_asyn_xfer); - - printk( -" int_count %ld, req_count %ld, busy_count %ld, cfg %x, saved_ptr2func %x\n", - h->int_count, h->req_count, h->busy_count, (unsigned) h->cfg, - (unsigned) h->saved_ptr2func); -} - -/* - * asc_prt_dvc_cfg() - */ -STATIC void -asc_prt_dvc_cfg(ASC_DVC_CFG *h) -{ - printk("ASC_DVC_CFG at addr %x\n", (unsigned) h); - - printk( -" can_tagged_qng %x, cmd_qng_enabled %x, disc_enable %x, res %x,\n", - h->can_tagged_qng, h->cmd_qng_enabled, h->disc_enable, h->res); - - printk( -" chip_scsi_id %d, isa_dma_speed %d, isa_dma_channel %d, chip_version %d,\n", - h->chip_scsi_id, h->isa_dma_speed, h->isa_dma_channel, - h->chip_version); - - printk( -" pci_device_id %d, lib_serial_no %d, lib_version %d, mcode_date %d,\n", - h->pci_device_id, h->lib_serial_no, h->lib_version, h->mcode_date); - - printk( -" mcode_version %d, overrun_buf %x\n", - h->mcode_version, (unsigned) h->overrun_buf); -} - -/* - * asc_prt_scsi_q() - */ -STATIC void -asc_prt_scsi_q(ASC_SCSI_Q *q) -{ - ASC_SG_HEAD *sgp; - int i; - - printk("ASC_SCSI_Q at addr %x\n", (unsigned) q); - - printk( -" target_ix %u, target_lun %u, srb_ptr %x, tag_code %u,\n", - q->q2.target_ix, q->q1.target_lun, - (unsigned) q->q2.srb_ptr, q->q2.tag_code); - - printk( -" data_addr %x, data_cnt %lu, sense_addr %x, sense_len %u,\n", - (unsigned) q->q1.data_addr, q->q1.data_cnt, - (unsigned) q->q1.sense_addr, q->q1.sense_len); - - printk( -" cdbptr %x, cdb_len %u, sg_head %x, sg_queue_cnt %u\n", - (unsigned) q->cdbptr, q->q2.cdb_len, - (unsigned) q->sg_head, q->q1.sg_queue_cnt); - - if (q->sg_head) { - sgp = q->sg_head; - printk("ASC_SG_HEAD at addr %x\n", (unsigned) sgp); - printk(" entry_cnt %u, queue_cnt %u\n", sgp->entry_cnt, sgp->queue_cnt); - for (i = 0; i < sgp->entry_cnt; i++) { - printk(" [%u]: addr %x, bytes %lu\n", - i, (unsigned) sgp->sg_list[i].addr, sgp->sg_list[i].bytes); - } - - } -} - -/* - * asc_prt_qdone_info() - */ -STATIC void -asc_prt_qdone_info(ASC_QDONE_INFO *q) -{ - printk("ASC_QDONE_INFO at addr %x\n", (unsigned) q); - printk( -" srb_ptr %x, target_ix %u, cdb_len %u, tag_code %u, done_stat %x\n", - (unsigned) q->d2.srb_ptr, q->d2.target_ix, q->d2.cdb_len, - q->d2.tag_code, q->d3.done_stat); - printk( -" host_stat %x, scsi_stat %x, scsi_msg %x\n", - q->d3.host_stat, q->d3.scsi_stat, q->d3.scsi_msg); -} - -/* - * asc_prt_hex() - * - * Print hexadecimal output in 4 byte groupings 32 bytes - * or 8 double-words per line. - */ -STATIC void -asc_prt_hex(char *f, uchar *s, int l) -{ - int i; - int j; - int k; - int m; - - printk("%s: (%d bytes)\n", f, l); - - for (i = 0; i < l; i += 32) { - - /* Display a maximum of 8 double-words per line. */ - if ((k = (l - i) / 4) >= 8) { - k = 8; - m = 0; - } else { - m = (l - i) % 4 ; - } - - for (j = 0; j < k; j++) { - printk(" %2.2X%2.2X%2.2X%2.2X", - (unsigned) s[i+(j*4)], (unsigned) s[i+(j*4)+1], - (unsigned) s[i+(j*4)+2], (unsigned) s[i+(j*4)+3]); - } - - switch (m) { - case 0: - default: - break; - case 1: - printk(" %2.2X", - (unsigned) s[i+(j*4)+4]); - break; - case 2: - printk(" %2.2X%2.2X", - (unsigned) s[i+(j*4)+4], - (unsigned) s[i+(j*4)+5]); - break; - case 3: - printk(" %2.2X%2.2X%2.2X", - (unsigned) s[i+(j*4)+4], - (unsigned) s[i+(j*4)+5], - (unsigned) s[i+(j*4)+6]); - break; - } - - printk("\n"); - } -} - -/* - * interrupts_enabled() - * - * Return 1 if interrupts are enabled, otherwise return 0. - */ -STATIC int -interrupts_enabled(void) -{ - int flags; - - save_flags(flags); - if (flags & 0x0200) { - return ASC_TRUE; - } else { - return ASC_FALSE; - } -} - -#endif /* ADVANSYS_DEBUG */ - - -/* - * --- Asc Library Functions - */ - -ushort -AscGetEisaChipCfg( - PortAddr iop_base -) -{ - PortAddr eisa_cfg_iop; - - eisa_cfg_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) | - (PortAddr) (ASC_EISA_CFG_IOP_MASK); - return (inpw(eisa_cfg_iop)); -} - -uchar -AscSetChipScsiID( - PortAddr iop_base, - uchar new_host_id -) -{ - ushort cfg_lsw; - - if (AscGetChipScsiID(iop_base) == new_host_id) { - return (new_host_id); - } - cfg_lsw = AscGetChipCfgLsw(iop_base); - cfg_lsw &= 0xF8FF; - cfg_lsw |= (ushort) ((new_host_id & ASC_MAX_TID) << 8); - AscSetChipCfgLsw(iop_base, cfg_lsw); - return (AscGetChipScsiID(iop_base)); -} - -ushort -AscGetChipBiosAddress( - PortAddr iop_base, - ushort bus_type -) -{ - ushort cfg_lsw; - ushort bios_addr; - - if ((bus_type & ASC_IS_EISA) != 0) { - cfg_lsw = AscGetEisaChipCfg(iop_base); - cfg_lsw &= 0x000F; - bios_addr = (ushort) (ASC_BIOS_MIN_ADDR + - (cfg_lsw * ASC_BIOS_BANK_SIZE)); - return (bios_addr); - } - cfg_lsw = AscGetChipCfgLsw(iop_base); - bios_addr = (ushort) (((cfg_lsw >> 12) * ASC_BIOS_BANK_SIZE) + ASC_BIOS_MIN_ADDR); - return (bios_addr); -} - -uchar -AscGetChipVersion( - PortAddr iop_base, - ushort bus_type -) -{ - if ((bus_type & ASC_IS_EISA) != 0) { - - PortAddr eisa_iop; - uchar revision; - - eisa_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) | - (PortAddr) ASC_EISA_REV_IOP_MASK; - revision = inp(eisa_iop); - return ((uchar) ((ASC_CHIP_MIN_VER_EISA - 1) + revision)); - } - return (AscGetChipVerNo(iop_base)); -} - -ushort -AscGetChipBusType( - PortAddr iop_base -) -{ - ushort chip_ver; - - chip_ver = AscGetChipVerNo(iop_base); - if ((chip_ver >= ASC_CHIP_MIN_VER_VL) && - (chip_ver <= ASC_CHIP_MAX_VER_VL)) { - if (((iop_base & 0x0C30) == 0x0C30) || - ((iop_base & 0x0C50) == 0x0C50)) { - return (ASC_IS_EISA); - } - return (ASC_IS_VL); - } else if ((chip_ver >= ASC_CHIP_MIN_VER_ISA) && - (chip_ver <= ASC_CHIP_MAX_VER_ISA)) { - if (chip_ver >= ASC_CHIP_MIN_VER_ISA_PNP) { - return (ASC_IS_ISAPNP); - } - return (ASC_IS_ISA); - } else if ((chip_ver >= ASC_CHIP_MIN_VER_PCI) && - (chip_ver <= ASC_CHIP_MAX_VER_PCI)) { - return (ASC_IS_PCI); - } else { - return (0); - } -} - -void -AscEnableIsaDma( - uchar dma_channel -) -{ - if (dma_channel < 4) { - outp(0x000B, (ushort) (0xC0 | dma_channel)); - outp(0x000A, dma_channel); - } else if (dma_channel < 8) { - - outp(0x00D6, (ushort) (0xC0 | (dma_channel - 4))); - outp(0x00D4, (ushort) (dma_channel - 4)); - } - return; -} - -ulong -AscLoadMicroCode( - PortAddr iop_base, - ushort s_addr, - ushort dosfar * mcode_buf, - ushort mcode_size -) -{ - ulong chksum; - ushort mcode_word_size; - ushort mcode_chksum; - - mcode_word_size = (ushort) (mcode_size >> 1); - AscMemWordSetLram(iop_base, s_addr, 0, mcode_word_size); - AscMemWordCopyToLram(iop_base, s_addr, mcode_buf, mcode_word_size); - - chksum = AscMemSumLramWord(iop_base, s_addr, mcode_word_size); - mcode_chksum = (ushort) AscMemSumLramWord(iop_base, - (ushort) ASC_CODE_SEC_BEG, - (ushort) ((mcode_size - s_addr - (ushort) ASC_CODE_SEC_BEG) / 2)); - AscWriteLramWord(iop_base, ASCV_MCODE_CHKSUM_W, mcode_chksum); - AscWriteLramWord(iop_base, ASCV_MCODE_SIZE_W, mcode_size); - return (chksum); -} - -uchar _hextbl_[16] = -{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - 'A', 'B', 'C', 'D', 'E', 'F'}; - -uchar _isa_pnp_inited = 0; - -PortAddr _asc_def_iop_base[ASC_IOADR_TABLE_MAX_IX] = -{ - 0x100, ASC_IOADR_1, 0x120, ASC_IOADR_2, 0x140, ASC_IOADR_3, ASC_IOADR_4, - ASC_IOADR_5, ASC_IOADR_6, ASC_IOADR_7, ASC_IOADR_8 -}; - -PortAddr -AscSearchIOPortAddr( - PortAddr iop_beg, - ushort bus_type -) -{ - if (bus_type & ASC_IS_VL) { - while ((iop_beg = AscSearchIOPortAddr11(iop_beg)) != 0) { - if (AscGetChipVersion(iop_beg, bus_type) <= ASC_CHIP_MAX_VER_VL) { - return (iop_beg); - } - } - return (0); - } - if (bus_type & ASC_IS_ISA) { - if (_isa_pnp_inited == 0) { - AscSetISAPNPWaitForKey(); - _isa_pnp_inited++; - } - while ((iop_beg = AscSearchIOPortAddr11(iop_beg)) != 0) { - if ((AscGetChipVersion(iop_beg, bus_type) & ASC_CHIP_VER_ISA_BIT) != 0) { - return (iop_beg); - } - } - return (0); - } - if (bus_type & ASC_IS_EISA) { - if ((iop_beg = AscSearchIOPortAddrEISA(iop_beg)) != 0) { - return (iop_beg); - } - return (0); - } - return (0); -} - -PortAddr -AscSearchIOPortAddr11( - PortAddr s_addr -) -{ - - int i; - PortAddr iop_base; - - for (i = 0; i < ASC_IOADR_TABLE_MAX_IX; i++) { - if (_asc_def_iop_base[i] > s_addr) { - break; - } - } - for (; i < ASC_IOADR_TABLE_MAX_IX; i++) { - iop_base = _asc_def_iop_base[i]; - if (AscFindSignature(iop_base)) { - return (iop_base); - } - } - return (0); -} - -int -AscFindSignature( - PortAddr iop_base -) -{ - ushort sig_word; - - if ((inp((PortAddr) (iop_base + 1)) & 0xFF) == (uchar) ASC_1000_ID1B) { - sig_word = inpw(iop_base); - if ((sig_word == (ushort) ASC_1000_ID0W) || - (sig_word == (ushort) ASC_1000_ID0W_FIX)) { - return (1); - } - } - return (0); -} - -void -AscToggleIRQAct( - PortAddr iop_base -) -{ - AscSetChipStatus(iop_base, CIW_IRQ_ACT); - AscSetChipStatus(iop_base, 0); - return; -} - -#if CC_INIT_INQ_DISPLAY - -#endif - -void -AscSetISAPNPWaitForKey( - void) -{ - - outp(ASC_ISA_PNP_PORT_ADDR, 0x02); - outp(ASC_ISA_PNP_PORT_WRITE, 0x02); - return; -} - -uchar -AscGetChipIRQ( - PortAddr iop_base, - ushort bus_type -) -{ - ushort cfg_lsw; - uchar chip_irq; - - if ((bus_type & ASC_IS_EISA) != 0) { - - cfg_lsw = AscGetEisaChipCfg(iop_base); - chip_irq = (uchar) (((cfg_lsw >> 8) & 0x07) + 10); - if ((chip_irq == 13) || (chip_irq > 15)) { - - return (0); - } - return (chip_irq); - } else { - - cfg_lsw = AscGetChipCfgLsw(iop_base); - - if ((bus_type & ASC_IS_VL) != 0) { - - chip_irq = (uchar) (((cfg_lsw >> 2) & 0x07)); - if ((chip_irq == 0) || - (chip_irq == 4) || - (chip_irq == 7)) { - return (0); - } - return ((uchar) (chip_irq + (ASC_MIN_IRQ_NO - 1))); - } - chip_irq = (uchar) (((cfg_lsw >> 2) & 0x03)); - if (chip_irq == 3) - chip_irq += (uchar) 2; - return ((uchar) (chip_irq + ASC_MIN_IRQ_NO)); - } -} - -uchar -AscSetChipIRQ( - PortAddr iop_base, - uchar irq_no, - ushort bus_type -) -{ - ushort cfg_lsw; - - if ((bus_type & ASC_IS_VL) != 0) { - - if (irq_no != 0) { - if ((irq_no < ASC_MIN_IRQ_NO) || (irq_no > ASC_MAX_IRQ_NO)) { - irq_no = 0; - } else { - irq_no -= (uchar) ((ASC_MIN_IRQ_NO - 1)); - } - } - cfg_lsw = (ushort) (AscGetChipCfgLsw(iop_base) & 0xFFE3); - cfg_lsw |= (ushort) 0x0010; - AscSetChipCfgLsw(iop_base, cfg_lsw); - AscToggleIRQAct(iop_base); - - cfg_lsw = (ushort) (AscGetChipCfgLsw(iop_base) & 0xFFE0); - cfg_lsw |= (ushort) ((irq_no & 0x07) << 2); - AscSetChipCfgLsw(iop_base, cfg_lsw); - AscToggleIRQAct(iop_base); - - return (AscGetChipIRQ(iop_base, bus_type)); - - } else if ((bus_type & (ASC_IS_ISA)) != 0) { - - if (irq_no == 15) - irq_no -= (uchar) 2; - irq_no -= (uchar) ASC_MIN_IRQ_NO; - cfg_lsw = (ushort) (AscGetChipCfgLsw(iop_base) & 0xFFF3); - cfg_lsw |= (ushort) ((irq_no & 0x03) << 2); - AscSetChipCfgLsw(iop_base, cfg_lsw); - return (AscGetChipIRQ(iop_base, bus_type)); - } else { - - return (0); - } -} - -uchar -AscGetChipScsiCtrl( - PortAddr iop_base -) -{ - uchar sc; - - AscSetBank(iop_base, 1); - sc = inp(iop_base + IOP_REG_SC); - AscSetBank(iop_base, 0); - return (sc); -} - -extern uchar _sdtr_period_tbl_[]; - -int -AscIsrChipHalted( - ASC_DVC_VAR asc_ptr_type * asc_dvc -) -{ - SDTR_XMSG sdtr_xmsg; - SDTR_XMSG out_msg; - ushort halt_q_addr; - int sdtr_accept; - ushort int_halt_code; - ASC_SCSI_BIT_ID_TYPE scsi_busy; - ASC_SCSI_BIT_ID_TYPE target_id; - PortAddr iop_base; - uchar tag_code; - uchar q_status; - uchar halt_qp; - uchar sdtr_data; - uchar target_ix; - uchar q_cntl, tid_no; - uchar cur_dvc_qng; - uchar asyn_sdtr; - uchar scsi_status; - - iop_base = asc_dvc->iop_base; - int_halt_code = AscReadLramWord(iop_base, ASCV_HALTCODE_W); - - halt_qp = AscReadLramByte(iop_base, ASCV_CURCDB_B); - halt_q_addr = ASC_QNO_TO_QADDR(halt_qp); - target_ix = AscReadLramByte(iop_base, - (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_TARGET_IX)); - q_cntl = AscReadLramByte(iop_base, - (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL)); - tid_no = ASC_TIX_TO_TID(target_ix); - target_id = (uchar) ASC_TID_TO_TARGET_ID(tid_no); - if (asc_dvc->pci_fix_asyn_xfer & target_id) { - - asyn_sdtr = ASYN_SDTR_DATA_FIX_PCI_REV_AB; - } else { - asyn_sdtr = 0; - } - if (int_halt_code == ASC_HALT_EXTMSG_IN) { - - AscMemWordCopyFromLram(iop_base, - ASCV_MSGIN_BEG, - (ushort dosfar *) & sdtr_xmsg, - (ushort) (sizeof (SDTR_XMSG) >> 1)); - if ((sdtr_xmsg.msg_type == MS_EXTEND) && - (sdtr_xmsg.msg_len == MS_SDTR_LEN)) { - sdtr_accept = TRUE; - if (sdtr_xmsg.msg_req == MS_SDTR_CODE) { - if (sdtr_xmsg.req_ack_offset > ASC_SYN_MAX_OFFSET) { - - sdtr_accept = FALSE; - sdtr_xmsg.req_ack_offset = ASC_SYN_MAX_OFFSET; - } - sdtr_data = AscCalSDTRData(sdtr_xmsg.xfer_period, - sdtr_xmsg.req_ack_offset); - if (sdtr_xmsg.req_ack_offset == 0) { - - q_cntl &= ~QC_MSG_OUT; - asc_dvc->init_sdtr &= ~target_id; - asc_dvc->sdtr_done &= ~target_id; - AscSetChipSDTR(iop_base, asyn_sdtr, tid_no); - } else if ((sdtr_data == 0xFF)) { - - q_cntl |= QC_MSG_OUT; - asc_dvc->init_sdtr &= ~target_id; - asc_dvc->sdtr_done &= ~target_id; - AscSetChipSDTR(iop_base, asyn_sdtr, tid_no); - } else { - if (sdtr_accept && (q_cntl & QC_MSG_OUT)) { - - q_cntl &= ~QC_MSG_OUT; - asc_dvc->sdtr_done |= target_id; - asc_dvc->init_sdtr |= target_id; - asc_dvc->pci_fix_asyn_xfer &= ~target_id; - AscSetChipSDTR(iop_base, sdtr_data, tid_no); - } else { - - q_cntl |= QC_MSG_OUT; - - AscMsgOutSDTR(iop_base, - sdtr_xmsg.xfer_period, - sdtr_xmsg.req_ack_offset); - asc_dvc->pci_fix_asyn_xfer &= ~target_id; - AscSetChipSDTR(iop_base, sdtr_data, tid_no); - asc_dvc->sdtr_done |= target_id; - asc_dvc->init_sdtr |= target_id; - } - } - - AscWriteLramByte(iop_base, - (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL), - q_cntl); - AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); - return (0); - } - } - } else if (int_halt_code == ASC_HALT_CHK_CONDITION) { - - q_cntl |= QC_REQ_SENSE; - if (((asc_dvc->init_sdtr & target_id) != 0) && - ((asc_dvc->sdtr_done & target_id) != 0)) { - - sdtr_data = AscReadLramByte(iop_base, - (ushort) ((ushort) ASCV_SDTR_DATA_BEG + (ushort) tid_no)); - AscMsgOutSDTR(iop_base, - _sdtr_period_tbl_[(sdtr_data >> 4) & (uchar) (ASC_SYN_XFER_NO - 1)], - (uchar) (sdtr_data & (uchar) ASC_SYN_MAX_OFFSET)); - q_cntl |= QC_MSG_OUT; - } - AscWriteLramByte(iop_base, - (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL), - q_cntl); - - tag_code = AscReadLramByte(iop_base, - (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_TAG_CODE)); - tag_code &= 0xDC; - AscWriteLramByte(iop_base, - (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_TAG_CODE), - tag_code); - - q_status = AscReadLramByte(iop_base, - (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_STATUS)); - q_status |= (QS_READY | QS_BUSY); - AscWriteLramByte(iop_base, - (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_STATUS), - q_status); - - scsi_busy = AscReadLramByte(iop_base, - (ushort) ASCV_SCSIBUSY_B); - scsi_busy &= ~target_id; - AscWriteLramByte(iop_base, (ushort) ASCV_SCSIBUSY_B, scsi_busy); - - AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); - return (0); - } else if (int_halt_code == ASC_HALT_SDTR_REJECTED) { - - AscMemWordCopyFromLram(iop_base, - ASCV_MSGOUT_BEG, - (ushort dosfar *) & out_msg, - (ushort) (sizeof (SDTR_XMSG) >> 1)); - - if ((out_msg.msg_type == MS_EXTEND) && - (out_msg.msg_len == MS_SDTR_LEN) && - (out_msg.msg_req == MS_SDTR_CODE)) { - - asc_dvc->init_sdtr &= ~target_id; - asc_dvc->sdtr_done &= ~target_id; - AscSetChipSDTR(iop_base, asyn_sdtr, tid_no); - - } else { - - } - - q_cntl &= ~QC_MSG_OUT; - AscWriteLramByte(iop_base, - (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL), - q_cntl); - AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); - return (0); - } else if (int_halt_code == ASC_HALT_SS_QUEUE_FULL) { - - scsi_status = AscReadLramByte(iop_base, - (ushort) ((ushort) halt_q_addr + (ushort) ASC_SCSIQ_SCSI_STATUS)); - cur_dvc_qng = AscReadLramByte(iop_base, - (ushort) ((ushort) ASC_QADR_BEG + (ushort) target_ix)); - if ((cur_dvc_qng > 0) && - (asc_dvc->cur_dvc_qng[tid_no] > 0)) { - - scsi_busy = AscReadLramByte(iop_base, - (ushort) ASCV_SCSIBUSY_B); - scsi_busy |= target_id; - AscWriteLramByte(iop_base, - (ushort) ASCV_SCSIBUSY_B, scsi_busy); - asc_dvc->queue_full_or_busy |= target_id; - - if (scsi_status == SS_QUEUE_FULL) { - if (cur_dvc_qng > ASC_MIN_TAGGED_CMD) { - cur_dvc_qng -= 1; - asc_dvc->max_dvc_qng[tid_no] = cur_dvc_qng; - - AscWriteLramByte(iop_base, - (ushort) ((ushort) ASCV_MAX_DVC_QNG_BEG + (ushort) tid_no), - cur_dvc_qng); - } - } - } - AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); - return (0); - } - return (0); -} - -uchar -_AscCopyLramScsiDoneQ( - PortAddr iop_base, - ushort q_addr, - ASC_QDONE_INFO dosfar * scsiq, - ulong max_dma_count -) -{ - ushort _val; - uchar sg_queue_cnt; - - DvcGetQinfo(iop_base, - (ushort) (q_addr + (ushort) ASC_SCSIQ_DONE_INFO_BEG), - (ushort dosfar *) scsiq, - (ushort) ((sizeof (ASC_SCSIQ_2) + sizeof (ASC_SCSIQ_3)) / 2)); - -#if !CC_LITTLE_ENDIAN_HOST - AscAdjEndianQDoneInfo(scsiq); -#endif - - _val = AscReadLramWord(iop_base, - (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS)); - scsiq->q_status = (uchar) _val; - scsiq->q_no = (uchar) (_val >> 8); - - _val = AscReadLramWord(iop_base, - (ushort) (q_addr + (ushort) ASC_SCSIQ_B_CNTL)); - scsiq->cntl = (uchar) _val; - sg_queue_cnt = (uchar) (_val >> 8); - - _val = AscReadLramWord(iop_base, - (ushort) (q_addr + (ushort) ASC_SCSIQ_B_SENSE_LEN)); - scsiq->sense_len = (uchar) _val; - scsiq->user_def = (uchar) (_val >> 8); - - scsiq->remain_bytes = AscReadLramDWord(iop_base, - (ushort) (q_addr + (ushort) ASC_SCSIQ_DW_REMAIN_XFER_CNT)); - scsiq->remain_bytes &= max_dma_count; - - return (sg_queue_cnt); -} - -int -AscIsrQDone( - ASC_DVC_VAR asc_ptr_type * asc_dvc -) -{ - uchar next_qp; - uchar i; - uchar n_q_used; - uchar sg_list_qp; - uchar sg_queue_cnt; - uchar done_q_tail; - - uchar tid_no; - ASC_SCSI_BIT_ID_TYPE scsi_busy; - ASC_SCSI_BIT_ID_TYPE target_id; - PortAddr iop_base; - ushort q_addr; - ushort sg_q_addr; - uchar cur_target_qng; - ASC_QDONE_INFO scsiq_buf; - ASC_QDONE_INFO dosfar *scsiq; - int false_overrun; - ASC_ISR_CALLBACK asc_isr_callback; - - uchar tag_code; - -#if CC_LINK_BUSY_Q - ushort n_busy_q_done; - -#endif - - iop_base = asc_dvc->iop_base; - asc_isr_callback = (ASC_ISR_CALLBACK) asc_dvc->isr_callback; - - n_q_used = 1; - scsiq = (ASC_QDONE_INFO dosfar *) & scsiq_buf; - done_q_tail = (uchar) AscGetVarDoneQTail(iop_base); - q_addr = ASC_QNO_TO_QADDR(done_q_tail); - next_qp = AscReadLramByte(iop_base, - (ushort) (q_addr + (ushort) ASC_SCSIQ_B_FWD)); - if (next_qp != ASC_QLINK_END) { - - AscPutVarDoneQTail(iop_base, next_qp); - q_addr = ASC_QNO_TO_QADDR(next_qp); - - sg_queue_cnt = _AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq, asc_dvc->max_dma_count); - - AscWriteLramByte(iop_base, - (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS), - (uchar) (scsiq->q_status & (uchar) ~ (QS_READY | QS_ABORTED))); - tid_no = ASC_TIX_TO_TID(scsiq->d2.target_ix); - target_id = ASC_TIX_TO_TARGET_ID(scsiq->d2.target_ix); - if ((scsiq->cntl & QC_SG_HEAD) != 0) { - sg_q_addr = q_addr; - sg_list_qp = next_qp; - for (i = 0; i < sg_queue_cnt; i++) { - sg_list_qp = AscReadLramByte(iop_base, - (ushort) (sg_q_addr + (ushort) ASC_SCSIQ_B_FWD)); - sg_q_addr = ASC_QNO_TO_QADDR(sg_list_qp); - if (sg_list_qp == ASC_QLINK_END) { - AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SG_Q_LINKS); - scsiq->d3.done_stat = QD_WITH_ERROR; - scsiq->d3.host_stat = QHSTA_D_QDONE_SG_LIST_CORRUPTED; - goto FATAL_ERR_QDONE; - } - AscWriteLramByte(iop_base, - (ushort) (sg_q_addr + (ushort) ASC_SCSIQ_B_STATUS), - QS_FREE); - } - - n_q_used = sg_queue_cnt + 1; - AscPutVarDoneQTail(iop_base, sg_list_qp); - } - if (asc_dvc->queue_full_or_busy & target_id) { - - cur_target_qng = AscReadLramByte(iop_base, - (ushort) ((ushort) ASC_QADR_BEG + (ushort) scsiq->d2.target_ix)); - if (cur_target_qng < asc_dvc->max_dvc_qng[tid_no]) { - scsi_busy = AscReadLramByte(iop_base, - (ushort) ASCV_SCSIBUSY_B); - scsi_busy &= ~target_id; - AscWriteLramByte(iop_base, - (ushort) ASCV_SCSIBUSY_B, scsi_busy); - asc_dvc->queue_full_or_busy &= ~target_id; - } - } - if (asc_dvc->cur_total_qng >= n_q_used) { - asc_dvc->cur_total_qng -= n_q_used; - if (asc_dvc->cur_dvc_qng[tid_no] != 0) { - asc_dvc->cur_dvc_qng[tid_no]--; - } - } else { - AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CUR_QNG); - scsiq->d3.done_stat = QD_WITH_ERROR; - goto FATAL_ERR_QDONE; - } - - if ((scsiq->d2.srb_ptr == 0UL) || - ((scsiq->q_status & QS_ABORTED) != 0)) { - - return (0x11); - } else if (scsiq->q_status == QS_DONE) { - - false_overrun = FALSE; - - if (asc_dvc->bug_fix_cntl) { - if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_ADD_ONE_BYTE) { - tag_code = AscReadLramByte(iop_base, - (ushort) (q_addr + (ushort) ASC_SCSIQ_B_TAG_CODE)); - if (tag_code & ASC_TAG_FLAG_ADD_ONE_BYTE) { - if (scsiq->remain_bytes != 0UL) { - scsiq->remain_bytes--; - if (scsiq->remain_bytes == 0UL) { - false_overrun = TRUE; - } - } - } - } - } - if ((scsiq->d3.done_stat == QD_WITH_ERROR) && - (scsiq->d3.host_stat == QHSTA_M_DATA_OVER_RUN)) { - if ((scsiq->cntl & (QC_DATA_IN | QC_DATA_OUT)) == 0) { - scsiq->d3.done_stat = QD_NO_ERROR; - scsiq->d3.host_stat = QHSTA_NO_ERROR; - } else if (false_overrun) { - scsiq->d3.done_stat = QD_NO_ERROR; - scsiq->d3.host_stat = QHSTA_NO_ERROR; - } - } -#if CC_CLEAR_LRAM_SRB_PTR - AscWriteLramDWord(iop_base, - (ushort) (q_addr + (ushort) ASC_SCSIQ_D_SRBPTR), - asc_dvc->int_count); -#endif - - if ((scsiq->cntl & QC_NO_CALLBACK) == 0) { - (*asc_isr_callback) (asc_dvc, scsiq); - } else { - if ((AscReadLramByte(iop_base, - (ushort) (q_addr + (ushort) ASC_SCSIQ_CDB_BEG)) == - SCSICMD_StartStopUnit)) { - - asc_dvc->unit_not_ready &= ~target_id; - if (scsiq->d3.done_stat != QD_NO_ERROR) { - asc_dvc->start_motor &= ~target_id; - } - } - } - -#if CC_LINK_BUSY_Q - n_busy_q_done = AscIsrExeBusyQueue(asc_dvc, tid_no); - if (n_busy_q_done == 0) { - - i = tid_no + 1; - while (TRUE) { - if (i > ASC_MAX_TID) - i = 0; - if (i == tid_no) - break; - n_busy_q_done = AscIsrExeBusyQueue(asc_dvc, i); - if (n_busy_q_done != 0) - break; - i++; - } - } - if (n_busy_q_done == 0xFFFF) - return (0x80); -#endif - - return (1); - } else { - - AscSetLibErrorCode(asc_dvc, ASCQ_ERR_Q_STATUS); - - FATAL_ERR_QDONE: - if ((scsiq->cntl & QC_NO_CALLBACK) == 0) { - (*asc_isr_callback) (asc_dvc, scsiq); - } - return (0x80); - } - } - return (0); -} - -int -AscISR( - ASC_DVC_VAR asc_ptr_type * asc_dvc -) -{ - ASC_CS_TYPE chipstat; - PortAddr iop_base; - ushort saved_ram_addr; - uchar ctrl_reg; - uchar saved_ctrl_reg; - int int_pending; - int status; - uchar host_flag; - - iop_base = asc_dvc->iop_base; - int_pending = FALSE; - - asc_dvc->int_count++; - - if (((asc_dvc->init_state & ASC_INIT_STATE_END_LOAD_MC) == 0) || - (asc_dvc->isr_callback == 0)) { - - return (ERR); - } - if (asc_dvc->in_critical_cnt != 0) { - AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_ON_CRITICAL); - return (ERR); - } - if (asc_dvc->is_in_int) { - AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_RE_ENTRY); - asc_dvc->busy_count++; - return (ERR); - } - asc_dvc->is_in_int = TRUE; - ctrl_reg = AscGetChipControl(iop_base); - saved_ctrl_reg = ctrl_reg & (~(CC_SCSI_RESET | CC_CHIP_RESET | - CC_SINGLE_STEP | CC_DIAG | CC_TEST)); - - if ((chipstat = AscGetChipStatus(iop_base)) & CSW_INT_PENDING) { - int_pending = TRUE; - AscAckInterrupt(iop_base); - - host_flag = AscReadLramByte(iop_base, ASCV_HOST_FLAG_B); - AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, - (uchar) (host_flag | (uchar) ASC_HOST_FLAG_IN_ISR)); - saved_ram_addr = AscGetChipLramAddr(iop_base); - - if ((chipstat & CSW_HALTED) && - (ctrl_reg & CC_SINGLE_STEP)) { - if (AscIsrChipHalted(asc_dvc) == ERR) { - - goto ISR_REPORT_QDONE_FATAL_ERROR; - - } else { - saved_ctrl_reg &= ~CC_HALT; - } - } else { - ISR_REPORT_QDONE_FATAL_ERROR: - if ((asc_dvc->dvc_cntl & ASC_CNTL_INT_MULTI_Q) != 0) { - while (((status = AscIsrQDone(asc_dvc)) & 0x01) != 0) { - - } - } else { - do { - if ((status = AscIsrQDone(asc_dvc)) == 1) { - - break; - } - } while (status == 0x11); - } - if ((status & 0x80) != 0) - int_pending = ERR; - } - AscSetChipLramAddr(iop_base, saved_ram_addr); - if (AscGetChipLramAddr(iop_base) != saved_ram_addr) { - AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SET_LRAM_ADDR); - } - AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag); - } - AscSetChipControl(iop_base, saved_ctrl_reg); - asc_dvc->is_in_int = FALSE; - return (int_pending); -} - -int -AscScsiSetupCmdQ( - ASC_DVC_VAR asc_ptr_type * asc_dvc, - ASC_SCSI_REQ_Q dosfar * scsiq, - uchar dosfar * buf_addr, - ulong buf_len -) -{ - ulong phy_addr; - - scsiq->r1.cntl = 0; - scsiq->r1.sg_queue_cnt = 0; - scsiq->r1.q_no = 0; - scsiq->r1.user_def = 0; - scsiq->cdbptr = (uchar dosfar *) scsiq->cdb; - scsiq->r3.scsi_stat = 0; - scsiq->r3.scsi_msg = 0; - scsiq->r3.host_stat = 0; - scsiq->r3.done_stat = 0; - scsiq->r2.vm_id = 0; - scsiq->r1.data_cnt = buf_len; - - scsiq->r2.tag_code = (uchar) M2_QTAG_MSG_SIMPLE; - scsiq->r2.flag = (uchar) ASC_FLAG_SCSIQ_REQ; - scsiq->r2.srb_ptr = (ulong) scsiq; - scsiq->r1.status = (uchar) QS_READY; - scsiq->r1.data_addr = 0L; - - if (buf_len != 0L) { - if ((phy_addr = AscGetOnePhyAddr(asc_dvc, - (uchar dosfar *) buf_addr, scsiq->r1.data_cnt)) == 0L) { - return (ERR); - } - scsiq->r1.data_addr = phy_addr; - } - return (0); -} - -uchar _mcode_buf[] = -{ - 0x01, 0x03, 0x01, 0x19, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xDD, 0x0A, 0x01, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFF, 0x80, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x23, 0x00, 0x16, 0x00, 0x00, 0x00, 0x07, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA4, 0x88, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x73, 0x48, 0x04, 0x36, 0x00, 0x00, 0xA2, 0xC8, 0x00, 0x80, 0x73, 0x03, 0x23, 0x36, 0x40, - 0xB6, 0x00, 0x36, 0x00, 0x06, 0xD6, 0x0D, 0xD2, 0x15, 0xDE, 0x12, 0xDA, 0x00, 0xA2, 0xC8, 0x00, - 0x92, 0x80, 0xE0, 0x97, 0x50, 0x00, 0xF5, 0x00, 0x0A, 0x98, 0xDF, 0x23, 0x36, 0x60, 0xB6, 0x00, - 0x92, 0x80, 0x4F, 0x00, 0xF5, 0x00, 0x0A, 0x98, 0xEF, 0x23, 0x36, 0x60, 0xB6, 0x00, 0x92, 0x80, - 0x80, 0x62, 0x92, 0x80, 0x00, 0x62, 0x92, 0x80, 0x00, 0x46, 0x17, 0xEE, 0x13, 0xEA, 0x02, 0x01, - 0x09, 0xD8, 0xCD, 0x04, 0x4D, 0x00, 0x00, 0xA3, 0xDC, 0x00, 0x68, 0x97, 0x7F, 0x23, 0x04, 0x61, - 0x84, 0x01, 0xB2, 0x84, 0xCF, 0xC1, 0x80, 0x73, 0xCD, 0x04, 0x4D, 0x00, 0x00, 0xA3, 0xE8, 0x01, - 0x68, 0x97, 0xD4, 0x81, 0x00, 0x33, 0x02, 0x00, 0x82, 0x88, 0x80, 0x73, 0x80, 0x77, 0x00, 0x01, - 0x01, 0xA1, 0x08, 0x01, 0x4F, 0x00, 0x46, 0x97, 0x07, 0xA6, 0x12, 0x01, 0x00, 0x33, 0x03, 0x00, - 0x82, 0x88, 0x03, 0x03, 0x03, 0xDE, 0x00, 0x33, 0x05, 0x00, 0x82, 0x88, 0xCE, 0x00, 0x69, 0x60, - 0xCE, 0x00, 0x02, 0x03, 0x4A, 0x60, 0x00, 0xA2, 0x86, 0x01, 0x80, 0x63, 0x07, 0xA6, 0x32, 0x01, - 0x86, 0x81, 0x03, 0x03, 0x80, 0x63, 0xE2, 0x00, 0x07, 0xA6, 0x42, 0x01, 0x00, 0x33, 0x04, 0x00, - 0x82, 0x88, 0x03, 0x07, 0x02, 0x01, 0x04, 0xCA, 0x0D, 0x23, 0x2A, 0x98, 0x4D, 0x04, 0xD0, 0x84, - 0x05, 0xD8, 0x0D, 0x23, 0x2A, 0x98, 0xCD, 0x04, 0x15, 0x23, 0xB8, 0x88, 0xFB, 0x23, 0x02, 0x61, - 0x82, 0x01, 0x80, 0x63, 0x02, 0x03, 0x06, 0xA3, 0x70, 0x01, 0x00, 0x33, 0x0A, 0x00, 0x82, 0x88, - 0x4E, 0x00, 0x07, 0xA3, 0x7C, 0x01, 0x00, 0x33, 0x0B, 0x00, 0x82, 0x88, 0xCD, 0x04, 0x36, 0x2D, - 0x00, 0x33, 0x1A, 0x00, 0x82, 0x88, 0x50, 0x04, 0x96, 0x81, 0x06, 0xAB, 0x90, 0x01, 0x96, 0x81, - 0x4E, 0x00, 0x07, 0xA3, 0xA0, 0x01, 0x50, 0x00, 0x00, 0xA3, 0x4A, 0x01, 0x00, 0x05, 0x8A, 0x81, - 0x08, 0x97, 0x02, 0x01, 0x05, 0xC6, 0x04, 0x23, 0xA0, 0x01, 0x15, 0x23, 0xA1, 0x01, 0xCC, 0x81, - 0xFD, 0x23, 0x02, 0x61, 0x82, 0x01, 0x0A, 0xDA, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA0, 0xC2, 0x01, - 0x80, 0x63, 0xCD, 0x04, 0x36, 0x2D, 0x00, 0x33, 0x1B, 0x00, 0x82, 0x88, 0x06, 0x23, 0x2A, 0x98, - 0xCD, 0x04, 0xB2, 0x84, 0x06, 0x01, 0x00, 0xA2, 0xE2, 0x01, 0x57, 0x60, 0x00, 0xA0, 0xE8, 0x01, - 0xB2, 0x84, 0x80, 0x23, 0xA0, 0x01, 0xB2, 0x84, 0x80, 0x73, 0x4B, 0x00, 0x06, 0x61, 0x00, 0xA2, - 0x10, 0x02, 0x04, 0x01, 0x0D, 0xDE, 0x02, 0x01, 0x03, 0xCC, 0x4F, 0x00, 0x46, 0x97, 0x0A, 0x82, - 0x08, 0x23, 0x02, 0x41, 0x82, 0x01, 0x4F, 0x00, 0x24, 0x97, 0x48, 0x04, 0xFF, 0x23, 0x84, 0x80, - 0xB2, 0x97, 0x00, 0x46, 0x56, 0x00, 0x03, 0xC0, 0x01, 0x23, 0xE8, 0x00, 0x81, 0x73, 0x06, 0x29, - 0x03, 0x42, 0x06, 0xE2, 0x03, 0xEE, 0x66, 0xEB, 0x11, 0x23, 0xB8, 0x88, 0xC6, 0x97, 0xFA, 0x80, - 0x80, 0x73, 0x80, 0x77, 0x06, 0xA6, 0x3E, 0x02, 0x00, 0x33, 0x31, 0x00, 0x82, 0x88, 0x04, 0x01, - 0x03, 0xD8, 0x74, 0x98, 0x02, 0x96, 0x50, 0x82, 0xA2, 0x95, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, - 0xB6, 0x2D, 0x02, 0xA6, 0x7A, 0x02, 0x07, 0xA6, 0x68, 0x02, 0x06, 0xA6, 0x6C, 0x02, 0x03, 0xA6, - 0x70, 0x02, 0x00, 0x33, 0x10, 0x00, 0x82, 0x88, 0x4A, 0x95, 0x52, 0x82, 0xF8, 0x95, 0x52, 0x82, - 0x04, 0x23, 0xA0, 0x01, 0x14, 0x23, 0xA1, 0x01, 0x16, 0x84, 0x04, 0x01, 0x0C, 0xDC, 0xE0, 0x23, - 0x25, 0x61, 0xEF, 0x00, 0x14, 0x01, 0x4F, 0x04, 0xA8, 0x01, 0x6F, 0x00, 0xA5, 0x01, 0x03, 0x23, - 0xA4, 0x01, 0x06, 0x23, 0x9C, 0x01, 0x24, 0x2B, 0x1C, 0x01, 0x02, 0xA6, 0xAC, 0x02, 0x07, 0xA6, - 0x68, 0x02, 0x06, 0xA6, 0x6C, 0x02, 0x00, 0x33, 0x12, 0x00, 0x82, 0x88, 0x00, 0x0E, 0x80, 0x63, - 0x00, 0x43, 0x00, 0xA0, 0x9A, 0x02, 0x4D, 0x04, 0x04, 0x01, 0x0B, 0xDC, 0xE7, 0x23, 0x04, 0x61, - 0x84, 0x01, 0x10, 0x31, 0x12, 0x35, 0x14, 0x01, 0xEC, 0x00, 0x6C, 0x38, 0x00, 0x3F, 0x00, 0x00, - 0xEC, 0x82, 0x18, 0x23, 0x04, 0x61, 0x18, 0xA0, 0xE4, 0x02, 0x04, 0x01, 0x8E, 0xC8, 0x00, 0x33, - 0x1F, 0x00, 0x82, 0x88, 0x08, 0x31, 0x0A, 0x35, 0x0C, 0x39, 0x0E, 0x3D, 0x40, 0x98, 0xB6, 0x2D, - 0x01, 0xA6, 0x0E, 0x03, 0x00, 0xA6, 0x1C, 0x03, 0x07, 0xA6, 0x2A, 0x03, 0x06, 0xA6, 0x2E, 0x03, - 0x03, 0xA6, 0xFA, 0x03, 0x02, 0xA6, 0x7A, 0x02, 0x00, 0x33, 0x33, 0x00, 0x82, 0x88, 0x08, 0x23, - 0xB3, 0x01, 0x04, 0x01, 0x0E, 0xD0, 0x00, 0x33, 0x14, 0x00, 0x82, 0x88, 0x10, 0x23, 0xB3, 0x01, - 0x04, 0x01, 0x07, 0xCC, 0x00, 0x33, 0x15, 0x00, 0x82, 0x88, 0x4A, 0x95, 0xF0, 0x82, 0xF8, 0x95, - 0xF0, 0x82, 0x44, 0x98, 0x80, 0x42, 0x40, 0x98, 0x48, 0xE4, 0x04, 0x01, 0x29, 0xC8, 0x31, 0x05, - 0x07, 0x01, 0x00, 0xA2, 0x72, 0x03, 0x00, 0x43, 0x87, 0x01, 0x05, 0x05, 0x48, 0x98, 0x40, 0x98, - 0x00, 0xA6, 0x34, 0x03, 0x07, 0xA6, 0x6A, 0x03, 0x03, 0xA6, 0x16, 0x04, 0x06, 0xA6, 0x6E, 0x03, - 0x01, 0xA6, 0x34, 0x03, 0x00, 0x33, 0x25, 0x00, 0x82, 0x88, 0x4A, 0x95, 0x50, 0x83, 0xF8, 0x95, - 0x50, 0x83, 0x04, 0x01, 0x0C, 0xCE, 0x03, 0xC8, 0x00, 0x33, 0x42, 0x00, 0x82, 0x88, 0x00, 0x01, - 0x05, 0x05, 0xFF, 0xA2, 0x90, 0x03, 0xB1, 0x01, 0x08, 0x23, 0xB2, 0x01, 0x4C, 0x83, 0x05, 0x05, - 0x01, 0xA6, 0x9A, 0x03, 0x00, 0xA6, 0xAA, 0x03, 0xF0, 0x83, 0x68, 0x98, 0x80, 0x42, 0x01, 0xA6, - 0x9A, 0x03, 0xBA, 0x83, 0x00, 0x33, 0x2F, 0x00, 0x82, 0x88, 0x68, 0x98, 0x80, 0x42, 0x00, 0xA6, - 0xAA, 0x03, 0xBA, 0x83, 0x00, 0x33, 0x26, 0x00, 0x82, 0x88, 0x38, 0x2B, 0x80, 0x32, 0x80, 0x36, - 0x04, 0x23, 0xA0, 0x01, 0x12, 0x23, 0xA1, 0x01, 0xF0, 0x83, 0x04, 0xF0, 0x80, 0x6B, 0x00, 0x33, - 0x20, 0x00, 0x82, 0x88, 0x03, 0xA6, 0xEE, 0x03, 0x07, 0xA6, 0xE6, 0x03, 0x06, 0xA6, 0xEA, 0x03, - 0x00, 0x33, 0x17, 0x00, 0x82, 0x88, 0x4A, 0x95, 0xD4, 0x83, 0xF8, 0x95, 0xD4, 0x83, 0xFA, 0x83, - 0x04, 0xF0, 0x80, 0x6B, 0x00, 0x33, 0x20, 0x00, 0x82, 0x88, 0xB6, 0x2D, 0x03, 0xA6, 0x16, 0x04, - 0x07, 0xA6, 0x0E, 0x04, 0x06, 0xA6, 0x12, 0x04, 0x00, 0x33, 0x30, 0x00, 0x82, 0x88, 0x4A, 0x95, - 0xFA, 0x83, 0xF8, 0x95, 0xFA, 0x83, 0xA2, 0x0D, 0x80, 0x63, 0x07, 0xA6, 0x24, 0x04, 0x00, 0x33, - 0x18, 0x00, 0x82, 0x88, 0x03, 0x03, 0x80, 0x63, 0xA3, 0x01, 0x07, 0xA4, 0x2E, 0x04, 0x23, 0x01, - 0x00, 0xA2, 0x50, 0x04, 0x0A, 0xA0, 0x40, 0x04, 0xE0, 0x00, 0x00, 0x33, 0x1D, 0x00, 0x82, 0x88, - 0x0B, 0xA0, 0x4C, 0x04, 0xE0, 0x00, 0x00, 0x33, 0x1E, 0x00, 0x82, 0x88, 0x42, 0x23, 0xB8, 0x88, - 0x00, 0x23, 0x22, 0xA3, 0xB2, 0x04, 0x08, 0x23, 0x22, 0xA3, 0x6C, 0x04, 0x28, 0x23, 0x22, 0xA3, - 0x78, 0x04, 0x02, 0x23, 0x22, 0xA3, 0x8E, 0x04, 0x42, 0x23, 0xB8, 0x88, 0x4A, 0x00, 0x06, 0x61, - 0x00, 0xA0, 0x78, 0x04, 0x45, 0x23, 0xB8, 0x88, 0xC6, 0x97, 0x00, 0xA2, 0x8A, 0x04, 0x74, 0x98, - 0x00, 0x33, 0x00, 0x82, 0xC0, 0x20, 0x81, 0x62, 0xF6, 0x81, 0x47, 0x23, 0xB8, 0x88, 0x04, 0x01, - 0x0C, 0xDE, 0x14, 0x01, 0x00, 0xA2, 0xA6, 0x04, 0xC6, 0x97, 0x74, 0x98, 0x00, 0x33, 0x00, 0x81, - 0xC0, 0x20, 0x81, 0x62, 0x10, 0x82, 0x43, 0x23, 0xB8, 0x88, 0x04, 0x23, 0xA0, 0x01, 0x44, 0x23, - 0xA1, 0x01, 0x80, 0x73, 0x4D, 0x00, 0x03, 0xA3, 0xC0, 0x04, 0x00, 0x33, 0x27, 0x00, 0x82, 0x88, - 0x04, 0x01, 0x04, 0xDC, 0x02, 0x23, 0xA2, 0x01, 0x04, 0x23, 0xA0, 0x01, 0xC6, 0x97, 0xF4, 0x94, - 0x4B, 0x00, 0xF6, 0x00, 0x4F, 0x04, 0x4F, 0x00, 0x00, 0xA3, 0xEE, 0x04, 0x00, 0x05, 0x76, 0x00, - 0x06, 0x61, 0x00, 0xA2, 0xE8, 0x04, 0xD6, 0x84, 0x08, 0x97, 0xCD, 0x04, 0xF2, 0x84, 0x48, 0x04, - 0xFF, 0x23, 0x84, 0x80, 0x02, 0x01, 0x03, 0xDA, 0x80, 0x23, 0x82, 0x01, 0x02, 0x85, 0x02, 0x23, - 0xA0, 0x01, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x0E, 0x05, 0x1D, 0x01, 0x04, 0xD6, 0xFF, 0x23, - 0x86, 0x41, 0x4B, 0x60, 0xCB, 0x00, 0xFF, 0x23, 0x80, 0x01, 0x49, 0x00, 0x81, 0x01, 0x04, 0x01, - 0x02, 0xC8, 0x30, 0x01, 0x80, 0x01, 0xF7, 0x04, 0x03, 0x01, 0x49, 0x04, 0x80, 0x01, 0xC9, 0x00, - 0x00, 0x05, 0x00, 0x01, 0xFF, 0xA0, 0x2E, 0x05, 0x77, 0x04, 0x01, 0x23, 0xEA, 0x00, 0x5D, 0x00, - 0xFE, 0xC7, 0x00, 0x62, 0x00, 0x23, 0xEA, 0x00, 0x00, 0x63, 0x07, 0xA4, 0xA0, 0x05, 0x03, 0x03, - 0x02, 0xA0, 0x5C, 0x05, 0x9C, 0x85, 0x00, 0x33, 0x2D, 0x00, 0x82, 0x88, 0x04, 0xA0, 0x82, 0x05, - 0x80, 0x63, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x6E, 0x05, 0x1D, 0x01, 0x06, 0xD6, 0x02, 0x23, - 0x02, 0x41, 0x82, 0x01, 0x50, 0x00, 0x24, 0x97, 0xD0, 0x84, 0x04, 0x23, 0x02, 0x41, 0x82, 0x01, - 0xD0, 0x84, 0x08, 0xA0, 0x88, 0x05, 0x9C, 0x85, 0x03, 0xA0, 0x8E, 0x05, 0x9C, 0x85, 0x01, 0xA0, - 0x9A, 0x05, 0x88, 0x00, 0x80, 0x63, 0x78, 0x96, 0x4A, 0x85, 0x88, 0x86, 0x80, 0x63, 0x4A, 0x85, - 0x00, 0x63, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0xDE, 0x05, 0x1D, 0x01, 0x18, 0xD4, 0xC0, 0x23, - 0x07, 0x41, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6, 0xC0, 0x05, 0x00, 0x33, 0x37, 0x00, 0x82, 0x88, - 0x1D, 0x01, 0x02, 0xD6, 0x46, 0x23, 0xB8, 0x88, 0x63, 0x60, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6, - 0xD8, 0x05, 0x00, 0x33, 0x38, 0x00, 0x82, 0x88, 0xEF, 0x04, 0x6F, 0x00, 0x00, 0x63, 0x4B, 0x00, - 0x06, 0x41, 0xCB, 0x00, 0x52, 0x00, 0x06, 0x61, 0x00, 0xA2, 0xF2, 0x05, 0xC0, 0x23, 0x07, 0x41, - 0x00, 0x63, 0x80, 0x23, 0x07, 0x41, 0x00, 0x63, 0x80, 0x67, 0x08, 0x23, 0x83, 0x03, 0x80, 0x63, - 0x00, 0x63, 0x06, 0xA6, 0x14, 0x06, 0x07, 0xA6, 0x64, 0x06, 0x02, 0xA6, 0xBC, 0x06, 0x00, 0x33, - 0x39, 0x00, 0x82, 0x88, 0x00, 0x00, 0x01, 0xA0, 0xD6, 0x06, 0xA2, 0x95, 0x83, 0x03, 0x80, 0x63, - 0x06, 0xA6, 0x28, 0x06, 0x07, 0xA6, 0x64, 0x06, 0x00, 0x00, 0x00, 0x2B, 0x40, 0x0E, 0x80, 0x63, - 0x01, 0x00, 0x06, 0xA6, 0x40, 0x06, 0x07, 0xA6, 0x64, 0x06, 0x00, 0x33, 0x3A, 0x00, 0x82, 0x88, - 0x40, 0x0E, 0x80, 0x63, 0x00, 0x43, 0x00, 0xA0, 0x32, 0x06, 0x06, 0xA6, 0x58, 0x06, 0x07, 0xA6, - 0x64, 0x06, 0x00, 0x33, 0x3B, 0x00, 0x82, 0x88, 0x80, 0x67, 0x40, 0x0E, 0x80, 0x63, 0x07, 0xA6, - 0x64, 0x06, 0x00, 0x63, 0x03, 0x03, 0x80, 0x63, 0x88, 0x00, 0x01, 0xA2, 0x78, 0x06, 0x07, 0xA2, - 0xBC, 0x06, 0x00, 0x33, 0x35, 0x00, 0x82, 0x88, 0x07, 0xA6, 0x82, 0x06, 0x00, 0x33, 0x2A, 0x00, - 0x82, 0x88, 0x03, 0x03, 0x03, 0xA2, 0x8E, 0x06, 0x07, 0x23, 0x80, 0x00, 0xC8, 0x86, 0x80, 0x63, - 0x89, 0x00, 0x0A, 0x2B, 0x07, 0xA6, 0x9E, 0x06, 0x00, 0x33, 0x29, 0x00, 0x82, 0x88, 0x00, 0x43, - 0x00, 0xA2, 0xAA, 0x06, 0xC0, 0x0E, 0x80, 0x63, 0x94, 0x86, 0xC0, 0x0E, 0x00, 0x33, 0x00, 0x80, - 0xC0, 0x20, 0x81, 0x62, 0x04, 0x01, 0x08, 0xDA, 0x80, 0x63, 0x00, 0x63, 0x80, 0x67, 0x00, 0x33, - 0x00, 0x40, 0xC0, 0x20, 0x81, 0x62, 0x00, 0x63, 0x80, 0x7B, 0x80, 0x63, 0x06, 0xA6, 0x20, 0x06, - 0x00, 0x33, 0x2C, 0x00, 0x82, 0x88, 0x0C, 0xA2, 0xF0, 0x06, 0xA2, 0x95, 0x83, 0x03, 0x80, 0x63, - 0x06, 0xA6, 0xEE, 0x06, 0x07, 0xA6, 0x64, 0x06, 0x00, 0x33, 0x3D, 0x00, 0x82, 0x88, 0x00, 0x00, - 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0x0C, 0xA0, 0x06, 0x07, 0x07, 0xA6, 0x64, 0x06, 0xBF, 0x23, - 0x04, 0x61, 0x84, 0x01, 0xB2, 0x84, 0x00, 0x63, 0xF0, 0x04, 0x01, 0x01, 0xF1, 0x00, 0x00, 0x01, - 0xF2, 0x00, 0x01, 0x05, 0x80, 0x01, 0x72, 0x04, 0x71, 0x00, 0x81, 0x01, 0x70, 0x04, 0x80, 0x05, - 0x81, 0x05, 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04, 0x01, 0x01, 0xF1, 0x00, 0x70, 0x00, - 0x81, 0x01, 0x70, 0x04, 0x71, 0x00, 0x81, 0x01, 0x72, 0x00, 0x80, 0x01, 0x71, 0x04, 0x70, 0x00, - 0x80, 0x01, 0x70, 0x04, 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04, 0x00, 0x01, 0xF1, 0x00, - 0x70, 0x00, 0x80, 0x01, 0x70, 0x04, 0x71, 0x00, 0x80, 0x01, 0x72, 0x00, 0x81, 0x01, 0x71, 0x04, - 0x70, 0x00, 0x81, 0x01, 0x70, 0x04, 0x00, 0x63, 0x00, 0x23, 0xB3, 0x01, 0x83, 0x05, 0xA3, 0x01, - 0xA2, 0x01, 0xA1, 0x01, 0x01, 0x23, 0xA0, 0x01, 0x00, 0x01, 0xC8, 0x00, 0x03, 0xA1, 0x86, 0x07, - 0x00, 0x33, 0x07, 0x00, 0x82, 0x88, 0x80, 0x05, 0x81, 0x05, 0x04, 0x01, 0x11, 0xC8, 0x48, 0x00, - 0xB0, 0x01, 0xB1, 0x01, 0x08, 0x23, 0xB2, 0x01, 0x05, 0x01, 0x48, 0x04, 0x00, 0x43, 0x00, 0xA2, - 0xA6, 0x07, 0x00, 0x05, 0x9C, 0x87, 0x00, 0x01, 0xC8, 0x00, 0xFF, 0x23, 0x80, 0x01, 0x05, 0x05, - 0x00, 0x63, 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04, 0x00, 0x02, 0x80, 0x43, 0x76, 0x08, - 0x80, 0x02, 0x77, 0x04, 0x00, 0x63, 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04, 0x00, 0x02, - 0x00, 0xA0, 0xD6, 0x07, 0xD8, 0x87, 0x00, 0x43, 0x76, 0x08, 0x80, 0x02, 0x77, 0x04, 0x00, 0x63, - 0xF3, 0x04, 0x00, 0x23, 0xF4, 0x00, 0x74, 0x00, 0x80, 0x43, 0xF4, 0x00, 0xCF, 0x40, 0x00, 0xA2, - 0x06, 0x08, 0x74, 0x04, 0x02, 0x01, 0xF7, 0xC9, 0xF6, 0xD9, 0x00, 0x01, 0x01, 0xA1, 0xE6, 0x07, - 0xC6, 0x97, 0xF4, 0x94, 0xE6, 0x87, 0x73, 0x04, 0x00, 0x63, 0xF3, 0x04, 0x75, 0x04, 0x1C, 0x88, - 0x02, 0x01, 0x04, 0xD8, 0x08, 0x97, 0xC6, 0x97, 0xF4, 0x94, 0x0C, 0x88, 0x75, 0x00, 0x00, 0xA3, - 0x26, 0x08, 0x00, 0x05, 0x10, 0x88, 0x73, 0x04, 0x00, 0x63, 0x80, 0x7B, 0x80, 0x63, 0x06, 0xA6, - 0x38, 0x08, 0x00, 0x33, 0x3E, 0x00, 0x82, 0x88, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0x00, 0x63, - 0x38, 0x2B, 0x5E, 0x88, 0x38, 0x2B, 0x54, 0x88, 0x32, 0x09, 0x31, 0x05, 0x54, 0x98, 0x05, 0x05, - 0xB2, 0x09, 0x00, 0x63, 0x00, 0x32, 0x00, 0x36, 0x00, 0x3A, 0x00, 0x3E, 0x00, 0x63, 0x80, 0x32, - 0x80, 0x36, 0x80, 0x3A, 0x80, 0x3E, 0x00, 0x63, 0x38, 0x2B, 0x40, 0x32, 0x40, 0x36, 0x40, 0x3A, - 0x40, 0x3E, 0x00, 0x63, 0x5A, 0x20, 0xC9, 0x40, 0x00, 0xA0, 0x74, 0x08, 0x5D, 0x00, 0xFE, 0xC3, - 0x00, 0x63, 0x80, 0x73, 0xE6, 0x20, 0x02, 0x23, 0xE8, 0x00, 0x82, 0x73, 0xFF, 0xFD, 0x80, 0x73, - 0x13, 0x23, 0xB8, 0x88, 0x66, 0x20, 0xC0, 0x20, 0x04, 0x23, 0xA0, 0x01, 0xA1, 0x23, 0xA1, 0x01, - 0x81, 0x62, 0xA2, 0x88, 0x80, 0x73, 0x80, 0x77, 0x68, 0x00, 0x00, 0xA2, 0x80, 0x00, 0x03, 0xC2, - 0xF1, 0xC7, 0x41, 0x23, 0xB8, 0x88, 0x11, 0x23, 0xA1, 0x01, 0x04, 0x23, 0xA0, 0x01, 0xB2, 0x84, - -}; - -ushort _mcode_size = sizeof (_mcode_buf); -ulong _mcode_chksum = 0x012258FBUL; - -extern uchar _sdtr_period_tbl_[]; - -int -AscExeScsiQueue( - ASC_DVC_VAR asc_ptr_type * asc_dvc, - ASC_SCSI_Q dosfar * scsiq -) -{ - PortAddr iop_base; - int last_int_level; - int sta; - ulong addr; - uchar sg_entry_cnt; - uchar target_ix; - int n_q_required; - uchar sg_entry_cnt_minus_one; - uchar tid_no; - uchar sdtr_data; - ASC_EXE_CALLBACK asc_exe_callback; - -#if CC_DEBUG_SG_LIST - int i; - -#endif -#if CC_LINK_BUSY_Q - ASC_SCSI_Q dosfar *scsiq_tail; - ASC_SCSI_Q dosfar *scsiq_next; - ASC_SCSI_Q dosfar *scsiq_prev; - -#endif - - iop_base = asc_dvc->iop_base; - asc_exe_callback = (ASC_EXE_CALLBACK) asc_dvc->exe_callback; - if (asc_dvc->err_code != 0) - return (ERR); - if (scsiq == (ASC_SCSI_Q dosfar *) 0L) { - AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SCSIQ_NULL_PTR); - return (ERR); - } - scsiq->q1.q_no = 0; - sta = 0; - target_ix = scsiq->q2.target_ix; - tid_no = ASC_TIX_TO_TID(target_ix); - - n_q_required = 1; - - if (scsiq->cdbptr[0] == SCSICMD_RequestSense) { - - if (((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) && - ((asc_dvc->sdtr_done & scsiq->q1.target_id) != 0)) { - sdtr_data = AscReadLramByte(iop_base, - (ushort) ((ushort) ASCV_SDTR_DATA_BEG + (ushort) tid_no)); - AscMsgOutSDTR(iop_base, - _sdtr_period_tbl_[(sdtr_data >> 4) & (uchar) (ASC_SYN_XFER_NO - 1)], - (uchar) (sdtr_data & (uchar) ASC_SYN_MAX_OFFSET)); - scsiq->q1.cntl |= (QC_MSG_OUT | QC_URGENT); - } - } - last_int_level = DvcEnterCritical(); - if (asc_dvc->in_critical_cnt != 0) { - DvcLeaveCritical(last_int_level); - AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CRITICAL_RE_ENTRY); - return (ERR); - } - asc_dvc->in_critical_cnt++; - - if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) { - - if ((sg_entry_cnt = scsiq->sg_head->entry_cnt) == 0) { - asc_dvc->in_critical_cnt--; - DvcLeaveCritical(last_int_level); - return (ERR); - } - if (sg_entry_cnt == 1) { - scsiq->q1.data_addr = scsiq->sg_head->sg_list[0].addr; - scsiq->q1.data_cnt = scsiq->sg_head->sg_list[0].bytes; - scsiq->q1.cntl &= ~(QC_SG_HEAD | QC_SG_SWAP_QUEUE); - goto NON_SG_LIST_REQ; - } - if (sg_entry_cnt > ASC_MAX_SG_LIST) { - - return (ERR); - } - sg_entry_cnt_minus_one = sg_entry_cnt - 1; - -#if CC_DEBUG_SG_LIST - if (asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL | ASC_IS_EISA)) { - for (i = 0; i < sg_entry_cnt_minus_one; i++) { - - addr = scsiq->sg_head->sg_list[i].addr + - scsiq->sg_head->sg_list[i].bytes; - - if (((ushort) addr & 0x0003) != 0) { - asc_dvc->in_critical_cnt--; - DvcLeaveCritical(last_int_level); - AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SG_LIST_ODD_ADDRESS); - return (ERR); - } - } - } -#endif - - if (asc_dvc->bug_fix_cntl) { - if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_ADD_ONE_BYTE) { - - addr = scsiq->sg_head->sg_list[sg_entry_cnt_minus_one].addr + - scsiq->sg_head->sg_list[sg_entry_cnt_minus_one].bytes; - if (((ushort) addr & 0x0003) != 0) { - if ((scsiq->cdbptr[0] == SCSICMD_Read6) || - (scsiq->cdbptr[0] == SCSICMD_Read10)) { - if ((scsiq->q2.tag_code & ASC_TAG_FLAG_ADD_ONE_BYTE) == 0) { - - scsiq->sg_head->sg_list[sg_entry_cnt_minus_one].bytes++; - scsiq->q2.tag_code |= ASC_TAG_FLAG_ADD_ONE_BYTE; - } - } - } - } - } - scsiq->sg_head->entry_to_copy = scsiq->sg_head->entry_cnt; - n_q_required = AscSgListToQueue(sg_entry_cnt); - -#if CC_LINK_BUSY_Q - scsiq_next = (ASC_SCSI_Q dosfar *) asc_dvc->scsiq_busy_head[tid_no]; - if (scsiq_next != (ASC_SCSI_Q dosfar *) 0L) { - goto link_scisq_to_busy_list; - } -#endif - - if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, n_q_required) - >= (uint) n_q_required) || - ((scsiq->q1.cntl & QC_URGENT) != 0)) { - if ((sta = AscSendScsiQueue(asc_dvc, scsiq, - n_q_required)) == 1) { - - asc_dvc->in_critical_cnt--; - if (asc_exe_callback != 0) { - (*asc_exe_callback) (asc_dvc, scsiq); - } - DvcLeaveCritical(last_int_level); - return (sta); - } - } - } else { - - NON_SG_LIST_REQ: - - if (asc_dvc->bug_fix_cntl) { - if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_ADD_ONE_BYTE) { - - addr = scsiq->q1.data_addr + scsiq->q1.data_cnt; - if ((scsiq->cdbptr[0] == SCSICMD_Read6) || - (scsiq->cdbptr[0] == SCSICMD_Read10)) { - if (((ushort) addr & 0x0003) != 0) { - if (((ushort) scsiq->q1.data_cnt & 0x01FF) == 0) { - - if ((scsiq->q2.tag_code & ASC_TAG_FLAG_ADD_ONE_BYTE) == 0) { - - scsiq->q2.tag_code |= ASC_TAG_FLAG_ADD_ONE_BYTE; - scsiq->q1.data_cnt++; - } - } - } - } - } - } - n_q_required = 1; - -#if CC_LINK_BUSY_Q - scsiq_next = (ASC_SCSI_Q dosfar *) asc_dvc->scsiq_busy_head[tid_no]; - if (scsiq_next != (ASC_SCSI_Q dosfar *) 0L) { - goto link_scisq_to_busy_list; - } -#endif - if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, 1) >= 1) || - ((scsiq->q1.cntl & QC_URGENT) != 0)) { - if ((sta = AscSendScsiQueue(asc_dvc, scsiq, - n_q_required)) == 1) { - - asc_dvc->in_critical_cnt--; - if (asc_exe_callback != 0) { - (*asc_exe_callback) (asc_dvc, scsiq); - } - DvcLeaveCritical(last_int_level); - return (sta); - } - } - } - -#if CC_LINK_BUSY_Q - if (sta == 0) { - - link_scisq_to_busy_list: - scsiq->ext.q_required = n_q_required; - if (scsiq_next == (ASC_SCSI_Q dosfar *) 0L) { - asc_dvc->scsiq_busy_head[tid_no] = (ASC_SCSI_Q dosfar *) scsiq; - asc_dvc->scsiq_busy_tail[tid_no] = (ASC_SCSI_Q dosfar *) scsiq; - scsiq->ext.next = (ASC_SCSI_Q dosfar *) 0L; - scsiq->ext.join = (ASC_SCSI_Q dosfar *) 0L; - scsiq->q1.status = QS_BUSY; - sta = 1; - } else { - scsiq_tail = (ASC_SCSI_Q dosfar *) asc_dvc->scsiq_busy_tail[tid_no]; - if (scsiq_tail->ext.next == (ASC_SCSI_Q dosfar *) 0L) { - if ((scsiq->q1.cntl & QC_URGENT) != 0) { - - asc_dvc->scsiq_busy_head[tid_no] = (ASC_SCSI_Q dosfar *) scsiq; - scsiq->ext.next = scsiq_next; - scsiq->ext.join = (ASC_SCSI_Q dosfar *) 0L; - } else { - if (scsiq->ext.cntl & QCX_SORT) { - do { - scsiq_prev = scsiq_next; - scsiq_next = scsiq_next->ext.next; - if (scsiq->ext.lba < scsiq_prev->ext.lba) - break; - } while (scsiq_next != (ASC_SCSI_Q dosfar *) 0L); - - scsiq_prev->ext.next = scsiq; - scsiq->ext.next = scsiq_next; - if (scsiq_next == (ASC_SCSI_Q dosfar *) 0L) { - asc_dvc->scsiq_busy_tail[tid_no] = (ASC_SCSI_Q dosfar *) scsiq; - } - scsiq->ext.join = (ASC_SCSI_Q dosfar *) 0L; - } else { - - scsiq_tail->ext.next = (ASC_SCSI_Q dosfar *) scsiq; - asc_dvc->scsiq_busy_tail[tid_no] = (ASC_SCSI_Q dosfar *) scsiq; - scsiq->ext.next = (ASC_SCSI_Q dosfar *) 0L; - scsiq->ext.join = (ASC_SCSI_Q dosfar *) 0L; - } - } - scsiq->q1.status = QS_BUSY; - sta = 1; - } else { - - AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SCSIQ_BAD_NEXT_PTR); - sta = ERR; - } - } - } -#endif - asc_dvc->in_critical_cnt--; - DvcLeaveCritical(last_int_level); - return (sta); -} - -int -AscSendScsiQueue( - ASC_DVC_VAR asc_ptr_type * asc_dvc, - ASC_SCSI_Q dosfar * scsiq, - uchar n_q_required -) -{ - PortAddr iop_base; - uchar free_q_head; - uchar next_qp; - uchar tid_no; - uchar target_ix; - int sta; - - iop_base = asc_dvc->iop_base; - target_ix = scsiq->q2.target_ix; - tid_no = ASC_TIX_TO_TID(target_ix); - sta = 0; - free_q_head = (uchar) AscGetVarFreeQHead(iop_base); - if (n_q_required > 1) { - if ((next_qp = AscAllocMultipleFreeQueue(iop_base, - free_q_head, (uchar) (n_q_required))) - != (uchar) ASC_QLINK_END) { - asc_dvc->last_q_shortage = 0; - scsiq->sg_head->queue_cnt = n_q_required - 1; - scsiq->q1.q_no = free_q_head; - - if ((sta = AscPutReadySgListQueue(asc_dvc, scsiq, - free_q_head)) == 1) { - -#if CC_WRITE_IO_COUNT - asc_dvc->req_count++; -#endif - - AscPutVarFreeQHead(iop_base, next_qp); - asc_dvc->cur_total_qng += (uchar) (n_q_required); - asc_dvc->cur_dvc_qng[tid_no]++; - } - return (sta); - } - } else if (n_q_required == 1) { - - if ((next_qp = AscAllocFreeQueue(iop_base, - free_q_head)) != ASC_QLINK_END) { - - scsiq->q1.q_no = free_q_head; - if ((sta = AscPutReadyQueue(asc_dvc, scsiq, - free_q_head)) == 1) { - -#if CC_WRITE_IO_COUNT - asc_dvc->req_count++; -#endif - - AscPutVarFreeQHead(iop_base, next_qp); - asc_dvc->cur_total_qng++; - asc_dvc->cur_dvc_qng[tid_no]++; - } - return (sta); - } - } - return (sta); -} - -int -AscSgListToQueue( - int sg_list -) -{ - int n_sg_list_qs; - - n_sg_list_qs = ((sg_list - 1) / ASC_SG_LIST_PER_Q); - if (((sg_list - 1) % ASC_SG_LIST_PER_Q) != 0) - n_sg_list_qs++; - return (n_sg_list_qs + 1); -} - -uint -AscGetNumOfFreeQueue( - ASC_DVC_VAR asc_ptr_type * asc_dvc, - uchar target_ix, uchar n_qs -) -{ - uint cur_used_qs; - uint cur_free_qs; - ASC_SCSI_BIT_ID_TYPE target_id; - uchar tid_no; - - target_id = ASC_TIX_TO_TARGET_ID(target_ix); - tid_no = ASC_TIX_TO_TID(target_ix); - if ((asc_dvc->unit_not_ready & target_id) || - (asc_dvc->queue_full_or_busy & target_id)) { - return (0); - } - if (n_qs == 1) { - cur_used_qs = (uint) asc_dvc->cur_total_qng + - (uint) asc_dvc->last_q_shortage + - (uint) ASC_MIN_FREE_Q; - } else { - cur_used_qs = (uint) asc_dvc->cur_total_qng + - (uint) ASC_MIN_FREE_Q; - } - - if ((uint) (cur_used_qs + n_qs) <= (uint) asc_dvc->max_total_qng) { - cur_free_qs = (uint) asc_dvc->max_total_qng - cur_used_qs; - if (asc_dvc->cur_dvc_qng[tid_no] >= - asc_dvc->max_dvc_qng[tid_no]) { - return (0); - } - return (cur_free_qs); - } - if (n_qs > 1) { - if (n_qs > asc_dvc->last_q_shortage) { - asc_dvc->last_q_shortage = n_qs; - } - } - return (0); -} - -int -AscPutReadyQueue( - ASC_DVC_VAR asc_ptr_type * asc_dvc, - ASC_SCSI_Q dosfar * scsiq, - uchar q_no -) -{ - ushort q_addr; - uchar tid_no; - uchar sdtr_data; - uchar syn_period_ix; - uchar syn_offset; - PortAddr iop_base; - - iop_base = asc_dvc->iop_base; - - if (((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) && - ((asc_dvc->sdtr_done & scsiq->q1.target_id) == 0)) { - - tid_no = ASC_TIX_TO_TID(scsiq->q2.target_ix); - - sdtr_data = AscReadLramByte(iop_base, - (ushort) ((ushort) ASCV_SDTR_DATA_BEG + (ushort) tid_no)); - syn_period_ix = (sdtr_data >> 4) & (ASC_SYN_XFER_NO - 1); - syn_offset = sdtr_data & ASC_SYN_MAX_OFFSET; - AscMsgOutSDTR(iop_base, - _sdtr_period_tbl_[syn_period_ix], - syn_offset); - - scsiq->q1.cntl |= QC_MSG_OUT; - } - q_addr = ASC_QNO_TO_QADDR(q_no); - - if ((scsiq->q1.target_id & asc_dvc->use_tagged_qng) == 0) { - scsiq->q2.tag_code &= ~M2_QTAG_MSG_SIMPLE; - } - scsiq->q1.status = QS_FREE; - - AscMemWordCopyToLram(iop_base, - (ushort) (q_addr + (ushort) ASC_SCSIQ_CDB_BEG), - (ushort dosfar *) scsiq->cdbptr, - (ushort) ((ushort) scsiq->q2.cdb_len >> 1)); - -#if !CC_LITTLE_ENDIAN_HOST - AscAdjEndianScsiQ(scsiq); -#endif - - DvcPutScsiQ(iop_base, - (ushort) (q_addr + (ushort) ASC_SCSIQ_CPY_BEG), - (ushort dosfar *) & scsiq->q1.cntl, - (ushort) ((((sizeof (ASC_SCSIQ_1) + sizeof (ASC_SCSIQ_2)) / 2) - 1))); - -#if CC_WRITE_IO_COUNT - AscWriteLramWord(iop_base, - (ushort) (q_addr + (ushort) ASC_SCSIQ_W_REQ_COUNT), - (ushort) asc_dvc->req_count); - -#endif - -#if CC_VERIFY_LRAM_COPY - if ((asc_dvc->dvc_cntl & ASC_CNTL_NO_VERIFY_COPY) == 0) { - - if (AscMemWordCmpToLram(iop_base, - (ushort) (q_addr + (ushort) ASC_SCSIQ_CDB_BEG), - (ushort dosfar *) scsiq->cdbptr, - (ushort) (scsiq->q2.cdb_len >> 1)) != 0) { - AscSetLibErrorCode(asc_dvc, ASCQ_ERR_LOCAL_MEM); - return (ERR); - } - if (AscMemWordCmpToLram(iop_base, - (ushort) (q_addr + (ushort) ASC_SCSIQ_CPY_BEG), - (ushort dosfar *) & scsiq->q1.cntl, - (ushort) (((sizeof (ASC_SCSIQ_1) + sizeof (ASC_SCSIQ_2)) / 2) - 1)) - != 0) { - AscSetLibErrorCode(asc_dvc, ASCQ_ERR_LOCAL_MEM); - return (ERR); - } - } -#endif - -#if CC_CLEAR_DMA_REMAIN - - AscWriteLramDWord(iop_base, - (ushort) (q_addr + (ushort) ASC_SCSIQ_DW_REMAIN_XFER_ADDR), 0UL); - AscWriteLramDWord(iop_base, - (ushort) (q_addr + (ushort) ASC_SCSIQ_DW_REMAIN_XFER_CNT), 0UL); - -#endif - - AscWriteLramWord(iop_base, - (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS), - (ushort) (((ushort) scsiq->q1.q_no << 8) | (ushort) QS_READY)); - return (1); -} - -int -AscPutReadySgListQueue( - ASC_DVC_VAR asc_ptr_type * asc_dvc, - ASC_SCSI_Q dosfar * scsiq, - uchar q_no -) -{ - uchar sg_list_dwords; - uchar sg_index, i; - uchar sg_entry_cnt; - uchar next_qp; - ushort q_addr; - int sta; - ASC_SG_HEAD dosfar *sg_head; - ASC_SG_LIST_Q scsi_sg_q; - ulong saved_data_addr; - ulong saved_data_cnt; - PortAddr iop_base; - - iop_base = asc_dvc->iop_base; - - sg_head = scsiq->sg_head; - - saved_data_addr = scsiq->q1.data_addr; - saved_data_cnt = scsiq->q1.data_cnt; - scsiq->q1.data_addr = sg_head->sg_list[0].addr; - scsiq->q1.data_cnt = sg_head->sg_list[0].bytes; - sg_entry_cnt = sg_head->entry_cnt - 1; - if (sg_entry_cnt != 0) { - scsiq->q1.cntl |= QC_SG_HEAD; - q_addr = ASC_QNO_TO_QADDR(q_no); - sg_index = 1; - scsiq->q1.sg_queue_cnt = sg_head->queue_cnt; - scsi_sg_q.sg_head_qp = q_no; - scsi_sg_q.cntl = QCSG_SG_XFER_LIST; - for (i = 0; i < sg_head->queue_cnt; i++) { - scsi_sg_q.seq_no = i + 1; - if (sg_entry_cnt > ASC_SG_LIST_PER_Q) { - sg_list_dwords = (uchar) (ASC_SG_LIST_PER_Q * 2); - sg_entry_cnt -= ASC_SG_LIST_PER_Q; - if (i == 0) { - scsi_sg_q.sg_list_cnt = ASC_SG_LIST_PER_Q; - scsi_sg_q.sg_cur_list_cnt = ASC_SG_LIST_PER_Q; - } else { - scsi_sg_q.sg_list_cnt = ASC_SG_LIST_PER_Q - 1; - scsi_sg_q.sg_cur_list_cnt = ASC_SG_LIST_PER_Q - 1; - } - } else { - - scsi_sg_q.cntl |= QCSG_SG_XFER_END; - sg_list_dwords = sg_entry_cnt << 1; - if (i == 0) { - scsi_sg_q.sg_list_cnt = sg_entry_cnt; - scsi_sg_q.sg_cur_list_cnt = sg_entry_cnt; - } else { - scsi_sg_q.sg_list_cnt = sg_entry_cnt - 1; - scsi_sg_q.sg_cur_list_cnt = sg_entry_cnt - 1; - } - sg_entry_cnt = 0; - } - next_qp = AscReadLramByte(iop_base, - (ushort) (q_addr + ASC_SCSIQ_B_FWD)); - scsi_sg_q.q_no = next_qp; - q_addr = ASC_QNO_TO_QADDR(next_qp); - - AscMemWordCopyToLram(iop_base, - (ushort) (q_addr + ASC_SCSIQ_SGHD_CPY_BEG), - (ushort dosfar *) & scsi_sg_q, - (ushort) (sizeof (ASC_SG_LIST_Q) >> 1)); - - AscMemDWordCopyToLram(iop_base, - (ushort) (q_addr + ASC_SGQ_LIST_BEG), - (ulong dosfar *) & sg_head->sg_list[sg_index], - (ushort) sg_list_dwords); - - sg_index += ASC_SG_LIST_PER_Q; - } - } else { - - scsiq->q1.cntl &= ~QC_SG_HEAD; - } - sta = AscPutReadyQueue(asc_dvc, scsiq, q_no); - - scsiq->q1.data_addr = saved_data_addr; - scsiq->q1.data_cnt = saved_data_cnt; - return (sta); -} - -int -AscAbortSRB( - ASC_DVC_VAR asc_ptr_type * asc_dvc, - ulong srb_ptr -) -{ - int sta; - ASC_SCSI_BIT_ID_TYPE saved_unit_not_ready; - PortAddr iop_base; - - iop_base = asc_dvc->iop_base; - sta = ERR; - saved_unit_not_ready = asc_dvc->unit_not_ready; - asc_dvc->unit_not_ready = 0xFF; - AscWaitISRDone(asc_dvc); - if (AscStopQueueExe(iop_base) == 1) { - if (AscRiscHaltedAbortSRB(asc_dvc, srb_ptr) == 1) { - sta = 1; - AscCleanUpBusyQueue(iop_base); - AscStartQueueExe(iop_base); - - } else { - sta = 0; - AscStartQueueExe(iop_base); - } - } - asc_dvc->unit_not_ready = saved_unit_not_ready; - return (sta); -} - -int -AscResetDevice( - ASC_DVC_VAR asc_ptr_type * asc_dvc, - uchar target_ix -) -{ - PortAddr iop_base; - int sta; - uchar tid_no; - ASC_SCSI_BIT_ID_TYPE target_id; - int i; - ASC_SCSI_REQ_Q scsiq_buf; - ASC_SCSI_REQ_Q dosfar *scsiq; - uchar dosfar *buf; - ASC_SCSI_BIT_ID_TYPE saved_unit_not_ready; - - iop_base = asc_dvc->iop_base; - tid_no = ASC_TIX_TO_TID(target_ix); - target_id = ASC_TID_TO_TARGET_ID(tid_no); - saved_unit_not_ready = asc_dvc->unit_not_ready; - asc_dvc->unit_not_ready = target_id; - sta = ERR; - AscWaitTixISRDone(asc_dvc, target_ix); - if (AscStopQueueExe(iop_base) == 1) { - if (AscRiscHaltedAbortTIX(asc_dvc, target_ix) == 1) { - - AscCleanUpBusyQueue(iop_base); - AscStartQueueExe(iop_base); - - AscWaitTixISRDone(asc_dvc, target_ix); - - sta = TRUE; - scsiq = (ASC_SCSI_REQ_Q dosfar *) & scsiq_buf; - buf = (uchar dosfar *) & scsiq_buf; - for (i = 0; i < sizeof (ASC_SCSI_REQ_Q); i++) { - *buf++ = 0x00; - } - - scsiq->r1.status = (uchar) QS_READY; - scsiq->r2.cdb_len = 6; - scsiq->r2.tag_code = M2_QTAG_MSG_SIMPLE; - scsiq->r1.target_id = target_id; - - scsiq->r2.target_ix = ASC_TIDLUN_TO_IX(tid_no, 0); - scsiq->cdbptr = (uchar dosfar *) scsiq->cdb; - - scsiq->r1.cntl = QC_NO_CALLBACK | QC_MSG_OUT | QC_URGENT; - AscWriteLramByte(asc_dvc->iop_base, ASCV_MSGOUT_BEG, - M1_BUS_DVC_RESET); - - asc_dvc->unit_not_ready &= ~target_id; - - asc_dvc->sdtr_done |= target_id; - - if (AscExeScsiQueue(asc_dvc, (ASC_SCSI_Q dosfar *) scsiq) - == 1) { - asc_dvc->unit_not_ready = target_id; - DvcSleepMilliSecond(1000); - _AscWaitQDone(iop_base, (ASC_SCSI_Q dosfar *) scsiq); - if (AscStopQueueExe(iop_base) == 1) { - - AscCleanUpDiscQueue(iop_base); - AscStartQueueExe(iop_base); - if (asc_dvc->pci_fix_asyn_xfer & target_id) { - - AscSetRunChipSynRegAtID(iop_base, tid_no, - ASYN_SDTR_DATA_FIX_PCI_REV_AB); - } - AscWaitTixISRDone(asc_dvc, target_ix); - } - } else { - - sta = 0; - } - - asc_dvc->sdtr_done &= ~target_id; - } else { - sta = ERR; - AscStartQueueExe(iop_base); - } - } - asc_dvc->unit_not_ready = saved_unit_not_ready; - return (sta); -} - -int -AscResetSB( - ASC_DVC_VAR asc_ptr_type * asc_dvc -) -{ - int sta; - int i; - PortAddr iop_base; - - iop_base = asc_dvc->iop_base; - asc_dvc->unit_not_ready = 0xFF; - sta = TRUE; - AscWaitISRDone(asc_dvc); - AscStopQueueExe(iop_base); - - asc_dvc->sdtr_done = 0; - AscResetChipAndScsiBus(iop_base); - - DvcSleepMilliSecond((ulong) ((ushort) asc_dvc->scsi_reset_wait * 1000)); - -#if CC_SCAM - if (!(asc_dvc->dvc_cntl & ASC_CNTL_NO_SCAM)) { - AscSCAM(asc_dvc); - } -#endif - AscReInitLram(asc_dvc); - - for (i = 0; i <= ASC_MAX_TID; i++) { - asc_dvc->cur_dvc_qng[i] = 0; - if (asc_dvc->pci_fix_asyn_xfer & (0x01 << i)) { - - AscSetChipSynRegAtID(iop_base, i, ASYN_SDTR_DATA_FIX_PCI_REV_AB); - } - } - - asc_dvc->err_code = 0; - - AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR); - if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) { - sta = ERR; - } - if (AscStartChip(iop_base) == 0) { - sta = ERR; - } - AscStartQueueExe(iop_base); - asc_dvc->unit_not_ready = 0; - asc_dvc->queue_full_or_busy = 0; - return (sta); -} - -int -AscSetRunChipSynRegAtID( - PortAddr iop_base, - uchar tid_no, - uchar sdtr_data -) -{ - int sta = FALSE; - - if (AscHostReqRiscHalt(iop_base)) { - sta = AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data); - - AscStartChip(iop_base); - return (sta); - } - return (sta); -} - -int -AscSetChipSynRegAtID( - PortAddr iop_base, - uchar id, - uchar sdtr_data -) -{ - AscSetBank(iop_base, 1); - AscWriteChipScsiID(iop_base, id); - if (AscReadChipScsiID(iop_base) != (0x01 << id)) { - return (FALSE); - } - AscSetBank(iop_base, 0); - AscWriteChipSyn(iop_base, sdtr_data); - if (AscReadChipSyn(iop_base) != sdtr_data) { - return (FALSE); - } - return (TRUE); -} - -int -AscReInitLram( - ASC_DVC_VAR asc_ptr_type * asc_dvc -) -{ - AscInitLram(asc_dvc); - AscInitQLinkVar(asc_dvc); - return (0); -} - -ushort -AscInitLram( - ASC_DVC_VAR asc_ptr_type * asc_dvc) -{ - uchar i; - ushort s_addr; - PortAddr iop_base; - ushort warn_code; - - iop_base = asc_dvc->iop_base; - warn_code = 0; - - AscMemWordSetLram(iop_base, ASC_QADR_BEG, 0, - (ushort) (((int) (asc_dvc->max_total_qng + 2 + 1) * 64) >> 1) - ); - - i = ASC_MIN_ACTIVE_QNO; - s_addr = ASC_QADR_BEG + ASC_QBLK_SIZE; - - AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_FWD), - (uchar) (i + 1)); - AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_BWD), - (uchar) (asc_dvc->max_total_qng)); - AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_QNO), - (uchar) i); - i++; - s_addr += ASC_QBLK_SIZE; - for (; i < asc_dvc->max_total_qng; i++, s_addr += ASC_QBLK_SIZE) { - AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_FWD), - (uchar) (i + 1)); - AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_BWD), - (uchar) (i - 1)); - AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_QNO), - (uchar) i); - } - - AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_FWD), - (uchar) ASC_QLINK_END); - AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_BWD), - (uchar) (asc_dvc->max_total_qng - 1)); - AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_QNO), - (uchar) asc_dvc->max_total_qng); - i++; - s_addr += ASC_QBLK_SIZE; - - for (; i <= (uchar) (asc_dvc->max_total_qng + 3); - i++, s_addr += ASC_QBLK_SIZE) { - - AscWriteLramByte(iop_base, - (ushort) (s_addr + (ushort) ASC_SCSIQ_B_FWD), i); - AscWriteLramByte(iop_base, - (ushort) (s_addr + (ushort) ASC_SCSIQ_B_BWD), i); - AscWriteLramByte(iop_base, - (ushort) (s_addr + (ushort) ASC_SCSIQ_B_QNO), i); - } - - return (warn_code); -} - -ushort -AscInitQLinkVar( - ASC_DVC_VAR asc_ptr_type * asc_dvc -) -{ - PortAddr iop_base; - int i; - ushort lram_addr; - - iop_base = asc_dvc->iop_base; - AscPutRiscVarFreeQHead(iop_base, 1); - AscPutRiscVarDoneQTail(iop_base, asc_dvc->max_total_qng); - - AscPutVarFreeQHead(iop_base, 1); - AscPutVarDoneQTail(iop_base, asc_dvc->max_total_qng); - - AscWriteLramByte(iop_base, ASCV_BUSY_QHEAD_B, - (uchar) ((int) asc_dvc->max_total_qng + 1)); - AscWriteLramByte(iop_base, ASCV_DISC1_QHEAD_B, - (uchar) ((int) asc_dvc->max_total_qng + 2)); - - AscWriteLramByte(iop_base, (ushort) ASCV_TOTAL_READY_Q_B, - asc_dvc->max_total_qng); - - AscWriteLramWord(iop_base, ASCV_ASCDVC_ERR_CODE_W, 0); - AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); - AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, 0); - AscWriteLramByte(iop_base, ASCV_SCSIBUSY_B, 0); - AscWriteLramByte(iop_base, ASCV_WTM_FLAG_B, 0); - - AscWriteLramByte(iop_base, (ushort) ASCV_CDBCNT_B, 0); - - lram_addr = ASC_QADR_BEG; - for (i = 0; i < 32; i++, lram_addr += 2) { - AscWriteLramWord(iop_base, lram_addr, 0); - } - - return (0); -} - -int -AscSetLibErrorCode( - ASC_DVC_VAR asc_ptr_type * asc_dvc, - ushort err_code -) -{ - if (asc_dvc->err_code == 0) { - - asc_dvc->err_code = err_code; - AscWriteLramWord(asc_dvc->iop_base, ASCV_ASCDVC_ERR_CODE_W, - err_code); - } - return (err_code); -} - -int -_AscWaitQDone( - PortAddr iop_base, - ASC_SCSI_Q dosfar * scsiq -) -{ - ushort q_addr; - uchar q_status; - int count = 0; - - while (scsiq->q1.q_no == 0) ; - q_addr = ASC_QNO_TO_QADDR(scsiq->q1.q_no); - - do { - q_status = AscReadLramByte(iop_base, q_addr + ASC_SCSIQ_B_STATUS); - DvcSleepMilliSecond(100L); - if (count++ > 30) { - return (0); - } - } while ((q_status & QS_READY) != 0); - return (1); -} - -uchar _sdtr_period_tbl_[ASC_SYN_XFER_NO] = -{ - SYN_XFER_NS_0, - SYN_XFER_NS_1, - SYN_XFER_NS_2, - SYN_XFER_NS_3, - SYN_XFER_NS_4, - SYN_XFER_NS_5, - SYN_XFER_NS_6, - SYN_XFER_NS_7}; - -uchar -AscMsgOutSDTR( - PortAddr iop_base, - uchar sdtr_period, - uchar sdtr_offset -) -{ - SDTR_XMSG sdtr_buf; - uchar sdtr_period_index; - - sdtr_buf.msg_type = MS_EXTEND; - sdtr_buf.msg_len = MS_SDTR_LEN; - sdtr_buf.msg_req = MS_SDTR_CODE; - sdtr_buf.xfer_period = sdtr_period; - sdtr_offset &= ASC_SYN_MAX_OFFSET; - sdtr_buf.req_ack_offset = sdtr_offset; - AscMemWordCopyToLram(iop_base, ASCV_MSGOUT_BEG, - (ushort dosfar *) & sdtr_buf, SYN_XMSG_WLEN); - if ((sdtr_period_index = AscGetSynPeriodIndex(sdtr_period)) <= - ASC_MAX_SDTR_PERIOD_INDEX) { - return ((sdtr_period_index << 4) | sdtr_offset); - } else { - - return (0); - } -} - -uchar -AscCalSDTRData( - uchar sdtr_period, - uchar syn_offset -) -{ - uchar byte; - uchar sdtr_period_ix; - - sdtr_period_ix = AscGetSynPeriodIndex(sdtr_period); - if ((sdtr_period_ix > ASC_MAX_SDTR_PERIOD_INDEX) || - (sdtr_period_ix > ASC_SDTR_PERIOD_IX_MIN)) { - return (0xFF); - } - byte = (sdtr_period_ix << 4) | (syn_offset & ASC_SYN_MAX_OFFSET); - return (byte); -} - -void -AscSetChipSDTR( - PortAddr iop_base, - uchar sdtr_data, - uchar tid_no -) -{ - - AscWriteChipSyn(iop_base, sdtr_data); - AscWriteLramByte(iop_base, - (ushort) ((ushort) ASCV_SDTR_DONE_BEG + (ushort) tid_no), - sdtr_data); - return; -} - -uchar -AscGetSynPeriodIndex( - uchar syn_time -) -{ - if ((syn_time >= SYN_XFER_NS_0) && (syn_time <= SYN_XFER_NS_7)) { - if (syn_time <= SYN_XFER_NS_6) { - if (syn_time <= SYN_XFER_NS_5) { - if (syn_time <= SYN_XFER_NS_4) { - if (syn_time <= SYN_XFER_NS_3) { - if (syn_time <= SYN_XFER_NS_2) { - if (syn_time <= SYN_XFER_NS_1) { - if (syn_time <= SYN_XFER_NS_0) { - return (0); - } else - return (1); - } else { - return (2); - } - } else { - return (3); - } - } else { - return (4); - } - } else { - return (5); - } - } else { - return (6); - } - } else { - return (7); - } - } else { - - return (8); - } -} - -uchar -AscAllocFreeQueue( - PortAddr iop_base, - uchar free_q_head -) -{ - ushort q_addr; - uchar next_qp; - uchar q_status; - - q_addr = ASC_QNO_TO_QADDR(free_q_head); - q_status = (uchar) AscReadLramByte(iop_base, - (ushort) (q_addr + ASC_SCSIQ_B_STATUS)); - next_qp = AscReadLramByte(iop_base, - (ushort) (q_addr + ASC_SCSIQ_B_FWD)); - if (((q_status & QS_READY) == 0) && - (next_qp != ASC_QLINK_END)) { - return (next_qp); - } - return (ASC_QLINK_END); -} - -uchar -AscAllocMultipleFreeQueue( - PortAddr iop_base, - uchar free_q_head, - uchar n_free_q -) -{ - uchar i; - - for (i = 0; i < n_free_q; i++) { - if ((free_q_head = AscAllocFreeQueue(iop_base, free_q_head)) - == ASC_QLINK_END) { - return (ASC_QLINK_END); - } - } - return (free_q_head); -} - -int -AscRiscHaltedAbortSRB( - ASC_DVC_VAR asc_ptr_type * asc_dvc, - ulong srb_ptr -) -{ - PortAddr iop_base; - ushort q_addr; - uchar q_no; - ASC_QDONE_INFO scsiq_buf; - ASC_QDONE_INFO dosfar *scsiq; - ASC_ISR_CALLBACK asc_isr_callback; - int last_int_level; - - iop_base = asc_dvc->iop_base; - asc_isr_callback = (ASC_ISR_CALLBACK) asc_dvc->isr_callback; - last_int_level = DvcEnterCritical(); - scsiq = (ASC_QDONE_INFO dosfar *) & scsiq_buf; - -#if CC_LINK_BUSY_Q - _AscAbortSrbBusyQueue(asc_dvc, scsiq, srb_ptr); -#endif - - for (q_no = ASC_MIN_ACTIVE_QNO; q_no <= asc_dvc->max_total_qng; - q_no++) { - q_addr = ASC_QNO_TO_QADDR(q_no); - scsiq->d2.srb_ptr = AscReadLramDWord(iop_base, - (ushort) (q_addr + (ushort) ASC_SCSIQ_D_SRBPTR)); - if (scsiq->d2.srb_ptr == srb_ptr) { - _AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq, asc_dvc->max_dma_count); - if (((scsiq->q_status & QS_READY) != 0) && - ((scsiq->q_status & QS_ABORTED) == 0) && - ((scsiq->cntl & QCSG_SG_XFER_LIST) == 0)) { - - scsiq->q_status |= QS_ABORTED; - scsiq->d3.done_stat = QD_ABORTED_BY_HOST; - AscWriteLramDWord(iop_base, - (ushort) (q_addr + (ushort) ASC_SCSIQ_D_SRBPTR), - 0L); - AscWriteLramByte(iop_base, - (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS), - scsiq->q_status); - (*asc_isr_callback) (asc_dvc, scsiq); - return (1); - } - } - } - DvcLeaveCritical(last_int_level); - return (0); -} - -int -AscRiscHaltedAbortTIX( - ASC_DVC_VAR asc_ptr_type * asc_dvc, - uchar target_ix -) -{ - PortAddr iop_base; - ushort q_addr; - uchar q_no; - ASC_QDONE_INFO scsiq_buf; - ASC_QDONE_INFO dosfar *scsiq; - ASC_ISR_CALLBACK asc_isr_callback; - int last_int_level; - -#if CC_LINK_BUSY_Q - uchar tid_no; - -#endif - - iop_base = asc_dvc->iop_base; - asc_isr_callback = (ASC_ISR_CALLBACK) asc_dvc->isr_callback; - last_int_level = DvcEnterCritical(); - scsiq = (ASC_QDONE_INFO dosfar *) & scsiq_buf; - -#if CC_LINK_BUSY_Q - - tid_no = ASC_TIX_TO_TID(target_ix); - _AscAbortTidBusyQueue(asc_dvc, scsiq, tid_no); - -#endif - - for (q_no = ASC_MIN_ACTIVE_QNO; q_no <= asc_dvc->max_total_qng; - q_no++) { - q_addr = ASC_QNO_TO_QADDR(q_no); - _AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq, asc_dvc->max_dma_count); - if (((scsiq->q_status & QS_READY) != 0) && - ((scsiq->q_status & QS_ABORTED) == 0) && - ((scsiq->cntl & QCSG_SG_XFER_LIST) == 0)) { - if (scsiq->d2.target_ix == target_ix) { - scsiq->q_status |= QS_ABORTED; - scsiq->d3.done_stat = QD_ABORTED_BY_HOST; - - AscWriteLramDWord(iop_base, - (ushort) (q_addr + (ushort) ASC_SCSIQ_D_SRBPTR), - 0L); - - AscWriteLramByte(iop_base, - (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS), - scsiq->q_status); - (*asc_isr_callback) (asc_dvc, scsiq); - } - } - } - DvcLeaveCritical(last_int_level); - return (1); -} - -#if CC_LINK_BUSY_Q - -#endif - -int -AscHostReqRiscHalt( - PortAddr iop_base -) -{ - int count = 0; - int sta = 0; - uchar saved_stop_code; - - if (AscIsChipHalted(iop_base)) - return (1); - saved_stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B); - - AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, - ASC_STOP_HOST_REQ_RISC_HALT | ASC_STOP_REQ_RISC_STOP - ); - do { - if (AscIsChipHalted(iop_base)) { - sta = 1; - break; - } - DvcSleepMilliSecond(100); - } while (count++ < 20); - - AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, saved_stop_code); - return (sta); -} - -int -AscStopQueueExe( - PortAddr iop_base -) -{ - int count; - - count = 0; - if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) == 0) { - AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, - ASC_STOP_REQ_RISC_STOP); - do { - if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) & - ASC_STOP_ACK_RISC_STOP) { - return (1); - } - DvcSleepMilliSecond(100); - } while (count++ < 20); - } - return (0); -} - -int -AscStartQueueExe( - PortAddr iop_base -) -{ - if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) != 0) { - AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, 0); - } - return (1); -} - -int -AscCleanUpBusyQueue( - PortAddr iop_base -) -{ - int count; - uchar stop_code; - - count = 0; - if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) != 0) { - AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, - ASC_STOP_CLEAN_UP_BUSY_Q); - do { - stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B); - if ((stop_code & ASC_STOP_CLEAN_UP_BUSY_Q) == 0) - break; - DvcSleepMilliSecond(100); - } while (count++ < 20); - } - return (1); -} - -int -AscCleanUpDiscQueue( - PortAddr iop_base -) -{ - int count; - uchar stop_code; - - count = 0; - if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) != 0) { - AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, - ASC_STOP_CLEAN_UP_DISC_Q); - do { - stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B); - if ((stop_code & ASC_STOP_CLEAN_UP_DISC_Q) == 0) - break; - DvcSleepMilliSecond(100); - } while (count++ < 20); - } - return (1); -} - -int -AscWaitTixISRDone( - ASC_DVC_VAR asc_ptr_type * asc_dvc, - uchar target_ix -) -{ - uchar cur_req; - uchar tid_no; - - tid_no = ASC_TIX_TO_TID(target_ix); - while (TRUE) { - if ((cur_req = asc_dvc->cur_dvc_qng[tid_no]) == 0) { - break; - } - DvcSleepMilliSecond(1000L); - if (asc_dvc->cur_dvc_qng[tid_no] == cur_req) { - break; - } - } - return (1); -} - -int -AscWaitISRDone( - ASC_DVC_VAR asc_ptr_type * asc_dvc -) -{ - int tid; - - for (tid = 0; tid <= ASC_MAX_TID; tid++) { - AscWaitTixISRDone(asc_dvc, ASC_TID_TO_TIX(tid)); - } - return (1); -} - -ulong -AscGetOnePhyAddr( - ASC_DVC_VAR asc_ptr_type * asc_dvc, - uchar dosfar * buf_addr, - ulong buf_size -) -{ - ASC_MIN_SG_HEAD sg_head; - - sg_head.entry_cnt = ASC_MIN_SG_LIST; - if (DvcGetSGList(asc_dvc, (uchar dosfar *) buf_addr, - buf_size, (ASC_SG_HEAD dosfar *) & sg_head) != buf_size) { - return (0L); - } - if (sg_head.entry_cnt > 1) { - return (0L); - } - return (sg_head.sg_list[0].addr); -} - -ulong -AscGetEisaProductID( - PortAddr iop_base -) -{ - PortAddr eisa_iop; - ushort product_id_high, product_id_low; - ulong product_id; - - eisa_iop = ASC_GET_EISA_SLOT(iop_base) | ASC_EISA_PID_IOP_MASK; - product_id_low = inpw(eisa_iop); - product_id_high = inpw(eisa_iop + 2); - product_id = ((ulong) product_id_high << 16) | (ulong) product_id_low; - return (product_id); -} - -PortAddr -AscSearchIOPortAddrEISA( - PortAddr iop_base -) -{ - ulong eisa_product_id; - - if (iop_base == 0) { - iop_base = ASC_EISA_MIN_IOP_ADDR; - } else { - if (iop_base == ASC_EISA_MAX_IOP_ADDR) - return (0); - if ((iop_base & 0x0050) == 0x0050) { - iop_base += ASC_EISA_BIG_IOP_GAP; - } else { - iop_base += ASC_EISA_SMALL_IOP_GAP; - } - } - while (iop_base <= ASC_EISA_MAX_IOP_ADDR) { - - eisa_product_id = AscGetEisaProductID(iop_base); - if ((eisa_product_id == ASC_EISA_ID_740) || - (eisa_product_id == ASC_EISA_ID_750)) { - if (AscFindSignature(iop_base)) { - - inpw(iop_base + 4); - return (iop_base); - } - } - if (iop_base == ASC_EISA_MAX_IOP_ADDR) - return (0); - if ((iop_base & 0x0050) == 0x0050) { - iop_base += ASC_EISA_BIG_IOP_GAP; - } else { - iop_base += ASC_EISA_SMALL_IOP_GAP; - } - } - return (0); -} - -int -AscStartChip( - PortAddr iop_base -) -{ - AscSetChipControl(iop_base, 0); - if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) { - return (0); - } - return (1); -} - -int -AscStopChip( - PortAddr iop_base -) -{ - uchar cc_val; - - cc_val = AscGetChipControl(iop_base) & (~(CC_SINGLE_STEP | CC_TEST | CC_DIAG)); - AscSetChipControl(iop_base, (uchar) (cc_val | CC_HALT)); - AscSetChipIH(iop_base, INS_HALT); - AscSetChipIH(iop_base, INS_RFLAG_WTM); - if ((AscGetChipStatus(iop_base) & CSW_HALTED) == 0) { - return (0); - } - return (1); -} - -int -AscIsChipHalted( - PortAddr iop_base -) -{ - - if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) { - if ((AscGetChipControl(iop_base) & CC_HALT) != 0) { - return (1); - } - } - return (0); -} - -void -AscSetChipIH( - PortAddr iop_base, - ushort ins_code -) -{ - AscSetBank(iop_base, 1); - AscWriteChipIH(iop_base, ins_code); - AscSetBank(iop_base, 0); - return; -} - -void -AscAckInterrupt( - PortAddr iop_base -) -{ - - uchar host_flag; - uchar risc_flag; - ushort loop; - - loop = 0; - do { - risc_flag = AscReadLramByte(iop_base, ASCV_RISC_FLAG_B); - if (loop++ > 0x7FFF) { - break; - } - } while ((risc_flag & ASC_RISC_FLAG_GEN_INT) != 0); - - host_flag = AscReadLramByte(iop_base, ASCV_HOST_FLAG_B); - AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, - (uchar) (host_flag | ASC_HOST_FLAG_ACK_INT)); - - AscSetChipStatus(iop_base, CIW_INT_ACK); - loop = 0; - while (AscGetChipStatus(iop_base) & CSW_INT_PENDING) { - - AscSetChipStatus(iop_base, CIW_INT_ACK); - if (loop++ > 3) { - break; - } - } - - AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag); - return; -} - -void -AscDisableInterrupt( - PortAddr iop_base -) -{ - ushort cfg; - - cfg = AscGetChipCfgLsw(iop_base); - AscSetChipCfgLsw(iop_base, cfg & (~ASC_CFG0_HOST_INT_ON)); - return; -} - -void -AscEnableInterrupt( - PortAddr iop_base -) -{ - ushort cfg; - - cfg = AscGetChipCfgLsw(iop_base); - AscSetChipCfgLsw(iop_base, cfg | ASC_CFG0_HOST_INT_ON); - return; -} - -void -AscSetBank( - PortAddr iop_base, - uchar bank -) -{ - uchar val; - - val = AscGetChipControl(iop_base) & - (~(CC_SINGLE_STEP | CC_TEST | CC_DIAG | CC_SCSI_RESET | CC_CHIP_RESET)); - if (bank == 1) { - val |= CC_BANK_ONE; - } else if (bank == 2) { - val |= CC_DIAG | CC_BANK_ONE; - } else { - val &= ~CC_BANK_ONE; - } - AscSetChipControl(iop_base, val); - return; -} - -int -AscResetChipAndScsiBus( - PortAddr iop_base -) -{ - AscStopChip(iop_base); - AscSetChipControl(iop_base, CC_CHIP_RESET | CC_SCSI_RESET | CC_HALT); - DvcSleepMilliSecond(200); - - AscSetChipIH(iop_base, INS_RFLAG_WTM); - AscSetChipIH(iop_base, INS_HALT); - - AscSetChipControl(iop_base, CC_CHIP_RESET | CC_HALT); - AscSetChipControl(iop_base, CC_HALT); - DvcSleepMilliSecond(200); - return (AscIsChipHalted(iop_base)); -} - -ushort -AscGetIsaDmaChannel( - PortAddr iop_base -) -{ - ushort channel; - - channel = AscGetChipCfgLsw(iop_base) & 0x0003; - if (channel == 0x03) - return (0); - else if (channel == 0x00) - return (7); - return (channel + 4); -} - -ushort -AscSetIsaDmaChannel( - PortAddr iop_base, - ushort dma_channel -) -{ - ushort cfg_lsw; - uchar value; - - if ((dma_channel >= 5) && (dma_channel <= 7)) { - - if (dma_channel == 7) - value = 0x00; - else - value = dma_channel - 4; - cfg_lsw = AscGetChipCfgLsw(iop_base) & 0xFFFC; - cfg_lsw |= value; - AscSetChipCfgLsw(iop_base, cfg_lsw); - return (AscGetIsaDmaChannel(iop_base)); - } - return (0); -} - -uchar -AscSetIsaDmaSpeed( - PortAddr iop_base, - uchar speed_value -) -{ - speed_value &= 0x07; - AscSetBank(iop_base, 1); - AscSetChipDmaSpeed(iop_base, speed_value); - AscSetBank(iop_base, 0); - return (AscGetIsaDmaSpeed(iop_base)); -} - -uchar -AscGetIsaDmaSpeed( - PortAddr iop_base -) -{ - uchar speed_value; - - AscSetBank(iop_base, 1); - speed_value = AscGetChipDmaSpeed(iop_base); - speed_value &= 0x07; - AscSetBank(iop_base, 0); - return (speed_value); -} - -ulong -AscGetMaxDmaCount( - ushort bus_type -) -{ - if (bus_type & ASC_IS_ISA) - return (ASC_MAX_ISA_DMA_COUNT); - else if (bus_type & (ASC_IS_EISA | ASC_IS_VL)) - return (ASC_MAX_VL_DMA_COUNT); - return (ASC_MAX_PCI_DMA_COUNT); -} - -ushort -AscInitGetConfig( - ASC_DVC_VAR asc_ptr_type * asc_dvc -) -{ - ushort warn_code; - - warn_code = 0; - asc_dvc->init_state = ASC_INIT_STATE_BEG_GET_CFG; - if (asc_dvc->err_code != 0) - return (UW_ERR); - if (AscFindSignature(asc_dvc->iop_base)) { - warn_code |= AscInitAscDvcVar(asc_dvc); - warn_code |= AscInitFromEEP(asc_dvc); - asc_dvc->init_state |= ASC_INIT_STATE_END_GET_CFG; - - if (asc_dvc->scsi_reset_wait > 10) - asc_dvc->scsi_reset_wait = 10; - - } else { - asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE; - } - return (warn_code); -} - -ushort -AscInitSetConfig( - ASC_DVC_VAR asc_ptr_type * asc_dvc -) -{ - ushort warn_code; - - warn_code = 0; - asc_dvc->init_state |= ASC_INIT_STATE_BEG_SET_CFG; - if (asc_dvc->err_code != 0) - return (UW_ERR); - if (AscFindSignature(asc_dvc->iop_base)) { - warn_code |= AscInitFromAscDvcVar(asc_dvc); - asc_dvc->init_state |= ASC_INIT_STATE_END_SET_CFG; - } else { - asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE; - } - return (warn_code); -} - -ushort -AscInitAsc1000Driver( - ASC_DVC_VAR asc_ptr_type * asc_dvc -) -{ - ushort warn_code; - PortAddr iop_base; - - extern ushort _mcode_size; - extern ulong _mcode_chksum; - extern uchar _mcode_buf[]; - - ASC_DBG(3, "AscInitAsc1000Driver: begin\n"); - iop_base = asc_dvc->iop_base; - warn_code = 0; - - if ((asc_dvc->dvc_cntl & ASC_CNTL_RESET_SCSI) && - !(asc_dvc->init_state & ASC_INIT_RESET_SCSI_DONE)) { - - ASC_DBG(3, "AscInitAsc1000Driver: AscResetChipAndScsiBus()\n"); - AscResetChipAndScsiBus(iop_base); - DvcSleepMilliSecond((ulong) ((ushort) asc_dvc->scsi_reset_wait * 1000)); - } - asc_dvc->init_state |= ASC_INIT_STATE_BEG_LOAD_MC; - if (asc_dvc->err_code != 0) - return (UW_ERR); - ASC_DBG(3, "AscInitAsc1000Driver: AscFindSignature()\n"); - if (!AscFindSignature(asc_dvc->iop_base)) { - asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE; - return (warn_code); - } - ASC_DBG(3, "AscInitAsc1000Driver: AscDisableInterrupt()\n"); - AscDisableInterrupt(iop_base); - - ASC_DBG(3, "AscInitAsc1000Driver: AscInitLram()\n"); - warn_code |= AscInitLram(asc_dvc); - if (asc_dvc->err_code != 0) - return (UW_ERR); - ASC_DBG(3, "AscInitAsc1000Driver: AscLoadMicroCode()\n"); - if (AscLoadMicroCode(iop_base, 0, (ushort dosfar *) _mcode_buf, - _mcode_size) != _mcode_chksum) { - asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM; - return (warn_code); - } - ASC_DBG(3, "AscInitAsc1000Driver: AscInitMicroCodeVar()\n"); - warn_code |= AscInitMicroCodeVar(asc_dvc); - asc_dvc->init_state |= ASC_INIT_STATE_END_LOAD_MC; - ASC_DBG(3, "AscInitAsc1000Driver: AscEnableInterrupt()\n"); - AscEnableInterrupt(iop_base); - return (warn_code); -} - -ushort -AscInitAscDvcVar( - ASC_DVC_VAR asc_ptr_type * asc_dvc -) -{ - int i; - PortAddr iop_base; - ushort warn_code; - - iop_base = asc_dvc->iop_base; - warn_code = 0; - asc_dvc->err_code = 0; - - if ((asc_dvc->bus_type & - (ASC_IS_ISA | ASC_IS_PCI | ASC_IS_EISA | ASC_IS_VL)) == 0) { - asc_dvc->err_code |= ASC_IERR_NO_BUS_TYPE; - } -#if CC_LINK_BUSY_Q - for (i = 0; i <= ASC_MAX_TID; i++) { - asc_dvc->scsiq_busy_head[i] = (ASC_SCSI_Q dosfar *) 0L; - asc_dvc->scsiq_busy_tail[i] = (ASC_SCSI_Q dosfar *) 0L; - } -#endif - - asc_dvc->dvc_cntl = ASC_DEF_DVC_CNTL; - asc_dvc->bug_fix_cntl = 0; - asc_dvc->pci_fix_asyn_xfer = 0; - asc_dvc->init_sdtr = 0; - asc_dvc->sdtr_done = 0; - asc_dvc->max_total_qng = ASC_DEF_MAX_TOTAL_QNG; - asc_dvc->cur_total_qng = 0; - asc_dvc->is_in_int = 0; - asc_dvc->scsi_reset_wait = 3; - asc_dvc->in_critical_cnt = 0; - - asc_dvc->last_q_shortage = 0; - asc_dvc->use_tagged_qng = 0; - asc_dvc->cfg->can_tagged_qng = 0; - asc_dvc->no_scam = 0; - asc_dvc->irq_no = 10; - asc_dvc->start_motor = ASC_SCSI_WIDTH_BIT_SET; - asc_dvc->cfg->disc_enable = ASC_SCSI_WIDTH_BIT_SET; - asc_dvc->cfg->cmd_qng_enabled = ASC_SCSI_WIDTH_BIT_SET; - asc_dvc->cfg->chip_scsi_id = ASC_DEF_CHIP_SCSI_ID; - asc_dvc->cfg->chip_version = AscGetChipVersion(iop_base, - asc_dvc->bus_type); - if (AscGetChipBusType(iop_base) == ASC_IS_ISAPNP) { - - AscPutChipIFC(iop_base, IFC_INIT_DEFAULT); - asc_dvc->bus_type = ASC_IS_ISAPNP; - } - asc_dvc->unit_not_ready = 0; - asc_dvc->queue_full_or_busy = 0; - - if ((asc_dvc->bus_type & ASC_IS_ISA) != 0) { - asc_dvc->cfg->isa_dma_channel = (uchar) AscGetIsaDmaChannel(iop_base); - asc_dvc->cfg->isa_dma_speed = ASC_DEF_ISA_DMA_SPEED; - } - asc_dvc->cfg->lib_serial_no = ASC_LIB_SERIAL_NUMBER; - asc_dvc->cfg->lib_version = (ASC_LIB_VERSION_MAJOR << 8) | - ASC_LIB_VERSION_MINOR; - asc_dvc->int_count = 0L; - asc_dvc->req_count = 0L; - asc_dvc->busy_count = 0L; - asc_dvc->max_dma_count = AscGetMaxDmaCount(asc_dvc->bus_type); - - for (i = 0; i <= ASC_MAX_TID; i++) { - asc_dvc->cfg->sdtr_data[i] = - (uchar) (ASC_DEF_SDTR_OFFSET | (ASC_DEF_SDTR_INDEX << 4)); - asc_dvc->cur_dvc_qng[i] = 0; - asc_dvc->max_dvc_qng[i] = ASC_MAX_SCSI1_QNG; - asc_dvc->scsiq_busy_head[i] = (ASC_SCSI_Q dosfar *) 0L; - asc_dvc->scsiq_busy_tail[i] = (ASC_SCSI_Q dosfar *) 0L; - } - return (warn_code); -} - -ushort -AscInitFromAscDvcVar( - ASC_DVC_VAR asc_ptr_type * asc_dvc -) -{ - PortAddr iop_base; - ushort cfg_msw; - ushort warn_code; - - iop_base = asc_dvc->iop_base; - warn_code = 0; - - cfg_msw = AscGetChipCfgMsw(iop_base); - - if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) { - cfg_msw &= (~(ASC_CFG_MSW_CLR_MASK)); - warn_code |= ASC_WARN_CFG_MSW_RECOVER; - AscSetChipCfgMsw(iop_base, cfg_msw); - } - if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) { - warn_code |= ASC_WARN_AUTO_CONFIG; - - } - if ((asc_dvc->cfg->cmd_qng_enabled & asc_dvc->cfg->disc_enable) != - asc_dvc->cfg->cmd_qng_enabled) { - asc_dvc->cfg->disc_enable = asc_dvc->cfg->cmd_qng_enabled; - warn_code |= ASC_WARN_CMD_QNG_CONFLICT; - } - if ((asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL)) != 0) { - - if (AscSetChipIRQ(iop_base, asc_dvc->irq_no, asc_dvc->bus_type) - != asc_dvc->irq_no) { - asc_dvc->err_code |= ASC_IERR_SET_IRQ_NO; - } - } - if (AscSetChipScsiID(iop_base, asc_dvc->cfg->chip_scsi_id) != - asc_dvc->cfg->chip_scsi_id) { - asc_dvc->err_code |= ASC_IERR_SET_SCSI_ID; - } - if ((asc_dvc->bus_type & ASC_IS_ISA) != 0) { - AscSetIsaDmaChannel(iop_base, asc_dvc->cfg->isa_dma_channel); - AscSetIsaDmaSpeed(iop_base, asc_dvc->cfg->isa_dma_speed); - } - return (warn_code); -} - -ushort -AscInitFromEEP( - ASC_DVC_VAR asc_ptr_type * asc_dvc -) -{ - ASCEEP_CONFIG eep_config_buf; - ASCEEP_CONFIG dosfar *eep_config; - PortAddr iop_base; - ushort chksum; - ushort warn_code; - ushort cfg_msw, cfg_lsw; - uchar i; - - iop_base = asc_dvc->iop_base; - warn_code = 0; - - AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0x00FE); - - AscStopQueueExe(iop_base); - if ((AscStopChip(iop_base) == FALSE) || - (AscGetChipScsiCtrl(iop_base) != 0)) { - asc_dvc->init_state |= ASC_INIT_RESET_SCSI_DONE; - AscResetChipAndScsiBus(iop_base); - DvcSleepMilliSecond((ulong) ((ushort) asc_dvc->scsi_reset_wait * 1000)); - } - if (AscIsChipHalted(iop_base) == FALSE) { - asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP; - return (warn_code); - } - AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR); - if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) { - asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR; - return (warn_code); - } - eep_config = (ASCEEP_CONFIG dosfar *) & eep_config_buf; - - cfg_msw = AscGetChipCfgMsw(iop_base); - cfg_lsw = AscGetChipCfgLsw(iop_base); - - if (asc_dvc->bus_type & ASC_IS_PCI) { -#if CC_DISABLE_PCI_PARITY_INT - cfg_msw &= 0xFFC0; - AscSetChipCfgMsw(iop_base, cfg_msw); -#endif - if (asc_dvc->cfg->pci_device_id == ASC_PCI_DEVICE_ID_REV_A) { - asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_ADD_ONE_BYTE; - } - } - if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) { - cfg_msw &= (~(ASC_CFG_MSW_CLR_MASK)); - warn_code |= ASC_WARN_CFG_MSW_RECOVER; - AscSetChipCfgMsw(iop_base, cfg_msw); - } - chksum = AscGetEEPConfig(iop_base, eep_config, asc_dvc->bus_type); - - eep_config->cfg_msw &= (~(ASC_CFG_MSW_CLR_MASK)); - - if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) { - warn_code |= ASC_WARN_AUTO_CONFIG; - - if (asc_dvc->cfg->chip_version == 3) { - - if (eep_config->cfg_lsw != cfg_lsw) { - warn_code |= ASC_WARN_EEPROM_RECOVER; - eep_config->cfg_lsw = AscGetChipCfgLsw(iop_base); - } - if (eep_config->cfg_msw != cfg_msw) { - warn_code |= ASC_WARN_EEPROM_RECOVER; - eep_config->cfg_msw = AscGetChipCfgMsw(iop_base); - } - } - } - eep_config->cfg_lsw |= ASC_CFG0_HOST_INT_ON; - if (chksum != eep_config->chksum) { - warn_code |= ASC_WARN_EEPROM_CHKSUM; - } - asc_dvc->init_sdtr = eep_config->init_sdtr; - asc_dvc->cfg->disc_enable = eep_config->disc_enable; - - asc_dvc->cfg->cmd_qng_enabled = eep_config->use_cmd_qng; - asc_dvc->cfg->isa_dma_speed = eep_config->isa_dma_speed; - asc_dvc->start_motor = eep_config->start_motor; - asc_dvc->dvc_cntl = eep_config->cntl; - asc_dvc->no_scam = eep_config->no_scam; - - if ((asc_dvc->bus_type & ASC_IS_PCI) && - !(asc_dvc->dvc_cntl & ASC_CNTL_NO_PCI_FIX_ASYN_XFER)) { - if ((asc_dvc->cfg->pci_device_id == ASC_PCI_DEVICE_ID_REV_A) || - (asc_dvc->cfg->pci_device_id == ASC_PCI_DEVICE_ID_REV_B)) { - asc_dvc->pci_fix_asyn_xfer = ASC_ALL_DEVICE_BIT_SET; - } - } else if (asc_dvc->bus_type & ASC_IS_ISAPNP) { - - if (AscGetChipVersion(iop_base, asc_dvc->bus_type) - == ASC_CHIP_VER_ASYN_BUG) { - asc_dvc->pci_fix_asyn_xfer = ASC_ALL_DEVICE_BIT_SET; - } - } - if (!AscTestExternalLram(asc_dvc)) { - if (asc_dvc->bus_type & ASC_IS_PCI) { - eep_config->cfg_msw |= 0x0800; - cfg_msw |= 0x0800; - AscSetChipCfgMsw(iop_base, cfg_msw); - eep_config->max_total_qng = ASC_MAX_PCI_INRAM_TOTAL_QNG; - eep_config->max_tag_qng = ASC_MAX_INRAM_TAG_QNG; - } - } else { -#if CC_TEST_RW_LRAM - asc_dvc->err_code |= AscTestLramEndian(iop_base); -#endif - } - if (eep_config->max_total_qng < ASC_MIN_TOTAL_QNG) { - eep_config->max_total_qng = ASC_MIN_TOTAL_QNG; - } - if (eep_config->max_total_qng > ASC_MAX_TOTAL_QNG) { - eep_config->max_total_qng = ASC_MAX_TOTAL_QNG; - } - if (eep_config->max_tag_qng > eep_config->max_total_qng) { - eep_config->max_tag_qng = eep_config->max_total_qng; - } - if (eep_config->max_tag_qng < ASC_MIN_TAG_Q_PER_DVC) { - eep_config->max_tag_qng = ASC_MIN_TAG_Q_PER_DVC; - } - asc_dvc->max_total_qng = eep_config->max_total_qng; - - if ((eep_config->use_cmd_qng & eep_config->disc_enable) != - eep_config->use_cmd_qng) { - eep_config->disc_enable = eep_config->use_cmd_qng; - warn_code |= ASC_WARN_CMD_QNG_CONFLICT; - } - asc_dvc->irq_no = AscGetChipIRQ(iop_base, asc_dvc->bus_type); - eep_config->chip_scsi_id &= ASC_MAX_TID; - asc_dvc->cfg->chip_scsi_id = eep_config->chip_scsi_id; - - for (i = 0; i <= ASC_MAX_TID; i++) { - asc_dvc->cfg->sdtr_data[i] = eep_config->sdtr_data[i]; - asc_dvc->cfg->max_tag_qng[i] = eep_config->max_tag_qng; - } - - eep_config->cfg_msw = AscGetChipCfgMsw(iop_base); - if (AscSetEEPConfig(iop_base, eep_config, asc_dvc->bus_type) != 0) { - asc_dvc->err_code |= ASC_IERR_WRITE_EEPROM; - } - return (warn_code); -} - -ushort -AscInitMicroCodeVar( - ASC_DVC_VAR asc_ptr_type * asc_dvc -) -{ - int i; - ushort warn_code; - PortAddr iop_base; - ulong phy_addr; - - iop_base = asc_dvc->iop_base; - warn_code = 0; - for (i = 0; i <= ASC_MAX_TID; i++) { - AscWriteLramByte(iop_base, (ushort) (ASCV_SDTR_DATA_BEG + i), - asc_dvc->cfg->sdtr_data[i]); - } - - AscInitQLinkVar(asc_dvc); - - AscWriteLramByte(iop_base, ASCV_DISC_ENABLE_B, - asc_dvc->cfg->disc_enable); - AscWriteLramByte(iop_base, ASCV_HOSTSCSI_ID_B, - ASC_TID_TO_TARGET_ID(asc_dvc->cfg->chip_scsi_id)); - if ((phy_addr = AscGetOnePhyAddr(asc_dvc, - (uchar dosfar *) asc_dvc->cfg->overrun_buf, - ASC_OVERRUN_BSIZE)) == 0L) { - asc_dvc->err_code |= ASC_IERR_GET_PHY_ADDR; - } else { - - phy_addr = (phy_addr & 0xFFFFFFF8UL) + 8; - AscWriteLramDWord(iop_base, ASCV_OVERRUN_PADDR_D, phy_addr); - AscWriteLramDWord(iop_base, ASCV_OVERRUN_BSIZE_D, - ASC_OVERRUN_BSIZE - 8); - } - - asc_dvc->cfg->mcode_date = AscReadLramWord(iop_base, - (ushort) ASCV_MC_DATE_W); - asc_dvc->cfg->mcode_version = AscReadLramWord(iop_base, - (ushort) ASCV_MC_VER_W); - AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR); - if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) { - asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR; - return (warn_code); - } - if (AscStartChip(iop_base) != 1) { - asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP; - return (warn_code); - } - return (warn_code); -} - -void dosfar -AscInitPollIsrCallBack( - ASC_DVC_VAR asc_ptr_type * asc_dvc, - ASC_QDONE_INFO dosfar * scsi_done_q -) -{ - ASC_SCSI_REQ_Q dosfar *scsiq_req; - ASC_ISR_CALLBACK asc_isr_callback; - uchar cp_sen_len; - uchar i; - - if ((scsi_done_q->d2.flag & ASC_FLAG_SCSIQ_REQ) != 0) { - scsiq_req = (ASC_SCSI_REQ_Q dosfar *) scsi_done_q->d2.srb_ptr; - ASC_DBG2(3, "AscInitPollIsrCallBack: done_stat %x, host_stat %x\n", - scsiq_req->r3.done_stat, scsiq_req->r3.host_stat); - scsiq_req->r3.done_stat = scsi_done_q->d3.done_stat; - scsiq_req->r3.host_stat = scsi_done_q->d3.host_stat; - scsiq_req->r3.scsi_stat = scsi_done_q->d3.scsi_stat; - scsiq_req->r3.scsi_msg = scsi_done_q->d3.scsi_msg; - if ((scsi_done_q->d3.scsi_stat == SS_CHK_CONDITION) && - (scsi_done_q->d3.host_stat == 0)) { - cp_sen_len = (uchar) ASC_MIN_SENSE_LEN; - if (scsiq_req->r1.sense_len < ASC_MIN_SENSE_LEN) { - cp_sen_len = (uchar) scsiq_req->r1.sense_len; - } - for (i = 0; i < cp_sen_len; i++) { - scsiq_req->sense[i] = scsiq_req->sense_ptr[i]; - } - } - } else { - ASC_DBG1(3, "AscInitPollIsrCallBack: isr_callback %x\n", - (unsigned) asc_dvc->isr_callback); - if (asc_dvc->isr_callback != 0) { - asc_isr_callback = (ASC_ISR_CALLBACK) asc_dvc->isr_callback; - (*asc_isr_callback) (asc_dvc, scsi_done_q); - } - } - return; -} - -int -AscTestExternalLram( - ASC_DVC_VAR asc_ptr_type * asc_dvc -) -{ - PortAddr iop_base; - ushort q_addr; - ushort saved_word; - int sta; - - iop_base = asc_dvc->iop_base; - sta = 0; - - q_addr = ASC_QNO_TO_QADDR(241); - saved_word = AscReadLramWord(iop_base, q_addr); - if (AscVerWriteLramWord(iop_base, q_addr, 0x55AA) == 0) { - sta = 1; - AscWriteLramWord(iop_base, q_addr, saved_word); - } - return (sta); -} - -#if CC_TEST_LRAM_ENDIAN - -#endif - -int -AscWriteEEPCmdReg( - PortAddr iop_base, - uchar cmd_reg -) -{ - uchar read_back; - int retry; - - retry = 0; - while (TRUE) { - AscSetChipEEPCmd(iop_base, cmd_reg); - DvcSleepMilliSecond(1); - read_back = AscGetChipEEPCmd(iop_base); - if (read_back == cmd_reg) { - return (1); - } - if (retry++ > ASC_EEP_MAX_RETRY) { - return (0); - } - } -} - -int -AscWriteEEPDataReg( - PortAddr iop_base, - ushort data_reg -) -{ - ushort read_back; - int retry; - - retry = 0; - while (TRUE) { - AscSetChipEEPData(iop_base, data_reg); - DvcSleepMilliSecond(1); - read_back = AscGetChipEEPData(iop_base); - if (read_back == data_reg) { - return (1); - } - if (retry++ > ASC_EEP_MAX_RETRY) { - return (0); - } - } -} - -void -AscWaitEEPRead( - void -) -{ - DvcSleepMilliSecond(1); - return; -} - -void -AscWaitEEPWrite( - void -) -{ - DvcSleepMilliSecond(20); - return; -} - -ushort -AscReadEEPWord( - PortAddr iop_base, - uchar addr -) -{ - ushort read_wval; - uchar cmd_reg; - - AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE); - AscWaitEEPRead(); - cmd_reg = addr | ASC_EEP_CMD_READ; - AscWriteEEPCmdReg(iop_base, cmd_reg); - AscWaitEEPRead(); - read_wval = AscGetChipEEPData(iop_base); - AscWaitEEPRead(); - return (read_wval); -} - -ushort -AscWriteEEPWord( - PortAddr iop_base, - uchar addr, - ushort word_val -) -{ - ushort read_wval; - - read_wval = AscReadEEPWord(iop_base, addr); - if (read_wval != word_val) { - AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_ABLE); - AscWaitEEPRead(); - - AscWriteEEPDataReg(iop_base, word_val); - AscWaitEEPRead(); - - AscWriteEEPCmdReg(iop_base, - (uchar) ((uchar) ASC_EEP_CMD_WRITE | addr)); - AscWaitEEPWrite(); - - AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE); - AscWaitEEPRead(); - return (AscReadEEPWord(iop_base, addr)); - } - return (read_wval); -} - -ushort -AscGetEEPConfig( - PortAddr iop_base, - ASCEEP_CONFIG dosfar * cfg_buf, ushort bus_type -) -{ - ushort wval; - ushort sum; - ushort dosfar *wbuf; - int cfg_beg; - int cfg_end; - int s_addr; - int isa_pnp_wsize; - - wbuf = (ushort dosfar *) cfg_buf; - sum = 0; - - isa_pnp_wsize = 0; - for (s_addr = 0; s_addr < (2 + isa_pnp_wsize); s_addr++, wbuf++) { - wval = AscReadEEPWord(iop_base, (uchar) s_addr); - sum += wval; - *wbuf = wval; - } - - if (bus_type & ASC_IS_VL) { - cfg_beg = ASC_EEP_DVC_CFG_BEG_VL; - cfg_end = ASC_EEP_MAX_DVC_ADDR_VL; - } else { - cfg_beg = ASC_EEP_DVC_CFG_BEG; - cfg_end = ASC_EEP_MAX_DVC_ADDR; - } - - for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); - s_addr++, wbuf++) { - wval = AscReadEEPWord(iop_base, (uchar) s_addr); - sum += wval; - *wbuf = wval; - } - *wbuf = AscReadEEPWord(iop_base, (uchar) s_addr); - return (sum); -} - -int -AscSetEEPConfigOnce( - PortAddr iop_base, - ASCEEP_CONFIG dosfar * cfg_buf, ushort bus_type -) -{ - int n_error; - ushort dosfar *wbuf; - ushort sum; - int s_addr; - int cfg_beg; - int cfg_end; - - wbuf = (ushort dosfar *) cfg_buf; - n_error = 0; - sum = 0; - for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) { - sum += *wbuf; - if (*wbuf != AscWriteEEPWord(iop_base, (uchar) s_addr, *wbuf)) { - n_error++; - } - } - if (bus_type & ASC_IS_VL) { - cfg_beg = ASC_EEP_DVC_CFG_BEG_VL; - cfg_end = ASC_EEP_MAX_DVC_ADDR_VL; - } else { - cfg_beg = ASC_EEP_DVC_CFG_BEG; - cfg_end = ASC_EEP_MAX_DVC_ADDR; - } - for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); - s_addr++, wbuf++) { - sum += *wbuf; - if (*wbuf != AscWriteEEPWord(iop_base, (uchar) s_addr, *wbuf)) { - n_error++; - } - } - *wbuf = sum; - if (sum != AscWriteEEPWord(iop_base, (uchar) s_addr, sum)) { - n_error++; - } - wbuf = (ushort dosfar *) cfg_buf; - for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) { - if (*wbuf != AscReadEEPWord(iop_base, (uchar) s_addr)) { - n_error++; - } - } - for (s_addr = cfg_beg; s_addr <= cfg_end; - s_addr++, wbuf++) { - if (*wbuf != AscReadEEPWord(iop_base, (uchar) s_addr)) { - n_error++; - } - } - return (n_error); -} - -int -AscSetEEPConfig( - PortAddr iop_base, - ASCEEP_CONFIG dosfar * cfg_buf, ushort bus_type -) -{ - int retry; - int n_error; - - retry = 0; - while (TRUE) { - if ((n_error = AscSetEEPConfigOnce(iop_base, cfg_buf, - bus_type)) == 0) { - break; - } - if (++retry > ASC_EEP_MAX_RETRY) { - break; - } - } - return (n_error); -} - -int -AscInitPollBegin( - ASC_DVC_VAR asc_ptr_type * asc_dvc -) -{ - PortAddr iop_base; - - iop_base = asc_dvc->iop_base; - -#if CC_INIT_INQ_DISPLAY - DvcDisplayString((uchar dosfar *) "\r\n"); -#endif - - AscDisableInterrupt(iop_base); - - asc_dvc->init_state |= ASC_INIT_STATE_BEG_INQUIRY; - - AscWriteLramByte(iop_base, ASCV_DISC_ENABLE_B, 0x00); - asc_dvc->use_tagged_qng = 0; - asc_dvc->cfg->can_tagged_qng = 0; - asc_dvc->saved_ptr2func = (ulong) asc_dvc->isr_callback; - asc_dvc->isr_callback = ASC_GET_PTR2FUNC(AscInitPollIsrCallBack); - return (0); -} - -int -AscInitPollEnd( - ASC_DVC_VAR asc_ptr_type * asc_dvc -) -{ - PortAddr iop_base; - int i; - - iop_base = asc_dvc->iop_base; - asc_dvc->isr_callback = (Ptr2Func) asc_dvc->saved_ptr2func; - AscWriteLramByte(iop_base, ASCV_DISC_ENABLE_B, - asc_dvc->cfg->disc_enable); - AscWriteLramByte(iop_base, ASCV_USE_TAGGED_QNG_B, - asc_dvc->use_tagged_qng); - AscWriteLramByte(iop_base, ASCV_CAN_TAGGED_QNG_B, - asc_dvc->cfg->can_tagged_qng); - - for (i = 0; i <= ASC_MAX_TID; i++) { - AscWriteLramByte(iop_base, - (ushort) ((ushort) ASCV_MAX_DVC_QNG_BEG + (ushort) i), - asc_dvc->max_dvc_qng[i]); - } - - AscEnableInterrupt(iop_base); - -#if CC_INIT_INQ_DISPLAY - DvcDisplayString((uchar dosfar *) "\r\n"); -#endif - asc_dvc->init_state |= ASC_INIT_STATE_END_INQUIRY; - - return (0); -} - -int _asc_wait_slow_device_ = FALSE; - -int -AscInitPollTarget( - ASC_DVC_VAR asc_ptr_type * asc_dvc, - ASC_SCSI_REQ_Q dosfar * scsiq, - ASC_SCSI_INQUIRY dosfar * inq, - ASC_CAP_INFO dosfar * cap_info -) -{ - uchar tid_no, lun; - uchar dvc_type; - ASC_SCSI_BIT_ID_TYPE tid_bits; - int dvc_found; - int support_read_cap; - int tmp_disable_init_sdtr; - ulong phy_addr; - - dvc_found = 0; - tmp_disable_init_sdtr = FALSE; - tid_bits = scsiq->r1.target_id; - lun = scsiq->r1.target_lun; - tid_no = ASC_TIX_TO_TID(scsiq->r2.target_ix); - if ((phy_addr = AscGetOnePhyAddr(asc_dvc, - (uchar dosfar *) scsiq->sense_ptr, - (ulong) scsiq->r1.sense_len)) == 0L) { - return (ERR); - } - scsiq->r1.sense_addr = phy_addr; - if (((asc_dvc->init_sdtr & tid_bits) != 0) && - ((asc_dvc->sdtr_done & tid_bits) == 0)) { - - asc_dvc->init_sdtr &= ~tid_bits; - tmp_disable_init_sdtr = TRUE; - } - ASC_DBG(3, "AscInitPollTarget: PollScsiInquiry()\n"); - if (PollScsiInquiry(asc_dvc, scsiq, (uchar dosfar *) inq, - sizeof (ASC_SCSI_INQUIRY)) == 1) { - dvc_found = 1; - support_read_cap = TRUE; - dvc_type = inq->byte0.peri_dvc_type; - if (dvc_type != SCSI_TYPE_UNKNOWN) { - if ((dvc_type != SCSI_TYPE_DASD) && - (dvc_type != SCSI_TYPE_WORM) && - (dvc_type != SCSI_TYPE_CDROM) && - (dvc_type != SCSI_TYPE_OPTMEM)) { - asc_dvc->start_motor &= ~tid_bits; - support_read_cap = FALSE; - } - if ((dvc_type != SCSI_TYPE_DASD) || - inq->byte1.rmb) { - - if (!_asc_wait_slow_device_) { - DvcSleepMilliSecond(3000 - ((int) tid_no * 250)); - _asc_wait_slow_device_ = TRUE; - } - } -#if CC_INIT_INQ_DISPLAY - AscDispInquiry(tid_no, lun, inq); -#endif - - if (lun == 0) { - - if ((inq->byte3.rsp_data_fmt >= 2) || - (inq->byte2.ansi_apr_ver >= 2)) { - - if (inq->byte7.CmdQue) { - asc_dvc->cfg->can_tagged_qng |= tid_bits; - if (asc_dvc->cfg->cmd_qng_enabled & tid_bits) { - asc_dvc->use_tagged_qng |= tid_bits; - asc_dvc->max_dvc_qng[tid_no] = - asc_dvc->cfg->max_tag_qng[tid_no]; - } - } - if (!inq->byte7.Sync) { - - asc_dvc->init_sdtr &= ~tid_bits; - asc_dvc->sdtr_done &= ~tid_bits; - } else if (tmp_disable_init_sdtr) { - - asc_dvc->init_sdtr |= tid_bits; - } - } else { - - asc_dvc->init_sdtr &= ~tid_bits; - asc_dvc->sdtr_done &= ~tid_bits; - asc_dvc->use_tagged_qng &= ~tid_bits; - } - } - if (asc_dvc->pci_fix_asyn_xfer & tid_bits) { - if (!(asc_dvc->init_sdtr & tid_bits)) { - - AscSetRunChipSynRegAtID(asc_dvc->iop_base, tid_no, - ASYN_SDTR_DATA_FIX_PCI_REV_AB); - } - } - ASC_DBG(3, "AscInitPollTarget: InitTestUnitReady()\n"); - if (InitTestUnitReady(asc_dvc, scsiq) != 1) { - - } else { - if ((cap_info != 0L) && support_read_cap) { - ASC_DBG(3, "AscInitPollTarget: PollScsiReadCapacity()\n"); - if (PollScsiReadCapacity(asc_dvc, scsiq, - cap_info) != 1) { - cap_info->lba = 0L; - cap_info->blk_size = 0x0000; - } else { - - } - } - } - } else { - asc_dvc->start_motor &= ~tid_bits; - } - } else { - - } - return (dvc_found); -} - -int -PollQueueDone( - ASC_DVC_VAR asc_ptr_type * asc_dvc, - ASC_SCSI_REQ_Q dosfar * scsiq, - int timeout_sec -) -{ - int status; - int retry; - - retry = 0; - do { - ASC_DBG(3, "PollQueueDone: AscExeScsiQueue()\n"); - if ((status = AscExeScsiQueue(asc_dvc, - (ASC_SCSI_Q dosfar *) scsiq)) == 1) { - ASC_DBG(3, "PollQueueDone: AscPollQDone()\n"); - if ((status = AscPollQDone(asc_dvc, scsiq, - timeout_sec)) != 1) { - ASC_DBG1(3, "PollQueueDone: AscPollQDone() status %x\n", status); - if (status == 0x80) { - if (retry++ > ASC_MAX_INIT_BUSY_RETRY) { - break; - } - scsiq->r3.done_stat = 0; - scsiq->r3.host_stat = 0; - scsiq->r3.scsi_stat = 0; - scsiq->r3.scsi_msg = 0; - DvcSleepMilliSecond(100); - continue; - } - scsiq->r3.done_stat = 0; - scsiq->r3.host_stat = 0; - scsiq->r3.scsi_stat = 0; - scsiq->r3.scsi_msg = 0; - ASC_DBG1(3, "PollQueueDone: AscAbortSRB() scsiq %x\n", - (unsigned) scsiq); - - AscAbortSRB(asc_dvc, (ulong) scsiq); - } - ASC_DBG1(3, "PollQueueDone: done_stat %x\n", scsiq->r3.done_stat); - return (scsiq->r3.done_stat); - } - } while ((status == 0) || (status == 0x80)); - ASC_DBG(3, "PollQueueDone: done_stat QD_WITH_ERROR\n"); - return (scsiq->r3.done_stat = QD_WITH_ERROR); -} - -int -PollScsiInquiry( - ASC_DVC_VAR asc_ptr_type * asc_dvc, - ASC_SCSI_REQ_Q dosfar * scsiq, - uchar dosfar * buf, - int buf_len -) -{ - if (AscScsiInquiry(asc_dvc, scsiq, buf, buf_len) == ERR) { - return (scsiq->r3.done_stat = QD_WITH_ERROR); - } - return (PollQueueDone(asc_dvc, (ASC_SCSI_REQ_Q dosfar *) scsiq, 4)); -} - -int -PollScsiReadCapacity( - ASC_DVC_VAR asc_ptr_type * asc_dvc, - ASC_SCSI_REQ_Q dosfar * scsiq, - ASC_CAP_INFO dosfar * cap_info -) -{ - ASC_CAP_INFO scsi_cap_info; - int status; - - if (AscScsiReadCapacity(asc_dvc, scsiq, - (uchar dosfar *) & scsi_cap_info) == ERR) { - return (scsiq->r3.done_stat = QD_WITH_ERROR); - } - status = PollQueueDone(asc_dvc, (ASC_SCSI_REQ_Q dosfar *) scsiq, 8); - if (status == 1) { -#if CC_LITTLE_ENDIAN_HOST - cap_info->lba = (ulong) * swapfarbuf4((uchar dosfar *) & scsi_cap_info.lba); - cap_info->blk_size = (ulong) * swapfarbuf4((uchar dosfar *) & scsi_cap_info.blk_size); -#else - cap_info->lba = scsi_cap_info.lba; - cap_info->blk_size = scsi_cap_info.blk_size; -#endif - return (scsiq->r3.done_stat); - } - return (scsiq->r3.done_stat = QD_WITH_ERROR); -} - -ulong dosfar * -swapfarbuf4( - uchar dosfar * buf -) -{ - uchar tmp; - - tmp = buf[3]; - buf[3] = buf[0]; - buf[0] = tmp; - - tmp = buf[1]; - buf[1] = buf[2]; - buf[2] = tmp; - - return ((ulong dosfar *) buf); -} - -int -PollScsiTestUnitReady( - ASC_DVC_VAR asc_ptr_type * asc_dvc, - ASC_SCSI_REQ_Q dosfar * scsiq -) -{ - if (AscScsiTestUnitReady(asc_dvc, scsiq) == ERR) { - return (scsiq->r3.done_stat = QD_WITH_ERROR); - } - return (PollQueueDone(asc_dvc, (ASC_SCSI_REQ_Q dosfar *) scsiq, 12)); -} - -int -PollScsiStartUnit( - ASC_DVC_VAR asc_ptr_type * asc_dvc, - ASC_SCSI_REQ_Q dosfar * scsiq -) -{ - if (AscScsiStartStopUnit(asc_dvc, scsiq, 1) == ERR) { - return (scsiq->r3.done_stat = QD_WITH_ERROR); - } - return (PollQueueDone(asc_dvc, (ASC_SCSI_REQ_Q dosfar *) scsiq, 40)); -} - -int -InitTestUnitReady( - ASC_DVC_VAR asc_ptr_type * asc_dvc, - ASC_SCSI_REQ_Q dosfar * scsiq -) -{ - ASC_SCSI_BIT_ID_TYPE tid_bits; - int retry; - ASC_REQ_SENSE dosfar *sen; - - retry = 0; - tid_bits = scsiq->r1.target_id; - while (retry++ < 2) { - ASC_DBG(3, "InitTestUnitReady: PollScsiTestUnitReady()\n"); - PollScsiTestUnitReady(asc_dvc, scsiq); - ASC_DBG1(3, "InitTestUnitReady: done_stat %x\n", scsiq->r3.done_stat); - if (scsiq->r3.done_stat == 0x01) { - return (1); - } else if (scsiq->r3.done_stat == QD_WITH_ERROR) { - DvcSleepMilliSecond(100); - - sen = (ASC_REQ_SENSE dosfar *) scsiq->sense_ptr; - - if ((scsiq->r3.scsi_stat == SS_CHK_CONDITION) && - ((sen->err_code & 0x70) != 0)) { - - if (sen->sense_key == SCSI_SENKEY_NOT_READY) { - - if (asc_dvc->start_motor & tid_bits) { - if (PollScsiStartUnit(asc_dvc, scsiq) == 1) { - retry = 0; - continue; - } else { - asc_dvc->start_motor &= ~tid_bits; - break; - } - } else { - DvcSleepMilliSecond(100); - } - } else if (sen->sense_key == SCSI_SENKEY_ATTENSION) { - DvcSleepMilliSecond(100); - } else { - break; - } - } else { - break; - } - } else if (scsiq->r3.done_stat == QD_ABORTED_BY_HOST) { - break; - } else { - break; - } - } - return (0); -} - -#if CC_INIT_INQ_DISPLAY - -#endif - -int -AscPollQDone( - ASC_DVC_VAR asc_ptr_type * asc_dvc, - ASC_SCSI_REQ_Q dosfar * scsiq, - int timeout_sec -) -{ - int loop, loop_end; - int sta; - PortAddr iop_base; - - iop_base = asc_dvc->iop_base; - loop = 0; - loop_end = timeout_sec * 100; - sta = 1; - - while (TRUE) { - ASC_DBG4(3, - "AscPollQDone: loop %d, err_code %x, done_stat %x, scsi_stat %x\n", - loop, asc_dvc->err_code, scsiq->r3.done_stat, scsiq->r3.scsi_stat); - if (asc_dvc->err_code != 0) { - scsiq->r3.done_stat = QD_WITH_ERROR; - sta = ERR; - break; - } - if (scsiq->r3.done_stat != QD_IN_PROGRESS) { - if ((scsiq->r3.done_stat == QD_WITH_ERROR) && - (scsiq->r3.scsi_stat == SS_TARGET_BUSY)) { - sta = 0x80; - break; - } - break; - } - DvcSleepMilliSecond(10); - if (loop++ > loop_end) { - sta = 0; - break; - } - if (AscIsChipHalted(iop_base)) { - AscISR(asc_dvc); - loop = 0; - } else { - ASC_DBG(3, "AscPollQDone: AscIsIntPending()\n"); - if (AscIsIntPending(iop_base)) { - ASC_DBG(3, "AscPollQDone: AscISR()\n"); - AscISR(asc_dvc); - } - } - } - ASC_DBG1(3, "AscPollQDone: sta %x\n", sta); - return (sta); -} - -uchar -AscReadLramByte( - PortAddr iop_base, - ushort addr -) -{ - uchar byte_data; - ushort word_data; - - if (isodd_word(addr)) { - AscSetChipLramAddr(iop_base, addr - 1); - word_data = AscGetChipLramData(iop_base); - -#if CC_LITTLE_ENDIAN_HOST - byte_data = (uchar) ((word_data >> 8) & 0xFF); -#else - byte_data = (uchar) (word_data & 0xFF); -#endif - - } else { - AscSetChipLramAddr(iop_base, addr); - word_data = AscGetChipLramData(iop_base); - -#if CC_LITTLE_ENDIAN_HOST - byte_data = (uchar) (word_data & 0xFF); -#else - byte_data = (uchar) ((word_data >> 8) & 0xFF); -#endif - - } - return (byte_data); -} - -ushort -AscReadLramWord( - PortAddr iop_base, - ushort addr -) -{ - ushort word_data; - - AscSetChipLramAddr(iop_base, addr); - word_data = AscGetChipLramData(iop_base); - return (word_data); -} - -ulong -AscReadLramDWord( - PortAddr iop_base, - ushort addr -) -{ - ushort val_low, val_high; - ulong dword_data; - - AscSetChipLramAddr(iop_base, addr); - -#if CC_LITTLE_ENDIAN_HOST - val_low = AscGetChipLramData(iop_base); - - val_high = AscGetChipLramData(iop_base); -#else - val_high = AscGetChipLramData(iop_base); - val_low = AscGetChipLramData(iop_base); -#endif - - dword_data = ((ulong) val_high << 16) | (ulong) val_low; - return (dword_data); -} - -void -AscWriteLramWord( - PortAddr iop_base, - ushort addr, - ushort word_val -) -{ - AscSetChipLramAddr(iop_base, addr); - AscPutChipLramData(iop_base, word_val); - return; -} - -void -AscWriteLramDWord( - PortAddr iop_base, - ushort addr, - ulong dword_val -) -{ - ushort word_val; - - AscSetChipLramAddr(iop_base, addr); - -#if CC_LITTLE_ENDIAN_HOST - word_val = (ushort) dword_val; - AscPutChipLramData(iop_base, word_val); - word_val = (ushort) (dword_val >> 16); - AscPutChipLramData(iop_base, word_val); -#else - word_val = (ushort) (dword_val >> 16); - AscPutChipLramData(iop_base, word_val); - word_val = (ushort) dword_val; - AscPutChipLramData(iop_base, word_val); -#endif - return; -} - -void -AscWriteLramByte( - PortAddr iop_base, - ushort addr, - uchar byte_val -) -{ - ushort word_data; - - if (isodd_word(addr)) { - addr--; - word_data = AscReadLramWord(iop_base, addr); - word_data &= 0x00FF; - word_data |= (((ushort) byte_val << 8) & 0xFF00); - } else { - word_data = AscReadLramWord(iop_base, addr); - word_data &= 0xFF00; - word_data |= ((ushort) byte_val & 0x00FF); - } - AscWriteLramWord(iop_base, addr, word_data); - return; -} - -int -AscVerWriteLramWord( - PortAddr iop_base, - ushort addr, - ushort word_val -) -{ - int sta; - - sta = 0; - AscSetChipLramAddr(iop_base, addr); - AscPutChipLramData(iop_base, word_val); - AscSetChipLramAddr(iop_base, addr); - if (word_val != AscGetChipLramData(iop_base)) { - sta = ERR; - } - return (sta); -} - -void -AscMemWordCopyToLram( - PortAddr iop_base, - ushort s_addr, - ushort dosfar * s_buffer, - int words -) -{ - AscSetChipLramAddr(iop_base, s_addr); - DvcOutPortWords(iop_base + IOP_RAM_DATA, s_buffer, words); - return; -} - -void -AscMemDWordCopyToLram( - PortAddr iop_base, - ushort s_addr, - ulong dosfar * s_buffer, - int dwords -) -{ - AscSetChipLramAddr(iop_base, s_addr); - DvcOutPortDWords(iop_base + IOP_RAM_DATA, s_buffer, dwords); - return; -} - -void -AscMemWordCopyFromLram( - PortAddr iop_base, - ushort s_addr, - ushort dosfar * d_buffer, - int words -) -{ - AscSetChipLramAddr(iop_base, s_addr); - DvcInPortWords(iop_base + IOP_RAM_DATA, d_buffer, words); - return; -} - -ulong -AscMemSumLramWord( - PortAddr iop_base, - ushort s_addr, - rint words -) -{ - ulong sum; - int i; - - sum = 0L; - for (i = 0; i < words; i++, s_addr += 2) { - sum += AscReadLramWord(iop_base, s_addr); - } - return (sum); -} - -void -AscMemWordSetLram( - PortAddr iop_base, - ushort s_addr, - ushort set_wval, - rint words -) -{ - rint i; - - AscSetChipLramAddr(iop_base, s_addr); - for (i = 0; i < words; i++) { - AscPutChipLramData(iop_base, set_wval); - } - return; -} - -int -AscScsiInquiry( - ASC_DVC_VAR asc_ptr_type * asc_dvc, - ASC_SCSI_REQ_Q dosfar * scsiq, - uchar dosfar * buf, int buf_len -) -{ - if (AscScsiSetupCmdQ(asc_dvc, scsiq, buf, - (ulong) buf_len) == ERR) { - return (scsiq->r3.done_stat = QD_WITH_ERROR); - } - scsiq->cdb[0] = (uchar) SCSICMD_Inquiry; - scsiq->cdb[1] = scsiq->r1.target_lun << 5; - scsiq->cdb[2] = 0; - scsiq->cdb[3] = 0; - scsiq->cdb[4] = buf_len; - scsiq->cdb[5] = 0; - scsiq->r2.cdb_len = 6; - return (0); -} - -int -AscScsiReadCapacity( - ASC_DVC_VAR asc_ptr_type * asc_dvc, - ASC_SCSI_REQ_Q dosfar * scsiq, - uchar dosfar * info -) -{ - if (AscScsiSetupCmdQ(asc_dvc, scsiq, info, 8L) == ERR) { - return (scsiq->r3.done_stat = QD_WITH_ERROR); - } - scsiq->cdb[0] = (uchar) SCSICMD_ReadCapacity; - scsiq->cdb[1] = scsiq->r1.target_lun << 5; - scsiq->cdb[2] = 0; - scsiq->cdb[3] = 0; - scsiq->cdb[4] = 0; - scsiq->cdb[5] = 0; - scsiq->cdb[6] = 0; - scsiq->cdb[7] = 0; - scsiq->cdb[8] = 0; - scsiq->cdb[9] = 0; - scsiq->r2.cdb_len = 10; - return (0); -} - -int -AscScsiTestUnitReady( - ASC_DVC_VAR asc_ptr_type * asc_dvc, - ASC_SCSI_REQ_Q dosfar * scsiq -) -{ - if (AscScsiSetupCmdQ(asc_dvc, scsiq, FNULLPTR, - (ulong) 0L) == ERR) { - return (scsiq->r3.done_stat = QD_WITH_ERROR); - } - scsiq->r1.cntl = (uchar) ASC_SCSIDIR_NODATA; - scsiq->cdb[0] = (uchar) SCSICMD_TestUnitReady; - scsiq->cdb[1] = scsiq->r1.target_lun << 5; - scsiq->cdb[2] = 0; - scsiq->cdb[3] = 0; - scsiq->cdb[4] = 0; - scsiq->cdb[5] = 0; - scsiq->r2.cdb_len = 6; - return (0); -} - -int -AscScsiStartStopUnit( - ASC_DVC_VAR asc_ptr_type * asc_dvc, - ASC_SCSI_REQ_Q dosfar * scsiq, - uchar op_mode -) -{ - if (AscScsiSetupCmdQ(asc_dvc, scsiq, FNULLPTR, (ulong) 0L) == ERR) { - return (scsiq->r3.done_stat = QD_WITH_ERROR); - } - scsiq->r1.cntl = (uchar) ASC_SCSIDIR_NODATA; - scsiq->cdb[0] = (uchar) SCSICMD_StartStopUnit; - scsiq->cdb[1] = scsiq->r1.target_lun << 5; - scsiq->cdb[2] = 0; - scsiq->cdb[3] = 0; - scsiq->cdb[4] = op_mode; - - scsiq->cdb[5] = 0; - scsiq->r2.cdb_len = 6; - return (0); -} diff --git a/i386/i386at/gpl/linux/scsi/advansys.h b/i386/i386at/gpl/linux/scsi/advansys.h deleted file mode 100644 index 255279ca..00000000 --- a/i386/i386at/gpl/linux/scsi/advansys.h +++ /dev/null @@ -1,131 +0,0 @@ -/* $Id: advansys.h,v 1.1.1.1 1997/02/25 21:27:46 thomas Exp $ */ -/* - * advansys.h - Linux Host Driver for AdvanSys SCSI Adapters - * - * Copyright (c) 1995-1996 Advanced System Products, Inc. - * - * This driver may be modified and freely distributed provided that - * the above copyright message and this comment are included in the - * distribution. The latest version of this driver is available at - * the AdvanSys FTP and BBS sites listed below. - * - * Please send questions, comments, and bug reports to: - * bobf@advansys.com (Bob Frey) - */ - -#ifndef _ADVANSYS_H -#define _ADVANSYS_H - -/* The driver can be used in Linux 1.2.X or 1.3.X. */ -#if !defined(LINUX_1_2) && !defined(LINUX_1_3) -#ifndef LINUX_VERSION_CODE -#include <linux/version.h> -#endif /* LINUX_VERSION_CODE */ -#if LINUX_VERSION_CODE > 65536 + 3 * 256 -#define LINUX_1_3 -#else /* LINUX_VERSION_CODE */ -#define LINUX_1_2 -#endif /* LINUX_VERSION_CODE */ -#endif /* !defined(LINUX_1_2) && !defined(LINUX_1_3) */ - -/* - * Scsi_Host_Template function prototypes. - */ -int advansys_detect(Scsi_Host_Template *); -int advansys_release(struct Scsi_Host *); -const char *advansys_info(struct Scsi_Host *); -int advansys_command(Scsi_Cmnd *); -int advansys_queuecommand(Scsi_Cmnd *, void (* done)(Scsi_Cmnd *)); -int advansys_abort(Scsi_Cmnd *); -int advansys_reset(Scsi_Cmnd *); -#ifdef LINUX_1_2 -int advansys_biosparam(Disk *, int, int[]); -#else /* LINUX_1_3 */ -int advansys_biosparam(Disk *, kdev_t, int[]); -extern struct proc_dir_entry proc_scsi_advansys; -int advansys_proc_info(char *, char **, off_t, int, int, int); -#endif /* LINUX_1_3 */ - -/* init/main.c setup function */ -void advansys_setup(char *, int *); - -/* - * AdvanSys Host Driver Scsi_Host_Template (struct SHT) from hosts.h. - */ -#ifdef LINUX_1_2 -#define ADVANSYS { \ - NULL, /* struct SHT *next */ \ - NULL, /* int *usage_count */ \ - "advansys", /* char *name */ \ - advansys_detect, /* int (*detect)(struct SHT *) */ \ - advansys_release, /* int (*release)(struct Scsi_Host *) */ \ - advansys_info, /* const char *(*info)(struct Scsi_Host *) */ \ - advansys_command, /* int (*command)(Scsi_Cmnd *) */ \ - advansys_queuecommand, \ - /* int (*queuecommand)(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)) */ \ - advansys_abort, /* int (*abort)(Scsi_Cmnd *) */ \ - advansys_reset, /* int (*reset)(Scsi_Cmnd *) */ \ - NULL, /* int (*slave_attach)(int, int) */ \ - advansys_biosparam, /* int (* bios_param)(Disk *, int, int []) */ \ - /* \ - * The following fields are set per adapter in advansys_detect(). \ - */ \ - 0, /* int can_queue */ \ - 0, /* int this_id */ \ - 0, /* short unsigned int sg_tablesize */ \ - 0, /* short cmd_per_lun */ \ - 0, /* unsigned char present */ \ - /* \ - * Because the driver may control an ISA adapter 'unchecked_isa_dma' \ - * must be set. The flag will be cleared in advansys_detect for non-ISA \ - * adapters. Refer to the comment in scsi_module.c for more information. \ - */ \ - 1, /* unsigned unchecked_isa_dma:1 */ \ - /* \ - * All adapters controlled by this driver are capable of large \ - * scatter-gather lists. This apparently obviates any performance - * gain provided by setting 'use_clustering'. \ - */ \ - DISABLE_CLUSTERING, /* unsigned use_clustering:1 */ \ -} -#else /* LINUX_1_3 */ -#define ADVANSYS { \ - NULL, /* struct SHT *next */ \ - NULL, /* long *usage_count */ \ - &proc_scsi_advansys, /* struct proc_dir_entry *proc_dir */ \ - advansys_proc_info, \ - /* int (*proc_info)(char *, char **, off_t, int, int, int) */ \ - "advansys", /* const char *name */ \ - advansys_detect, /* int (*detect)(struct SHT *) */ \ - advansys_release, /* int (*release)(struct Scsi_Host *) */ \ - advansys_info, /* const char *(*info)(struct Scsi_Host *) */ \ - advansys_command, /* int (*command)(Scsi_Cmnd *) */ \ - advansys_queuecommand, \ - /* int (*queuecommand)(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)) */ \ - advansys_abort, /* int (*abort)(Scsi_Cmnd *) */ \ - advansys_reset, /* int (*reset)(Scsi_Cmnd *) */ \ - NULL, /* int (*slave_attach)(int, int) */ \ - advansys_biosparam, /* int (* bios_param)(Disk *, kdev_t, int []) */ \ - /* \ - * The following fields are set per adapter in advansys_detect(). \ - */ \ - 0, /* int can_queue */ \ - 0, /* int this_id */ \ - 0, /* short unsigned int sg_tablesize */ \ - 0, /* short cmd_per_lun */ \ - 0, /* unsigned char present */ \ - /* \ - * Because the driver may control an ISA adapter 'unchecked_isa_dma' \ - * must be set. The flag will be cleared in advansys_detect for non-ISA \ - * adapters. Refer to the comment in scsi_module.c for more information. \ - */ \ - 1, /* unsigned unchecked_isa_dma:1 */ \ - /* \ - * All adapters controlled by this driver are capable of large \ - * scatter-gather lists. This apparently obviates any performance - * gain provided by setting 'use_clustering'. \ - */ \ - DISABLE_CLUSTERING, /* unsigned use_clustering:1 */ \ -} -#endif /* LINUX_1_3 */ -#endif /* _ADVANSYS_H */ diff --git a/i386/i386at/gpl/linux/scsi/aha152x.c b/i386/i386at/gpl/linux/scsi/aha152x.c deleted file mode 100644 index 67dcd102..00000000 --- a/i386/i386at/gpl/linux/scsi/aha152x.c +++ /dev/null @@ -1,2985 +0,0 @@ -/* aha152x.c -- Adaptec AHA-152x driver - * Author: Juergen E. Fischer, fischer@et-inf.fho-emden.de - * Copyright 1993, 1994, 1995 Juergen E. Fischer - * - * - * This driver is based on - * fdomain.c -- Future Domain TMC-16x0 driver - * which is - * Copyright 1992, 1993 Rickard E. Faith (faith@cs.unc.edu) - * - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * - * $Id: aha152x.c,v 1.1.1.1 1997/02/25 21:27:46 thomas Exp $ - * - * $Log: aha152x.c,v $ - * Revision 1.1.1.1 1996/10/30 01:40:01 thomas - * Imported from UK22 - * - * Revision 1.1 1996/03/25 20:25:17 goel - * Linux driver merge. - * - * Revision 1.14 1996/01/17 15:11:20 fischer - * - fixed lockup in MESSAGE IN phase after reconnection - * - * Revision 1.13 1996/01/09 02:15:53 fischer - * - some cleanups - * - moved request_irq behind controller initialization - * (to avoid spurious interrupts) - * - * Revision 1.12 1995/12/16 12:26:07 fischer - * - barrier()'s added - * - configurable RESET delay added - * - * Revision 1.11 1995/12/06 21:18:35 fischer - * - some minor updates - * - * Revision 1.10 1995/07/22 19:18:45 fischer - * - support for 2 controllers - * - started synchronous data transfers (not working yet) - * - * Revision 1.9 1995/03/18 09:20:24 root - * - patches for PCMCIA and modules - * - * Revision 1.8 1995/01/21 22:07:19 root - * - snarf_region => request_region - * - aha152x_intr interface change - * - * Revision 1.7 1995/01/02 23:19:36 root - * - updated COMMAND_SIZE to cmd_len - * - changed sti() to restore_flags() - * - fixed some #ifdef which generated warnings - * - * Revision 1.6 1994/11/24 20:35:27 root - * - problem with odd number of bytes in fifo fixed - * - * Revision 1.5 1994/10/30 14:39:56 root - * - abort code fixed - * - debugging improved - * - * Revision 1.4 1994/09/12 11:33:01 root - * - irqaction to request_irq - * - abortion updated - * - * Revision 1.3 1994/08/04 13:53:05 root - * - updates for mid-level-driver changes - * - accept unexpected BUSFREE phase as error condition - * - parity check now configurable - * - * Revision 1.2 1994/07/03 12:56:36 root - * - cleaned up debugging code - * - more tweaking on reset delays - * - updated abort/reset code (pretty untested...) - * - * Revision 1.1 1994/05/28 21:18:49 root - * - update for mid-level interface change (abort-reset) - * - delays after resets adjusted for some slow devices - * - * Revision 1.0 1994/03/25 12:52:00 root - * - Fixed "more data than expected" problem - * - added new BIOS signatures - * - * Revision 0.102 1994/01/31 20:44:12 root - * - minor changes in insw/outsw handling - * - * Revision 0.101 1993/12/13 01:16:27 root - * - fixed STATUS phase (non-GOOD stati were dropped sometimes; - * fixes problems with CD-ROM sector size detection & media change) - * - * Revision 0.100 1993/12/10 16:58:47 root - * - fix for unsuccessful selections in case of non-continuous id assignments - * on the scsi bus. - * - * Revision 0.99 1993/10/24 16:19:59 root - * - fixed DATA IN (rare read errors gone) - * - * Revision 0.98 1993/10/17 12:54:44 root - * - fixed some recent fixes (shame on me) - * - moved initialization of scratch area to aha152x_queue - * - * Revision 0.97 1993/10/09 18:53:53 root - * - DATA IN fixed. Rarely left data in the fifo. - * - * Revision 0.96 1993/10/03 00:53:59 root - * - minor changes on DATA IN - * - * Revision 0.95 1993/09/24 10:36:01 root - * - change handling of MSGI after reselection - * - fixed sti/cli - * - minor changes - * - * Revision 0.94 1993/09/18 14:08:22 root - * - fixed bug in multiple outstanding command code - * - changed detection - * - support for kernel command line configuration - * - reset corrected - * - changed message handling - * - * Revision 0.93 1993/09/15 20:41:19 root - * - fixed bugs with multiple outstanding commands - * - * Revision 0.92 1993/09/13 02:46:33 root - * - multiple outstanding commands work (no problems with IBM drive) - * - * Revision 0.91 1993/09/12 20:51:46 root - * added multiple outstanding commands - * (some problem with this $%&? IBM device remain) - * - * Revision 0.9 1993/09/12 11:11:22 root - * - corrected auto-configuration - * - changed the auto-configuration (added some '#define's) - * - added support for dis-/reconnection - * - * Revision 0.8 1993/09/06 23:09:39 root - * - added support for the drive activity light - * - minor changes - * - * Revision 0.7 1993/09/05 14:30:15 root - * - improved phase detection - * - now using the new snarf_region code of 0.99pl13 - * - * Revision 0.6 1993/09/02 11:01:38 root - * first public release; added some signatures and biosparam() - * - * Revision 0.5 1993/08/30 10:23:30 root - * fixed timing problems with my IBM drive - * - * Revision 0.4 1993/08/29 14:06:52 root - * fixed some problems with timeouts due incomplete commands - * - * Revision 0.3 1993/08/28 15:55:03 root - * writing data works too. mounted and worked on a dos partition - * - * Revision 0.2 1993/08/27 22:42:07 root - * reading data works. Mounted a msdos partition. - * - * Revision 0.1 1993/08/25 13:38:30 root - * first "damn thing doesn't work" version - * - * Revision 0.0 1993/08/14 19:54:25 root - * empty function bodies; detect() works. - * - * - ************************************************************************** - - - - DESCRIPTION: - - This is the Linux low-level SCSI driver for Adaptec AHA-1520/1522 - SCSI host adapters. - - - PER-DEFINE CONFIGURABLE OPTIONS: - - AUTOCONF: - use configuration the controller reports (only 152x) - - SKIP_BIOSTEST: - Don't test for BIOS signature (AHA-1510 or disabled BIOS) - - SETUP0 { IOPORT, IRQ, SCSI_ID, RECONNECT, PARITY, SYNCHRONOUS, DELAY }: - override for the first controller - - SETUP1 { IOPORT, IRQ, SCSI_ID, RECONNECT, PARITY, SYNCHRONOUS, DELAY }: - override for the second controller - - - LILO COMMAND LINE OPTIONS: - - aha152x=<IOPORT>[,<IRQ>[,<SCSI-ID>[,<RECONNECT>[,<PARITY>[,<SYNCHRONOUS>[,<DELAY>]]]]]] - - The normal configuration can be overridden by specifying a command line. - When you do this, the BIOS test is skipped. Entered values have to be - valid (known). Don't use values that aren't supported under normal operation. - If you think that you need other values: contact me. For two controllers - use the aha152x statement twice. - - - REFERENCES USED: - - "AIC-6260 SCSI Chip Specification", Adaptec Corporation. - - "SCSI COMPUTER SYSTEM INTERFACE - 2 (SCSI-2)", X3T9.2/86-109 rev. 10h - - "Writing a SCSI device driver for Linux", Rik Faith (faith@cs.unc.edu) - - "Kernel Hacker's Guide", Michael K. Johnson (johnsonm@sunsite.unc.edu) - - "Adaptec 1520/1522 User's Guide", Adaptec Corporation. - - Michael K. Johnson (johnsonm@sunsite.unc.edu) - - Drew Eckhardt (drew@cs.colorado.edu) - - Eric Youngdale (ericy@cais.com) - - special thanks to Eric Youngdale for the free(!) supplying the - documentation on the chip. - - **************************************************************************/ - -#ifdef PCMCIA -#define MODULE -#endif - -#include <linux/module.h> - -#ifdef PCMCIA -#undef MODULE -#endif - -#include <linux/sched.h> -#include <asm/io.h> -#include <linux/blk.h> -#include "scsi.h" -#include "sd.h" -#include "hosts.h" -#include "constants.h" -#include <asm/system.h> -#include <linux/errno.h> -#include <linux/string.h> -#include <linux/wait.h> -#include <linux/ioport.h> -#include <linux/proc_fs.h> - -#include "aha152x.h" -#include <linux/stat.h> - -struct proc_dir_entry proc_scsi_aha152x = { - PROC_SCSI_AHA152X, 7, "aha152x", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - -/* DEFINES */ - -#ifdef MACH -#define AUTOCONF -#endif - -/* For PCMCIA cards, always use AUTOCONF */ -#if defined(PCMCIA) || defined(MODULE) -#if !defined(AUTOCONF) -#define AUTOCONF -#endif -#endif - -#if !defined(AUTOCONF) && !defined(SETUP0) -#error define AUTOCONF or SETUP0 -#endif - -#if defined(DEBUG_AHA152X) - -#undef SKIP_PORTS /* don't display ports */ - -#undef DEBUG_QUEUE /* debug queue() */ -#undef DEBUG_RESET /* debug reset() */ -#undef DEBUG_INTR /* debug intr() */ -#undef DEBUG_SELECTION /* debug selection part in intr() */ -#undef DEBUG_MSGO /* debug message out phase in intr() */ -#undef DEBUG_MSGI /* debug message in phase in intr() */ -#undef DEBUG_STATUS /* debug status phase in intr() */ -#undef DEBUG_CMD /* debug command phase in intr() */ -#undef DEBUG_DATAI /* debug data in phase in intr() */ -#undef DEBUG_DATAO /* debug data out phase in intr() */ -#undef DEBUG_ABORT /* debug abort() */ -#undef DEBUG_DONE /* debug done() */ -#undef DEBUG_BIOSPARAM /* debug biosparam() */ - -#undef DEBUG_RACE /* debug race conditions */ -#undef DEBUG_PHASES /* debug phases (useful to trace) */ -#undef DEBUG_QUEUES /* debug reselection */ - -/* recently used for debugging */ -#if 0 -#endif - -#define DEBUG_SELECTION -#define DEBUG_PHASES -#define DEBUG_RESET -#define DEBUG_ABORT - -#define DEBUG_DEFAULT (debug_reset|debug_abort) - -#endif - -/* END OF DEFINES */ - -extern long loops_per_sec; - -#define DELAY_DEFAULT 100 - -/* some additional "phases" for getphase() */ -#define P_BUSFREE 1 -#define P_PARITY 2 - -/* possible irq range */ -#define IRQ_MIN 9 -#define IRQ_MAX 12 -#define IRQS IRQ_MAX-IRQ_MIN+1 - -enum { - not_issued = 0x0001, - in_selection = 0x0002, - disconnected = 0x0004, - aborted = 0x0008, - sent_ident = 0x0010, - in_other = 0x0020, - in_sync = 0x0040, - sync_ok = 0x0080, -}; - -/* set by aha152x_setup according to the command line */ -static int setup_count=0; -static struct aha152x_setup { - int io_port; - int irq; - int scsiid; - int reconnect; - int parity; - int synchronous; - int delay; -#ifdef DEBUG_AHA152X - int debug; -#endif - char *conf; -} setup[2]; - -static struct Scsi_Host *aha152x_host[IRQS]; - -#define HOSTDATA(shpnt) ((struct aha152x_hostdata *) &shpnt->hostdata) -#define CURRENT_SC (HOSTDATA(shpnt)->current_SC) -#define ISSUE_SC (HOSTDATA(shpnt)->issue_SC) -#define DISCONNECTED_SC (HOSTDATA(shpnt)->disconnected_SC) -#define DELAY (HOSTDATA(shpnt)->delay) -#define SYNCRATE (HOSTDATA(shpnt)->syncrate[CURRENT_SC->target]) -#define MSG(i) (HOSTDATA(shpnt)->message[i]) -#define MSGLEN (HOSTDATA(shpnt)->message_len) -#define ADDMSG(x) (MSG(MSGLEN++)=x) - -struct aha152x_hostdata { - Scsi_Cmnd *issue_SC; - Scsi_Cmnd *current_SC; - Scsi_Cmnd *disconnected_SC; - int aborting; - int abortion_complete; - int abort_result; - int commands; - - int reconnect; - int parity; - int synchronous; - int delay; - - unsigned char syncrate[8]; - - unsigned char message[256]; - int message_len; - -#ifdef DEBUG_AHA152X - int debug; -#endif -}; - -void aha152x_intr(int irq, struct pt_regs *); -void aha152x_done(struct Scsi_Host *shpnt, int error); -void aha152x_setup(char *str, int *ints); -int aha152x_checksetup(struct aha152x_setup *setup); - -static void aha152x_reset_ports(struct Scsi_Host *shpnt); -static void aha152x_panic(struct Scsi_Host *shpnt, char *msg); - -static void disp_ports(struct Scsi_Host *shpnt); -static void show_command(Scsi_Cmnd *ptr); -static void show_queues(struct Scsi_Host *shpnt); -static void disp_enintr(struct Scsi_Host *shpnt); - -#if defined(DEBUG_RACE) -static void enter_driver(const char *); -static void leave_driver(const char *); -#endif - -/* possible i/o addresses for the AIC-6260 */ -static unsigned short ports[] = -{ - 0x340, /* default first */ - 0x140 -}; -#define PORT_COUNT (sizeof(ports) / sizeof(unsigned short)) - -#if !defined(SKIP_BIOSTEST) -/* possible locations for the Adaptec BIOS */ -static void *addresses[] = -{ - (void *) 0xdc000, /* default first */ - (void *) 0xc8000, - (void *) 0xcc000, - (void *) 0xd0000, - (void *) 0xd4000, - (void *) 0xd8000, - (void *) 0xe0000, - (void *) 0xeb800, /* VTech Platinum SMP */ - (void *) 0xf0000, -}; -#define ADDRESS_COUNT (sizeof(addresses) / sizeof(void *)) - -/* signatures for various AIC-6[23]60 based controllers. - The point in detecting signatures is to avoid useless - and maybe harmful probes on ports. I'm not sure that - all listed boards pass auto-configuration. For those - which fail the BIOS signature is obsolete, because - user intervention to supply the configuration is - needed anyway. */ -static struct signature { - char *signature; - int sig_offset; - int sig_length; -} signatures[] = -{ - { "Adaptec AHA-1520 BIOS", 0x102e, 21 }, /* Adaptec 152x */ - { "Adaptec ASW-B626 BIOS", 0x1029, 21 }, /* on-board controller */ - { "Adaptec BIOS: ASW-B626", 0x0f, 22 }, /* on-board controller */ - { "Adaptec ASW-B626 S2", 0x2e6c, 19 }, /* on-board controller */ - { "Adaptec BIOS:AIC-6360", 0xc, 21 }, /* on-board controller */ - { "ScsiPro SP-360 BIOS", 0x2873, 19 }, /* ScsiPro-Controller */ - { "GA-400 LOCAL BUS SCSI BIOS", 0x102e, 26 }, /* Gigabyte Local-Bus-SCSI */ - { "Adaptec BIOS:AVA-282X", 0xc, 21 }, /* Adaptec 282x */ - { "Adaptec IBM Dock II SCSI", 0x2edd, 24 }, /* IBM Thinkpad Dock II */ - { "Adaptec BIOS:AHA-1532P", 0x1c, 22 }, /* IBM Thinkpad Dock II SCSI */ -}; -#define SIGNATURE_COUNT (sizeof(signatures) / sizeof(struct signature)) -#endif - - -static void do_pause(unsigned amount) /* Pause for amount*10 milliseconds */ -{ - unsigned long the_time = jiffies + amount; /* 0.01 seconds per jiffy */ - - while (jiffies < the_time) - barrier(); -} - -/* - * queue services: - */ -static inline void append_SC(Scsi_Cmnd **SC, Scsi_Cmnd *new_SC) -{ - Scsi_Cmnd *end; - - new_SC->host_scribble = (unsigned char *) NULL; - if(!*SC) - *SC=new_SC; - else - { - for(end=*SC; end->host_scribble; end = (Scsi_Cmnd *) end->host_scribble) - ; - end->host_scribble = (unsigned char *) new_SC; - } -} - -static inline Scsi_Cmnd *remove_first_SC(Scsi_Cmnd **SC) -{ - Scsi_Cmnd *ptr; - - ptr=*SC; - if(ptr) - *SC= (Scsi_Cmnd *) (*SC)->host_scribble; - return ptr; -} - -static inline Scsi_Cmnd *remove_SC(Scsi_Cmnd **SC, int target, int lun) -{ - Scsi_Cmnd *ptr, *prev; - - for(ptr=*SC, prev=NULL; - ptr && ((ptr->target!=target) || (ptr->lun!=lun)); - prev = ptr, ptr = (Scsi_Cmnd *) ptr->host_scribble) - ; - - if(ptr) - if(prev) - prev->host_scribble = ptr->host_scribble; - else - *SC= (Scsi_Cmnd *) ptr->host_scribble; - return ptr; -} - -/* - * read inbound byte and wait for ACK to get low - */ -static void make_acklow(struct Scsi_Host *shpnt) -{ - SETPORT(SXFRCTL0, CH1|SPIOEN); - GETPORT(SCSIDAT); - SETPORT(SXFRCTL0, CH1); - - while(TESTHI(SCSISIG, ACKI)) - barrier(); -} - -/* - * detect current phase more reliable: - * phase is valid, when the target asserts REQ after we've deasserted ACK. - * - * return value is a valid phase or an error code. - * - * errorcodes: - * P_BUSFREE BUS FREE phase detected - * P_PARITY parity error in DATA phase - */ -static int getphase(struct Scsi_Host *shpnt) -{ - int phase, sstat1; - - while(1) - { - do - { - while(!((sstat1 = GETPORT(SSTAT1)) & (BUSFREE|SCSIRSTI|REQINIT))) - barrier(); - if(sstat1 & BUSFREE) - return P_BUSFREE; - if(sstat1 & SCSIRSTI) - { - printk("aha152x: RESET IN\n"); - SETPORT(SSTAT1, SCSIRSTI); - } - } - while(TESTHI(SCSISIG, ACKI) || TESTLO(SSTAT1, REQINIT)); - - SETPORT(SSTAT1, CLRSCSIPERR); - - phase = GETPORT(SCSISIG) & P_MASK ; - - if(TESTHI(SSTAT1, SCSIPERR)) - { - if((phase & (CDO|MSGO))==0) /* DATA phase */ - return P_PARITY; - - make_acklow(shpnt); - } - else - return phase; - } -} - -/* called from init/main.c */ -void aha152x_setup(char *str, int *ints) -{ - if(setup_count>2) - panic("aha152x: you can only configure up to two controllers\n"); - - setup[setup_count].conf = str; - setup[setup_count].io_port = ints[0] >= 1 ? ints[1] : 0x340; - setup[setup_count].irq = ints[0] >= 2 ? ints[2] : 11; - setup[setup_count].scsiid = ints[0] >= 3 ? ints[3] : 7; - setup[setup_count].reconnect = ints[0] >= 4 ? ints[4] : 1; - setup[setup_count].parity = ints[0] >= 5 ? ints[5] : 1; - setup[setup_count].synchronous = ints[0] >= 6 ? ints[6] : 0 /* FIXME: 1 */; - setup[setup_count].delay = ints[0] >= 7 ? ints[7] : DELAY_DEFAULT; -#ifdef DEBUG_AHA152X - setup[setup_count].debug = ints[0] >= 8 ? ints[8] : DEBUG_DEFAULT; - if(ints[0]>8) - { - printk("aha152x: usage: aha152x=<IOBASE>[,<IRQ>[,<SCSI ID>" - "[,<RECONNECT>[,<PARITY>[,<SYNCHRONOUS>[,<DELAY>[,<DEBUG>]]]]]]]\n"); -#else - if(ints[0]>7) - { - printk("aha152x: usage: aha152x=<IOBASE>[,<IRQ>[,<SCSI ID>" - "[,<RECONNECT>[,<PARITY>[,<SYNCHRONOUS>[,<DELAY>]]]]]]\n"); -#endif - } - else - setup_count++; -} - -/* - Test, if port_base is valid. - */ -static int aha152x_porttest(int io_port) -{ - int i; - - if(check_region(io_port, IO_RANGE)) - return 0; - - SETPORT(io_port+O_DMACNTRL1, 0); /* reset stack pointer */ - for(i=0; i<16; i++) - SETPORT(io_port+O_STACK, i); - - SETPORT(io_port+O_DMACNTRL1, 0); /* reset stack pointer */ - for(i=0; i<16 && GETPORT(io_port+O_STACK)==i; i++) - ; - - return(i==16); -} - -int aha152x_checksetup(struct aha152x_setup *setup) -{ - int i; - -#ifndef PCMCIA - for(i=0; i<PORT_COUNT && (setup->io_port != ports[i]); i++) - ; - - if(i==PORT_COUNT) - return 0; -#endif - - if(!aha152x_porttest(setup->io_port)) - return 0; - - if((setup->irq < IRQ_MIN) && (setup->irq > IRQ_MAX)) - return 0; - - if((setup->scsiid < 0) || (setup->scsiid > 7)) - return 0; - - if((setup->reconnect < 0) || (setup->reconnect > 1)) - return 0; - - if((setup->parity < 0) || (setup->parity > 1)) - return 0; - - if((setup->synchronous < 0) || (setup->synchronous > 1)) - return 0; - - return 1; -} - - -int aha152x_detect(Scsi_Host_Template * tpnt) -{ - int i, j, ok; -#if defined(AUTOCONF) - aha152x_config conf; -#endif - - tpnt->proc_dir = &proc_scsi_aha152x; - - for(i=0; i<IRQS; i++) - aha152x_host[i] = (struct Scsi_Host *) NULL; - - if(setup_count) - { - printk("aha152x: processing commandline: "); - - for(i=0; i<setup_count; i++) - if(!aha152x_checksetup(&setup[i])) - { - printk("\naha152x: %s\n", setup[i].conf); - printk("aha152x: invalid line (controller=%d)\n", i+1); - } - - printk("ok\n"); - } - -#ifdef SETUP0 - if(setup_count<2) - { - struct aha152x_setup override = SETUP0; - - if(setup_count==0 || (override.io_port != setup[0].io_port)) - if(!aha152x_checksetup(&override)) - { - printk("\naha152x: SETUP0 (0x%x, %d, %d, %d, %d, %d, %d) invalid\n", - override.io_port, - override.irq, - override.scsiid, - override.reconnect, - override.parity, - override.synchronous, - override.delay); - } - else - setup[setup_count++] = override; - } -#endif - -#ifdef SETUP1 - if(setup_count<2) - { - struct aha152x_setup override = SETUP1; - - if(setup_count==0 || (override.io_port != setup[0].io_port)) - if(!aha152x_checksetup(&override)) - { - printk("\naha152x: SETUP1 (0x%x, %d, %d, %d, %d, %d, %d) invalid\n", - override.io_port, - override.irq, - override.scsiid, - override.reconnect, - override.parity, - override.synchronous, - override.delay); - } - else - setup[setup_count++] = override; - } -#endif - -#if defined(AUTOCONF) - if(setup_count<2) - { -#if !defined(SKIP_BIOSTEST) - ok=0; - for(i=0; i < ADDRESS_COUNT && !ok; i++) - for(j=0; (j < SIGNATURE_COUNT) && !ok; j++) - ok=!memcmp((void *) addresses[i]+signatures[j].sig_offset, - (void *) signatures[j].signature, - (int) signatures[j].sig_length); - - if(!ok && setup_count==0) - return 0; - - printk("aha152x: BIOS test: passed, "); -#else - printk("aha152x: "); -#endif /* !SKIP_BIOSTEST */ - - for(i=0; i<PORT_COUNT && setup_count<2; i++) - { - if((setup_count==1) && (setup[0].io_port == ports[i])) - continue; - - if(aha152x_porttest(ports[i])) - { - setup[setup_count].io_port = ports[i]; - - conf.cf_port = - (GETPORT(ports[i]+O_PORTA)<<8) + GETPORT(ports[i]+O_PORTB); - - setup[setup_count].irq = IRQ_MIN + conf.cf_irq; - setup[setup_count].scsiid = conf.cf_id; - setup[setup_count].reconnect = conf.cf_tardisc; - setup[setup_count].parity = !conf.cf_parity; - setup[setup_count].synchronous = 0 /* FIXME: conf.cf_syncneg */; - setup[setup_count].delay = DELAY_DEFAULT; -#ifdef DEBUG_AHA152X - setup[setup_count].debug = DEBUG_DEFAULT; -#endif - setup_count++; - } - } - - printk("auto configuration: ok, "); - } -#endif - - printk("detection complete\n"); - - for(i=0; i<setup_count; i++) - { - struct Scsi_Host *shpnt; - - shpnt = aha152x_host[setup[i].irq-IRQ_MIN] = - scsi_register(tpnt, sizeof(struct aha152x_hostdata)); - - shpnt->io_port = setup[i].io_port; - shpnt->n_io_port = IO_RANGE; - shpnt->irq = setup[i].irq; - - ISSUE_SC = (Scsi_Cmnd *) NULL; - CURRENT_SC = (Scsi_Cmnd *) NULL; - DISCONNECTED_SC = (Scsi_Cmnd *) NULL; - - HOSTDATA(shpnt)->reconnect = setup[i].reconnect; - HOSTDATA(shpnt)->parity = setup[i].parity; - HOSTDATA(shpnt)->synchronous = setup[i].synchronous; - HOSTDATA(shpnt)->delay = setup[i].delay; -#ifdef DEBUG_AHA152X - HOSTDATA(shpnt)->debug = setup[i].debug; -#endif - - HOSTDATA(shpnt)->aborting = 0; - HOSTDATA(shpnt)->abortion_complete = 0; - HOSTDATA(shpnt)->abort_result = 0; - HOSTDATA(shpnt)->commands = 0; - - HOSTDATA(shpnt)->message_len = 0; - - for(j=0; j<8; j++) - HOSTDATA(shpnt)->syncrate[j] = 0; - - SETPORT(SCSIID, setup[i].scsiid << 4); - shpnt->this_id=setup[i].scsiid; - - if(setup[i].reconnect) - shpnt->hostt->can_queue=AHA152X_MAXQUEUE; - - /* RESET OUT */ - SETBITS(SCSISEQ, SCSIRSTO); - do_pause(30); - CLRBITS(SCSISEQ, SCSIRSTO); - do_pause(setup[i].delay); - - aha152x_reset_ports(shpnt); - - printk("aha152x%d: vital data: PORTBASE=0x%03x, IRQ=%d, SCSI ID=%d," - " reconnect=%s, parity=%s, synchronous=%s, delay=%d\n", - i, - shpnt->io_port, - shpnt->irq, - shpnt->this_id, - HOSTDATA(shpnt)->reconnect ? "enabled" : "disabled", - HOSTDATA(shpnt)->parity ? "enabled" : "disabled", - HOSTDATA(shpnt)->synchronous ? "enabled" : "disabled", - HOSTDATA(shpnt)->delay); - - request_region(shpnt->io_port, IO_RANGE, "aha152x"); /* Register */ - - /* not expecting any interrupts */ - SETPORT(SIMODE0, 0); - SETPORT(SIMODE1, 0); - - SETBITS(DMACNTRL0, INTEN); - - ok = request_irq(setup[i].irq, aha152x_intr, SA_INTERRUPT, "aha152x"); - - if(ok<0) - { - if(ok == -EINVAL) - { - printk("aha152x%d: bad IRQ %d.\n", i, setup[i].irq); - printk(" Contact author.\n"); - } - else - if(ok == -EBUSY) - printk("aha152x%d: IRQ %d already in use. Configure another.\n", - i, setup[i].irq); - else - { - printk("\naha152x%d: Unexpected error code on" - " requesting IRQ %d.\n", i, setup[i].irq); - printk(" Contact author.\n"); - } - printk("aha152x: driver needs an IRQ.\n"); - continue; - } - } - - return (setup_count>0); -} - -/* - * Queue a command and setup interrupts for a free bus. - */ -int aha152x_queue(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) -{ - struct Scsi_Host *shpnt = SCpnt->host; - unsigned long flags; - -#if defined(DEBUG_RACE) - enter_driver("queue"); -#else -#if defined(DEBUG_QUEUE) - if(HOSTDATA(shpnt)->debug & debug_queue) - printk("aha152x: queue(), "); -#endif -#endif - -#if defined(DEBUG_QUEUE) - if(HOSTDATA(shpnt)->debug & debug_queue) - { - printk("SCpnt (target = %d lun = %d cmnd = ", - SCpnt->target, SCpnt->lun); - print_command(SCpnt->cmnd); - printk(", cmd_len=%d, pieces = %d size = %u), ", - SCpnt->cmd_len, SCpnt->use_sg, SCpnt->request_bufflen); - disp_ports(shpnt); - } -#endif - - SCpnt->scsi_done = done; - - /* setup scratch area - SCp.ptr : buffer pointer - SCp.this_residual : buffer length - SCp.buffer : next buffer - SCp.buffers_residual : left buffers in list - SCp.phase : current state of the command */ - SCpnt->SCp.phase = not_issued; - if (SCpnt->use_sg) - { - SCpnt->SCp.buffer = - (struct scatterlist *) SCpnt->request_buffer; - SCpnt->SCp.ptr = SCpnt->SCp.buffer->address; - SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length; - SCpnt->SCp.buffers_residual = SCpnt->use_sg - 1; - } - else - { - SCpnt->SCp.ptr = (char *)SCpnt->request_buffer; - SCpnt->SCp.this_residual = SCpnt->request_bufflen; - SCpnt->SCp.buffer = NULL; - SCpnt->SCp.buffers_residual = 0; - } - - SCpnt->SCp.Status = CHECK_CONDITION; - SCpnt->SCp.Message = 0; - SCpnt->SCp.have_data_in = 0; - SCpnt->SCp.sent_command = 0; - - /* Turn led on, when this is the first command. */ - save_flags(flags); - cli(); - HOSTDATA(shpnt)->commands++; - if(HOSTDATA(shpnt)->commands==1) - SETPORT(PORTA, 1); - -#if defined(DEBUG_QUEUES) - if(HOSTDATA(shpnt)->debug & debug_queues) - printk("i+ (%d), ", HOSTDATA(shpnt)->commands); -#endif - append_SC(&ISSUE_SC, SCpnt); - - /* Enable bus free interrupt, when we aren't currently on the bus */ - if(!CURRENT_SC) - { - SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0); - SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0); - } - restore_flags(flags); - -#if defined(DEBUG_RACE) - leave_driver("queue"); -#endif - - return 0; -} - -/* - * We only support commands in interrupt-driven fashion - */ -int aha152x_command(Scsi_Cmnd *SCpnt) -{ - printk("aha152x: interrupt driven driver; use aha152x_queue()\n"); - return -1; -} - -/* - * Abort a queued command - * (commands that are on the bus can't be aborted easily) - */ -int aha152x_abort(Scsi_Cmnd *SCpnt) -{ - struct Scsi_Host *shpnt = SCpnt->host; - unsigned long flags; - Scsi_Cmnd *ptr, *prev; - - save_flags(flags); - cli(); - -#if defined(DEBUG_ABORT) - if(HOSTDATA(shpnt)->debug & debug_abort) - { - printk("aha152x: abort(), SCpnt=0x%08x, ", (unsigned int) SCpnt); - show_queues(shpnt); - } -#endif - - /* look for command in issue queue */ - for(ptr=ISSUE_SC, prev=NULL; - ptr && ptr!=SCpnt; - prev=ptr, ptr=(Scsi_Cmnd *) ptr->host_scribble) - ; - - if(ptr) - { - /* dequeue */ - if(prev) - prev->host_scribble = ptr->host_scribble; - else - ISSUE_SC = (Scsi_Cmnd *) ptr->host_scribble; - restore_flags(flags); - - ptr->host_scribble = NULL; - ptr->result = DID_ABORT << 16; - ptr->scsi_done(ptr); - return SCSI_ABORT_SUCCESS; - } - - /* if the bus is busy or a command is currently processed, - we can't do anything more */ - if (TESTLO(SSTAT1, BUSFREE) || (CURRENT_SC && CURRENT_SC!=SCpnt)) - { - /* fail abortion, if bus is busy */ - - if(!CURRENT_SC) - printk("bus busy w/o current command, "); - - restore_flags(flags); - return SCSI_ABORT_BUSY; - } - - /* bus is free */ - - if(CURRENT_SC) - { - /* target entered bus free before COMMAND COMPLETE, nothing to abort */ - restore_flags(flags); - CURRENT_SC->result = DID_ERROR << 16; - CURRENT_SC->scsi_done(CURRENT_SC); - CURRENT_SC = (Scsi_Cmnd *) NULL; - return SCSI_ABORT_SUCCESS; - } - - /* look for command in disconnected queue */ - for(ptr=DISCONNECTED_SC, prev=NULL; - ptr && ptr!=SCpnt; - prev=ptr, ptr=(Scsi_Cmnd *) ptr->host_scribble) - ; - - if(ptr) - if(!HOSTDATA(shpnt)->aborting) - { - /* dequeue */ - if(prev) - prev->host_scribble = ptr->host_scribble; - else - DISCONNECTED_SC = (Scsi_Cmnd *) ptr->host_scribble; - - /* set command current and initiate selection, - let the interrupt routine take care of the abortion */ - CURRENT_SC = ptr; - ptr->SCp.phase = in_selection|aborted; - SETPORT(SCSIID, (shpnt->this_id << OID_) | CURRENT_SC->target); - - ADDMSG(ABORT); - - /* enable interrupts for SELECTION OUT DONE and SELECTION TIME OUT */ - SETPORT(SIMODE0, ENSELDO | (DISCONNECTED_SC ? ENSELDI : 0)); - SETPORT(SIMODE1, ENSELTIMO); - - /* Enable SELECTION OUT sequence */ - SETBITS(SCSISEQ, ENSELO | ENAUTOATNO); - - SETBITS(DMACNTRL0, INTEN); - HOSTDATA(shpnt)->abort_result=SCSI_ABORT_SUCCESS; - HOSTDATA(shpnt)->aborting++; - HOSTDATA(shpnt)->abortion_complete=0; - - sti(); /* Hi Eric, guess what ;-) */ - - /* sleep until the abortion is complete */ - while(!HOSTDATA(shpnt)->abortion_complete) - barrier(); - HOSTDATA(shpnt)->aborting=0; - return HOSTDATA(shpnt)->abort_result; - } - else - { - /* we're already aborting a command */ - restore_flags(flags); - return SCSI_ABORT_BUSY; - } - - /* command wasn't found */ - printk("command not found\n"); - restore_flags(flags); - return SCSI_ABORT_NOT_RUNNING; -} - -/* - * Restore default values to the AIC-6260 registers and reset the fifos - */ -static void aha152x_reset_ports(struct Scsi_Host *shpnt) -{ - /* disable interrupts */ - SETPORT(DMACNTRL0, RSTFIFO); - - SETPORT(SCSISEQ, 0); - - SETPORT(SXFRCTL1, 0); - SETPORT(SCSISIG, 0); - SETPORT(SCSIRATE, 0); - - /* clear all interrupt conditions */ - SETPORT(SSTAT0, 0x7f); - SETPORT(SSTAT1, 0xef); - - SETPORT(SSTAT4, SYNCERR|FWERR|FRERR); - - SETPORT(DMACNTRL0, 0); - SETPORT(DMACNTRL1, 0); - - SETPORT(BRSTCNTRL, 0xf1); - - /* clear SCSI fifo and transfer count */ - SETPORT(SXFRCTL0, CH1|CLRCH1|CLRSTCNT); - SETPORT(SXFRCTL0, CH1); - - /* enable interrupts */ - SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0); - SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0); -} - -/* - * Reset registers, reset a hanging bus and - * kill active and disconnected commands for target w/o soft reset - */ -int aha152x_reset(Scsi_Cmnd *SCpnt) -{ - struct Scsi_Host *shpnt = SCpnt->host; - unsigned long flags; - Scsi_Cmnd *ptr, *prev, *next; - - aha152x_reset_ports(shpnt); - - /* Reset, if bus hangs */ - if(TESTLO(SSTAT1, BUSFREE)) - { - CLRBITS(DMACNTRL0, INTEN); - -#if defined(DEBUG_RESET) - if(HOSTDATA(shpnt)->debug & debug_reset) - { - printk("aha152x: reset(), bus not free: SCSI RESET OUT\n"); - show_queues(shpnt); - } -#endif - - ptr=CURRENT_SC; - if(ptr && !ptr->device->soft_reset) - { - ptr->host_scribble = NULL; - ptr->result = DID_RESET << 16; - ptr->scsi_done(CURRENT_SC); - CURRENT_SC=NULL; - } - - save_flags(flags); - cli(); - prev=NULL; ptr=DISCONNECTED_SC; - while(ptr) - { - if(!ptr->device->soft_reset) - { - if(prev) - prev->host_scribble = ptr->host_scribble; - else - DISCONNECTED_SC = (Scsi_Cmnd *) ptr->host_scribble; - - next = (Scsi_Cmnd *) ptr->host_scribble; - - ptr->host_scribble = NULL; - ptr->result = DID_RESET << 16; - ptr->scsi_done(ptr); - - ptr = next; - } - else - { - prev=ptr; - ptr = (Scsi_Cmnd *) ptr->host_scribble; - } - } - restore_flags(flags); - -#if defined(DEBUG_RESET) - if(HOSTDATA(shpnt)->debug & debug_reset) - { - printk("commands on targets w/ soft-resets:\n"); - show_queues(shpnt); - } -#endif - - /* RESET OUT */ - SETPORT(SCSISEQ, SCSIRSTO); - do_pause(30); - SETPORT(SCSISEQ, 0); - do_pause(DELAY); - - SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0); - SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0); - - SETPORT(DMACNTRL0, INTEN); - } - - return SCSI_RESET_SUCCESS; -} - -/* - * Return the "logical geometry" - */ -int aha152x_biosparam(Scsi_Disk * disk, kdev_t dev, int *info_array) -{ - int size = disk->capacity; - -#if defined(DEBUG_BIOSPARAM) - if(HOSTDATA(shpnt)->debug & debug_biosparam) - printk("aha152x_biosparam: dev=%s, size=%d, ", kdevname(dev), size); -#endif - -/* I took this from other SCSI drivers, since it provides - the correct data for my devices. */ - info_array[0]=64; - info_array[1]=32; - info_array[2]=size>>11; - -#if defined(DEBUG_BIOSPARAM) - if(HOSTDATA(shpnt)->debug & debug_biosparam) - { - printk("bios geometry: head=%d, sec=%d, cyl=%d\n", - info_array[0], info_array[1], info_array[2]); - printk("WARNING: check, if the bios geometry is correct.\n"); - } -#endif - - return 0; -} - -/* - * Internal done function - */ -void aha152x_done(struct Scsi_Host *shpnt, int error) -{ - unsigned long flags; - Scsi_Cmnd *done_SC; - -#if defined(DEBUG_DONE) - if(HOSTDATA(shpnt)->debug & debug_done) - { - printk("\naha152x: done(), "); - disp_ports(shpnt); - } -#endif - - if (CURRENT_SC) - { -#if defined(DEBUG_DONE) - if(HOSTDATA(shpnt)->debug & debug_done) - printk("done(%x), ", error); -#endif - - save_flags(flags); - cli(); - - done_SC = CURRENT_SC; - CURRENT_SC = NULL; - - /* turn led off, when no commands are in the driver */ - HOSTDATA(shpnt)->commands--; - if(!HOSTDATA(shpnt)->commands) - SETPORT(PORTA, 0); /* turn led off */ - -#if defined(DEBUG_QUEUES) - if(HOSTDATA(shpnt)->debug & debug_queues) - printk("ok (%d), ", HOSTDATA(shpnt)->commands); -#endif - restore_flags(flags); - - SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0); - SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0); - -#if defined(DEBUG_PHASES) - if(HOSTDATA(shpnt)->debug & debug_phases) - printk("BUS FREE loop, "); -#endif - while(TESTLO(SSTAT1, BUSFREE)) - barrier(); -#if defined(DEBUG_PHASES) - if(HOSTDATA(shpnt)->debug & debug_phases) - printk("BUS FREE\n"); -#endif - - done_SC->result = error; - if(done_SC->scsi_done) - { -#if defined(DEBUG_DONE) - if(HOSTDATA(shpnt)->debug & debug_done) - printk("calling scsi_done, "); -#endif - done_SC->scsi_done(done_SC); -#if defined(DEBUG_DONE) - if(HOSTDATA(shpnt)->debug & debug_done) - printk("done returned, "); -#endif - } - else - panic("aha152x: current_SC->scsi_done() == NULL"); - } - else - aha152x_panic(shpnt, "done() called outside of command"); -} - -/* - * Interrupts handler (main routine of the driver) - */ -void aha152x_intr(int irqno, struct pt_regs * regs) -{ - struct Scsi_Host *shpnt = aha152x_host[irqno-IRQ_MIN]; - unsigned int flags; - int done=0, phase; - -#if defined(DEBUG_RACE) - enter_driver("intr"); -#else -#if defined(DEBUG_INTR) - if(HOSTDATA(shpnt)->debug & debug_intr) - printk("\naha152x: intr(), "); -#endif -#endif - - /* no more interrupts from the controller, while we busy. - INTEN has to be restored, when we're ready to leave - intr(). To avoid race conditions we have to return - immediately afterwards. */ - CLRBITS(DMACNTRL0, INTEN); - sti(); /* Yes, sti() really needs to be here */ - - /* disconnected target is trying to reconnect. - Only possible, if we have disconnected nexuses and - nothing is occupying the bus. - */ - if(TESTHI(SSTAT0, SELDI) && - DISCONNECTED_SC && - (!CURRENT_SC || (CURRENT_SC->SCp.phase & in_selection)) ) - { - int identify_msg, target, i; - - /* Avoid conflicts when a target reconnects - while we are trying to connect to another. */ - if(CURRENT_SC) - { -#if defined(DEBUG_QUEUES) - if(HOSTDATA(shpnt)->debug & debug_queues) - printk("i+, "); -#endif - save_flags(flags); - cli(); - append_SC(&ISSUE_SC, CURRENT_SC); - CURRENT_SC=NULL; - restore_flags(flags); - } - - /* disable sequences */ - SETPORT(SCSISEQ, 0); - SETPORT(SSTAT0, CLRSELDI); - SETPORT(SSTAT1, CLRBUSFREE); - -#if defined(DEBUG_QUEUES) || defined(DEBUG_PHASES) - if(HOSTDATA(shpnt)->debug & (debug_queues|debug_phases)) - printk("reselected, "); -#endif - - i = GETPORT(SELID) & ~(1 << shpnt->this_id); - target=0; - if(i) - for(; (i & 1)==0; target++, i>>=1) - ; - else - aha152x_panic(shpnt, "reconnecting target unknown"); - -#if defined(DEBUG_QUEUES) - if(HOSTDATA(shpnt)->debug & debug_queues) - printk("SELID=%02x, target=%d, ", GETPORT(SELID), target); -#endif - SETPORT(SCSIID, (shpnt->this_id << OID_) | target); - SETPORT(SCSISEQ, ENRESELI); - - if(TESTLO(SSTAT0, SELDI)) - aha152x_panic(shpnt, "RESELI failed"); - - SETPORT(SCSIRATE, HOSTDATA(shpnt)->syncrate[target]&0x7f); - - SETPORT(SCSISIG, P_MSGI); - - /* Get identify message */ - if((i=getphase(shpnt))!=P_MSGI) - { - printk("target doesn't enter MSGI to identify (phase=%02x)\n", i); - aha152x_panic(shpnt, "unknown lun"); - } - SETPORT(SCSISEQ, 0); - - SETPORT(SXFRCTL0, CH1); - - identify_msg = GETPORT(SCSIBUS); - - if(!(identify_msg & IDENTIFY_BASE)) - { - printk("target=%d, inbound message (%02x) != IDENTIFY\n", - target, identify_msg); - aha152x_panic(shpnt, "unknown lun"); - } - - -#if defined(DEBUG_QUEUES) - if(HOSTDATA(shpnt)->debug & debug_queues) - printk("identify=%02x, lun=%d, ", identify_msg, identify_msg & 0x3f); -#endif - - save_flags(flags); - cli(); - -#if defined(DEBUG_QUEUES) - if(HOSTDATA(shpnt)->debug & debug_queues) - printk("d-, "); -#endif - CURRENT_SC = remove_SC(&DISCONNECTED_SC, - target, - identify_msg & 0x3f); - - if(!CURRENT_SC) - { - printk("lun=%d, ", identify_msg & 0x3f); - aha152x_panic(shpnt, "no disconnected command for that lun"); - } - - CURRENT_SC->SCp.phase &= ~disconnected; - restore_flags(flags); - - make_acklow(shpnt); - if(getphase(shpnt)!=P_MSGI) { - SETPORT(SIMODE0, 0); - SETPORT(SIMODE1, ENPHASEMIS|ENBUSFREE); -#if defined(DEBUG_RACE) - leave_driver("(reselected) intr"); -#endif - SETBITS(DMACNTRL0, INTEN); - return; - } - } - - /* Check, if we aren't busy with a command */ - if(!CURRENT_SC) - { - /* bus is free to issue a queued command */ - if(TESTHI(SSTAT1, BUSFREE) && ISSUE_SC) - { - save_flags(flags); - cli(); -#if defined(DEBUG_QUEUES) - if(HOSTDATA(shpnt)->debug & debug_queues) - printk("i-, "); -#endif - CURRENT_SC = remove_first_SC(&ISSUE_SC); - restore_flags(flags); - -#if defined(DEBUG_INTR) || defined(DEBUG_SELECTION) || defined(DEBUG_PHASES) - if(HOSTDATA(shpnt)->debug & (debug_intr|debug_selection|debug_phases)) - printk("issuing command, "); -#endif - CURRENT_SC->SCp.phase = in_selection; - -#if defined(DEBUG_INTR) || defined(DEBUG_SELECTION) || defined(DEBUG_PHASES) - if(HOSTDATA(shpnt)->debug & (debug_intr|debug_selection|debug_phases)) - printk("selecting %d, ", CURRENT_SC->target); -#endif - SETPORT(SCSIID, (shpnt->this_id << OID_) | CURRENT_SC->target); - - /* Enable interrupts for SELECTION OUT DONE and SELECTION OUT INITIATED */ - SETPORT(SXFRCTL1, HOSTDATA(shpnt)->parity ? (ENSPCHK|ENSTIMER) : ENSTIMER); - - /* enable interrupts for SELECTION OUT DONE and SELECTION TIME OUT */ - SETPORT(SIMODE0, ENSELDO | (DISCONNECTED_SC ? ENSELDI : 0)); - SETPORT(SIMODE1, ENSELTIMO); - - /* Enable SELECTION OUT sequence */ - SETBITS(SCSISEQ, ENSELO | ENAUTOATNO); - - } - else - { - /* No command we are busy with and no new to issue */ - printk("aha152x: ignoring spurious interrupt, nothing to do\n"); - if(TESTHI(DMACNTRL0, SWINT)) { - printk("aha152x: SWINT is set! Why?\n"); - CLRBITS(DMACNTRL0, SWINT); - } - show_queues(shpnt); - } - -#if defined(DEBUG_RACE) - leave_driver("(selecting) intr"); -#endif - SETBITS(DMACNTRL0, INTEN); - return; - } - - /* the bus is busy with something */ - -#if defined(DEBUG_INTR) - if(HOSTDATA(shpnt)->debug & debug_intr) - disp_ports(shpnt); -#endif - - /* we are waiting for the result of a selection attempt */ - if(CURRENT_SC->SCp.phase & in_selection) - { - if(TESTLO(SSTAT1, SELTO)) - /* no timeout */ - if(TESTHI(SSTAT0, SELDO)) - { - /* clear BUS FREE interrupt */ - SETPORT(SSTAT1, CLRBUSFREE); - - /* Disable SELECTION OUT sequence */ - CLRBITS(SCSISEQ, ENSELO|ENAUTOATNO); - - /* Disable SELECTION OUT DONE interrupt */ - CLRBITS(SIMODE0, ENSELDO); - CLRBITS(SIMODE1, ENSELTIMO); - - if(TESTLO(SSTAT0, SELDO)) - { - printk("aha152x: passing bus free condition\n"); - -#if defined(DEBUG_RACE) - leave_driver("(passing bus free) intr"); -#endif - SETBITS(DMACNTRL0, INTEN); - - if(CURRENT_SC->SCp.phase & aborted) - { - HOSTDATA(shpnt)->abort_result=SCSI_ABORT_ERROR; - HOSTDATA(shpnt)->abortion_complete++; - } - - aha152x_done(shpnt, DID_NO_CONNECT << 16); - return; - } -#if defined(DEBUG_SELECTION) || defined(DEBUG_PHASES) - if(HOSTDATA(shpnt)->debug & (debug_selection|debug_phases)) - printk("SELDO (SELID=%x), ", GETPORT(SELID)); -#endif - - /* selection was done */ - SETPORT(SSTAT0, CLRSELDO); - -#if defined(DEBUG_ABORT) - if((HOSTDATA(shpnt)->debug & debug_abort) && (CURRENT_SC->SCp.phase & aborted)) - printk("(ABORT) target selected, "); -#endif - - CURRENT_SC->SCp.phase &= ~in_selection; - CURRENT_SC->SCp.phase |= in_other; - - ADDMSG(IDENTIFY(HOSTDATA(shpnt)->reconnect,CURRENT_SC->lun)); - - if(!(SYNCRATE&0x80) && HOSTDATA(shpnt)->synchronous) - { - ADDMSG(EXTENDED_MESSAGE); - ADDMSG(3); - ADDMSG(EXTENDED_SDTR); - ADDMSG(50); - ADDMSG(8); - - printk("outbound SDTR: "); - print_msg(&MSG(MSGLEN-5)); - - SYNCRATE=0x80; - CURRENT_SC->SCp.phase |= in_sync; - } - -#if defined(DEBUG_RACE) - leave_driver("(SELDO) intr"); -#endif - SETPORT(SCSIRATE, SYNCRATE&0x7f); - - SETPORT(SCSISIG, P_MSGO); - - SETPORT(SIMODE0, 0); - SETPORT(SIMODE1, ENREQINIT|ENBUSFREE); - SETBITS(DMACNTRL0, INTEN); - return; - } - else - aha152x_panic(shpnt, "neither timeout nor selection\007"); - else - { -#if defined(DEBUG_SELECTION) || defined(DEBUG_PHASES) - if(HOSTDATA(shpnt)->debug & (debug_selection|debug_phases)) - printk("SELTO, "); -#endif - /* end selection attempt */ - CLRBITS(SCSISEQ, ENSELO|ENAUTOATNO); - - /* timeout */ - SETPORT(SSTAT1, CLRSELTIMO); - - SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0); - SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0); - SETBITS(DMACNTRL0, INTEN); -#if defined(DEBUG_RACE) - leave_driver("(SELTO) intr"); -#endif - - if(CURRENT_SC->SCp.phase & aborted) - { -#if defined(DEBUG_ABORT) - if(HOSTDATA(shpnt)->debug & debug_abort) - printk("(ABORT) selection timeout, "); -#endif - HOSTDATA(shpnt)->abort_result=SCSI_ABORT_ERROR; - HOSTDATA(shpnt)->abortion_complete++; - } - - if(TESTLO(SSTAT0, SELINGO)) - /* ARBITRATION not won */ - aha152x_done(shpnt, DID_BUS_BUSY << 16); - else - /* ARBITRATION won, but SELECTION failed */ - aha152x_done(shpnt, DID_NO_CONNECT << 16); - - return; - } - } - - /* enable interrupt, when target leaves current phase */ - phase = getphase(shpnt); - if(!(phase & ~P_MASK)) /* "real" phase */ - SETPORT(SCSISIG, phase); - SETPORT(SSTAT1, CLRPHASECHG); - CURRENT_SC->SCp.phase = - (CURRENT_SC->SCp.phase & ~((P_MASK|1)<<16)) | (phase << 16); - - /* information transfer phase */ - switch(phase) - { - case P_MSGO: /* MESSAGE OUT */ - { - int i, identify=0, abort=0; - -#if defined(DEBUG_INTR) || defined(DEBUG_MSGO) || defined(DEBUG_PHASES) - if(HOSTDATA(shpnt)->debug & (debug_intr|debug_msgo|debug_phases)) - printk("MESSAGE OUT, "); -#endif - if(MSGLEN==0) - { - ADDMSG(MESSAGE_REJECT); -#if defined(DEBUG_MSGO) - if(HOSTDATA(shpnt)->debug & debug_msgo) - printk("unexpected MSGO; rejecting, "); -#endif - } - - - CLRBITS(SXFRCTL0, ENDMA); - - SETPORT(SIMODE0, 0); - SETPORT(SIMODE1, ENPHASEMIS|ENREQINIT|ENBUSFREE); - - /* wait for data latch to become ready or a phase change */ - while(TESTLO(DMASTAT, INTSTAT)) - barrier(); - -#if defined(DEBUG_MSGO) - if(HOSTDATA(shpnt)->debug & debug_msgo) - { - int i; - - printk("messages ("); - for(i=0; i<MSGLEN; i+=print_msg(&MSG(i)), printk(" ")) - ; - printk("), "); - } -#endif - - for(i=0; i<MSGLEN && TESTLO(SSTAT1, PHASEMIS); i++) - { -#if defined(DEBUG_MSGO) - if(HOSTDATA(shpnt)->debug & debug_msgo) - printk("%x ", MSG(i)); -#endif - if(i==MSGLEN-1) - { - /* Leave MESSAGE OUT after transfer */ - SETPORT(SSTAT1, CLRATNO); - } - - SETPORT(SCSIDAT, MSG(i)); - - make_acklow(shpnt); - getphase(shpnt); - - if(MSG(i)==IDENTIFY(HOSTDATA(shpnt)->reconnect,CURRENT_SC->lun)) - identify++; - - if(MSG(i)==ABORT) - abort++; - - } - - MSGLEN=0; - - if(identify) - CURRENT_SC->SCp.phase |= sent_ident; - - if(abort) - { - /* revive abort(); abort() enables interrupts */ - HOSTDATA(shpnt)->abort_result=SCSI_ABORT_SUCCESS; - HOSTDATA(shpnt)->abortion_complete++; - - CURRENT_SC->SCp.phase &= ~(P_MASK<<16); - - /* exit */ - SETBITS(DMACNTRL0, INTEN); -#if defined(DEBUG_RACE) - leave_driver("(ABORT) intr"); -#endif - aha152x_done(shpnt, DID_ABORT<<16); - return; - } - } - break; - - case P_CMD: /* COMMAND phase */ -#if defined(DEBUG_INTR) || defined(DEBUG_CMD) || defined(DEBUG_PHASES) - if(HOSTDATA(shpnt)->debug & (debug_intr|debug_cmd|debug_phases)) - printk("COMMAND, "); -#endif - if(!(CURRENT_SC->SCp.sent_command)) - { - int i; - - CLRBITS(SXFRCTL0, ENDMA); - - SETPORT(SIMODE0, 0); - SETPORT(SIMODE1, ENPHASEMIS|ENREQINIT|ENBUSFREE); - - /* wait for data latch to become ready or a phase change */ - while(TESTLO(DMASTAT, INTSTAT)) - barrier(); - - for(i=0; i<CURRENT_SC->cmd_len && TESTLO(SSTAT1, PHASEMIS); i++) - { - SETPORT(SCSIDAT, CURRENT_SC->cmnd[i]); - - make_acklow(shpnt); - getphase(shpnt); - } - - if(i<CURRENT_SC->cmd_len && TESTHI(SSTAT1, PHASEMIS)) - aha152x_panic(shpnt, "target left COMMAND"); - - CURRENT_SC->SCp.sent_command++; - } - else - aha152x_panic(shpnt, "Nothing to send while in COMMAND"); - break; - - case P_MSGI: /* MESSAGE IN phase */ - { - int start_sync=0; - -#if defined(DEBUG_INTR) || defined(DEBUG_MSGI) || defined(DEBUG_PHASES) - if(HOSTDATA(shpnt)->debug & (debug_intr|debug_msgi|debug_phases)) - printk("MESSAGE IN, "); -#endif - SETPORT(SXFRCTL0, CH1); - - SETPORT(SIMODE0, 0); - SETPORT(SIMODE1, ENBUSFREE); - - while(phase == P_MSGI) - { - CURRENT_SC->SCp.Message = GETPORT(SCSIDAT); - switch(CURRENT_SC->SCp.Message) - { - case DISCONNECT: -#if defined(DEBUG_MSGI) || defined(DEBUG_PHASES) - if(HOSTDATA(shpnt)->debug & (debug_msgi|debug_phases)) - printk("target disconnected, "); -#endif - CURRENT_SC->SCp.Message = 0; - CURRENT_SC->SCp.phase |= disconnected; - if(!HOSTDATA(shpnt)->reconnect) - aha152x_panic(shpnt, "target was not allowed to disconnect"); - break; - - case COMMAND_COMPLETE: -#if defined(DEBUG_MSGI) || defined(DEBUG_PHASES) - if(HOSTDATA(shpnt)->debug & (debug_msgi|debug_phases)) - printk("inbound message (COMMAND COMPLETE), "); -#endif - done++; - break; - - case MESSAGE_REJECT: - if(CURRENT_SC->SCp.phase & in_sync) - { - CURRENT_SC->SCp.phase &= ~in_sync; - SYNCRATE=0x80; - printk("synchronous rejected, "); - } - else - printk("inbound message (MESSAGE REJECT), "); -#if defined(DEBUG_MSGI) - if(HOSTDATA(shpnt)->debug & debug_msgi) - printk("inbound message (MESSAGE REJECT), "); -#endif - break; - - case SAVE_POINTERS: -#if defined(DEBUG_MSGI) - if(HOSTDATA(shpnt)->debug & debug_msgi) - printk("inbound message (SAVE DATA POINTERS), "); -#endif - break; - - case EXTENDED_MESSAGE: - { - char buffer[16]; - int i; - -#if defined(DEBUG_MSGI) - if(HOSTDATA(shpnt)->debug & debug_msgi) - printk("inbound message (EXTENDED MESSAGE), "); -#endif - make_acklow(shpnt); - if(getphase(shpnt)!=P_MSGI) - break; - - buffer[0]=EXTENDED_MESSAGE; - buffer[1]=GETPORT(SCSIDAT); - - for(i=0; i<buffer[1] && - (make_acklow(shpnt), getphase(shpnt)==P_MSGI); i++) - buffer[2+i]=GETPORT(SCSIDAT); - -#if defined(DEBUG_MSGI) - if(HOSTDATA(shpnt)->debug & debug_msgi) - print_msg(buffer); -#endif - - switch(buffer [2]) - { - case EXTENDED_SDTR: - { - long ticks; - - if(buffer[1]!=3) - aha152x_panic(shpnt, "SDTR message length != 3"); - - if(!HOSTDATA(shpnt)->synchronous) - break; - - printk("inbound SDTR: "); print_msg(buffer); - - ticks=(buffer[3]*4+49)/50; - - if(CURRENT_SC->SCp.phase & in_sync) - { - /* we initiated SDTR */ - if(ticks>9 || buffer[4]<1 || buffer[4]>8) - aha152x_panic(shpnt, "received SDTR invalid"); - - SYNCRATE |= ((ticks-2)<<4) + buffer[4]; - } - else if(ticks<=9 && buffer[4]>=1) - { - if(buffer[4]>8) - buffer[4]=8; - - ADDMSG(EXTENDED_MESSAGE); - ADDMSG(3); - ADDMSG(EXTENDED_SDTR); - if(ticks<4) - { - ticks=4; - ADDMSG(50); - } - else - ADDMSG(buffer[3]); - - ADDMSG(buffer[4]); - - printk("outbound SDTR: "); - print_msg(&MSG(MSGLEN-5)); - - CURRENT_SC->SCp.phase |= in_sync; - - SYNCRATE |= ((ticks-2)<<4) + buffer[4]; - - start_sync++; - } - else - { - /* requested SDTR is too slow, do it asynchronously */ - ADDMSG(MESSAGE_REJECT); - SYNCRATE = 0; - } - - SETPORT(SCSIRATE, SYNCRATE&0x7f); - } - break; - - case EXTENDED_MODIFY_DATA_POINTER: - case EXTENDED_EXTENDED_IDENTIFY: - case EXTENDED_WDTR: - default: - ADDMSG(MESSAGE_REJECT); - break; - } - } - break; - - default: - printk("unsupported inbound message %x, ", - CURRENT_SC->SCp.Message); - break; - - } - - make_acklow(shpnt); - phase=getphase(shpnt); - } - - if(start_sync) - CURRENT_SC->SCp.phase |= in_sync; - else - CURRENT_SC->SCp.phase &= ~in_sync; - - if(MSGLEN>0) - SETPORT(SCSISIG, P_MSGI|ATNO); - - /* clear SCSI fifo on BUSFREE */ - if(phase==P_BUSFREE) - SETPORT(SXFRCTL0, CH1|CLRCH1); - - if(CURRENT_SC->SCp.phase & disconnected) - { - save_flags(flags); - cli(); -#if defined(DEBUG_QUEUES) - if(HOSTDATA(shpnt)->debug & debug_queues) - printk("d+, "); -#endif - append_SC(&DISCONNECTED_SC, CURRENT_SC); - CURRENT_SC->SCp.phase |= 1<<16; - CURRENT_SC = NULL; - restore_flags(flags); - - SETBITS(SCSISEQ, ENRESELI); - - SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0); - SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0); - - SETBITS(DMACNTRL0, INTEN); - return; - } - } - break; - - case P_STATUS: /* STATUS IN phase */ -#if defined(DEBUG_STATUS) || defined(DEBUG_INTR) || defined(DEBUG_PHASES) - if(HOSTDATA(shpnt)->debug & (debug_status|debug_intr|debug_phases)) - printk("STATUS, "); -#endif - SETPORT(SXFRCTL0, CH1); - - SETPORT(SIMODE0, 0); - SETPORT(SIMODE1, ENREQINIT|ENBUSFREE); - - if(TESTHI(SSTAT1, PHASEMIS)) - printk("aha152x: passing STATUS phase"); - - CURRENT_SC->SCp.Status = GETPORT(SCSIBUS); - make_acklow(shpnt); - getphase(shpnt); - -#if defined(DEBUG_STATUS) - if(HOSTDATA(shpnt)->debug & debug_status) - { - printk("inbound status "); - print_status(CURRENT_SC->SCp.Status); - printk(", "); - } -#endif - break; - - case P_DATAI: /* DATA IN phase */ - { - int fifodata, data_count, done; - -#if defined(DEBUG_DATAI) || defined(DEBUG_INTR) || defined(DEBUG_PHASES) - if(HOSTDATA(shpnt)->debug & (debug_datai|debug_intr|debug_phases)) - printk("DATA IN, "); -#endif - -#if 0 - if(GETPORT(FIFOSTAT) || GETPORT(SSTAT2) & (SFULL|SFCNT)) - printk("aha152x: P_DATAI: %d(%d) bytes left in FIFO, resetting\n", - GETPORT(FIFOSTAT), GETPORT(SSTAT2) & (SFULL|SFCNT)); -#endif - - /* reset host fifo */ - SETPORT(DMACNTRL0, RSTFIFO); - SETPORT(DMACNTRL0, RSTFIFO|ENDMA); - - SETPORT(SXFRCTL0, CH1|SCSIEN|DMAEN); - - SETPORT(SIMODE0, 0); - SETPORT(SIMODE1, ENPHASEMIS|ENBUSFREE); - - /* done is set when the FIFO is empty after the target left DATA IN */ - done=0; - - /* while the target stays in DATA to transfer data */ - while (!done) - { -#if defined(DEBUG_DATAI) - if(HOSTDATA(shpnt)->debug & debug_datai) - printk("expecting data, "); -#endif - /* wait for PHASEMIS or full FIFO */ - while(TESTLO (DMASTAT, DFIFOFULL|INTSTAT)) - barrier(); - -#if defined(DEBUG_DATAI) - if(HOSTDATA(shpnt)->debug & debug_datai) - printk("ok, "); -#endif - - if(TESTHI(DMASTAT, DFIFOFULL)) - fifodata=GETPORT(FIFOSTAT); - else - { - /* wait for SCSI fifo to get empty */ - while(TESTLO(SSTAT2, SEMPTY)) - barrier(); - - /* rest of data in FIFO */ - fifodata=GETPORT(FIFOSTAT); -#if defined(DEBUG_DATAI) - if(HOSTDATA(shpnt)->debug & debug_datai) - printk("last transfer, "); -#endif - done=1; - } - -#if defined(DEBUG_DATAI) - if(HOSTDATA(shpnt)->debug & debug_datai) - printk("fifodata=%d, ", fifodata); -#endif - - while(fifodata && CURRENT_SC->SCp.this_residual) - { - data_count=fifodata; - - /* limit data transfer to size of first sg buffer */ - if (data_count > CURRENT_SC->SCp.this_residual) - data_count = CURRENT_SC->SCp.this_residual; - - fifodata -= data_count; - -#if defined(DEBUG_DATAI) - if(HOSTDATA(shpnt)->debug & debug_datai) - printk("data_count=%d, ", data_count); -#endif - - if(data_count&1) - { - /* get a single byte in byte mode */ - SETBITS(DMACNTRL0, _8BIT); - *CURRENT_SC->SCp.ptr++ = GETPORT(DATAPORT); - CURRENT_SC->SCp.this_residual--; - } - if(data_count>1) - { - CLRBITS(DMACNTRL0, _8BIT); - data_count >>= 1; /* Number of words */ - insw(DATAPORT, CURRENT_SC->SCp.ptr, data_count); -#if defined(DEBUG_DATAI) - if(HOSTDATA(shpnt)->debug & debug_datai) - /* show what comes with the last transfer */ - if(done) - { -#ifdef 0 - int i; - unsigned char *data; -#endif - - printk("data on last transfer (%d bytes) ", - 2*data_count); -#ifdef 0 - printk("data on last transfer (%d bytes: ", - 2*data_count); - data = (unsigned char *) CURRENT_SC->SCp.ptr; - for(i=0; i<2*data_count; i++) - printk("%2x ", *data++); - printk("), "); -#endif - } -#endif - CURRENT_SC->SCp.ptr += 2 * data_count; - CURRENT_SC->SCp.this_residual -= 2 * data_count; - } - - /* if this buffer is full and there are more buffers left */ - if (!CURRENT_SC->SCp.this_residual && - CURRENT_SC->SCp.buffers_residual) - { - /* advance to next buffer */ - CURRENT_SC->SCp.buffers_residual--; - CURRENT_SC->SCp.buffer++; - CURRENT_SC->SCp.ptr = - CURRENT_SC->SCp.buffer->address; - CURRENT_SC->SCp.this_residual = - CURRENT_SC->SCp.buffer->length; - } - } - - /* - * Fifo should be empty - */ - if(fifodata>0) - { - printk("aha152x: more data than expected (%d bytes)\n", - GETPORT(FIFOSTAT)); - SETBITS(DMACNTRL0, _8BIT); - printk("aha152x: data ("); - while(fifodata--) - printk("%2x ", GETPORT(DATAPORT)); - printk(")\n"); - } - -#if defined(DEBUG_DATAI) - if(HOSTDATA(shpnt)->debug & debug_datai) - if(!fifodata) - printk("fifo empty, "); - else - printk("something left in fifo, "); -#endif - } - -#if defined(DEBUG_DATAI) - if((HOSTDATA(shpnt)->debug & debug_datai) && - (CURRENT_SC->SCp.buffers_residual || - CURRENT_SC->SCp.this_residual)) - printk("left buffers (buffers=%d, bytes=%d), ", - CURRENT_SC->SCp.buffers_residual, - CURRENT_SC->SCp.this_residual); -#endif - /* transfer can be considered ended, when SCSIEN reads back zero */ - CLRBITS(SXFRCTL0, SCSIEN|DMAEN); - while(TESTHI(SXFRCTL0, SCSIEN)) - barrier(); - CLRBITS(DMACNTRL0, ENDMA); - -#if defined(DEBUG_DATAI) || defined(DEBUG_INTR) - if(HOSTDATA(shpnt)->debug & (debug_datai|debug_intr)) - printk("got %d bytes, ", GETSTCNT()); -#endif - - CURRENT_SC->SCp.have_data_in++; - } - break; - - case P_DATAO: /* DATA OUT phase */ - { - int data_count; - -#if defined(DEBUG_DATAO) || defined(DEBUG_INTR) || defined(DEBUG_PHASES) - if(HOSTDATA(shpnt)->debug & (debug_datao|debug_intr|debug_phases)) - printk("DATA OUT, "); -#endif -#if defined(DEBUG_DATAO) - if(HOSTDATA(shpnt)->debug & debug_datao) - printk("got data to send (bytes=%d, buffers=%d), ", - CURRENT_SC->SCp.this_residual, - CURRENT_SC->SCp.buffers_residual); -#endif - - if(GETPORT(FIFOSTAT) || GETPORT(SSTAT2) & (SFULL|SFCNT)) - { - printk("%d(%d) left in FIFO, ", - GETPORT(FIFOSTAT), GETPORT(SSTAT2) & (SFULL|SFCNT)); - aha152x_panic(shpnt, "FIFO should be empty"); - } - - SETPORT(SXFRCTL0, CH1|CLRSTCNT|CLRCH1); - SETPORT(SXFRCTL0, SCSIEN|DMAEN|CH1); - - SETPORT(DMACNTRL0, WRITE_READ|RSTFIFO); - SETPORT(DMACNTRL0, ENDMA|WRITE_READ); - - SETPORT(SIMODE0, 0); - SETPORT(SIMODE1, ENPHASEMIS|ENBUSFREE); - - /* while current buffer is not empty or - there are more buffers to transfer */ - while(TESTLO(SSTAT1, PHASEMIS) && - (CURRENT_SC->SCp.this_residual || - CURRENT_SC->SCp.buffers_residual)) - { -#if defined(DEBUG_DATAO) - if(HOSTDATA(shpnt)->debug & debug_datao) - printk("sending data (left: bytes=%d, buffers=%d), waiting, ", - CURRENT_SC->SCp.this_residual, - CURRENT_SC->SCp.buffers_residual); -#endif - /* transfer rest of buffer, but max. 128 byte */ - data_count = - CURRENT_SC->SCp.this_residual > 128 ? - 128 : CURRENT_SC->SCp.this_residual ; - -#if defined(DEBUG_DATAO) - if(HOSTDATA(shpnt)->debug & debug_datao) - printk("data_count=%d, ", data_count); -#endif - - if(data_count&1) - { - /* put a single byte in byte mode */ - SETBITS(DMACNTRL0, _8BIT); - SETPORT(DATAPORT, *CURRENT_SC->SCp.ptr++); - CURRENT_SC->SCp.this_residual--; - } - if(data_count>1) - { - CLRBITS(DMACNTRL0, _8BIT); - data_count >>= 1; /* number of words */ - outsw(DATAPORT, CURRENT_SC->SCp.ptr, data_count); - CURRENT_SC->SCp.ptr += 2 * data_count; - CURRENT_SC->SCp.this_residual -= 2 * data_count; - } - - /* wait for FIFO to get empty */ - while(TESTLO(DMASTAT, DFIFOEMP|INTSTAT)) - barrier(); - -#if defined(DEBUG_DATAO) - if(HOSTDATA(shpnt)->debug & debug_datao) - printk("fifo (%d bytes), transfered (%d bytes), ", - GETPORT(FIFOSTAT), GETSTCNT()); -#endif - - /* if this buffer is empty and there are more buffers left */ - if (TESTLO(SSTAT1, PHASEMIS) && - !CURRENT_SC->SCp.this_residual && - CURRENT_SC->SCp.buffers_residual) - { - /* advance to next buffer */ - CURRENT_SC->SCp.buffers_residual--; - CURRENT_SC->SCp.buffer++; - CURRENT_SC->SCp.ptr = - CURRENT_SC->SCp.buffer->address; - CURRENT_SC->SCp.this_residual = - CURRENT_SC->SCp.buffer->length; - } - } - - if (CURRENT_SC->SCp.this_residual || CURRENT_SC->SCp.buffers_residual) - { - /* target leaves DATA OUT for an other phase - (perhaps disconnect) */ - - /* data in fifos has to be resend */ - data_count = GETPORT(SSTAT2) & (SFULL|SFCNT); - - data_count += GETPORT(FIFOSTAT) ; - CURRENT_SC->SCp.ptr -= data_count; - CURRENT_SC->SCp.this_residual += data_count; -#if defined(DEBUG_DATAO) - if(HOSTDATA(shpnt)->debug & debug_datao) - printk("left data (bytes=%d, buffers=%d), fifos (bytes=%d), " - "transfer incomplete, resetting fifo, ", - CURRENT_SC->SCp.this_residual, - CURRENT_SC->SCp.buffers_residual, - data_count); -#endif - SETPORT(DMACNTRL0, WRITE_READ|RSTFIFO); - CLRBITS(SXFRCTL0, SCSIEN|DMAEN); - CLRBITS(DMACNTRL0, ENDMA); - } - else - { -#if defined(DEBUG_DATAO) - if(HOSTDATA(shpnt)->debug & debug_datao) - printk("waiting for SCSI fifo to get empty, "); -#endif - /* wait for SCSI fifo to get empty */ - while(TESTLO(SSTAT2, SEMPTY)) - barrier(); -#if defined(DEBUG_DATAO) - if(HOSTDATA(shpnt)->debug & debug_datao) - printk("ok, left data (bytes=%d, buffers=%d) ", - CURRENT_SC->SCp.this_residual, - CURRENT_SC->SCp.buffers_residual); -#endif - CLRBITS(SXFRCTL0, SCSIEN|DMAEN); - - /* transfer can be considered ended, when SCSIEN reads back zero */ - while(TESTHI(SXFRCTL0, SCSIEN)) - barrier(); - - CLRBITS(DMACNTRL0, ENDMA); - } - -#if defined(DEBUG_DATAO) || defined(DEBUG_INTR) - if(HOSTDATA(shpnt)->debug & (debug_datao|debug_intr)) - printk("sent %d data bytes, ", GETSTCNT()); -#endif - } - break; - - case P_BUSFREE: /* BUSFREE */ -#if defined(DEBUG_RACE) - leave_driver("(BUSFREE) intr"); -#endif -#if defined(DEBUG_PHASES) - if(HOSTDATA(shpnt)->debug & debug_phases) - printk("unexpected BUS FREE, "); -#endif - CURRENT_SC->SCp.phase &= ~(P_MASK<<16); - - aha152x_done(shpnt, DID_ERROR << 16); /* Don't know any better */ - return; - break; - - case P_PARITY: /* parity error in DATA phase */ -#if defined(DEBUG_RACE) - leave_driver("(DID_PARITY) intr"); -#endif - printk("PARITY error in DATA phase, "); - - CURRENT_SC->SCp.phase &= ~(P_MASK<<16); - - SETBITS(DMACNTRL0, INTEN); - aha152x_done(shpnt, DID_PARITY << 16); - return; - break; - - default: - printk("aha152x: unexpected phase\n"); - break; - } - - if(done) - { -#if defined(DEBUG_INTR) - if(HOSTDATA(shpnt)->debug & debug_intr) - printk("command done.\n"); -#endif -#if defined(DEBUG_RACE) - leave_driver("(done) intr"); -#endif - - SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0); - SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0); - SETPORT(SCSISEQ, DISCONNECTED_SC ? ENRESELI : 0); - - SETBITS(DMACNTRL0, INTEN); - - aha152x_done(shpnt, - (CURRENT_SC->SCp.Status & 0xff) - | ((CURRENT_SC->SCp.Message & 0xff) << 8) - | (DID_OK << 16)); - -#if defined(DEBUG_RACE) - printk("done returned (DID_OK: Status=%x; Message=%x).\n", - CURRENT_SC->SCp.Status, CURRENT_SC->SCp.Message); -#endif - return; - } - - if(CURRENT_SC) - CURRENT_SC->SCp.phase |= 1<<16 ; - - SETPORT(SIMODE0, 0); - SETPORT(SIMODE1, ENPHASEMIS|ENBUSFREE); -#if defined(DEBUG_INTR) - if(HOSTDATA(shpnt)->debug & debug_intr) - disp_enintr(shpnt); -#endif -#if defined(DEBUG_RACE) - leave_driver("(PHASEEND) intr"); -#endif - - SETBITS(DMACNTRL0, INTEN); - return; -} - -/* - * Dump the current driver status and panic... - */ -static void aha152x_panic(struct Scsi_Host *shpnt, char *msg) -{ - printk("\naha152x: %s\n", msg); - show_queues(shpnt); - panic("aha152x panic"); -} - -/* - * Display registers of AIC-6260 - */ -static void disp_ports(struct Scsi_Host *shpnt) -{ -#ifdef DEBUG_AHA152X - int s; - -#ifdef SKIP_PORTS - if(HOSTDATA(shpnt)->debug & debug_skipports) - return; -#endif - - printk("\n%s: ", CURRENT_SC ? "on bus" : "waiting"); - - s=GETPORT(SCSISEQ); - printk("SCSISEQ ("); - if(s & TEMODEO) printk("TARGET MODE "); - if(s & ENSELO) printk("SELO "); - if(s & ENSELI) printk("SELI "); - if(s & ENRESELI) printk("RESELI "); - if(s & ENAUTOATNO) printk("AUTOATNO "); - if(s & ENAUTOATNI) printk("AUTOATNI "); - if(s & ENAUTOATNP) printk("AUTOATNP "); - if(s & SCSIRSTO) printk("SCSIRSTO "); - printk(");"); - - printk(" SCSISIG ("); - s=GETPORT(SCSISIG); - switch(s & P_MASK) - { - case P_DATAO: - printk("DATA OUT"); - break; - case P_DATAI: - printk("DATA IN"); - break; - case P_CMD: - printk("COMMAND"); - break; - case P_STATUS: - printk("STATUS"); - break; - case P_MSGO: - printk("MESSAGE OUT"); - break; - case P_MSGI: - printk("MESSAGE IN"); - break; - default: - printk("*illegal*"); - break; - } - - printk("); "); - - printk("INTSTAT (%s); ", TESTHI(DMASTAT, INTSTAT) ? "hi" : "lo"); - - printk("SSTAT ("); - s=GETPORT(SSTAT0); - if(s & TARGET) printk("TARGET "); - if(s & SELDO) printk("SELDO "); - if(s & SELDI) printk("SELDI "); - if(s & SELINGO) printk("SELINGO "); - if(s & SWRAP) printk("SWRAP "); - if(s & SDONE) printk("SDONE "); - if(s & SPIORDY) printk("SPIORDY "); - if(s & DMADONE) printk("DMADONE "); - - s=GETPORT(SSTAT1); - if(s & SELTO) printk("SELTO "); - if(s & ATNTARG) printk("ATNTARG "); - if(s & SCSIRSTI) printk("SCSIRSTI "); - if(s & PHASEMIS) printk("PHASEMIS "); - if(s & BUSFREE) printk("BUSFREE "); - if(s & SCSIPERR) printk("SCSIPERR "); - if(s & PHASECHG) printk("PHASECHG "); - if(s & REQINIT) printk("REQINIT "); - printk("); "); - - - printk("SSTAT ("); - - s=GETPORT(SSTAT0) & GETPORT(SIMODE0); - - if(s & TARGET) printk("TARGET "); - if(s & SELDO) printk("SELDO "); - if(s & SELDI) printk("SELDI "); - if(s & SELINGO) printk("SELINGO "); - if(s & SWRAP) printk("SWRAP "); - if(s & SDONE) printk("SDONE "); - if(s & SPIORDY) printk("SPIORDY "); - if(s & DMADONE) printk("DMADONE "); - - s=GETPORT(SSTAT1) & GETPORT(SIMODE1); - - if(s & SELTO) printk("SELTO "); - if(s & ATNTARG) printk("ATNTARG "); - if(s & SCSIRSTI) printk("SCSIRSTI "); - if(s & PHASEMIS) printk("PHASEMIS "); - if(s & BUSFREE) printk("BUSFREE "); - if(s & SCSIPERR) printk("SCSIPERR "); - if(s & PHASECHG) printk("PHASECHG "); - if(s & REQINIT) printk("REQINIT "); - printk("); "); - - printk("SXFRCTL0 ("); - - s=GETPORT(SXFRCTL0); - if(s & SCSIEN) printk("SCSIEN "); - if(s & DMAEN) printk("DMAEN "); - if(s & CH1) printk("CH1 "); - if(s & CLRSTCNT) printk("CLRSTCNT "); - if(s & SPIOEN) printk("SPIOEN "); - if(s & CLRCH1) printk("CLRCH1 "); - printk("); "); - - printk("SIGNAL ("); - - s=GETPORT(SCSISIG); - if(s & ATNI) printk("ATNI "); - if(s & SELI) printk("SELI "); - if(s & BSYI) printk("BSYI "); - if(s & REQI) printk("REQI "); - if(s & ACKI) printk("ACKI "); - printk("); "); - - printk("SELID (%02x), ", GETPORT(SELID)); - - printk("SSTAT2 ("); - - s=GETPORT(SSTAT2); - if(s & SOFFSET) printk("SOFFSET "); - if(s & SEMPTY) printk("SEMPTY "); - if(s & SFULL) printk("SFULL "); - printk("); SFCNT (%d); ", s & (SFULL|SFCNT)); - - s=GETPORT(SSTAT3); - printk("SCSICNT (%d), OFFCNT(%d), ", (s&0xf0)>>4, s&0x0f); - - printk("SSTAT4 ("); - s=GETPORT(SSTAT4); - if(s & SYNCERR) printk("SYNCERR "); - if(s & FWERR) printk("FWERR "); - if(s & FRERR) printk("FRERR "); - printk("); "); - - printk("DMACNTRL0 ("); - s=GETPORT(DMACNTRL0); - printk("%s ", s & _8BIT ? "8BIT" : "16BIT"); - printk("%s ", s & DMA ? "DMA" : "PIO" ); - printk("%s ", s & WRITE_READ ? "WRITE" : "READ" ); - if(s & ENDMA) printk("ENDMA "); - if(s & INTEN) printk("INTEN "); - if(s & RSTFIFO) printk("RSTFIFO "); - if(s & SWINT) printk("SWINT "); - printk("); "); - - -#if 0 - printk("DMACNTRL1 ("); - - s=GETPORT(DMACNTRL1); - if(s & PWRDWN) printk("PWRDN "); - printk("); "); - - - printk("STK (%d); ", s & 0xf); - -#endif - - printk("DMASTAT ("); - s=GETPORT(DMASTAT); - if(s & ATDONE) printk("ATDONE "); - if(s & WORDRDY) printk("WORDRDY "); - if(s & DFIFOFULL) printk("DFIFOFULL "); - if(s & DFIFOEMP) printk("DFIFOEMP "); - printk(")"); - - printk("\n"); -#endif -} - -/* - * display enabled interrupts - */ -static void disp_enintr(struct Scsi_Host *shpnt) -{ - int s; - - printk("enabled interrupts ("); - - s=GETPORT(SIMODE0); - if(s & ENSELDO) printk("ENSELDO "); - if(s & ENSELDI) printk("ENSELDI "); - if(s & ENSELINGO) printk("ENSELINGO "); - if(s & ENSWRAP) printk("ENSWRAP "); - if(s & ENSDONE) printk("ENSDONE "); - if(s & ENSPIORDY) printk("ENSPIORDY "); - if(s & ENDMADONE) printk("ENDMADONE "); - - s=GETPORT(SIMODE1); - if(s & ENSELTIMO) printk("ENSELTIMO "); - if(s & ENATNTARG) printk("ENATNTARG "); - if(s & ENPHASEMIS) printk("ENPHASEMIS "); - if(s & ENBUSFREE) printk("ENBUSFREE "); - if(s & ENSCSIPERR) printk("ENSCSIPERR "); - if(s & ENPHASECHG) printk("ENPHASECHG "); - if(s & ENREQINIT) printk("ENREQINIT "); - printk(")\n"); -} - -#if defined(DEBUG_RACE) - -static const char *should_leave; -static int in_driver=0; - -/* - * Only one routine can be in the driver at once. - */ -static void enter_driver(const char *func) -{ - unsigned long flags; - - save_flags(flags); - cli(); - printk("aha152x: entering %s() (%x)\n", func, jiffies); - if(in_driver) - { - printk("%s should leave first.\n", should_leave); - panic("aha152x: already in driver\n"); - } - - in_driver++; - should_leave=func; - restore_flags(flags); -} - -static void leave_driver(const char *func) -{ - unsigned long flags; - - save_flags(flags); - cli(); - printk("\naha152x: leaving %s() (%x)\n", func, jiffies); - if(!in_driver) - { - printk("aha152x: %s already left.\n", should_leave); - panic("aha152x: %s already left driver.\n"); - } - - in_driver--; - should_leave=func; - restore_flags(flags); -} -#endif - -/* - * Show the command data of a command - */ -static void show_command(Scsi_Cmnd *ptr) -{ - printk("0x%08x: target=%d; lun=%d; cmnd=(", - (unsigned int) ptr, ptr->target, ptr->lun); - - print_command(ptr->cmnd); - - printk("); residual=%d; buffers=%d; phase |", - ptr->SCp.this_residual, ptr->SCp.buffers_residual); - - if(ptr->SCp.phase & not_issued ) printk("not issued|"); - if(ptr->SCp.phase & in_selection) printk("in selection|"); - if(ptr->SCp.phase & disconnected) printk("disconnected|"); - if(ptr->SCp.phase & aborted ) printk("aborted|"); - if(ptr->SCp.phase & sent_ident ) printk("send_ident|"); - if(ptr->SCp.phase & in_other) - { - printk("; in other("); - switch((ptr->SCp.phase >> 16) & P_MASK) - { - case P_DATAO: - printk("DATA OUT"); - break; - case P_DATAI: - printk("DATA IN"); - break; - case P_CMD: - printk("COMMAND"); - break; - case P_STATUS: - printk("STATUS"); - break; - case P_MSGO: - printk("MESSAGE OUT"); - break; - case P_MSGI: - printk("MESSAGE IN"); - break; - default: - printk("*illegal*"); - break; - } - printk(")"); - if(ptr->SCp.phase & (1<<16)) - printk("; phaseend"); - } - printk("; next=0x%08x\n", (unsigned int) ptr->host_scribble); -} - -/* - * Dump the queued data - */ -static void show_queues(struct Scsi_Host *shpnt) -{ - unsigned long flags; - Scsi_Cmnd *ptr; - - save_flags(flags); - cli(); - printk("QUEUE STATUS:\nissue_SC:\n"); - for(ptr=ISSUE_SC; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble) - show_command(ptr); - - printk("current_SC:\n"); - if(CURRENT_SC) - show_command(CURRENT_SC); - else - printk("none\n"); - - printk("disconnected_SC:\n"); - for(ptr=DISCONNECTED_SC; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble) - show_command(ptr); - - disp_ports(shpnt); - disp_enintr(shpnt); - restore_flags(flags); -} - -int aha152x_set_info(char *buffer, int length, struct Scsi_Host *shpnt) -{ - return(-ENOSYS); /* Currently this is a no-op */ -} - -#undef SPRINTF -#define SPRINTF(args...) pos += sprintf(pos, ## args) - -static int get_command(char *pos, Scsi_Cmnd *ptr) -{ - char *start = pos; - int i; - - SPRINTF("0x%08x: target=%d; lun=%d; cmnd=(", - (unsigned int) ptr, ptr->target, ptr->lun); - - for(i=0; i<COMMAND_SIZE(ptr->cmnd[0]); i++) - SPRINTF("0x%02x", ptr->cmnd[i]); - - SPRINTF("); residual=%d; buffers=%d; phase |", - ptr->SCp.this_residual, ptr->SCp.buffers_residual); - - if(ptr->SCp.phase & not_issued ) SPRINTF("not issued|"); - if(ptr->SCp.phase & in_selection) SPRINTF("in selection|"); - if(ptr->SCp.phase & disconnected) SPRINTF("disconnected|"); - if(ptr->SCp.phase & aborted ) SPRINTF("aborted|"); - if(ptr->SCp.phase & sent_ident ) SPRINTF("send_ident|"); - if(ptr->SCp.phase & in_other) - { - SPRINTF("; in other("); - switch((ptr->SCp.phase >> 16) & P_MASK) - { - case P_DATAO: - SPRINTF("DATA OUT"); - break; - case P_DATAI: - SPRINTF("DATA IN"); - break; - case P_CMD: - SPRINTF("COMMAND"); - break; - case P_STATUS: - SPRINTF("STATUS"); - break; - case P_MSGO: - SPRINTF("MESSAGE OUT"); - break; - case P_MSGI: - SPRINTF("MESSAGE IN"); - break; - default: - SPRINTF("*illegal*"); - break; - } - SPRINTF(")"); - if(ptr->SCp.phase & (1<<16)) - SPRINTF("; phaseend"); - } - SPRINTF("; next=0x%08x\n", (unsigned int) ptr->host_scribble); - - return(pos-start); -} - -#undef SPRINTF -#define SPRINTF(args...) do { if(pos < buffer + length) pos += sprintf(pos, ## args); } while(0) - -int aha152x_proc_info( - char *buffer, - char **start, - off_t offset, - int length, - int hostno, - int inout - ) -{ - int i; - char *pos = buffer; - Scsi_Device *scd; - struct Scsi_Host *shpnt; - unsigned long flags; - Scsi_Cmnd *ptr; - - for(i=0, shpnt= (struct Scsi_Host *) NULL; i<IRQS; i++) - if(aha152x_host[i] && aha152x_host[i]->host_no == hostno) - shpnt=aha152x_host[i]; - - if(!shpnt) - return(-ESRCH); - - if(inout) /* Has data been written to the file ? */ - return(aha152x_set_info(buffer, length, shpnt)); - - SPRINTF(AHA152X_REVID "\n"); - - save_flags(flags); - cli(); - - SPRINTF("vital data:\nioports 0x%04x to 0x%04x\n", - shpnt->io_port, shpnt->io_port+shpnt->n_io_port-1); - SPRINTF("interrupt 0x%02x\n", shpnt->irq); - SPRINTF("disconnection/reconnection %s\n", - HOSTDATA(shpnt)->reconnect ? "enabled" : "disabled"); - SPRINTF("parity checking %s\n", - HOSTDATA(shpnt)->parity ? "enabled" : "disabled"); - SPRINTF("synchronous transfers %s\n", - HOSTDATA(shpnt)->synchronous ? "enabled" : "disabled"); - SPRINTF("current queued %d commands\n", - HOSTDATA(shpnt)->commands); - -#if 0 - SPRINTF("synchronously operating targets (tick=%ld ns):\n", - 250000000/loops_per_sec); - for(i=0; i<8; i++) - if(HOSTDATA(shpnt)->syncrate[i]&0x7f) - SPRINTF("target %d: period %dT/%ldns; req/ack offset %d\n", - i, - (((HOSTDATA(shpnt)->syncrate[i]&0x70)>>4)+2), - (((HOSTDATA(shpnt)->syncrate[i]&0x70)>>4)+2)* - 250000000/loops_per_sec, - HOSTDATA(shpnt)->syncrate[i]&0x0f); -#else - SPRINTF("synchronously operating targets (tick=50 ns):\n"); - for(i=0; i<8; i++) - if(HOSTDATA(shpnt)->syncrate[i]&0x7f) - SPRINTF("target %d: period %dT/%dns; req/ack offset %d\n", - i, - (((HOSTDATA(shpnt)->syncrate[i]&0x70)>>4)+2), - (((HOSTDATA(shpnt)->syncrate[i]&0x70)>>4)+2)*50, - HOSTDATA(shpnt)->syncrate[i]&0x0f); -#endif - -#ifdef DEBUG_AHA152X -#define PDEBUG(flags,txt) if(HOSTDATA(shpnt)->debug & flags) SPRINTF("(%s) ", txt); - - SPRINTF("enabled debugging options:\n"); - - PDEBUG(debug_skipports, "skip ports"); - PDEBUG(debug_queue, "queue"); - PDEBUG(debug_intr, "interrupt"); - PDEBUG(debug_selection, "selection"); - PDEBUG(debug_msgo, "message out"); - PDEBUG(debug_msgi, "message in"); - PDEBUG(debug_status, "status"); - PDEBUG(debug_cmd, "command"); - PDEBUG(debug_datai, "data in"); - PDEBUG(debug_datao, "data out"); - PDEBUG(debug_abort, "abort"); - PDEBUG(debug_done, "done"); - PDEBUG(debug_biosparam, "bios parameters"); - PDEBUG(debug_phases, "phases"); - PDEBUG(debug_queues, "queues"); - PDEBUG(debug_reset, "reset"); - - SPRINTF("\n"); -#endif - - SPRINTF("queue status:\nnot yet issued commands:\n"); - for(ptr=ISSUE_SC; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble) - pos += get_command(pos, ptr); - - if(CURRENT_SC) - { - SPRINTF("current command:\n"); - pos += get_command(pos, CURRENT_SC); - } - - SPRINTF("disconnected commands:\n"); - for(ptr=DISCONNECTED_SC; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble) - pos += get_command(pos, ptr); - - restore_flags(flags); - - scd = scsi_devices; - - SPRINTF("Attached devices: %s\n", (scd)?"":"none"); - - while (scd) { - if (scd->host == shpnt) { - - SPRINTF("Channel: %02d Id: %02d Lun: %02d\n Vendor: ", - scd->channel, scd->id, scd->lun); - for (i=0; i<8; i++) { - if (scd->vendor[i] >= 0x20) - SPRINTF("%c", scd->vendor[i]); - else - SPRINTF(" "); - } - SPRINTF(" Model: "); - for (i = 0; i < 16; i++) { - if (scd->model[i] >= 0x20) - SPRINTF("%c", scd->model[i]); - else - SPRINTF(" "); - } - SPRINTF(" Rev: "); - for (i = 0; i < 4; i++) { - if (scd->rev[i] >= 0x20) - SPRINTF("%c", scd->rev[i]); - else - SPRINTF(" "); - } - SPRINTF("\n"); - - SPRINTF(" Type: %d ", scd->type); - SPRINTF(" ANSI SCSI revision: %02x", - (scd->scsi_level < 3)?1:2); - - if (scd->scsi_level == 2) - SPRINTF(" CCS\n"); - else - SPRINTF("\n"); - } - scd = scd->next; - } - - *start=buffer+offset; - if (pos - buffer < offset) - return 0; - else if (pos - buffer - offset < length) - return pos - buffer - offset; - else - return length; -} - -#ifdef MODULE -/* Eventually this will go into an include file, but this will be later */ -Scsi_Host_Template driver_template = AHA152X; - -#include "scsi_module.c" -#endif diff --git a/i386/i386at/gpl/linux/scsi/aha152x.h b/i386/i386at/gpl/linux/scsi/aha152x.h deleted file mode 100644 index d62e5cfe..00000000 --- a/i386/i386at/gpl/linux/scsi/aha152x.h +++ /dev/null @@ -1,373 +0,0 @@ -#ifndef _AHA152X_H -#define _AHA152X_H - -/* - * $Id: aha152x.h,v 1.1.1.1 1997/02/25 21:27:46 thomas Exp $ - */ - -#if defined(__KERNEL__) - -#include <linux/blk.h> -#include "scsi.h" -#include <asm/io.h> - -int aha152x_detect(Scsi_Host_Template *); -int aha152x_command(Scsi_Cmnd *); -int aha152x_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); -int aha152x_abort(Scsi_Cmnd *); -int aha152x_reset(Scsi_Cmnd *); -int aha152x_biosparam(Disk *, kdev_t, int*); -int aha152x_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout); - -/* number of queueable commands - (unless we support more than 1 cmd_per_lun this should do) */ -#define AHA152X_MAXQUEUE 7 - -#define AHA152X_REVID "Adaptec 152x SCSI driver; $Revision: 1.1.1.1 $" - -extern struct proc_dir_entry proc_scsi_aha152x; - -/* Initial value of Scsi_Host entry */ -#define AHA152X { /* next */ NULL, \ - /* usage_count */ NULL, \ - /* proc_dir */ &proc_scsi_aha152x, \ - /* proc_info */ aha152x_proc_info, \ - /* name */ AHA152X_REVID, \ - /* detect */ aha152x_detect, \ - /* release */ NULL, \ - /* info */ NULL, \ - /* command */ aha152x_command, \ - /* queuecommand */ aha152x_queue, \ - /* abort */ aha152x_abort, \ - /* reset */ aha152x_reset, \ - /* slave_attach */ /* NULL */ 0, \ - /* bios_param */ aha152x_biosparam, \ - /* can_queue */ 1, \ - /* this_id */ 7, \ - /* sg_tablesize */ SG_ALL, \ - /* cmd_per_lun */ 1, \ - /* present */ 0, \ - /* unchecked_isa_dma */ 0, \ - /* use_clustering */ DISABLE_CLUSTERING } -#endif - - -/* port addresses */ -#define SCSISEQ (shpnt->io_port+0x00) /* SCSI sequence control */ -#define SXFRCTL0 (shpnt->io_port+0x01) /* SCSI transfer control 0 */ -#define SXFRCTL1 (shpnt->io_port+0x02) /* SCSI transfer control 1 */ -#define SCSISIG (shpnt->io_port+0x03) /* SCSI signal in/out */ -#define SCSIRATE (shpnt->io_port+0x04) /* SCSI rate control */ -#define SELID (shpnt->io_port+0x05) /* selection/reselection ID */ -#define SCSIID SELID /* SCSI ID */ -#define SCSIDAT (shpnt->io_port+0x06) /* SCSI latched data */ -#define SCSIBUS (shpnt->io_port+0x07) /* SCSI data bus */ -#define STCNT0 (shpnt->io_port+0x08) /* SCSI transfer count 0 */ -#define STCNT1 (shpnt->io_port+0x09) /* SCSI transfer count 1 */ -#define STCNT2 (shpnt->io_port+0x0a) /* SCSI transfer count 2 */ -#define SSTAT0 (shpnt->io_port+0x0b) /* SCSI interrupt status 0 */ -#define SSTAT1 (shpnt->io_port+0x0c) /* SCSI interrupt status 1 */ -#define SSTAT2 (shpnt->io_port+0x0d) /* SCSI interrupt status 2 */ -#define SCSITEST (shpnt->io_port+0x0e) /* SCSI test control */ -#define SSTAT3 SCSITEST /* SCSI interrupt status 3 */ -#define SSTAT4 (shpnt->io_port+0x0f) /* SCSI status 4 */ -#define SIMODE0 (shpnt->io_port+0x10) /* SCSI interrupt mode 0 */ -#define SIMODE1 (shpnt->io_port+0x11) /* SCSI interrupt mode 1 */ -#define DMACNTRL0 (shpnt->io_port+0x12) /* DMA control 0 */ -#define DMACNTRL1 (shpnt->io_port+0x13) /* DMA control 1 */ -#define DMASTAT (shpnt->io_port+0x14) /* DMA status */ -#define FIFOSTAT (shpnt->io_port+0x15) /* FIFO status */ -#define DATAPORT (shpnt->io_port+0x16) /* DATA port */ -#define BRSTCNTRL (shpnt->io_port+0x18) /* burst control */ -#define PORTA (shpnt->io_port+0x1a) /* PORT A */ -#define PORTB (shpnt->io_port+0x1b) /* PORT B */ -#define REV (shpnt->io_port+0x1c) /* revision */ -#define STACK (shpnt->io_port+0x1d) /* stack */ -#define TEST (shpnt->io_port+0x1e) /* test register */ - -/* used in aha152x_porttest */ -#define O_PORTA (0x1a) /* PORT A */ -#define O_PORTB (0x1b) /* PORT B */ -#define O_DMACNTRL1 (0x13) /* DMA control 1 */ -#define O_STACK (0x1d) /* stack */ -#define IO_RANGE 0x20 - -/* bits and bitmasks to ports */ - -/* SCSI sequence control */ -#define TEMODEO 0x80 -#define ENSELO 0x40 -#define ENSELI 0x20 -#define ENRESELI 0x10 -#define ENAUTOATNO 0x08 -#define ENAUTOATNI 0x04 -#define ENAUTOATNP 0x02 -#define SCSIRSTO 0x01 - -/* SCSI transfer control 0 */ -#define SCSIEN 0x80 -#define DMAEN 0x40 -#define CH1 0x20 -#define CLRSTCNT 0x10 -#define SPIOEN 0x08 -#define CLRCH1 0x02 - -/* SCSI transfer control 1 */ -#define BITBUCKET 0x80 -#define SWRAPEN 0x40 -#define ENSPCHK 0x20 -#define STIMESEL 0x18 /* mask */ -#define STIMESEL_ 3 -#define ENSTIMER 0x04 -#define BYTEALIGN 0x02 - -/* SCSI signal IN */ -#define CDI 0x80 -#define IOI 0x40 -#define MSGI 0x20 -#define ATNI 0x10 -#define SELI 0x08 -#define BSYI 0x04 -#define REQI 0x02 -#define ACKI 0x01 - -/* SCSI Phases */ -#define P_MASK (MSGI|CDI|IOI) -#define P_DATAO (0) -#define P_DATAI (IOI) -#define P_CMD (CDI) -#define P_STATUS (CDI|IOI) -#define P_MSGO (MSGI|CDI) -#define P_MSGI (MSGI|CDI|IOI) - -/* SCSI signal OUT */ -#define CDO 0x80 -#define IOO 0x40 -#define MSGO 0x20 -#define ATNO 0x10 -#define SELO 0x08 -#define BSYO 0x04 -#define REQO 0x02 -#define ACKO 0x01 - -/* SCSI rate control */ -#define SXFR 0x70 /* mask */ -#define SXFR_ 4 -#define SOFS 0x0f /* mask */ - -/* SCSI ID */ -#define OID 0x70 -#define OID_ 4 -#define TID 0x07 - -/* SCSI transfer count */ -#define GETSTCNT() ( (GETPORT(STCNT2)<<16) \ - + (GETPORT(STCNT1)<< 8) \ - + GETPORT(STCNT0) ) - -#define SETSTCNT(X) { SETPORT(STCNT2, ((X) & 0xFF0000) >> 16); \ - SETPORT(STCNT1, ((X) & 0x00FF00) >> 8); \ - SETPORT(STCNT0, ((X) & 0x0000FF) ); } - -/* SCSI interrupt status */ -#define TARGET 0x80 -#define SELDO 0x40 -#define SELDI 0x20 -#define SELINGO 0x10 -#define SWRAP 0x08 -#define SDONE 0x04 -#define SPIORDY 0x02 -#define DMADONE 0x01 - -#define SETSDONE 0x80 -#define CLRSELDO 0x40 -#define CLRSELDI 0x20 -#define CLRSELINGO 0x10 -#define CLRSWRAP 0x08 -#define CLRSDONE 0x04 -#define CLRSPIORDY 0x02 -#define CLRDMADONE 0x01 - -/* SCSI status 1 */ -#define SELTO 0x80 -#define ATNTARG 0x40 -#define SCSIRSTI 0x20 -#define PHASEMIS 0x10 -#define BUSFREE 0x08 -#define SCSIPERR 0x04 -#define PHASECHG 0x02 -#define REQINIT 0x01 - -#define CLRSELTIMO 0x80 -#define CLRATNO 0x40 -#define CLRSCSIRSTI 0x20 -#define CLRBUSFREE 0x08 -#define CLRSCSIPERR 0x04 -#define CLRPHASECHG 0x02 -#define CLRREQINIT 0x01 - -/* SCSI status 2 */ -#define SOFFSET 0x20 -#define SEMPTY 0x10 -#define SFULL 0x08 -#define SFCNT 0x07 /* mask */ - -/* SCSI status 3 */ -#define SCSICNT 0xf0 /* mask */ -#define SCSICNT_ 4 -#define OFFCNT 0x0f /* mask */ - -/* SCSI TEST control */ -#define SCTESTU 0x08 -#define SCTESTD 0x04 -#define STCTEST 0x01 - -/* SCSI status 4 */ -#define SYNCERR 0x04 -#define FWERR 0x02 -#define FRERR 0x01 - -#define CLRSYNCERR 0x04 -#define CLRFWERR 0x02 -#define CLRFRERR 0x01 - -/* SCSI interrupt mode 0 */ -#define ENSELDO 0x40 -#define ENSELDI 0x20 -#define ENSELINGO 0x10 -#define ENSWRAP 0x08 -#define ENSDONE 0x04 -#define ENSPIORDY 0x02 -#define ENDMADONE 0x01 - -/* SCSI interrupt mode 1 */ -#define ENSELTIMO 0x80 -#define ENATNTARG 0x40 -#define ENSCSIRST 0x20 -#define ENPHASEMIS 0x10 -#define ENBUSFREE 0x08 -#define ENSCSIPERR 0x04 -#define ENPHASECHG 0x02 -#define ENREQINIT 0x01 - -/* DMA control 0 */ -#define ENDMA 0x80 -#define _8BIT 0x40 -#define DMA 0x20 -#define WRITE_READ 0x08 -#define INTEN 0x04 -#define RSTFIFO 0x02 -#define SWINT 0x01 - -/* DMA control 1 */ -#define PWRDWN 0x80 -#define STK 0x07 /* mask */ - -/* DMA status */ -#define ATDONE 0x80 -#define WORDRDY 0x40 -#define INTSTAT 0x20 -#define DFIFOFULL 0x10 -#define DFIFOEMP 0x08 - -/* BURST control */ -#define BON 0xf0 -#define BOFF 0x0f - -/* TEST REGISTER */ -#define BOFFTMR 0x40 -#define BONTMR 0x20 -#define STCNTH 0x10 -#define STCNTM 0x08 -#define STCNTL 0x04 -#define SCSIBLK 0x02 -#define DMABLK 0x01 - -/* On the AHA-152x board PORTA and PORTB contain - some information about the board's configuration. */ -typedef union { - struct { - unsigned reserved:2; /* reserved */ - unsigned tardisc:1; /* Target disconnect: 0=disabled, 1=enabled */ - unsigned syncneg:1; /* Initial sync neg: 0=disabled, 1=enabled */ - unsigned msgclasses:2; /* Message classes - 0=#4 - 1=#0, #1, #2, #3, #4 - 2=#0, #3, #4 - 3=#0, #4 - */ - unsigned boot:1; /* boot: 0=disabled, 1=enabled */ - unsigned dma:1; /* Transfer mode: 0=PIO; 1=DMA */ - unsigned id:3; /* SCSI-id */ - unsigned irq:2; /* IRQ-Channel: 0,3=12, 1=10, 2=11 */ - unsigned dmachan:2; /* DMA-Channel: 0=0, 1=5, 2=6, 3=7 */ - unsigned parity:1; /* SCSI-parity: 1=enabled 0=disabled */ - } fields; - unsigned short port; -} aha152x_config ; - -#define cf_parity fields.parity -#define cf_dmachan fields.dmachan -#define cf_irq fields.irq -#define cf_id fields.id -#define cf_dma fields.dma -#define cf_boot fields.boot -#define cf_msgclasses fields.msgclasses -#define cf_syncneg fields.syncneg -#define cf_tardisc fields.tardisc -#define cf_port port - -/* Some macros to manipulate ports and their bits */ - -#define SETPORT(PORT, VAL) \ - outb( (VAL), (PORT) ) - -#define SETPORTP(PORT, VAL) \ - outb_p( (VAL), (PORT) ) - -#define SETPORTW(PORT, VAL) \ - outw( (VAL), (PORT) ) - -#define GETPORT(PORT) \ - inb( PORT ) - -#define GETPORTW(PORT) \ - inw( PORT ) - -#define SETBITS(PORT, BITS) \ - outb( (inb(PORT) | (BITS)), (PORT) ) - -#define CLRBITS(PORT, BITS) \ - outb( (inb(PORT) & ~(BITS)), (PORT) ) - -#define CLRSETBITS(PORT, CLR, SET) \ - outb( (inb(PORT) & ~(CLR)) | (SET) , (PORT) ) - -#define TESTHI(PORT, BITS) \ - ((inb(PORT) & (BITS)) == BITS) - -#define TESTLO(PORT, BITS) \ - ((inb(PORT) & (BITS)) == 0) - -#ifdef DEBUG_AHA152X -enum { - debug_skipports =0x0001, - debug_queue =0x0002, - debug_intr =0x0004, - debug_selection =0x0008, - debug_msgo =0x0010, - debug_msgi =0x0020, - debug_status =0x0040, - debug_cmd =0x0080, - debug_datai =0x0100, - debug_datao =0x0200, - debug_abort =0x0400, - debug_done =0x0800, - debug_biosparam =0x1000, - debug_phases =0x2000, - debug_queues =0x4000, - debug_reset =0x8000, -}; -#endif - -#endif /* _AHA152X_H */ diff --git a/i386/i386at/gpl/linux/scsi/aha1542.c b/i386/i386at/gpl/linux/scsi/aha1542.c deleted file mode 100644 index 026292eb..00000000 --- a/i386/i386at/gpl/linux/scsi/aha1542.c +++ /dev/null @@ -1,1323 +0,0 @@ -/* $Id: aha1542.c,v 1.1.1.1 1997/02/25 21:27:46 thomas Exp $ - * linux/kernel/aha1542.c - * - * Copyright (C) 1992 Tommy Thorn - * Copyright (C) 1993, 1994, 1995 Eric Youngdale - * - * Modified by Eric Youngdale - * Use request_irq and request_dma to help prevent unexpected conflicts - * Set up on-board DMA controller, such that we do not have to - * have the bios enabled to use the aha1542. - * Modified by David Gentzel - * Don't call request_dma if dma mask is 0 (for BusLogic BT-445S VL-Bus - * controller). - * Modified by Matti Aarnio - * Accept parameters from LILO cmd-line. -- 1-Oct-94 - */ - -#include <linux/module.h> - -#include <linux/kernel.h> -#include <linux/head.h> -#include <linux/types.h> -#include <linux/string.h> -#include <linux/ioport.h> -#include <linux/delay.h> -#include <linux/sched.h> -#include <linux/proc_fs.h> -#include <asm/dma.h> -#include <asm/system.h> -#include <asm/io.h> -#include <linux/blk.h> -#include "scsi.h" -#include "hosts.h" - - -#include "aha1542.h" - -#include<linux/stat.h> - -struct proc_dir_entry proc_scsi_aha1542 = { - PROC_SCSI_AHA1542, 7, "aha1542", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - -#ifdef DEBUG -#define DEB(x) x -#else -#define DEB(x) -#endif -/* -static const char RCSid[] = "$Header: cvs/gnumach/i386/i386at/gpl/linux/scsi/Attic/aha1542.c,v 1.1.1.1 1997/02/25 21:27:46 thomas Exp $"; -*/ - -/* The adaptec can be configured for quite a number of addresses, but -I generally do not want the card poking around at random. We allow -two addresses - this allows people to use the Adaptec with a Midi -card, which also used 0x330 -- can be overridden with LILO! */ - -#define MAXBOARDS 2 /* Increase this and the sizes of the - arrays below, if you need more.. */ - -static unsigned int bases[MAXBOARDS]={0x330, 0x334}; - -/* set by aha1542_setup according to the command line */ -static int setup_called[MAXBOARDS] = {0,0}; -static int setup_buson[MAXBOARDS] = {0,0}; -static int setup_busoff[MAXBOARDS] = {0,0}; -static int setup_dmaspeed[MAXBOARDS] = {-1,-1}; - -static char *setup_str[MAXBOARDS] = {(char *)NULL,(char *)NULL}; - -/* - * LILO params: aha1542=<PORTBASE>[,<BUSON>,<BUSOFF>[,<DMASPEED>]] - * - * Where: <PORTBASE> is any of the valid AHA addresses: - * 0x130, 0x134, 0x230, 0x234, 0x330, 0x334 - * <BUSON> is the time (in microsecs) that AHA spends on the AT-bus - * when transferring data. 1542A power-on default is 11us, - * valid values are in range: 2..15 (decimal) - * <BUSOFF> is the time that AHA spends OFF THE BUS after while - * it is transferring data (not to monopolize the bus). - * Power-on default is 4us, valid range: 1..64 microseconds. - * <DMASPEED> Default is jumper selected (1542A: on the J1), - * but experimenter can alter it with this. - * Valid values: 5, 6, 7, 8, 10 (MB/s) - * Factory default is 5 MB/s. - */ - - -/* The DMA-Controller. We need to fool with this because we want to - be able to use the aha1542 without having to have the bios enabled */ -#define DMA_MODE_REG 0xd6 -#define DMA_MASK_REG 0xd4 -#define CASCADE 0xc0 - -#define BIOS_TRANSLATION_1632 0 /* Used by some old 1542A boards */ -#define BIOS_TRANSLATION_6432 1 /* Default case these days */ -#define BIOS_TRANSLATION_25563 2 /* Big disk case */ - -struct aha1542_hostdata{ - /* This will effectively start both of them at the first mailbox */ - int bios_translation; /* Mapping bios uses - for compatibility */ - int aha1542_last_mbi_used; - int aha1542_last_mbo_used; - Scsi_Cmnd * SCint[AHA1542_MAILBOXES]; - struct mailbox mb[2*AHA1542_MAILBOXES]; - struct ccb ccb[AHA1542_MAILBOXES]; -}; - -#define HOSTDATA(host) ((struct aha1542_hostdata *) &host->hostdata) - -static struct Scsi_Host * aha_host[7] = {NULL,}; /* One for each IRQ level (9-15) */ - - - - -#define WAITnexttimeout 3000000 - -static void setup_mailboxes(int base_io, struct Scsi_Host * shpnt); -static int aha1542_restart(struct Scsi_Host * shost); - -#define aha1542_intr_reset(base) outb(IRST, CONTROL(base)) - -#define WAIT(port, mask, allof, noneof) \ - { register WAITbits; \ - register WAITtimeout = WAITnexttimeout; \ - while (1) { \ - WAITbits = inb(port) & (mask); \ - if ((WAITbits & (allof)) == (allof) && ((WAITbits & (noneof)) == 0)) \ - break; \ - if (--WAITtimeout == 0) goto fail; \ - } \ - } - -/* Similar to WAIT, except we use the udelay call to regulate the - amount of time we wait. */ -#define WAITd(port, mask, allof, noneof, timeout) \ - { register WAITbits; \ - register WAITtimeout = timeout; \ - while (1) { \ - WAITbits = inb(port) & (mask); \ - if ((WAITbits & (allof)) == (allof) && ((WAITbits & (noneof)) == 0)) \ - break; \ - udelay(1000); \ - if (--WAITtimeout == 0) goto fail; \ - } \ - } - -static void aha1542_stat(void) -{ -/* int s = inb(STATUS), i = inb(INTRFLAGS); - printk("status=%x intrflags=%x\n", s, i, WAITnexttimeout-WAITtimeout); */ -} - -/* This is a bit complicated, but we need to make sure that an interrupt - routine does not send something out while we are in the middle of this. - Fortunately, it is only at boot time that multi-byte messages - are ever sent. */ -static int aha1542_out(unsigned int base, unchar *cmdp, int len) -{ - unsigned long flags = 0; - - save_flags(flags); - if(len == 1) { - while(1==1){ - WAIT(STATUS(base), CDF, 0, CDF); - cli(); - if(inb(STATUS(base)) & CDF) {restore_flags(flags); continue;} - outb(*cmdp, DATA(base)); - restore_flags(flags); - return 0; - } - } else { - cli(); - while (len--) - { - WAIT(STATUS(base), CDF, 0, CDF); - outb(*cmdp++, DATA(base)); - } - restore_flags(flags); - } - return 0; - fail: - restore_flags(flags); - printk("aha1542_out failed(%d): ", len+1); aha1542_stat(); - return 1; -} - -/* Only used at boot time, so we do not need to worry about latency as much - here */ -static int aha1542_in(unsigned int base, unchar *cmdp, int len) -{ - unsigned long flags; - - save_flags(flags); - cli(); - while (len--) - { - WAIT(STATUS(base), DF, DF, 0); - *cmdp++ = inb(DATA(base)); - } - restore_flags(flags); - return 0; - fail: - restore_flags(flags); - printk("aha1542_in failed(%d): ", len+1); aha1542_stat(); - return 1; -} - -/* Similar to aha1542_in, except that we wait a very short period of time. - We use this if we know the board is alive and awake, but we are not sure - if the board will respond the the command we are about to send or not */ -static int aha1542_in1(unsigned int base, unchar *cmdp, int len) -{ - unsigned long flags; - - save_flags(flags); - cli(); - while (len--) - { - WAITd(STATUS(base), DF, DF, 0, 100); - *cmdp++ = inb(DATA(base)); - } - restore_flags(flags); - return 0; - fail: - restore_flags(flags); - return 1; -} - -static int makecode(unsigned hosterr, unsigned scsierr) -{ - switch (hosterr) { - case 0x0: - case 0xa: /* Linked command complete without error and linked normally */ - case 0xb: /* Linked command complete without error, interrupt generated */ - hosterr = 0; - break; - - case 0x11: /* Selection time out-The initiator selection or target - reselection was not complete within the SCSI Time out period */ - hosterr = DID_TIME_OUT; - break; - - case 0x12: /* Data overrun/underrun-The target attempted to transfer more data - than was allocated by the Data Length field or the sum of the - Scatter / Gather Data Length fields. */ - - case 0x13: /* Unexpected bus free-The target dropped the SCSI BSY at an unexpected time. */ - - case 0x15: /* MBO command was not 00, 01 or 02-The first byte of the CB was - invalid. This usually indicates a software failure. */ - - case 0x16: /* Invalid CCB Operation Code-The first byte of the CCB was invalid. - This usually indicates a software failure. */ - - case 0x17: /* Linked CCB does not have the same LUN-A subsequent CCB of a set - of linked CCB's does not specify the same logical unit number as - the first. */ - case 0x18: /* Invalid Target Direction received from Host-The direction of a - Target Mode CCB was invalid. */ - - case 0x19: /* Duplicate CCB Received in Target Mode-More than once CCB was - received to service data transfer between the same target LUN - and initiator SCSI ID in the same direction. */ - - case 0x1a: /* Invalid CCB or Segment List Parameter-A segment list with a zero - length segment or invalid segment list boundaries was received. - A CCB parameter was invalid. */ - DEB(printk("Aha1542: %x %x\n", hosterr, scsierr)); - hosterr = DID_ERROR; /* Couldn't find any better */ - break; - - case 0x14: /* Target bus phase sequence failure-An invalid bus phase or bus - phase sequence was requested by the target. The host adapter - will generate a SCSI Reset Condition, notifying the host with - a SCRD interrupt */ - hosterr = DID_RESET; - break; - default: - printk("makecode: unknown hoststatus %x\n", hosterr); - break; - } - return scsierr|(hosterr << 16); -} - -static int aha1542_test_port(int bse, struct Scsi_Host * shpnt) -{ - int i; - unchar inquiry_cmd[] = {CMD_INQUIRY }; - unchar inquiry_result[4]; - unchar *cmdp; - int len; - volatile int debug = 0; - - /* Quick and dirty test for presence of the card. */ - if(inb(STATUS(bse)) == 0xff) return 0; - - /* Reset the adapter. I ought to make a hard reset, but it's not really necessary */ - - /* DEB(printk("aha1542_test_port called \n")); */ - - /* In case some other card was probing here, reset interrupts */ - aha1542_intr_reset(bse); /* reset interrupts, so they don't block */ - - outb(SRST|IRST/*|SCRST*/, CONTROL(bse)); - - i = jiffies + 2; - while (i>jiffies); /* Wait a little bit for things to settle down. */ - - debug = 1; - /* Expect INIT and IDLE, any of the others are bad */ - WAIT(STATUS(bse), STATMASK, INIT|IDLE, STST|DIAGF|INVDCMD|DF|CDF); - - debug = 2; - /* Shouldn't have generated any interrupts during reset */ - if (inb(INTRFLAGS(bse))&INTRMASK) goto fail; - - - /* Perform a host adapter inquiry instead so we do not need to set - up the mailboxes ahead of time */ - - aha1542_out(bse, inquiry_cmd, 1); - - debug = 3; - len = 4; - cmdp = &inquiry_result[0]; - - while (len--) - { - WAIT(STATUS(bse), DF, DF, 0); - *cmdp++ = inb(DATA(bse)); - } - - debug = 8; - /* Reading port should reset DF */ - if (inb(STATUS(bse)) & DF) goto fail; - - debug = 9; - /* When HACC, command is completed, and we're though testing */ - WAIT(INTRFLAGS(bse), HACC, HACC, 0); - /* now initialize adapter */ - - debug = 10; - /* Clear interrupts */ - outb(IRST, CONTROL(bse)); - - debug = 11; - - return debug; /* 1 = ok */ - fail: - return 0; /* 0 = not ok */ -} - -/* A "high" level interrupt handler */ -static void aha1542_intr_handle(int irq, struct pt_regs *regs) -{ - void (*my_done)(Scsi_Cmnd *) = NULL; - int errstatus, mbi, mbo, mbistatus; - int number_serviced; - unsigned int flags; - struct Scsi_Host * shost; - Scsi_Cmnd * SCtmp; - int flag; - int needs_restart; - struct mailbox * mb; - struct ccb *ccb; - - shost = aha_host[irq - 9]; - if(!shost) panic("Splunge!"); - - mb = HOSTDATA(shost)->mb; - ccb = HOSTDATA(shost)->ccb; - -#ifdef DEBUG - { - flag = inb(INTRFLAGS(shost->io_port)); - printk("aha1542_intr_handle: "); - if (!(flag&ANYINTR)) printk("no interrupt?"); - if (flag&MBIF) printk("MBIF "); - if (flag&MBOA) printk("MBOF "); - if (flag&HACC) printk("HACC "); - if (flag&SCRD) printk("SCRD "); - printk("status %02x\n", inb(STATUS(shost->io_port))); - }; -#endif - number_serviced = 0; - needs_restart = 0; - - while(1==1){ - flag = inb(INTRFLAGS(shost->io_port)); - - /* Check for unusual interrupts. If any of these happen, we should - probably do something special, but for now just printing a message - is sufficient. A SCSI reset detected is something that we really - need to deal with in some way. */ - if (flag & ~MBIF) { - if (flag&MBOA) printk("MBOF "); - if (flag&HACC) printk("HACC "); - if (flag&SCRD) { - needs_restart = 1; - printk("SCRD "); - } - } - - aha1542_intr_reset(shost->io_port); - - save_flags(flags); - cli(); - mbi = HOSTDATA(shost)->aha1542_last_mbi_used + 1; - if (mbi >= 2*AHA1542_MAILBOXES) mbi = AHA1542_MAILBOXES; - - do{ - if(mb[mbi].status != 0) break; - mbi++; - if (mbi >= 2*AHA1542_MAILBOXES) mbi = AHA1542_MAILBOXES; - } while (mbi != HOSTDATA(shost)->aha1542_last_mbi_used); - - if(mb[mbi].status == 0){ - restore_flags(flags); - /* Hmm, no mail. Must have read it the last time around */ - if (!number_serviced && !needs_restart) - printk("aha1542.c: interrupt received, but no mail.\n"); - /* We detected a reset. Restart all pending commands for - devices that use the hard reset option */ - if(needs_restart) aha1542_restart(shost); - return; - }; - - mbo = (scsi2int(mb[mbi].ccbptr) - ((unsigned int) &ccb[0])) / sizeof(struct ccb); - mbistatus = mb[mbi].status; - mb[mbi].status = 0; - HOSTDATA(shost)->aha1542_last_mbi_used = mbi; - restore_flags(flags); - -#ifdef DEBUG - { - if (ccb[mbo].tarstat|ccb[mbo].hastat) - printk("aha1542_command: returning %x (status %d)\n", - ccb[mbo].tarstat + ((int) ccb[mbo].hastat << 16), mb[mbi].status); - }; -#endif - - if(mbistatus == 3) continue; /* Aborted command not found */ - -#ifdef DEBUG - printk("...done %d %d\n",mbo, mbi); -#endif - - SCtmp = HOSTDATA(shost)->SCint[mbo]; - - if (!SCtmp || !SCtmp->scsi_done) { - printk("aha1542_intr_handle: Unexpected interrupt\n"); - printk("tarstat=%x, hastat=%x idlun=%x ccb#=%d \n", ccb[mbo].tarstat, - ccb[mbo].hastat, ccb[mbo].idlun, mbo); - return; - } - - my_done = SCtmp->scsi_done; - if (SCtmp->host_scribble) scsi_free(SCtmp->host_scribble, 512); - - /* Fetch the sense data, and tuck it away, in the required slot. The - Adaptec automatically fetches it, and there is no guarantee that - we will still have it in the cdb when we come back */ - if (ccb[mbo].tarstat == 2) - memcpy(SCtmp->sense_buffer, &ccb[mbo].cdb[ccb[mbo].cdblen], - sizeof(SCtmp->sense_buffer)); - - - /* is there mail :-) */ - - /* more error checking left out here */ - if (mbistatus != 1) - /* This is surely wrong, but I don't know what's right */ - errstatus = makecode(ccb[mbo].hastat, ccb[mbo].tarstat); - else - errstatus = 0; - -#ifdef DEBUG - if(errstatus) printk("(aha1542 error:%x %x %x) ",errstatus, - ccb[mbo].hastat, ccb[mbo].tarstat); -#endif - - if (ccb[mbo].tarstat == 2) { -#ifdef DEBUG - int i; -#endif - DEB(printk("aha1542_intr_handle: sense:")); -#ifdef DEBUG - for (i = 0; i < 12; i++) - printk("%02x ", ccb[mbo].cdb[ccb[mbo].cdblen+i]); - printk("\n"); -#endif - /* - DEB(printk("aha1542_intr_handle: buf:")); - for (i = 0; i < bufflen; i++) - printk("%02x ", ((unchar *)buff)[i]); - printk("\n"); - */ - } - DEB(if (errstatus) printk("aha1542_intr_handle: returning %6x\n", errstatus)); - SCtmp->result = errstatus; - HOSTDATA(shost)->SCint[mbo] = NULL; /* This effectively frees up the mailbox slot, as - far as queuecommand is concerned */ - my_done(SCtmp); - number_serviced++; - }; -} - -int aha1542_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) -{ - unchar ahacmd = CMD_START_SCSI; - unchar direction; - unchar *cmd = (unchar *) SCpnt->cmnd; - unchar target = SCpnt->target; - unchar lun = SCpnt->lun; - unsigned long flags; - void *buff = SCpnt->request_buffer; - int bufflen = SCpnt->request_bufflen; - int mbo; - struct mailbox * mb; - struct ccb *ccb; - - DEB(int i); - - mb = HOSTDATA(SCpnt->host)->mb; - ccb = HOSTDATA(SCpnt->host)->ccb; - - DEB(if (target > 1) { - SCpnt->result = DID_TIME_OUT << 16; - done(SCpnt); return 0;}); - - if(*cmd == REQUEST_SENSE){ -#ifndef DEBUG - if (bufflen != sizeof(SCpnt->sense_buffer)) { - printk("Wrong buffer length supplied for request sense (%d)\n",bufflen); - }; -#endif - SCpnt->result = 0; - done(SCpnt); - return 0; - }; - -#ifdef DEBUG - if (*cmd == READ_10 || *cmd == WRITE_10) - i = xscsi2int(cmd+2); - else if (*cmd == READ_6 || *cmd == WRITE_6) - i = scsi2int(cmd+2); - else - i = -1; - if (done) - printk("aha1542_queuecommand: dev %d cmd %02x pos %d len %d ", target, *cmd, i, bufflen); - else - printk("aha1542_command: dev %d cmd %02x pos %d len %d ", target, *cmd, i, bufflen); - aha1542_stat(); - printk("aha1542_queuecommand: dumping scsi cmd:"); - for (i = 0; i < SCpnt->cmd_len; i++) printk("%02x ", cmd[i]); - printk("\n"); - if (*cmd == WRITE_10 || *cmd == WRITE_6) - return 0; /* we are still testing, so *don't* write */ -#endif -/* Use the outgoing mailboxes in a round-robin fashion, because this - is how the host adapter will scan for them */ - - save_flags(flags); - cli(); - mbo = HOSTDATA(SCpnt->host)->aha1542_last_mbo_used + 1; - if (mbo >= AHA1542_MAILBOXES) mbo = 0; - - do{ - if(mb[mbo].status == 0 && HOSTDATA(SCpnt->host)->SCint[mbo] == NULL) - break; - mbo++; - if (mbo >= AHA1542_MAILBOXES) mbo = 0; - } while (mbo != HOSTDATA(SCpnt->host)->aha1542_last_mbo_used); - - if(mb[mbo].status || HOSTDATA(SCpnt->host)->SCint[mbo]) - panic("Unable to find empty mailbox for aha1542.\n"); - - HOSTDATA(SCpnt->host)->SCint[mbo] = SCpnt; /* This will effectively prevent someone else from - screwing with this cdb. */ - - HOSTDATA(SCpnt->host)->aha1542_last_mbo_used = mbo; - restore_flags(flags); - -#ifdef DEBUG - printk("Sending command (%d %x)...",mbo, done); -#endif - - any2scsi(mb[mbo].ccbptr, &ccb[mbo]); /* This gets trashed for some reason*/ - - memset(&ccb[mbo], 0, sizeof(struct ccb)); - - ccb[mbo].cdblen = SCpnt->cmd_len; - - direction = 0; - if (*cmd == READ_10 || *cmd == READ_6) - direction = 8; - else if (*cmd == WRITE_10 || *cmd == WRITE_6) - direction = 16; - - memcpy(ccb[mbo].cdb, cmd, ccb[mbo].cdblen); - - if (SCpnt->use_sg) { - struct scatterlist * sgpnt; - struct chain * cptr; -#ifdef DEBUG - unsigned char * ptr; -#endif - int i; - ccb[mbo].op = 2; /* SCSI Initiator Command w/scatter-gather*/ - SCpnt->host_scribble = (unsigned char *) scsi_malloc(512); - sgpnt = (struct scatterlist *) SCpnt->request_buffer; - cptr = (struct chain *) SCpnt->host_scribble; - if (cptr == NULL) panic("aha1542.c: unable to allocate DMA memory\n"); - for(i=0; i<SCpnt->use_sg; i++) { - if(sgpnt[i].length == 0 || SCpnt->use_sg > 16 || - (((int)sgpnt[i].address) & 1) || (sgpnt[i].length & 1)){ - unsigned char * ptr; - printk("Bad segment list supplied to aha1542.c (%d, %d)\n",SCpnt->use_sg,i); - for(i=0;i<SCpnt->use_sg;i++){ - printk("%d: %x %x %d\n",i,(unsigned int) sgpnt[i].address, (unsigned int) sgpnt[i].alt_address, - sgpnt[i].length); - }; - printk("cptr %x: ",(unsigned int) cptr); - ptr = (unsigned char *) &cptr[i]; - for(i=0;i<18;i++) printk("%02x ", ptr[i]); - panic("Foooooooood fight!"); - }; - any2scsi(cptr[i].dataptr, sgpnt[i].address); - if(((unsigned int) sgpnt[i].address) & 0xff000000) goto baddma; - any2scsi(cptr[i].datalen, sgpnt[i].length); - }; - any2scsi(ccb[mbo].datalen, SCpnt->use_sg * sizeof(struct chain)); - any2scsi(ccb[mbo].dataptr, cptr); -#ifdef DEBUG - printk("cptr %x: ",cptr); - ptr = (unsigned char *) cptr; - for(i=0;i<18;i++) printk("%02x ", ptr[i]); -#endif - } else { - ccb[mbo].op = 0; /* SCSI Initiator Command */ - SCpnt->host_scribble = NULL; - any2scsi(ccb[mbo].datalen, bufflen); - if(((unsigned int) buff & 0xff000000)) goto baddma; - any2scsi(ccb[mbo].dataptr, buff); - }; - ccb[mbo].idlun = (target&7)<<5 | direction | (lun & 7); /*SCSI Target Id*/ - ccb[mbo].rsalen = 12; - ccb[mbo].linkptr[0] = ccb[mbo].linkptr[1] = ccb[mbo].linkptr[2] = 0; - ccb[mbo].commlinkid = 0; - -#ifdef DEBUG - { int i; - printk("aha1542_command: sending.. "); - for (i = 0; i < sizeof(ccb[mbo])-10; i++) - printk("%02x ", ((unchar *)&ccb[mbo])[i]); - }; -#endif - - if (done) { - DEB(printk("aha1542_queuecommand: now waiting for interrupt "); aha1542_stat()); - SCpnt->scsi_done = done; - mb[mbo].status = 1; - aha1542_out(SCpnt->host->io_port, &ahacmd, 1); /* start scsi command */ - DEB(aha1542_stat()); - } - else - printk("aha1542_queuecommand: done can't be NULL\n"); - - return 0; - baddma: - panic("Buffer at address > 16Mb used for 1542B"); -} - -static void internal_done(Scsi_Cmnd * SCpnt) -{ - SCpnt->SCp.Status++; -} - -int aha1542_command(Scsi_Cmnd * SCpnt) -{ - DEB(printk("aha1542_command: ..calling aha1542_queuecommand\n")); - - aha1542_queuecommand(SCpnt, internal_done); - - SCpnt->SCp.Status = 0; - while (!SCpnt->SCp.Status) - barrier(); - return SCpnt->result; -} - -/* Initialize mailboxes */ -static void setup_mailboxes(int bse, struct Scsi_Host * shpnt) -{ - int i; - struct mailbox * mb; - struct ccb *ccb; - - unchar cmd[5] = {CMD_MBINIT, AHA1542_MAILBOXES, 0, 0, 0}; - - mb = HOSTDATA(shpnt)->mb; - ccb = HOSTDATA(shpnt)->ccb; - - for(i=0; i<AHA1542_MAILBOXES; i++){ - mb[i].status = mb[AHA1542_MAILBOXES+i].status = 0; - any2scsi(mb[i].ccbptr, &ccb[i]); - }; - aha1542_intr_reset(bse); /* reset interrupts, so they don't block */ - any2scsi((cmd+2), mb); - aha1542_out(bse, cmd, 5); - WAIT(INTRFLAGS(bse), INTRMASK, HACC, 0); - while (0) { - fail: - printk("aha1542_detect: failed setting up mailboxes\n"); - } - aha1542_intr_reset(bse); -} - -static int aha1542_getconfig(int base_io, unsigned char * irq_level, unsigned char * dma_chan, unsigned char * scsi_id) -{ - unchar inquiry_cmd[] = {CMD_RETCONF }; - unchar inquiry_result[3]; - int i; - i = inb(STATUS(base_io)); - if (i & DF) { - i = inb(DATA(base_io)); - }; - aha1542_out(base_io, inquiry_cmd, 1); - aha1542_in(base_io, inquiry_result, 3); - WAIT(INTRFLAGS(base_io), INTRMASK, HACC, 0); - while (0) { - fail: - printk("aha1542_detect: query board settings\n"); - } - aha1542_intr_reset(base_io); - switch(inquiry_result[0]){ - case 0x80: - *dma_chan = 7; - break; - case 0x40: - *dma_chan = 6; - break; - case 0x20: - *dma_chan = 5; - break; - case 0x01: - printk("DMA priority 0 not available for Adaptec driver\n"); - return -1; - case 0: - /* This means that the adapter, although Adaptec 1542 compatible, doesn't use a DMA channel. - Currently only aware of the BusLogic BT-445S VL-Bus adapter which needs this. */ - *dma_chan = 0xFF; - break; - default: - printk("Unable to determine Adaptec DMA priority. Disabling board\n"); - return -1; - }; - switch(inquiry_result[1]){ - case 0x40: - *irq_level = 15; - break; - case 0x20: - *irq_level = 14; - break; - case 0x8: - *irq_level = 12; - break; - case 0x4: - *irq_level = 11; - break; - case 0x2: - *irq_level = 10; - break; - case 0x1: - *irq_level = 9; - break; - default: - printk("Unable to determine Adaptec IRQ level. Disabling board\n"); - return -1; - }; - *scsi_id=inquiry_result[2] & 7; - return 0; -} - -/* This function should only be called for 1542C boards - we can detect - the special firmware settings and unlock the board */ - -static int aha1542_mbenable(int base) -{ - static unchar mbenable_cmd[3]; - static unchar mbenable_result[2]; - int retval; - - retval = BIOS_TRANSLATION_6432; - - mbenable_cmd[0]=CMD_EXTBIOS; - aha1542_out(base,mbenable_cmd,1); - if(aha1542_in1(base,mbenable_result,2)) - return retval; - WAITd(INTRFLAGS(base),INTRMASK,HACC,0,100); - aha1542_intr_reset(base); - - if ((mbenable_result[0] & 0x08) || mbenable_result[1]) { - mbenable_cmd[0]=CMD_MBENABLE; - mbenable_cmd[1]=0; - mbenable_cmd[2]=mbenable_result[1]; - if(mbenable_result[1] & 1) retval = BIOS_TRANSLATION_25563; - aha1542_out(base,mbenable_cmd,3); - WAIT(INTRFLAGS(base),INTRMASK,HACC,0); - }; - while(0) { -fail: - printk("aha1542_mbenable: Mailbox init failed\n"); - } -aha1542_intr_reset(base); -return retval; -} - -/* Query the board to find out if it is a 1542 or a 1740, or whatever. */ -static int aha1542_query(int base_io, int * transl) -{ - unchar inquiry_cmd[] = {CMD_INQUIRY }; - unchar inquiry_result[4]; - int i; - i = inb(STATUS(base_io)); - if (i & DF) { - i = inb(DATA(base_io)); - }; - aha1542_out(base_io, inquiry_cmd, 1); - aha1542_in(base_io, inquiry_result, 4); - WAIT(INTRFLAGS(base_io), INTRMASK, HACC, 0); - while (0) { - fail: - printk("aha1542_detect: query card type\n"); - } - aha1542_intr_reset(base_io); - - *transl = BIOS_TRANSLATION_6432; /* Default case */ - -/* For an AHA1740 series board, we ignore the board since there is a - hardware bug which can lead to wrong blocks being returned if the board - is operating in the 1542 emulation mode. Since there is an extended mode - driver, we simply ignore the board and let the 1740 driver pick it up. -*/ - - if (inquiry_result[0] == 0x43) { - printk("aha1542.c: Emulation mode not supported for AHA 174N hardware.\n"); - return 1; - }; - - /* Always call this - boards that do not support extended bios translation - will ignore the command, and we will set the proper default */ - - *transl = aha1542_mbenable(base_io); - - return 0; -} - -/* called from init/main.c */ -void aha1542_setup( char *str, int *ints) -{ - const char *ahausage = "aha1542: usage: aha1542=<PORTBASE>[,<BUSON>,<BUSOFF>[,<DMASPEED>]]\n"; - static int setup_idx = 0; - int setup_portbase; - - if(setup_idx >= MAXBOARDS) - { - printk("aha1542: aha1542_setup called too many times! Bad LILO params ?\n"); - printk(" Entryline 1: %s\n",setup_str[0]); - printk(" Entryline 2: %s\n",setup_str[1]); - printk(" This line: %s\n",str); - return; - } - if (ints[0] < 1 || ints[0] > 4) - { - printk("aha1542: %s\n", str ); - printk(ahausage); - printk("aha1542: Wrong parameters may cause system malfunction.. We try anyway..\n"); - } - - setup_called[setup_idx]=ints[0]; - setup_str[setup_idx]=str; - - setup_portbase = ints[0] >= 1 ? ints[1] : 0; /* Preserve the default value.. */ - setup_buson [setup_idx] = ints[0] >= 2 ? ints[2] : 7; - setup_busoff [setup_idx] = ints[0] >= 3 ? ints[3] : 5; - if (ints[0] >= 4) { - int atbt = -1; - switch (ints[4]) { - case 5: - atbt = 0x00; - break; - case 6: - atbt = 0x04; - break; - case 7: - atbt = 0x01; - break; - case 8: - atbt = 0x02; - break; - case 10: - atbt = 0x03; - break; - default: - printk("aha1542: %s\n", str ); - printk(ahausage); - printk("aha1542: Valid values for DMASPEED are 5-8, 10 MB/s. Using jumper defaults.\n"); - break; - } - setup_dmaspeed[setup_idx] = atbt; - } - - if (setup_portbase != 0) - bases[setup_idx] = setup_portbase; - - ++setup_idx; -} - -/* return non-zero on detection */ -int aha1542_detect(Scsi_Host_Template * tpnt) -{ - unsigned char dma_chan; - unsigned char irq_level; - unsigned char scsi_id; - unsigned long flags; - unsigned int base_io; - int trans; - struct Scsi_Host * shpnt = NULL; - int count = 0; - int indx; - - DEB(printk("aha1542_detect: \n")); - - tpnt->proc_dir = &proc_scsi_aha1542; - - for(indx = 0; indx < sizeof(bases)/sizeof(bases[0]); indx++) - if(bases[indx] != 0 && !check_region(bases[indx], 4)) { - shpnt = scsi_register(tpnt, - sizeof(struct aha1542_hostdata)); - - /* For now we do this - until kmalloc is more intelligent - we are resigned to stupid hacks like this */ - if ((unsigned int) shpnt > 0xffffff) { - printk("Invalid address for shpnt with 1542.\n"); - goto unregister; - } - - if(!aha1542_test_port(bases[indx], shpnt)) goto unregister; - - - base_io = bases[indx]; - - /* Set the Bus on/off-times as not to ruin floppy performance */ - { - unchar oncmd[] = {CMD_BUSON_TIME, 7}; - unchar offcmd[] = {CMD_BUSOFF_TIME, 5}; - - if(setup_called[indx]) - { - oncmd[1] = setup_buson[indx]; - offcmd[1] = setup_busoff[indx]; - } - - aha1542_intr_reset(base_io); - aha1542_out(base_io, oncmd, 2); - WAIT(INTRFLAGS(base_io), INTRMASK, HACC, 0); - aha1542_intr_reset(base_io); - aha1542_out(base_io, offcmd, 2); - WAIT(INTRFLAGS(base_io), INTRMASK, HACC, 0); - if (setup_dmaspeed[indx] >= 0) - { - unchar dmacmd[] = {CMD_DMASPEED, 0}; - dmacmd[1] = setup_dmaspeed[indx]; - aha1542_intr_reset(base_io); - aha1542_out(base_io, dmacmd, 2); - WAIT(INTRFLAGS(base_io), INTRMASK, HACC, 0); - } - while (0) { - fail: - printk("aha1542_detect: setting bus on/off-time failed\n"); - } - aha1542_intr_reset(base_io); - } - if(aha1542_query(base_io, &trans)) goto unregister; - - if (aha1542_getconfig(base_io, &irq_level, &dma_chan, &scsi_id) == -1) goto unregister; - - printk("Configuring Adaptec (SCSI-ID %d) at IO:%x, IRQ %d", scsi_id, base_io, irq_level); - if (dma_chan != 0xFF) - printk(", DMA priority %d", dma_chan); - printk("\n"); - - DEB(aha1542_stat()); - setup_mailboxes(base_io, shpnt); - - DEB(aha1542_stat()); - - DEB(printk("aha1542_detect: enable interrupt channel %d\n", irq_level)); - save_flags(flags); - cli(); - if (request_irq(irq_level,aha1542_intr_handle, 0, "aha1542")) { - printk("Unable to allocate IRQ for adaptec controller.\n"); - goto unregister; - } - - if (dma_chan != 0xFF) { - if (request_dma(dma_chan,"aha1542")) { - printk("Unable to allocate DMA channel for Adaptec.\n"); - free_irq(irq_level); - goto unregister; - } - - if (dma_chan >= 5) { - outb((dma_chan - 4) | CASCADE, DMA_MODE_REG); - outb(dma_chan - 4, DMA_MASK_REG); - } - } - aha_host[irq_level - 9] = shpnt; - shpnt->this_id = scsi_id; - shpnt->unique_id = base_io; - shpnt->io_port = base_io; - shpnt->n_io_port = 4; /* Number of bytes of I/O space used */ - shpnt->dma_channel = dma_chan; - shpnt->irq = irq_level; - HOSTDATA(shpnt)->bios_translation = trans; - if(trans == 2) - printk("aha1542.c: Using extended bios translation\n"); - HOSTDATA(shpnt)->aha1542_last_mbi_used = (2*AHA1542_MAILBOXES - 1); - HOSTDATA(shpnt)->aha1542_last_mbo_used = (AHA1542_MAILBOXES - 1); - memset(HOSTDATA(shpnt)->SCint, 0, sizeof(HOSTDATA(shpnt)->SCint)); - restore_flags(flags); -#if 0 - DEB(printk(" *** READ CAPACITY ***\n")); - - { - unchar buf[8]; - static unchar cmd[] = { READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - int i; - - for (i = 0; i < sizeof(buf); ++i) buf[i] = 0x87; - for (i = 0; i < 2; ++i) - if (!aha1542_command(i, cmd, buf, sizeof(buf))) { - printk("aha_detect: LU %d sector_size %d device_size %d\n", - i, xscsi2int(buf+4), xscsi2int(buf)); - } - } - - DEB(printk(" *** NOW RUNNING MY OWN TEST *** \n")); - - for (i = 0; i < 4; ++i) - { - unsigned char cmd[10]; - static buffer[512]; - - cmd[0] = READ_10; - cmd[1] = 0; - xany2scsi(cmd+2, i); - cmd[6] = 0; - cmd[7] = 0; - cmd[8] = 1; - cmd[9] = 0; - aha1542_command(0, cmd, buffer, 512); - } -#endif - request_region(bases[indx], 4,"aha1542"); /* Register the IO ports that we use */ - count++; - continue; - unregister: - scsi_unregister(shpnt); - continue; - - }; - - return count; -} - -static int aha1542_restart(struct Scsi_Host * shost) -{ - int i; - int count = 0; -#if 0 - unchar ahacmd = CMD_START_SCSI; -#endif - - for(i=0; i< AHA1542_MAILBOXES; i++) - if(HOSTDATA(shost)->SCint[i] && - !(HOSTDATA(shost)->SCint[i]->device->soft_reset)) - { -#if 0 - HOSTDATA(shost)->mb[i].status = 1; /* Indicate ready to restart... */ -#endif - count++; - } - - printk("Potential to restart %d stalled commands...\n", count); -#if 0 - /* start scsi command */ - if (count) aha1542_out(shost->io_port, &ahacmd, 1); -#endif - return 0; -} - -/* The abort command does not leave the device in a clean state where - it is available to be used again. Until this gets worked out, we will - leave it commented out. */ - -int aha1542_abort(Scsi_Cmnd * SCpnt) -{ -#if 0 - unchar ahacmd = CMD_START_SCSI; - unsigned long flags; - struct mailbox * mb; - int mbi, mbo, i; - - printk("In aha1542_abort: %x %x\n", - inb(STATUS(SCpnt->host->io_port)), - inb(INTRFLAGS(SCpnt->host->io_port))); - - save_flags(flags); - cli(); - mb = HOSTDATA(SCpnt->host)->mb; - mbi = HOSTDATA(SCpnt->host)->aha1542_last_mbi_used + 1; - if (mbi >= 2*AHA1542_MAILBOXES) mbi = AHA1542_MAILBOXES; - - do{ - if(mb[mbi].status != 0) break; - mbi++; - if (mbi >= 2*AHA1542_MAILBOXES) mbi = AHA1542_MAILBOXES; - } while (mbi != HOSTDATA(SCpnt->host)->aha1542_last_mbi_used); - restore_flags(flags); - - if(mb[mbi].status) { - printk("Lost interrupt discovered on irq %d - attempting to recover\n", - SCpnt->host->irq); - aha1542_intr_handle(SCpnt->host->irq, NULL); - return 0; - } - - /* OK, no lost interrupt. Try looking to see how many pending commands - we think we have. */ - - for(i=0; i< AHA1542_MAILBOXES; i++) - if(HOSTDATA(SCpnt->host)->SCint[i]) - { - if(HOSTDATA(SCpnt->host)->SCint[i] == SCpnt) { - printk("Timed out command pending for %s\n", - kdevname(SCpnt->request.rq_dev)); - if (HOSTDATA(SCpnt->host)->mb[i].status) { - printk("OGMB still full - restarting\n"); - aha1542_out(SCpnt->host->io_port, &ahacmd, 1); - }; - } else - printk("Other pending command %s\n", - kdevname(SCpnt->request.rq_dev)); - } - -#endif - - DEB(printk("aha1542_abort\n")); -#if 0 - save_flags(flags); - cli(); - for(mbo = 0; mbo < AHA1542_MAILBOXES; mbo++) - if (SCpnt == HOSTDATA(SCpnt->host)->SCint[mbo]){ - mb[mbo].status = 2; /* Abort command */ - aha1542_out(SCpnt->host->io_port, &ahacmd, 1); /* start scsi command */ - restore_flags(flags); - break; - }; -#endif - return SCSI_ABORT_SNOOZE; -} - -/* We do not implement a reset function here, but the upper level code - assumes that it will get some kind of response for the command in - SCpnt. We must oblige, or the command will hang the scsi system. - For a first go, we assume that the 1542 notifies us with all of the - pending commands (it does implement soft reset, after all). */ - -int aha1542_reset(Scsi_Cmnd * SCpnt) -{ - unchar ahacmd = CMD_START_SCSI; - int i; - - /* - * See if a bus reset was suggested. - */ - if( SCpnt->host->suggest_bus_reset ) - { - /* - * This does a scsi reset for all devices on the bus. - * In principle, we could also reset the 1542 - should - * we do this? Try this first, and we can add that later - * if it turns out to be useful. - */ - outb(HRST | SCRST, CONTROL(SCpnt->host->io_port)); - - /* - * Wait for the thing to settle down a bit. Unfortunately - * this is going to basically lock up the machine while we - * wait for this to complete. To be 100% correct, we need to - * check for timeout, and if we are doing something like this - * we are pretty desperate anyways. - */ - WAIT(STATUS(SCpnt->host->io_port), - STATMASK, INIT|IDLE, STST|DIAGF|INVDCMD|DF|CDF); - - /* - * We need to do this too before the 1542 can interact with - * us again. - */ - setup_mailboxes(SCpnt->host->io_port, SCpnt->host); - - /* - * Now try and pick up the pieces. Restart all commands - * that are currently active on the bus, and reset all of - * the datastructures. We have some time to kill while - * things settle down, so print a nice message. - */ - printk("Sent BUS RESET to scsi host %d\n", SCpnt->host->host_no); - - for(i=0; i< AHA1542_MAILBOXES; i++) - if(HOSTDATA(SCpnt->host)->SCint[i] != NULL) - { - Scsi_Cmnd * SCtmp; - SCtmp = HOSTDATA(SCpnt->host)->SCint[i]; - SCtmp->result = DID_RESET << 16; - if (SCtmp->host_scribble) scsi_free(SCtmp->host_scribble, 512); - printk("Sending DID_RESET for target %d\n", SCpnt->target); - SCtmp->scsi_done(SCpnt); - - HOSTDATA(SCpnt->host)->SCint[i] = NULL; - HOSTDATA(SCpnt->host)->mb[i].status = 0; - } - /* - * Now tell the mid-level code what we did here. Since - * we have restarted all of the outstanding commands, - * then report SUCCESS. - */ - return (SCSI_RESET_SUCCESS | SCSI_RESET_BUS_RESET); -fail: - printk("aha1542.c: Unable to perform hard reset.\n"); - printk("Power cycle machine to reset\n"); - return (SCSI_RESET_ERROR | SCSI_RESET_BUS_RESET); - - - } - else - { - /* This does a selective reset of just the one device */ - /* First locate the ccb for this command */ - for(i=0; i< AHA1542_MAILBOXES; i++) - if(HOSTDATA(SCpnt->host)->SCint[i] == SCpnt) - { - HOSTDATA(SCpnt->host)->ccb[i].op = 0x81; /* BUS DEVICE RESET */ - /* Now tell the 1542 to flush all pending commands for this target */ - aha1542_out(SCpnt->host->io_port, &ahacmd, 1); - - /* Here is the tricky part. What to do next. Do we get an interrupt - for the commands that we aborted with the specified target, or - do we generate this on our own? Try it without first and see - what happens */ - printk("Sent BUS DEVICE RESET to target %d\n", SCpnt->target); - - /* If the first does not work, then try the second. I think the - first option is more likely to be correct. Free the command - block for all commands running on this target... */ - for(i=0; i< AHA1542_MAILBOXES; i++) - if(HOSTDATA(SCpnt->host)->SCint[i] && - HOSTDATA(SCpnt->host)->SCint[i]->target == SCpnt->target) - { - Scsi_Cmnd * SCtmp; - SCtmp = HOSTDATA(SCpnt->host)->SCint[i]; - SCtmp->result = DID_RESET << 16; - if (SCtmp->host_scribble) scsi_free(SCtmp->host_scribble, 512); - printk("Sending DID_RESET for target %d\n", SCpnt->target); - SCtmp->scsi_done(SCpnt); - - HOSTDATA(SCpnt->host)->SCint[i] = NULL; - HOSTDATA(SCpnt->host)->mb[i].status = 0; - } - return SCSI_RESET_SUCCESS; - } - } - /* No active command at this time, so this means that each time we got - some kind of response the last time through. Tell the mid-level code - to request sense information in order to decide what to do next. */ - return SCSI_RESET_PUNT; -} - -#include "sd.h" - -int aha1542_biosparam(Scsi_Disk * disk, kdev_t dev, int * ip) -{ - int translation_algorithm; - int size = disk->capacity; - - translation_algorithm = HOSTDATA(disk->device->host)->bios_translation; - /* Should this be > 1024, or >= 1024? Enquiring minds want to know. */ - if((size>>11) > 1024 && translation_algorithm == 2) { - /* Please verify that this is the same as what DOS returns */ - ip[0] = 255; - ip[1] = 63; - ip[2] = size /255/63; - } else { - ip[0] = 64; - ip[1] = 32; - ip[2] = size >> 11; - }; -/* if (ip[2] >= 1024) ip[2] = 1024; */ - return 0; -} - - -#ifdef MODULE -/* Eventually this will go into an include file, but this will be later */ -Scsi_Host_Template driver_template = AHA1542; - -#include "scsi_module.c" -#endif - diff --git a/i386/i386at/gpl/linux/scsi/aha1542.h b/i386/i386at/gpl/linux/scsi/aha1542.h deleted file mode 100644 index 4e0c6503..00000000 --- a/i386/i386at/gpl/linux/scsi/aha1542.h +++ /dev/null @@ -1,177 +0,0 @@ -#ifndef _AHA1542_H - -/* $Id: aha1542.h,v 1.1.1.1 1997/02/25 21:27:46 thomas Exp $ - * - * Header file for the adaptec 1542 driver for Linux - * - * $Log: aha1542.h,v $ - * Revision 1.1.1.1 1996/10/30 01:40:02 thomas - * Imported from UK22 - * - * Revision 1.1 1996/03/25 20:25:20 goel - * Linux driver merge. - * - * Revision 1.1 1992/07/24 06:27:38 root - * Initial revision - * - * Revision 1.2 1992/07/04 18:41:49 root - * Replaced distribution with current drivers - * - * Revision 1.3 1992/06/23 23:58:20 root - * Fixes. - * - * Revision 1.2 1992/05/26 22:13:23 root - * Changed bug that prevented DMA above first 2 mbytes. - * - * Revision 1.1 1992/05/22 21:00:29 root - * Initial revision - * - * Revision 1.1 1992/04/24 18:01:50 root - * Initial revision - * - * Revision 1.1 1992/04/02 03:23:13 drew - * Initial revision - * - * Revision 1.3 1992/01/27 14:46:29 tthorn - * *** empty log message *** - * - */ - -#include <linux/types.h> -#include <linux/kdev_t.h> - -/* I/O Port interface 4.2 */ -/* READ */ -#define STATUS(base) base -#define STST 0x80 /* Self Test in Progress */ -#define DIAGF 0x40 /* Internal Diagnostic Failure */ -#define INIT 0x20 /* Mailbox Initialization Required */ -#define IDLE 0x10 /* SCSI Host Adapter Idle */ -#define CDF 0x08 /* Command/Data Out Port Full */ -#define DF 0x04 /* Data In Port Full */ -#define INVDCMD 0x01 /* Invalid H A Command */ -#define STATMASK 0xfd /* 0x02 is reserved */ - -#define INTRFLAGS(base) (STATUS(base)+2) -#define ANYINTR 0x80 /* Any Interrupt */ -#define SCRD 0x08 /* SCSI Reset Detected */ -#define HACC 0x04 /* HA Command Complete */ -#define MBOA 0x02 /* MBO Empty */ -#define MBIF 0x01 /* MBI Full */ -#define INTRMASK 0x8f - -/* WRITE */ -#define CONTROL(base) STATUS(base) -#define HRST 0x80 /* Hard Reset */ -#define SRST 0x40 /* Soft Reset */ -#define IRST 0x20 /* Interrupt Reset */ -#define SCRST 0x10 /* SCSI Bus Reset */ - -/* READ/WRITE */ -#define DATA(base) (STATUS(base)+1) -#define CMD_NOP 0x00 /* No Operation */ -#define CMD_MBINIT 0x01 /* Mailbox Initialization */ -#define CMD_START_SCSI 0x02 /* Start SCSI Command */ -#define CMD_INQUIRY 0x04 /* Adapter Inquiry */ -#define CMD_EMBOI 0x05 /* Enable MailBox Out Interrupt */ -#define CMD_BUSON_TIME 0x07 /* Set Bus-On Time */ -#define CMD_BUSOFF_TIME 0x08 /* Set Bus-Off Time */ -#define CMD_DMASPEED 0x09 /* Set AT Bus Transfer Speed */ -#define CMD_RETDEVS 0x0a /* Return Installed Devices */ -#define CMD_RETCONF 0x0b /* Return Configuration Data */ -#define CMD_RETSETUP 0x0d /* Return Setup Data */ -#define CMD_ECHO 0x1f /* ECHO Command Data */ - -#define CMD_EXTBIOS 0x28 /* Return extend bios information only 1542C */ -#define CMD_MBENABLE 0x29 /* Set Mailbox Interface enable only 1542C */ - -/* Mailbox Definition 5.2.1 and 5.2.2 */ -struct mailbox { - unchar status; /* Command/Status */ - unchar ccbptr[3]; /* msb, .., lsb */ -}; - -/* This is used with scatter-gather */ -struct chain { - unchar datalen[3]; /* Size of this part of chain */ - unchar dataptr[3]; /* Location of data */ -}; - -/* These belong in scsi.h also */ -#define any2scsi(up, p) \ -(up)[0] = (((unsigned long)(p)) >> 16) ; \ -(up)[1] = (((unsigned long)(p)) >> 8); \ -(up)[2] = ((unsigned long)(p)); - -#define scsi2int(up) ( (((long)*(up)) << 16) + (((long)(up)[1]) << 8) + ((long)(up)[2]) ) - -#define xany2scsi(up, p) \ -(up)[0] = ((long)(p)) >> 24; \ -(up)[1] = ((long)(p)) >> 16; \ -(up)[2] = ((long)(p)) >> 8; \ -(up)[3] = ((long)(p)); - -#define xscsi2int(up) ( (((long)(up)[0]) << 24) + (((long)(up)[1]) << 16) \ - + (((long)(up)[2]) << 8) + ((long)(up)[3]) ) - -#define MAX_CDB 12 -#define MAX_SENSE 14 - -struct ccb { /* Command Control Block 5.3 */ - unchar op; /* Command Control Block Operation Code */ - unchar idlun; /* op=0,2:Target Id, op=1:Initiator Id */ - /* Outbound data transfer, length is checked*/ - /* Inbound data transfer, length is checked */ - /* Logical Unit Number */ - unchar cdblen; /* SCSI Command Length */ - unchar rsalen; /* Request Sense Allocation Length/Disable */ - unchar datalen[3]; /* Data Length (msb, .., lsb) */ - unchar dataptr[3]; /* Data Pointer */ - unchar linkptr[3]; /* Link Pointer */ - unchar commlinkid; /* Command Linking Identifier */ - unchar hastat; /* Host Adapter Status (HASTAT) */ - unchar tarstat; /* Target Device Status */ - unchar reserved[2]; - unchar cdb[MAX_CDB+MAX_SENSE];/* SCSI Command Descriptor Block */ - /* REQUEST SENSE */ -}; - -int aha1542_detect(Scsi_Host_Template *); -int aha1542_command(Scsi_Cmnd *); -int aha1542_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); -int aha1542_abort(Scsi_Cmnd *); -int aha1542_reset(Scsi_Cmnd *); -int aha1542_biosparam(Disk *, kdev_t, int*); - -#define AHA1542_MAILBOXES 8 -#define AHA1542_SCATTER 16 -#define AHA1542_CMDLUN 1 - -#ifndef NULL - #define NULL 0 -#endif - -extern struct proc_dir_entry proc_scsi_aha1542; - -#define AHA1542 { NULL, NULL, \ - &proc_scsi_aha1542,/* proc_dir_entry */ \ - NULL, \ - "Adaptec 1542", \ - aha1542_detect, \ - NULL, \ - NULL, \ - aha1542_command, \ - aha1542_queuecommand, \ - aha1542_abort, \ - aha1542_reset, \ - NULL, \ - aha1542_biosparam, \ - AHA1542_MAILBOXES, \ - 7, \ - AHA1542_SCATTER, \ - AHA1542_CMDLUN, \ - 0, \ - 1, \ - ENABLE_CLUSTERING} - -#endif diff --git a/i386/i386at/gpl/linux/scsi/aha1740.c b/i386/i386at/gpl/linux/scsi/aha1740.c deleted file mode 100644 index 250aa1b8..00000000 --- a/i386/i386at/gpl/linux/scsi/aha1740.c +++ /dev/null @@ -1,531 +0,0 @@ -/* $Id: aha1740.c,v 1.2 1997/03/24 21:51:17 thomas Exp $ - * 1993/03/31 - * linux/kernel/aha1740.c - * - * Based loosely on aha1542.c which is - * Copyright (C) 1992 Tommy Thorn and - * Modified by Eric Youngdale - * - * This file is aha1740.c, written and - * Copyright (C) 1992,1993 Brad McLean - * - * Modifications to makecode and queuecommand - * for proper handling of multiple devices courteously - * provided by Michael Weller, March, 1993 - * - * aha1740_makecode may still need even more work - * if it doesn't work for your devices, take a look. - */ - -#ifdef MODULE -#include <linux/module.h> -#endif - -#include <linux/kernel.h> -#include <linux/head.h> -#include <linux/types.h> -#include <linux/string.h> -#include <linux/ioport.h> -#include <linux/proc_fs.h> -#include <linux/sched.h> -#include <asm/dma.h> - -#include <asm/system.h> -#include <asm/io.h> -#include <linux/blk.h> -#include "scsi.h" -#include "hosts.h" -#include "sd.h" - -#include "aha1740.h" -#include<linux/stat.h> - -struct proc_dir_entry proc_scsi_aha1740 = { - PROC_SCSI_AHA1740, 7, "aha1740", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - -/* IF YOU ARE HAVING PROBLEMS WITH THIS DRIVER, AND WANT TO WATCH - IT WORK, THEN: -#define DEBUG -*/ -#ifdef DEBUG -#define DEB(x) x -#else -#define DEB(x) -#endif - -/* -static const char RCSid[] = "$Header: cvs/gnumach/i386/i386at/gpl/linux/scsi/Attic/aha1740.c,v 1.2 1997/03/24 21:51:17 thomas Exp $"; -*/ - -static unsigned int slot, base; -static unsigned char irq_level; - -static struct ecb ecb[AHA1740_ECBS]; /* One for each queued operation */ - -static int aha1740_last_ecb_used = 0; /* optimization */ - -int aha1740_makecode(unchar *sense, unchar *status) -{ - struct statusword - { - ushort don:1, /* Command Done - No Error */ - du:1, /* Data underrun */ - :1, qf:1, /* Queue full */ - sc:1, /* Specification Check */ - dor:1, /* Data overrun */ - ch:1, /* Chaining Halted */ - intr:1, /* Interrupt issued */ - asa:1, /* Additional Status Available */ - sns:1, /* Sense information Stored */ - :1, ini:1, /* Initialization Required */ - me:1, /* Major error or exception */ - :1, eca:1, /* Extended Contingent alliance */ - :1; - } status_word; - int retval = DID_OK; - - status_word = * (struct statusword *) status; -#ifdef DEBUG -printk("makecode from %x,%x,%x,%x %x,%x,%x,%x",status[0],status[1],status[2],status[3], -sense[0],sense[1],sense[2],sense[3]); -#endif - if (!status_word.don) /* Anything abnormal was detected */ - { - if ( (status[1]&0x18) || status_word.sc ) /*Additional info available*/ - { - /* Use the supplied info for further diagnostics */ - switch ( status[2] ) - { - case 0x12: - if ( status_word.dor ) - retval=DID_ERROR; /* It's an Overrun */ - /* If not overrun, assume underrun and ignore it! */ - case 0x00: /* No info, assume no error, should not occur */ - break; - case 0x11: - case 0x21: - retval=DID_TIME_OUT; - break; - case 0x0a: - retval=DID_BAD_TARGET; - break; - case 0x04: - case 0x05: - retval=DID_ABORT; /* Either by this driver or the AHA1740 - itself */ - break; - default: - retval=DID_ERROR; /* No further diagnostics possible */ - } - } - else - { /* Michael suggests, and Brad concurs: */ - if ( status_word.qf ) - { - retval = DID_TIME_OUT; /* forces a redo */ - /* I think this specific one should not happen -Brad */ - printk("aha1740.c: WARNING: AHA1740 queue overflow!\n"); - } - else if ( status[0]&0x60 ) - { - retval = DID_ERROR; /* Didn't find a better error */ - } - /* In any other case return DID_OK so for example - CONDITION_CHECKS make it through to the appropriate - device driver */ - } - } - /* Under all circumstances supply the target status -Michael */ - return status[3] | retval << 16; -} - -int aha1740_test_port(void) -{ - char name[4],tmp; - - /* Okay, look for the EISA ID's */ - name[0]= 'A' -1 + ((tmp = inb(HID0)) >> 2); /* First character */ - name[1]= 'A' -1 + ((tmp & 3) << 3); - name[1]+= ((tmp = inb(HID1)) >> 5)&0x7; /* Second Character */ - name[2]= 'A' -1 + (tmp & 0x1f); /* Third Character */ - name[3]=0; - tmp = inb(HID2); - if ( strcmp ( name, HID_MFG ) || inb(HID2) != HID_PRD ) - return 0; /* Not an Adaptec 174x */ - -/* if ( inb(HID3) != HID_REV ) - printk("aha1740: Warning; board revision of %d; expected %d\n", - inb(HID3),HID_REV); */ - - if ( inb(EBCNTRL) != EBCNTRL_VALUE ) - { - printk("aha1740: Board detected, but EBCNTRL = %x, so disabled it.\n", - inb(EBCNTRL)); - return 0; - } - - /* Try and turn on enhanced mode */ - tmp = inb (PORTADR); - outb (PORTADR, tmp | PORTADDR_ENH); - if ( inb(PORTADR) & PORTADDR_ENH ) - return 1; /* Okay, we're all set */ - - printk("aha1740: Board detected, but not in enhanced mode, so disabled it.\n"); - return 0; -} - -/* A "high" level interrupt handler */ -void aha1740_intr_handle(int irq, struct pt_regs * regs) -{ - void (*my_done)(Scsi_Cmnd *); - int errstatus, adapstat; - int number_serviced; - struct ecb *ecbptr; - Scsi_Cmnd *SCtmp; - - number_serviced = 0; - - while(inb(G2STAT) & G2STAT_INTPEND) - { - DEB(printk("aha1740_intr top of loop.\n")); - adapstat = inb(G2INTST); - ecbptr = (struct ecb *) bus_to_virt(inl(MBOXIN0)); - outb(G2CNTRL_IRST,G2CNTRL); /* interrupt reset */ - - switch ( adapstat & G2INTST_MASK ) - { - case G2INTST_CCBRETRY: - case G2INTST_CCBERROR: - case G2INTST_CCBGOOD: - outb(G2CNTRL_HRDY,G2CNTRL); /* Host Ready -> Mailbox in complete */ - if (!ecbptr) - { - printk("Aha1740 null ecbptr in interrupt (%x,%x,%x,%d)\n", - inb(G2STAT),adapstat,inb(G2INTST),number_serviced++); - continue; - } - SCtmp = ecbptr->SCpnt; - if (!SCtmp) - { - printk("Aha1740 null SCtmp in interrupt (%x,%x,%x,%d)\n", - inb(G2STAT),adapstat,inb(G2INTST),number_serviced++); - continue; - } - if (SCtmp->host_scribble) - scsi_free(SCtmp->host_scribble, 512); - /* Fetch the sense data, and tuck it away, in the required slot. The - Adaptec automatically fetches it, and there is no guarantee that - we will still have it in the cdb when we come back */ - if ( (adapstat & G2INTST_MASK) == G2INTST_CCBERROR ) - { - memcpy(SCtmp->sense_buffer, ecbptr->sense, - sizeof(SCtmp->sense_buffer)); - errstatus = aha1740_makecode(ecbptr->sense,ecbptr->status); - } - else - errstatus = 0; - DEB(if (errstatus) printk("aha1740_intr_handle: returning %6x\n", errstatus)); - SCtmp->result = errstatus; - my_done = ecbptr->done; - memset(ecbptr,0,sizeof(struct ecb)); - if ( my_done ) - my_done(SCtmp); - break; - case G2INTST_HARDFAIL: - printk("aha1740 hardware failure!\n"); - panic("aha1740.c"); /* Goodbye */ - case G2INTST_ASNEVENT: - printk("aha1740 asynchronous event: %02x %02x %02x %02x %02x\n",adapstat, - inb(MBOXIN0),inb(MBOXIN1),inb(MBOXIN2),inb(MBOXIN3)); /* Say What? */ - outb(G2CNTRL_HRDY,G2CNTRL); /* Host Ready -> Mailbox in complete */ - break; - case G2INTST_CMDGOOD: - /* set immediate command success flag here: */ - break; - case G2INTST_CMDERROR: - /* Set immediate command failure flag here: */ - break; - } - number_serviced++; - } -} - -int aha1740_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) -{ - unchar direction; - unchar *cmd = (unchar *) SCpnt->cmnd; - unchar target = SCpnt->target; - unsigned long flags; - void *buff = SCpnt->request_buffer; - int bufflen = SCpnt->request_bufflen; - int ecbno; - DEB(int i); - - - if(*cmd == REQUEST_SENSE) - { - if (bufflen != sizeof(SCpnt->sense_buffer)) - { - printk("Wrong buffer length supplied for request sense (%d)\n",bufflen); - } - SCpnt->result = 0; - done(SCpnt); - return 0; - } - -#ifdef DEBUG - if (*cmd == READ_10 || *cmd == WRITE_10) - i = xscsi2int(cmd+2); - else if (*cmd == READ_6 || *cmd == WRITE_6) - i = scsi2int(cmd+2); - else - i = -1; - printk("aha1740_queuecommand: dev %d cmd %02x pos %d len %d ", target, *cmd, i, bufflen); - printk("scsi cmd:"); - for (i = 0; i < SCpnt->cmd_len; i++) printk("%02x ", cmd[i]); - printk("\n"); -#endif - - /* locate an available ecb */ - - save_flags(flags); - cli(); - ecbno = aha1740_last_ecb_used + 1; /* An optimization */ - if (ecbno >= AHA1740_ECBS) ecbno = 0; - - do{ - if( ! ecb[ecbno].cmdw ) - break; - ecbno++; - if (ecbno >= AHA1740_ECBS ) ecbno = 0; - } while (ecbno != aha1740_last_ecb_used); - - if( ecb[ecbno].cmdw ) - panic("Unable to find empty ecb for aha1740.\n"); - - ecb[ecbno].cmdw = AHA1740CMD_INIT; /* SCSI Initiator Command doubles as reserved flag */ - - aha1740_last_ecb_used = ecbno; - restore_flags(flags); - -#ifdef DEBUG - printk("Sending command (%d %x)...",ecbno, done); -#endif - - ecb[ecbno].cdblen = SCpnt->cmd_len; /* SCSI Command Descriptor Block Length */ - - direction = 0; - if (*cmd == READ_10 || *cmd == READ_6) - direction = 1; - else if (*cmd == WRITE_10 || *cmd == WRITE_6) - direction = 0; - - memcpy(ecb[ecbno].cdb, cmd, ecb[ecbno].cdblen); - - if (SCpnt->use_sg) - { - struct scatterlist * sgpnt; - struct aha1740_chain * cptr; - int i; -#ifdef DEBUG - unsigned char * ptr; -#endif - ecb[ecbno].sg = 1; /* SCSI Initiator Command w/scatter-gather*/ - SCpnt->host_scribble = (unsigned char *) scsi_malloc(512); - sgpnt = (struct scatterlist *) SCpnt->request_buffer; - cptr = (struct aha1740_chain *) SCpnt->host_scribble; - if (cptr == NULL) panic("aha1740.c: unable to allocate DMA memory\n"); - for(i=0; i<SCpnt->use_sg; i++) - { - cptr[i].dataptr = (long) sgpnt[i].address; - cptr[i].datalen = sgpnt[i].length; - } - ecb[ecbno].datalen = SCpnt->use_sg * sizeof(struct aha1740_chain); - ecb[ecbno].dataptr = (long) cptr; -#ifdef DEBUG - printk("cptr %x: ",cptr); - ptr = (unsigned char *) cptr; - for(i=0;i<24;i++) printk("%02x ", ptr[i]); -#endif - } - else - { - SCpnt->host_scribble = NULL; - ecb[ecbno].datalen = bufflen; - ecb[ecbno].dataptr = (long) buff; - } - ecb[ecbno].lun = SCpnt->lun; - ecb[ecbno].ses = 1; /* Suppress underrun errors */ - ecb[ecbno].dir= direction; - ecb[ecbno].ars=1; /* Yes, get the sense on an error */ - ecb[ecbno].senselen = 12; - ecb[ecbno].senseptr = (long) ecb[ecbno].sense; - ecb[ecbno].statusptr = (long) ecb[ecbno].status; - ecb[ecbno].done = done; - ecb[ecbno].SCpnt = SCpnt; -#ifdef DEBUG - { - int i; - printk("aha1740_command: sending.. "); - for (i = 0; i < sizeof(ecb[ecbno])-10; i++) - printk("%02x ", ((unchar *)&ecb[ecbno])[i]); - } - printk("\n"); -#endif - if (done) - { /* You may question the code below, which contains potentially - non-terminating while loops with interrupts disabled. So did - I when I wrote it, but the Adaptec Spec says the card is so fast, - that this problem virtually never occurs so I've kept it. We - do printk a warning first, so that you'll know if it happens. - In practice the only time we've seen this message is when some- - thing else is in the driver was broken, like _makecode(), or - when a scsi device hung the scsi bus. Even under these conditions, - The loop actually only cycled < 3 times (we instrumented it). */ - - DEB(printk("aha1740[%d] critical section\n",ecbno)); - save_flags(flags); - cli(); - if ( ! (inb(G2STAT) & G2STAT_MBXOUT) ) - { - printk("aha1740[%d]_mbxout wait!\n",ecbno); - cli(); /* printk may have done a sti()! */ - } - mb(); - while ( ! (inb(G2STAT) & G2STAT_MBXOUT) ); /* Oh Well. */ - outl(virt_to_bus(ecb+ecbno), MBOXOUT0); - if ( inb(G2STAT) & G2STAT_BUSY ) - { - printk("aha1740[%d]_attn wait!\n",ecbno); - cli(); - } - while ( inb(G2STAT) & G2STAT_BUSY ); /* And Again! */ - outb(ATTN_START | (target & 7), ATTN); /* Start it up */ - restore_flags(flags); - DEB(printk("aha1740[%d] request queued.\n",ecbno)); - } - else - printk("aha1740_queuecommand: done can't be NULL\n"); - - return 0; -} - -static volatile int internal_done_flag = 0; -static volatile int internal_done_errcode = 0; - -static void internal_done(Scsi_Cmnd * SCpnt) -{ - internal_done_errcode = SCpnt->result; - ++internal_done_flag; -} - -int aha1740_command(Scsi_Cmnd * SCpnt) -{ - aha1740_queuecommand(SCpnt, internal_done); - - while (!internal_done_flag); - internal_done_flag = 0; - return internal_done_errcode; -} - -/* Query the board for its irq_level. Nothing else matters - in enhanced mode on an EISA bus. */ - -void aha1740_getconfig(void) -{ - static int intab[] = { 9,10,11,12,0,14,15,0 }; - - irq_level = intab [ inb(INTDEF)&0x7 ]; - outb(inb(INTDEF) | 0x10, INTDEF); -} - -int aha1740_detect(Scsi_Host_Template * tpnt) -{ - tpnt->proc_dir = &proc_scsi_aha1740; - - memset(&ecb, 0, sizeof(struct ecb)); - DEB(printk("aha1740_detect: \n")); - - for ( slot=MINEISA; slot <= MAXEISA; slot++ ) - { - base = SLOTBASE(slot); - /* - * The ioports for eisa boards are generally beyond that used in the - * check/allocate region code, but this may change at some point, - * so we go through the motions. - */ - if(check_region(base, 0x5c)) continue; /* See if in use */ - if ( aha1740_test_port()) break; - } - if ( slot > MAXEISA ) - return 0; - - aha1740_getconfig(); - - if ( (inb(G2STAT) & (G2STAT_MBXOUT | G2STAT_BUSY) ) != G2STAT_MBXOUT ) - { /* If the card isn't ready, hard reset it */ - outb(G2CNTRL_HRST,G2CNTRL); - outb(0,G2CNTRL); - } - - printk("Configuring Adaptec at IO:%x, IRQ %d\n",base, - irq_level); - - DEB(printk("aha1740_detect: enable interrupt channel %d\n", irq_level)); - - if (request_irq(irq_level,aha1740_intr_handle, 0, "aha1740")) - { - printk("Unable to allocate IRQ for adaptec controller.\n"); - return 0; - } - request_region(base, 0x5c,"aha1740"); /* Reserve the space that we need to use */ - return 1; -} - -/* Note: They following two functions do not apply very well to the Adaptec, -which basically manages its own affairs quite well without our interference, -so I haven't put anything into them. I can faintly imagine someone with a -*very* badly behaved SCSI target (perhaps an old tape?) wanting the abort(), -but it hasn't happened yet, and doing aborts brings the Adaptec to its -knees. I cannot (at this moment in time) think of any reason to reset the -card once it's running. So there. */ - -int aha1740_abort(Scsi_Cmnd * SCpnt) -{ - DEB(printk("aha1740_abort called\n")); - return SCSI_ABORT_SNOOZE; -} - -/* We do not implement a reset function here, but the upper level code assumes - that it will get some kind of response for the command in SCpnt. We must - oblige, or the command will hang the scsi system */ - -int aha1740_reset(Scsi_Cmnd * SCpnt) -{ - DEB(printk("aha1740_reset called\n")); - return SCSI_RESET_PUNT; -} - -int aha1740_biosparam(Disk * disk, kdev_t dev, int* ip) -{ - int size = disk->capacity; -DEB(printk("aha1740_biosparam\n")); - ip[0] = 64; - ip[1] = 32; - ip[2] = size >> 11; -/* if (ip[2] >= 1024) ip[2] = 1024; */ - return 0; -} - -#ifdef MODULE -/* Eventually this will go into an include file, but this will be later */ -Scsi_Host_Template driver_template = AHA1740; - -#include "scsi_module.c" -#endif - -/* Okay, you made it all the way through. As of this writing, 3/31/93, I'm -brad@saturn.gaylord.com or brad@bradpc.gaylord.com. I'll try to help as time -permits if you have any trouble with this driver. Happy Linuxing! */ diff --git a/i386/i386at/gpl/linux/scsi/aha1740.h b/i386/i386at/gpl/linux/scsi/aha1740.h deleted file mode 100644 index 79d94697..00000000 --- a/i386/i386at/gpl/linux/scsi/aha1740.h +++ /dev/null @@ -1,193 +0,0 @@ -#ifndef _AHA1740_H - -/* $Id: aha1740.h,v 1.1.1.1 1997/02/25 21:27:46 thomas Exp $ - * - * Header file for the adaptec 1740 driver for Linux - * - * With minor revisions 3/31/93 - * Written and (C) 1992,1993 Brad McLean. See aha1740.c - * for more info - * - */ - -#include <linux/types.h> -#include <linux/kdev_t.h> - -/* Eisa Enhanced mode operation - slot locating and addressing */ -#define MINEISA 1 /* I don't have an EISA Spec to know these ranges, so I */ -#define MAXEISA 8 /* Just took my machine's specifications. Adjust to fit.*/ - /* I just saw an ad, and bumped this from 6 to 8 */ -#define SLOTBASE(x) ((x << 12)+ 0xc80 ) -#define BASE (base) - -/* EISA configuration registers & values */ -#define HID0 (base + 0x0) -#define HID1 (base + 0x1) -#define HID2 (base + 0x2) -#define HID3 (base + 0x3) -#define EBCNTRL (base + 0x4) -#define PORTADR (base + 0x40) -#define BIOSADR (base + 0x41) -#define INTDEF (base + 0x42) -#define SCSIDEF (base + 0x43) -#define BUSDEF (base + 0x44) -#define RESV0 (base + 0x45) -#define RESV1 (base + 0x46) -#define RESV2 (base + 0x47) - -#define HID_MFG "ADP" -#define HID_PRD 0 -#define HID_REV 2 -#define EBCNTRL_VALUE 1 -#define PORTADDR_ENH 0x80 -/* READ */ -#define G2INTST (BASE + 0x56) -#define G2STAT (BASE + 0x57) -#define MBOXIN0 (BASE + 0x58) -#define MBOXIN1 (BASE + 0x59) -#define MBOXIN2 (BASE + 0x5a) -#define MBOXIN3 (BASE + 0x5b) -#define G2STAT2 (BASE + 0x5c) - -#define G2INTST_MASK 0xf0 /* isolate the status */ -#define G2INTST_CCBGOOD 0x10 /* CCB Completed */ -#define G2INTST_CCBRETRY 0x50 /* CCB Completed with a retry */ -#define G2INTST_HARDFAIL 0x70 /* Adapter Hardware Failure */ -#define G2INTST_CMDGOOD 0xa0 /* Immediate command success */ -#define G2INTST_CCBERROR 0xc0 /* CCB Completed with error */ -#define G2INTST_ASNEVENT 0xd0 /* Asynchronous Event Notification */ -#define G2INTST_CMDERROR 0xe0 /* Immediate command error */ - -#define G2STAT_MBXOUT 4 /* Mailbox Out Empty Bit */ -#define G2STAT_INTPEND 2 /* Interrupt Pending Bit */ -#define G2STAT_BUSY 1 /* Busy Bit (attention pending) */ - -#define G2STAT2_READY 0 /* Host Ready Bit */ - -/* WRITE (and ReadBack) */ -#define MBOXOUT0 (BASE + 0x50) -#define MBOXOUT1 (BASE + 0x51) -#define MBOXOUT2 (BASE + 0x52) -#define MBOXOUT3 (BASE + 0x53) -#define ATTN (BASE + 0x54) -#define G2CNTRL (BASE + 0x55) - -#define ATTN_IMMED 0x10 /* Immediate Command */ -#define ATTN_START 0x40 /* Start CCB */ -#define ATTN_ABORT 0x50 /* Abort CCB */ - -#define G2CNTRL_HRST 0x80 /* Hard Reset */ -#define G2CNTRL_IRST 0x40 /* Clear EISA Interrupt */ -#define G2CNTRL_HRDY 0x20 /* Sets HOST ready */ - -/* This is used with scatter-gather */ -struct aha1740_chain { - u32 dataptr; /* Location of data */ - u32 datalen; /* Size of this part of chain */ -}; - -/* These belong in scsi.h */ -#define any2scsi(up, p) \ -(up)[0] = (((unsigned long)(p)) >> 16) ; \ -(up)[1] = (((unsigned long)(p)) >> 8); \ -(up)[2] = ((unsigned long)(p)); - -#define scsi2int(up) ( (((long)*(up)) << 16) + (((long)(up)[1]) << 8) + ((long)(up)[2]) ) - -#define xany2scsi(up, p) \ -(up)[0] = ((long)(p)) >> 24; \ -(up)[1] = ((long)(p)) >> 16; \ -(up)[2] = ((long)(p)) >> 8; \ -(up)[3] = ((long)(p)); - -#define xscsi2int(up) ( (((long)(up)[0]) << 24) + (((long)(up)[1]) << 16) \ - + (((long)(up)[2]) << 8) + ((long)(up)[3]) ) - -#define MAX_CDB 12 -#define MAX_SENSE 14 -#define MAX_STATUS 32 - -struct ecb { /* Enhanced Control Block 6.1 */ - u16 cmdw; /* Command Word */ - /* Flag Word 1 */ - u16 cne:1, /* Control Block Chaining */ - :6, di:1, /* Disable Interrupt */ - :2, ses:1, /* Suppress Underrun error */ - :1, sg:1, /* Scatter/Gather */ - :1, dsb:1, /* Disable Status Block */ - ars:1; /* Automatic Request Sense */ - /* Flag Word 2 */ - u16 lun:3, /* Logical Unit */ - tag:1, /* Tagged Queuing */ - tt:2, /* Tag Type */ - nd:1, /* No Disconnect */ - :1, dat:1, /* Data transfer - check direction */ - dir:1, /* Direction of transfer 1 = datain */ - st:1, /* Suppress Transfer */ - chk:1, /* Calculate Checksum */ - :2, rec:1, :1; /* Error Recovery */ - u16 nil0; /* nothing */ - u32 dataptr; /* Data or Scatter List ptr */ - u32 datalen; /* Data or Scatter List len */ - u32 statusptr; /* Status Block ptr */ - u32 linkptr; /* Chain Address */ - u32 nil1; /* nothing */ - u32 senseptr; /* Sense Info Pointer */ - u8 senselen; /* Sense Length */ - u8 cdblen; /* CDB Length */ - u16 datacheck; /* Data checksum */ - u8 cdb[MAX_CDB]; /* CDB area */ -/* Hardware defined portion ends here, rest is driver defined */ - u8 sense[MAX_SENSE]; /* Sense area */ - u8 status[MAX_STATUS]; /* Status area */ - Scsi_Cmnd *SCpnt; /* Link to the SCSI Command Block */ - void (*done)(Scsi_Cmnd *); /* Completion Function */ -}; - -#define AHA1740CMD_NOP 0x00 /* No OP */ -#define AHA1740CMD_INIT 0x01 /* Initiator SCSI Command */ -#define AHA1740CMD_DIAG 0x05 /* Run Diagnostic Command */ -#define AHA1740CMD_SCSI 0x06 /* Initialize SCSI */ -#define AHA1740CMD_SENSE 0x08 /* Read Sense Information */ -#define AHA1740CMD_DOWN 0x09 /* Download Firmware (yeah, I bet!) */ -#define AHA1740CMD_RINQ 0x0a /* Read Host Adapter Inquiry Data */ -#define AHA1740CMD_TARG 0x10 /* Target SCSI Command */ - -int aha1740_detect(Scsi_Host_Template *); -int aha1740_command(Scsi_Cmnd *); -int aha1740_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); -int aha1740_abort(Scsi_Cmnd *); -int aha1740_reset(Scsi_Cmnd *); -int aha1740_biosparam(Disk *, kdev_t, int*); - -#define AHA1740_ECBS 32 -#define AHA1740_SCATTER 16 - -#ifndef NULL -#define NULL 0 -#endif - - -#define AHA1740 {NULL, NULL, \ - NULL, \ - NULL, \ - "Adaptec 174x (EISA)", \ - aha1740_detect, \ - NULL, \ - NULL, \ - aha1740_command, \ - aha1740_queuecommand, \ - aha1740_abort, \ - aha1740_reset, \ - NULL, \ - aha1740_biosparam, \ - AHA1740_ECBS, \ - 7, \ - AHA1740_SCATTER, \ - 1, \ - 0, \ - 0, \ - ENABLE_CLUSTERING} - -#endif - diff --git a/i386/i386at/gpl/linux/scsi/aic7xxx.c b/i386/i386at/gpl/linux/scsi/aic7xxx.c deleted file mode 100644 index 3b238983..00000000 --- a/i386/i386at/gpl/linux/scsi/aic7xxx.c +++ /dev/null @@ -1,4645 +0,0 @@ -/*+M************************************************************************* - * Adaptec AIC7xxx device driver for Linux. - * - * Copyright (c) 1994 John Aycock - * The University of Calgary Department of Computer Science. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to - * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Sources include the Adaptec 1740 driver (aha1740.c), the Ultrastor 24F - * driver (ultrastor.c), various Linux kernel source, the Adaptec EISA - * config file (!adp7771.cfg), the Adaptec AHA-2740A Series User's Guide, - * the Linux Kernel Hacker's Guide, Writing a SCSI Device Driver for Linux, - * the Adaptec 1542 driver (aha1542.c), the Adaptec EISA overlay file - * (adp7770.ovl), the Adaptec AHA-2740 Series Technical Reference Manual, - * the Adaptec AIC-7770 Data Book, the ANSI SCSI specification, the - * ANSI SCSI-2 specification (draft 10c), ... - * - * ---------------------------------------------------------------- - * Modified to include support for wide and twin bus adapters, - * DMAing of SCBs, tagged queueing, IRQ sharing, bug fixes, - * and other rework of the code. - * - * Parts of this driver are based on the FreeBSD driver by Justin - * T. Gibbs. - * - * A Boot time option was also added for not resetting the scsi bus. - * - * Form: aic7xxx=extended,no_reset - * - * -- Daniel M. Eischen, deischen@iworks.InterWorks.org, 04/03/95 - * - * $Id: aic7xxx.c,v 1.1.1.1 1997/02/25 21:27:46 thomas Exp $ - *-M*************************************************************************/ - -#ifdef MODULE -#include <linux/module.h> -#endif - -#include <stdarg.h> -#include <asm/io.h> -#include <linux/string.h> -#include <linux/errno.h> -#include <linux/kernel.h> -#include <linux/ioport.h> -#include <linux/bios32.h> -#include <linux/delay.h> -#include <linux/sched.h> -#include <linux/pci.h> -#include <linux/proc_fs.h> -#include <linux/blk.h> -#include "sd.h" -#include "scsi.h" -#include "hosts.h" -#include "aic7xxx.h" -#include "aic7xxx_reg.h" -#include <linux/stat.h> - -#include <linux/config.h> /* for CONFIG_PCI */ - -struct proc_dir_entry proc_scsi_aic7xxx = { - PROC_SCSI_AIC7XXX, 7, "aic7xxx", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - -#define AIC7XXX_C_VERSION "$Revision: 1.1.1.1 $" - -#define NUMBER(arr) (sizeof(arr) / sizeof(arr[0])) -#define MIN(a,b) ((a < b) ? a : b) -#define ALL_TARGETS -1 -#ifndef TRUE -# define TRUE 1 -#endif -#ifndef FALSE -# define FALSE 0 -#endif - -/* - * Defines for PCI bus support, testing twin bus support, DMAing of - * SCBs, tagged queueing, commands (SCBs) per lun, and SCSI bus reset - * delay time. - * - * o PCI bus support - this has been implemented and working since - * the December 1, 1994 release of this driver. If you don't have - * a PCI bus, then you can configure your kernel without PCI - * support because all PCI dependent code is bracketed with - * "#ifdef CONFIG_PCI ... #endif CONFIG_PCI". - * - * o Twin bus support - this has been tested and does work. - * - * o DMAing of SCBs - thanks to Kai Makisara, this now works. - * This define is now taken out and DMAing of SCBs is always - * performed (8/12/95 - DE). - * - * o Tagged queueing - this driver is capable of tagged queueing - * but I am unsure as to how well the higher level driver implements - * tagged queueing. Therefore, the maximum commands per lun is - * set to 2. If you want to implement tagged queueing, ensure - * this define is not commented out. - * - * o Sharing IRQs - allowed for sharing of IRQs. This will allow - * for multiple aic7xxx host adapters sharing the same IRQ, but - * not for sharing IRQs with other devices. The higher level - * PCI code and interrupt handling needs to be modified to - * support this. - * - * o Commands per lun - If tagged queueing is enabled, then you - * may want to try increasing AIC7XXX_CMDS_PER_LUN to more - * than 2. By default, we limit the SCBs per lun to 2 with - * or without tagged queueing enabled. If tagged queueing is - * disabled, the sequencer will keep the 2nd SCB in the input - * queue until the first one completes - so it is OK to to have - * more than 1 SCB queued. If tagged queueing is enabled, then - * the sequencer will attempt to send the 2nd SCB to the device - * while the first SCB is executing and the device is disconnected. - * For adapters limited to 4 SCBs, you may want to actually - * decrease the commands per lun to 1, if you often have more - * than 2 devices active at the same time. This will allocate - * 1 SCB for each device and ensure that there will always be - * a free SCB for up to 4 devices active at the same time. - * - * o 3985 support - The 3985 adapter is much like the 3940, but - * has three 7870 controllers as opposed to two for the 3940. - * It will get probed and recognized as three different adapters, - * but all three controllers share the same bank of 255 SCBs - * instead of each controller having their own bank (like the - * controllers on the 3940). For this reason, it is important - * that all devices be resident on just one channel of the 3985. - * In the near future, we'll modify the driver to reserve 1/3 - * of the SCBs for each controller. - * - * Daniel M. Eischen, deischen@iworks.InterWorks.org, 01/11/96 - */ - -/* Uncomment this for testing twin bus support. */ -#define AIC7XXX_TWIN_SUPPORT - -/* Uncomment this for tagged queueing. */ -/* #define AIC7XXX_TAGGED_QUEUEING */ - -/* Uncomment this for allowing sharing of IRQs. */ -#define AIC7XXX_SHARE_IRQS - -/* - * You can try raising me if tagged queueing is enabled, or lowering - * me if you only have 4 SCBs. - */ -#define AIC7XXX_CMDS_PER_LUN 2 - -/* Set this to the delay in seconds after SCSI bus reset. */ -#define AIC7XXX_RESET_DELAY 15 - -/* - * Uncomment the following define for collection of SCSI transfer statistics - * for the /proc filesystem. - * - * NOTE: This does affect performance since it has to maintain statistics. - */ -/* #define AIC7XXX_PROC_STATS */ - -/* - * For debugging the abort/reset code. - */ -/* #define AIC7XXX_DEBUG_ABORT */ - -/* - * For general debug messages - */ -#define AIC7XXX_DEBUG - -/* - * Controller type and options - */ -typedef enum { - AIC_NONE, - AIC_7770, /* EISA aic7770 on motherboard */ - AIC_7771, /* EISA aic7771 on 274x */ - AIC_284x, /* VLB aic7770 on 284x */ - AIC_7850, /* PCI aic7850 */ - AIC_7870, /* PCI aic7870 on motherboard */ - AIC_7871, /* PCI aic7871 on 294x */ - AIC_7872, /* PCI aic7872 on 3940 */ - AIC_7873, /* PCI aic7873 on 3985 */ - AIC_7874, /* PCI aic7874 on 294x Differential */ - AIC_7880, /* PCI aic7880 on motherboard */ - AIC_7881, /* PCI aic7881 on 294x Ultra */ - AIC_7882, /* PCI aic7882 on 3940 Ultra */ - AIC_7883, /* PCI aic7883 on 3985 Ultra */ - AIC_7884 /* PCI aic7884 on 294x Ultra Differential */ -} aha_type; - -typedef enum { - AIC_777x, /* AIC-7770 based */ - AIC_785x, /* AIC-7850 based */ - AIC_787x, /* AIC-7870 based */ - AIC_788x /* AIC-7880 based */ -} aha_chip_type; - -typedef enum { - AIC_SINGLE, /* Single Channel */ - AIC_TWIN, /* Twin Channel */ - AIC_WIDE /* Wide Channel */ -} aha_bus_type; - -typedef enum { - AIC_UNKNOWN, - AIC_ENABLED, - AIC_DISABLED -} aha_status_type; - -typedef enum { - LIST_HEAD, - LIST_SECOND -} insert_type; - -typedef enum { - ABORT_RESET_INACTIVE, - ABORT_RESET_PENDING, - ABORT_RESET_SUCCESS -} aha_abort_reset_type; - -/* - * Define an array of board names that can be indexed by aha_type. - * Don't forget to change this when changing the types! - */ -static const char * board_names[] = { - "<AIC-7xxx Unknown>", /* AIC_NONE */ - "AIC-7770", /* AIC_7770 */ - "AHA-2740", /* AIC_7771 */ - "AHA-2840", /* AIC_284x */ - "AIC-7850", /* AIC_7850 */ - "AIC-7870", /* AIC_7870 */ - "AHA-2940", /* AIC_7871 */ - "AHA-3940", /* AIC_7872 */ - "AHA-3985", /* AIC_7873 */ - "AHA-2940 Differential", /* AIC_7874 */ - "AIC-7880 Ultra", /* AIC_7880 */ - "AHA-2940 Ultra", /* AIC_7881 */ - "AHA-3940 Ultra", /* AIC_7882 */ - "AHA-3985 Ultra", /* AIC_7883 */ - "AHA-2940 Ultra Differential" /* AIC_7884 */ -}; - -/* - * There should be a specific return value for this in scsi.h, but - * it seems that most drivers ignore it. - */ -#define DID_UNDERFLOW DID_ERROR - -/* - * What we want to do is have the higher level scsi driver requeue - * the command to us. There is no specific driver status for this - * condition, but the higher level scsi driver will requeue the - * command on a DID_BUS_BUSY error. - */ -#define DID_RETRY_COMMAND DID_BUS_BUSY - -/* - * EISA/VL-bus stuff - */ -#define MINSLOT 1 -#define MAXSLOT 15 -#define SLOTBASE(x) ((x) << 12) -#define MAXIRQ 15 - -/* - * Standard EISA Host ID regs (Offset from slot base) - */ -#define HID0 0x80 /* 0,1: msb of ID2, 2-7: ID1 */ -#define HID1 0x81 /* 0-4: ID3, 5-7: LSB ID2 */ -#define HID2 0x82 /* product */ -#define HID3 0x83 /* firmware revision */ - -/* - * AIC-7770 I/O range to reserve for a card - */ -#define MINREG 0xC00 -#define MAXREG 0xCBF - -#define INTDEF 0x5C /* Interrupt Definition Register */ - -/* - * Some defines for the HCNTRL register. - */ -#define REQ_PAUSE IRQMS | INTEN | PAUSE -#define UNPAUSE_274X IRQMS | INTEN -#define UNPAUSE_284X INTEN -#define UNPAUSE_294X IRQMS | INTEN - -/* - * AIC-78X0 PCI registers - */ -#define CLASS_PROGIF_REVID 0x08 -#define DEVREVID 0x000000FFul -#define PROGINFC 0x0000FF00ul -#define SUBCLASS 0x00FF0000ul -#define BASECLASS 0xFF000000ul - -#define CSIZE_LATTIME 0x0C -#define CACHESIZE 0x0000003Ful /* only 5 bits */ -#define LATTIME 0x0000FF00ul - -#define DEVCONFIG 0x40 -#define MPORTMODE 0x00000400ul /* aic7870 only */ -#define RAMPSM 0x00000200ul /* aic7870 only */ -#define VOLSENSE 0x00000100ul -#define SCBRAMSEL 0x00000080ul -#define MRDCEN 0x00000040ul -#define EXTSCBTIME 0x00000020ul /* aic7870 only */ -#define EXTSCBPEN 0x00000010ul /* aic7870 only */ -#define BERREN 0x00000008ul -#define DACEN 0x00000004ul -#define STPWLEVEL 0x00000002ul -#define DIFACTNEGEN 0x00000001ul /* aic7870 only */ - -/* - * - * Define the format of the SEEPROM registers (16 bits). - * - */ -struct seeprom_config { - -/* - * SCSI ID Configuration Flags - */ -#define CFXFER 0x0007 /* synchronous transfer rate */ -#define CFSYNCH 0x0008 /* enable synchronous transfer */ -#define CFDISC 0x0010 /* enable disconnection */ -#define CFWIDEB 0x0020 /* wide bus device (wide card) */ -/* UNUSED 0x00C0 */ -#define CFSTART 0x0100 /* send start unit SCSI command */ -#define CFINCBIOS 0x0200 /* include in BIOS scan */ -#define CFRNFOUND 0x0400 /* report even if not found */ -/* UNUSED 0xF800 */ - unsigned short device_flags[16]; /* words 0-15 */ - -/* - * BIOS Control Bits - */ -#define CFSUPREM 0x0001 /* support all removeable drives */ -#define CFSUPREMB 0x0002 /* support removeable drives for boot only */ -#define CFBIOSEN 0x0004 /* BIOS enabled */ -/* UNUSED 0x0008 */ -#define CFSM2DRV 0x0010 /* support more than two drives */ -#define CF284XEXTEND 0x0020 /* extended translation (284x cards) */ -/* UNUSED 0x0040 */ -#define CFEXTEND 0x0080 /* extended translation enabled */ -/* UNUSED 0xFF00 */ - unsigned short bios_control; /* word 16 */ - -/* - * Host Adapter Control Bits - */ -/* UNUSED 0x0001 */ -#define CFULTRAEN 0x0002 /* Ultra SCSI speed enable (Ultra cards) */ -#define CF284XSELTO 0x0003 /* Selection timeout (284x cards) */ -#define CF284XFIFO 0x000C /* FIFO Threshold (284x cards) */ -#define CFSTERM 0x0004 /* SCSI low byte termination (non-wide cards) */ -#define CFWSTERM 0x0008 /* SCSI high byte termination (wide card) */ -#define CFSPARITY 0x0010 /* SCSI parity */ -#define CF284XSTERM 0x0020 /* SCSI low byte termination (284x cards) */ -#define CFRESETB 0x0040 /* reset SCSI bus at IC initialization */ -/* UNUSED 0xFF80 */ - unsigned short adapter_control; /* word 17 */ - -/* - * Bus Release, Host Adapter ID - */ -#define CFSCSIID 0x000F /* host adapter SCSI ID */ -/* UNUSED 0x00F0 */ -#define CFBRTIME 0xFF00 /* bus release time */ - unsigned short brtime_id; /* word 18 */ - -/* - * Maximum targets - */ -#define CFMAXTARG 0x00FF /* maximum targets */ -/* UNUSED 0xFF00 */ - unsigned short max_targets; /* word 19 */ - - unsigned short res_1[11]; /* words 20-30 */ - unsigned short checksum; /* word 31 */ -}; - -/* - * Pause the sequencer and wait for it to actually stop - this - * is important since the sequencer can disable pausing for critical - * sections. - */ -#define PAUSE_SEQUENCER(p) \ - outb(p->pause, HCNTRL + p->base); \ - while ((inb(HCNTRL + p->base) & PAUSE) == 0) \ - ; \ - -/* - * Unpause the sequencer. Unremarkable, yet done often enough to - * warrant an easy way to do it. - */ -#define UNPAUSE_SEQUENCER(p) \ - outb(p->unpause, HCNTRL + p->base) - -/* - * Restart the sequencer program from address zero - */ -#define RESTART_SEQUENCER(p) \ - do { \ - outb(SEQRESET | FASTMODE, SEQCTL + p->base); \ - } while (inb(SEQADDR0 + p->base) != 0 && \ - inb(SEQADDR1 + p->base) != 0); \ - UNPAUSE_SEQUENCER(p); - -/* - * If an error occurs during a data transfer phase, run the comand - * to completion - it's easier that way - making a note of the error - * condition in this location. This then will modify a DID_OK status - * into an appropriate error for the higher-level SCSI code. - */ -#define aic7xxx_error(cmd) ((cmd)->SCp.Status) - -/* - * Keep track of the targets returned status. - */ -#define aic7xxx_status(cmd) ((cmd)->SCp.sent_command) - -/* - * The position of the SCSI commands scb within the scb array. - */ -#define aic7xxx_position(cmd) ((cmd)->SCp.have_data_in) - -/* - * Since the sequencer code DMAs the scatter-gather structures - * directly from memory, we use this macro to assert that the - * kernel structure hasn't changed. - */ -#define SG_STRUCT_CHECK(sg) \ - ((char *) &(sg).address - (char *) &(sg) != 0 || \ - (char *) &(sg).length - (char *) &(sg) != 8 || \ - sizeof((sg).address) != 4 || \ - sizeof((sg).length) != 4 || \ - sizeof(sg) != 12) - -/* - * "Static" structures. Note that these are NOT initialized - * to zero inside the kernel - we have to initialize them all - * explicitly. - * - * We support multiple adapter cards per interrupt, but keep a - * linked list of Scsi_Host structures for each IRQ. On an interrupt, - * use the IRQ as an index into aic7xxx_boards[] to locate the card - * information. - */ -static struct Scsi_Host *aic7xxx_boards[MAXIRQ + 1]; - -/* - * When we detect and register the card, it is possible to - * have the card raise a spurious interrupt. Because we need - * to support multiple cards, we cannot tell which card caused - * the spurious interrupt. And, we might not even have added - * the card info to the linked list at the time the spurious - * interrupt gets raised. This variable is suppose to keep track - * of when we are registering a card and how many spurious - * interrupts we have encountered. - * - * 0 - do not allow spurious interrupts. - * 1 - allow 1 spurious interrupt - * 2 - have 1 spurious interrupt, do not allow any more. - * - * I've made it an integer instead of a boolean in case we - * want to allow more than one spurious interrupt for debugging - * purposes. Otherwise, it could just go from true to false to - * true (or something like that). - * - * When the driver detects the cards, we'll set the count to 1 - * for each card detection and registration. After the registration - * of a card completes, we'll set the count back to 0. So far, it - * seems to be enough to allow a spurious interrupt only during - * card registration; if a spurious interrupt is going to occur, - * this is where it happens. - * - * We should be able to find a way to avoid getting the spurious - * interrupt. But until we do, we have to keep this ugly code. - */ -static int aic7xxx_spurious_count; - -/* - * The driver keeps up to four scb structures per card in memory. Only the - * first 25 bytes of the structure are valid for the hardware, the rest used - * for driver level bookkeeping. - */ - -struct aic7xxx_scb { -/* ------------ Begin hardware supported fields ---------------- */ -/* 0*/ unsigned char control; -/* 1*/ unsigned char target_channel_lun; /* 4/1/3 bits */ -/* 2*/ unsigned char target_status; -/* 3*/ unsigned char SG_segment_count; -/* 4*/ unsigned char SG_list_pointer[4] __attribute__ ((packed)); -/* 8*/ unsigned char residual_SG_segment_count; -/* 9*/ unsigned char residual_data_count[3]; -/*12*/ unsigned char data_pointer[4] __attribute__ ((packed)); -/*16*/ unsigned long data_count; -/*20*/ unsigned char SCSI_cmd_pointer[4] __attribute__ ((packed)); -/*24*/ unsigned char SCSI_cmd_length; -#define SCB_PIO_TRANSFER_SIZE 25 /* - * amount we need to upload/download - * via rep in/outsb to perform - * a request sense. The second - * RESERVED byte is initialized to - * 0 in getscb(). - */ -/*25*/ u_char next_waiting; /* Used to thread SCBs awaiting selection. */ - /*-----------------end of hardware supported fields----------------*/ - struct aic7xxx_scb *next; /* next ptr when in free list */ - Scsi_Cmnd *cmd; /* Scsi_Cmnd for this scb */ -#define SCB_FREE 0x00 -#define SCB_ACTIVE 0x01 -#define SCB_ABORTED 0x02 -#define SCB_DEVICE_RESET 0x04 -#define SCB_IMMED 0x08 -#define SCB_SENSE 0x10 - int state; /* current state of scb */ - unsigned int position; /* Position in scb array */ - struct scatterlist sg; - struct scatterlist sense_sg; - unsigned char sense_cmd[6]; /* Allocate 6 characters for sense command */ -}; - -static struct { - unsigned char errno; - const char *errmesg; -} hard_error[] = { - { ILLHADDR, "Illegal Host Access" }, - { ILLSADDR, "Illegal Sequencer Address referrenced" }, - { ILLOPCODE, "Illegal Opcode in sequencer program" }, - { PARERR, "Sequencer Ram Parity Error" } -}; - -static unsigned char -generic_sense[] = { REQUEST_SENSE, 0, 0, 0, 255, 0 }; - -/* - * The maximum number of SCBs we could have for ANY type - * of card. DON'T FORGET TO CHANGE THE SCB MASK IN THE - * SEQUENCER CODE IF THIS IS MODIFIED! - */ -#define AIC7XXX_MAXSCB 255 - -/* - * Define a structure used for each host adapter, only one per IRQ. - */ -struct aic7xxx_host { - int base; /* card base address */ - int maxscb; /* hardware SCBs */ - int numscb; /* current number of scbs */ - int extended; /* extended xlate? */ - aha_type type; /* card type */ - aha_chip_type chip_type; /* chip base type */ - int ultra_enabled; /* Ultra SCSI speed enabled */ - int chan_num; /* for 3940/3985, channel number */ - aha_bus_type bus_type; /* normal/twin/wide bus */ - unsigned char a_scanned; /* 0 not scanned, 1 scanned */ - unsigned char b_scanned; /* 0 not scanned, 1 scanned */ - unsigned int isr_count; /* Interrupt count */ - volatile unsigned char unpause; /* unpause value for HCNTRL */ - volatile unsigned char pause; /* pause value for HCNTRL */ - volatile unsigned short needsdtr_copy; /* default config */ - volatile unsigned short needsdtr; - volatile unsigned short sdtr_pending; - volatile unsigned short needwdtr_copy; /* default config */ - volatile unsigned short needwdtr; - volatile unsigned short wdtr_pending; - volatile unsigned short discenable; /* Targets allowed to disconnect */ - struct seeprom_config seeprom; - int have_seeprom; - struct Scsi_Host *next; /* allow for multiple IRQs */ - struct aic7xxx_scb scb_array[AIC7XXX_MAXSCB]; /* active commands */ - struct aic7xxx_scb *free_scb; /* list of free SCBs */ -#ifdef AIC7XXX_PROC_STATS - /* - * Statistics Kept: - * - * Total Xfers (count for each command that has a data xfer), - * broken down further by reads && writes. - * - * Binned sizes, writes && reads: - * < 512, 512, 1-2K, 2-4K, 4-8K, 8-16K, 16-32K, 32-64K, 64K-128K, > 128K - * - * Total amounts read/written above 512 bytes (amts under ignored) - */ - struct aic7xxx_xferstats { - long xfers; /* total xfer count */ - long w_total; /* total writes */ - long w_total512; /* 512 byte blocks written */ - long w_bins[10]; /* binned write */ - long r_total; /* total reads */ - long r_total512; /* 512 byte blocks read */ - long r_bins[10]; /* binned reads */ - } stats[2][16][8]; /* channel, target, lun */ -#endif /* AIC7XXX_PROC_STATS */ -}; - -struct aic7xxx_host_config { - int irq; /* IRQ number */ - int base; /* I/O base */ - int maxscb; /* hardware SCBs */ - int unpause; /* unpause value for HCNTRL */ - int pause; /* pause value for HCNTRL */ - int scsi_id; /* host SCSI ID */ - int scsi_id_b; /* host SCSI ID B channel for twin cards */ - int extended; /* extended xlate? */ - int busrtime; /* bus release time */ - int walk_scbs; /* external SCB RAM detected; walk the scb array */ - aha_type type; /* card type */ - aha_chip_type chip_type; /* chip base type */ - int ultra_enabled; /* Ultra SCSI speed enabled */ - int chan_num; /* for 3940/3985, channel number */ - aha_bus_type bus_type; /* normal/twin/wide bus */ - aha_status_type parity; /* bus parity enabled/disabled */ - aha_status_type low_term; /* bus termination low byte */ - aha_status_type high_term; /* bus termination high byte (wide cards only) */ -}; - -/* - * Valid SCSIRATE values. (p. 3-17) - * Provides a mapping of tranfer periods in ns to the proper value to - * stick in the scsiscfr reg to use that transfer rate. - */ -static struct { - short period; - /* Rates in Ultra mode have bit 8 of sxfr set */ -#define ULTRA_SXFR 0x100 - short rate; - const char *english; -} aic7xxx_syncrates[] = { - { 50, 0x100, "20.0" }, - { 62, 0x110, "16.0" }, - { 75, 0x120, "13.4" }, - { 100, 0x140, "10.0" }, - { 100, 0x000, "10.0" }, - { 125, 0x010, "8.0" }, - { 150, 0x020, "6.67" }, - { 175, 0x030, "5.7" }, - { 200, 0x040, "5.0" }, - { 225, 0x050, "4.4" }, - { 250, 0x060, "4.0" }, - { 275, 0x070, "3.6" } -}; - -static int num_aic7xxx_syncrates = - sizeof(aic7xxx_syncrates) / sizeof(aic7xxx_syncrates[0]); - -#ifdef CONFIG_PCI -static int number_of_39xxs = 0; -#endif CONFIG_PCI - -#ifdef AIC7XXX_DEBUG -static void -debug(const char *fmt, ...) -{ - va_list ap; - char buf[256]; - - va_start(ap, fmt); - vsprintf(buf, fmt, ap); - printk(buf); - va_end(ap); -} - -static void -debug_config(struct aic7xxx_host_config *p) -{ - int host_conf, scsi_conf; - unsigned char brelease; - unsigned char dfthresh; - - static int DFT[] = { 0, 50, 75, 100 }; - static int SST[] = { 256, 128, 64, 32 }; - static const char *BUSW[] = { "", "-TWIN", "-WIDE" }; - - host_conf = inb(HOSTCONF + p->base); - scsi_conf = inb(SCSICONF + p->base); - - /* - * The 7870 gets the bus release time and data FIFO threshold - * from the serial EEPROM (stored in the config structure) and - * scsi_conf register respectively. The 7770 gets the bus - * release time and data FIFO threshold from the scsi_conf and - * host_conf registers respectively. - */ - if (p->chip_type == AIC_777x) - { - dfthresh = (host_conf >> 6); - } - else - { - dfthresh = (scsi_conf >> 6); - } - - brelease = p->busrtime; - if (brelease == 0) - { - brelease = 2; - } - - switch (p->type) - { - case AIC_7770: - case AIC_7771: - printk("%s%s AT EISA SLOT %d:\n", board_names[p->type], BUSW[p->bus_type], - p->base >> 12); - break; - - case AIC_284x: - printk("%s%s AT VLB SLOT %d:\n", board_names[p->type], BUSW[p->bus_type], - p->base >> 12); - break; - - case AIC_7850: - case AIC_7870: - case AIC_7871: - case AIC_7872: - case AIC_7873: - case AIC_7874: - case AIC_7880: - case AIC_7881: - case AIC_7882: - case AIC_7883: - case AIC_7884: - printk("%s%s (PCI-bus):\n", board_names[p->type], BUSW[p->bus_type]); - break; - - default: - panic("aic7xxx: (debug_config) internal error.\n"); - } - - printk(" irq %d\n" - " bus release time %d bclks\n" - " data fifo threshold %d%%\n", - p->irq, - brelease, - DFT[dfthresh]); - - printk(" SCSI CHANNEL A:\n" - " scsi id %d\n" - " scsi selection timeout %d ms\n" - " scsi bus reset at power-on %sabled\n", - scsi_conf & 0x07, - SST[(scsi_conf >> 3) & 0x03], - (scsi_conf & 0x40) ? "en" : "dis"); - - if ((p->chip_type == AIC_777x) && (p->parity == AIC_UNKNOWN)) - { - /* - * Set the parity for 7770 based cards. - */ - p->parity = (scsi_conf & 0x20) ? AIC_ENABLED : AIC_DISABLED; - } - if (p->parity != AIC_UNKNOWN) - { - printk(" scsi bus parity %sabled\n", - (p->parity == AIC_ENABLED) ? "en" : "dis"); - } - - if ((p->type == AIC_7770) || (p->type == AIC_7771)) - { - p->low_term = (scsi_conf & 0x80) ? AIC_ENABLED : AIC_DISABLED; - } - if (p->low_term != AIC_UNKNOWN) - { - printk(" scsi bus termination (low byte) %sabled\n", - (p->low_term == AIC_ENABLED) ? "en" : "dis"); - } - if ((p->bus_type == AIC_WIDE) && (p->high_term != AIC_UNKNOWN)) - { - printk(" scsi bus termination (high byte) %sabled\n", - (p->high_term == AIC_ENABLED) ? "en" : "dis"); - } -} - -#if 0 -static void -debug_scb(struct aic7xxx_scb *scb) -{ - printk("control 0x%x, tcl 0x%x, sg_count %d, sg_ptr 0x%x, cmdp 0x%x, cmdlen %d\n", - scb->control, scb->target_channel_lun, scb->SG_segment_count, - (scb->SG_list_pointer[3] << 24) | (scb->SG_list_pointer[2] << 16) | - (scb->SG_list_pointer[1] << 8) | scb->SG_list_pointer[0], - (scb->SCSI_cmd_pointer[3] << 24) | (scb->SCSI_cmd_pointer[2] << 16) | - (scb->SCSI_cmd_pointer[1] << 8) | scb->SCSI_cmd_pointer[0], - scb->SCSI_cmd_length); - printk("reserved 0x%x, target status 0x%x, resid SG count %d, resid data count %d\n", - (scb->RESERVED[1] << 8) | scb->RESERVED[0], scb->target_status, - scb->residual_SG_segment_count, scb->residual_data_count); - printk("data ptr 0x%x, data count %d, next waiting %d\n", - (scb->data_pointer[3] << 24) | (scb->data_pointer[2] << 16) | - (scb->data_pointer[1] << 8) | scb->data_pointer[0], - scb->data_count, scb->next_waiting); - printk("next ptr 0x%lx, Scsi Cmnd 0x%lx, state 0x%x, position %d\n", - (unsigned long) scb->next, (unsigned long) scb->cmd, scb->state, - scb->position); -} -#endif - -#else -# define debug(fmt, args...) -# define debug_config(x) -# define debug_scb(x) -#endif AIC7XXX_DEBUG - -/* - * XXX - these options apply unilaterally to _all_ 274x/284x/294x - * cards in the system. This should be fixed, but then, - * does anyone really have more than one in a machine? - */ -static unsigned int aic7xxx_extended = 0; /* extended translation on? */ -static unsigned int aic7xxx_no_reset = 0; /* no resetting of SCSI bus */ - -/*+F************************************************************************* - * Function: - * aic7xxx_setup - * - * Description: - * Handle Linux boot parameters. This routine allows for assigning a value - * to a parameter with a ':' between the parameter and the value. - * ie. aic7xxx=unpause:0x0A,extended - *-F*************************************************************************/ -void -aic7xxx_setup(char *s, int *dummy) -{ - int i, n; - char *p; - - static struct { - const char *name; - unsigned int *flag; - } options[] = { - { "extended", &aic7xxx_extended }, - { "no_reset", &aic7xxx_no_reset }, - { NULL, NULL } - }; - - for (p = strtok(s, ","); p; p = strtok(NULL, ",")) - { - for (i = 0; options[i].name; i++) - { - n = strlen(options[i].name); - if (!strncmp(options[i].name, p, n)) - { - if (p[n] == ':') - { - *(options[i].flag) = simple_strtoul(p + n + 1, NULL, 0); - } - else - { - *(options[i].flag) = !0; - } - } - } - } -} - -/*+F************************************************************************* - * Function: - * aic7xxx_loadseq - * - * Description: - * Load the sequencer code into the controller memory. - *-F*************************************************************************/ -static void -aic7xxx_loadseq(int base) -{ - static unsigned char seqprog[] = { - /* - * Each sequencer instruction is 29 bits - * long (fill in the excess with zeroes) - * and has to be loaded from least -> most - * significant byte, so this table has the - * byte ordering reversed. - */ -# include "aic7xxx_seq.h" - }; - - /* - * When the AIC-7770 is paused (as on chip reset), the - * sequencer address can be altered and a sequencer - * program can be loaded by writing it, byte by byte, to - * the sequencer RAM port - the Adaptec documentation - * recommends using REP OUTSB to do this, hence the inline - * assembly. Since the address autoincrements as we load - * the program, reset it back to zero afterward. Disable - * sequencer RAM parity error detection while loading, and - * make sure the LOADRAM bit is enabled for loading. - */ - outb(PERRORDIS | SEQRESET | LOADRAM, SEQCTL + base); - - outsb(SEQRAM + base, seqprog, sizeof(seqprog)); - - /* - * WARNING! This is a magic sequence! After extensive - * experimentation, it seems that you MUST turn off the - * LOADRAM bit before you play with SEQADDR again, else - * you will end up with parity errors being flagged on - * your sequencer program. (You would also think that - * turning off LOADRAM and setting SEQRESET to reset the - * address to zero would work, but you need to do it twice - * for it to take effect on the address. Timing problem?) - */ - do { - /* - * Actually, reset it until - * the address shows up as - * zero just to be safe.. - */ - outb(SEQRESET | FASTMODE, SEQCTL + base); - } while ((inb(SEQADDR0 + base) != 0) && (inb(SEQADDR1 + base) != 0)); -} - -/*+F************************************************************************* - * Function: - * aic7xxx_delay - * - * Description: - * Delay for specified amount of time. - *-F*************************************************************************/ -static void -aic7xxx_delay(int seconds) -{ - unsigned long i; - - i = jiffies + (seconds * HZ); /* compute time to stop */ - - while (jiffies < i) - { - ; /* Do nothing! */ - } -} - -/*+F************************************************************************* - * Function: - * rcs_version - * - * Description: - * Return a string containing just the RCS version number from either - * an Id or Revison RCS clause. - *-F*************************************************************************/ -const char * -rcs_version(const char *version_info) -{ - static char buf[10]; - char *bp, *ep; - - bp = NULL; - strcpy(buf, "????"); - if (!strncmp(version_info, "$Id: ", 5)) - { - if ((bp = strchr(version_info, ' ')) != NULL) - { - bp++; - if ((bp = strchr(bp, ' ')) != NULL) - { - bp++; - } - } - } - else - { - if (!strncmp(version_info, "$Revision: ", 11)) - { - if ((bp = strchr(version_info, ' ')) != NULL) - { - bp++; - } - } - } - - if (bp != NULL) - { - if ((ep = strchr(bp, ' ')) != NULL) - { - register int len = ep - bp; - - strncpy(buf, bp, len); - buf[len] = '\0'; - } - } - - return buf; -} - -/*+F************************************************************************* - * Function: - * aic7xxx_info - * - * Description: - * Return a string describing the driver. - *-F*************************************************************************/ -const char * -aic7xxx_info(struct Scsi_Host *notused) -{ - static char buffer[128]; - - strcpy(buffer, "Adaptec AHA274x/284x/294x (EISA/VLB/PCI-Fast SCSI) "); - strcat(buffer, rcs_version(AIC7XXX_C_VERSION)); - strcat(buffer, "/"); - strcat(buffer, rcs_version(AIC7XXX_H_VERSION)); - strcat(buffer, "/"); - strcat(buffer, rcs_version(AIC7XXX_SEQ_VER)); - - return buffer; -} - -/*+F************************************************************************* - * Function: - * aic7xxx_length - * - * Description: - * How much data should be transferred for this SCSI command? Stop - * at segment sg_last if it's a scatter-gather command so we can - * compute underflow easily. - *-F*************************************************************************/ -static unsigned -aic7xxx_length(Scsi_Cmnd *cmd, int sg_last) -{ - int i, segments; - unsigned length; - struct scatterlist *sg; - - segments = cmd->use_sg - sg_last; - sg = (struct scatterlist *) cmd->buffer; - - if (cmd->use_sg) - { - for (i = length = 0; (i < cmd->use_sg) && (i < segments); i++) - { - length += sg[i].length; - } - } - else - { - length = cmd->request_bufflen; - } - - return (length); -} - -/*+F************************************************************************* - * Function: - * aic7xxx_scsirate - * - * Description: - * Look up the valid period to SCSIRATE conversion in our table - *-F*************************************************************************/ -static void -aic7xxx_scsirate(struct aic7xxx_host *p, unsigned char *scsirate, - short period, unsigned char offset, - int target, char channel) -{ - int i; - - for (i = 0; i < num_aic7xxx_syncrates; i++) - { - if ((aic7xxx_syncrates[i].period - period) >= 0) - { - /* - * Watch out for Ultra speeds when ultra is not enabled and - * vice-versa. - */ - if (p->ultra_enabled) - { - if (!(aic7xxx_syncrates[i].rate & ULTRA_SXFR)) - { - printk ("aic7xxx: Target %d, channel %c, requests %sMHz transfers, " - "but adapter in Ultra mode can only sync at 10MHz or " - "above.\n", target, channel, aic7xxx_syncrates[i].english); - break; /* Use asynchronous transfers. */ - } - } - else - { - /* - * Check for an Ultra device trying to negotiate an Ultra rate - * on an adapter with Ultra mode disabled. - */ - if (aic7xxx_syncrates[i].rate & ULTRA_SXFR) - { - /* - * This should only happen if the driver is the first to negotiate - * and chooses a high rate. We'll just move down the table until - * we hit a non Ultra speed. - */ - continue; - } - } - *scsirate = (aic7xxx_syncrates[i].rate) | (offset & 0x0F); - printk("aic7xxx: Target %d, channel %c, now synchronous at %sMHz, " - "offset(0x%x).\n", - target, channel, aic7xxx_syncrates[i].english, offset); - return; - } - } - - /* - * Default to asynchronous transfer - */ - *scsirate = 0; - printk("aic7xxx: Target %d, channel %c, using asynchronous transfers.\n", - target, channel); -} - -/*+F************************************************************************* - * Function: - * aic7xxx_putscb - * - * Description: - * Transfer a SCB to the controller. - *-F*************************************************************************/ -static inline void -aic7xxx_putscb(struct aic7xxx_host *p, struct aic7xxx_scb *scb) -{ - unsigned char curscb; - int base = p->base; - - curscb = inb(SCBPTR + base); - outb(scb->position, SCBPTR + base); - outb(SCBAUTO, SCBCNT + base); - - /* - * By turning on the SCB auto increment, any reference - * to the SCB I/O space postincrements the SCB address - * we're looking at. So turn this on and dump the relevant - * portion of the SCB to the card. - * - * We can do 16bit transfers on all but 284x. - */ - if (p->type == AIC_284x) - { - outsb(SCBARRAY + base, scb, SCB_PIO_TRANSFER_SIZE); - } - else - { - outsl(SCBARRAY + base, scb, (SCB_PIO_TRANSFER_SIZE + 3) / 4); - } - - outb(0, SCBCNT + base); - outb(curscb, SCBPTR + base); -} - -/*+F************************************************************************* - * Function: - * aic7xxx_getscb - * - * Description: - * Get a SCB from the controller. - *-F*************************************************************************/ -static inline void -aic7xxx_getscb(struct aic7xxx_host *p, struct aic7xxx_scb *scb) -{ - int base = p->base; - - /* - * This is almost identical to aic7xxx_putscb(). - */ - outb(SCBAUTO, SCBCNT + base); - insb(SCBARRAY + base, scb, SCB_PIO_TRANSFER_SIZE); - outb(0, SCBCNT + base); -} - -/*+F************************************************************************* - * Function: - * aic7xxx_match_scb - * - * Description: - * Checks to see if an scb matches the target/channel as specified. - * If target is ALL_TARGETS (-1), then we're looking for any device - * on the specified channel; this happens when a channel is going - * to be reset and all devices on that channel must be aborted. - *-F*************************************************************************/ -static int -aic7xxx_match_scb(struct aic7xxx_scb *scb, int target, char channel) -{ - int targ = (scb->target_channel_lun >> 4) & 0x0F; - char chan = (scb->target_channel_lun & SELBUSB) ? 'B' : 'A'; - -#ifdef AIC7XXX_DEBUG_ABORT - printk ("aic7xxx: (match_scb) comparing target/channel %d/%c to scb %d/%c\n", - target, channel, targ, chan); -#endif - if (target == ALL_TARGETS) - { - return (chan == channel); - } - else - { - return ((chan == channel) && (targ == target)); - } -} - -/*+F************************************************************************* - * Function: - * aic7xxx_busy_target - * - * Description: - * Set the specified target active. - *-F*************************************************************************/ -static void -aic7xxx_busy_target(unsigned char target, char channel, int base) -{ - unsigned char active; - unsigned long active_port = ACTIVE_A + base; - - if ((target > 0x07) || (channel == 'B')) - { - /* - * targets on the Second channel or above id 7 store info in byte two - * of ACTIVE - */ - active_port++; - } - active = inb(active_port); - active |= (0x01 << (target & 0x07)); - outb(active, active_port); -} - -/*+F************************************************************************* - * Function: - * aic7xxx_unbusy_target - * - * Description: - * Set the specified target inactive. - *-F*************************************************************************/ -static void -aic7xxx_unbusy_target(unsigned char target, char channel, int base) -{ - unsigned char active; - unsigned long active_port = ACTIVE_A + base; - -#ifdef 0 - printk ("aic7xxx: (unbusy_target) target/channel %d/%c\n", - target, channel); -#endif - if ((target > 0x07) || (channel == 'B')) - { - /* - * targets on the Second channel or above id 7 store info in byte two - * of ACTIVE - */ - active_port++; - } - active = inb(active_port); - active &= ~(0x01 << (target & 0x07)); - outb(active, active_port); -} - -/*+F************************************************************************* - * Function: - * aic7xxx_done - * - * Description: - * Calls the higher level scsi done function and frees the scb. - *-F*************************************************************************/ -static void -aic7xxx_done(struct aic7xxx_host *p, struct aic7xxx_scb *scb) -{ - long flags; - Scsi_Cmnd *cmd = scb->cmd; - -#ifdef 0 - printk ("aic7xxx: (done) target/channel %d/%d\n", - cmd->target, cmd->channel); -#endif - /* - * This is a critical section, since we don't want the - * queue routine mucking with the host data. - */ - save_flags(flags); - cli(); - - /* - * Process the command after marking the scb as free - * and adding it to the free list. - */ - scb->state = SCB_FREE; - scb->next = p->free_scb; - p->free_scb = scb; - scb->cmd = NULL; - - restore_flags(flags); - - cmd->scsi_done(cmd); -} - -/*+F************************************************************************* - * Function: - * aic7xxx_add_waiting_scb - * - * Description: - * Add this SCB to the "waiting for selection" list. - *-F*************************************************************************/ -static void -aic7xxx_add_waiting_scb(u_long base, - struct aic7xxx_scb *scb, - insert_type where) -{ - unsigned char head; - unsigned char curscb; - - curscb = inb(SCBPTR + base); - head = inb(WAITING_SCBH + base); - if (head == SCB_LIST_NULL) - { - /* - * List was empty - */ - head = scb->position; - } - else - { - if (where == LIST_HEAD) - { - outb(scb->position, SCBPTR + base); - outb(head, SCB_NEXT_WAITING + base); - head = scb->position; - } - else - { - /* where == LIST_SECOND */ - unsigned char third_scb; - - outb(head, SCBPTR + base); - third_scb = inb(SCB_NEXT_WAITING + base); - outb(scb->position, SCB_NEXT_WAITING + base); - outb(scb->position, SCBPTR + base); - outb(third_scb, SCB_NEXT_WAITING + base); - } - } - outb(head, WAITING_SCBH + base); - outb(curscb, SCBPTR + base); -} - -/*+F************************************************************************* - * Function: - * aic7xxx_abort_waiting_scb - * - * Description: - * Manipulate the waiting for selection list and return the - * scb that follows the one that we remove. - *-F*************************************************************************/ -static unsigned char -aic7xxx_abort_waiting_scb(struct aic7xxx_host *p, struct aic7xxx_scb *scb, - unsigned char prev, unsigned char timedout_scb) -{ - unsigned char curscb, next; - int target = (scb->target_channel_lun >> 4) & 0x0F; - char channel = (scb->target_channel_lun & SELBUSB) ? 'B' : 'A'; - int base = p->base; - - /* - * Select the SCB we want to abort and - * pull the next pointer out of it. - */ - curscb = inb(SCBPTR + base); - outb(scb->position, SCBPTR + base); - next = inb(SCB_NEXT_WAITING + base); - - /* - * Clear the necessary fields - */ - outb(0, SCBARRAY + base); - outb(SCB_LIST_NULL, SCB_NEXT_WAITING + base); - aic7xxx_unbusy_target(target, channel, base); - - /* - * Update the waiting list - */ - if (prev == SCB_LIST_NULL) - { - /* - * First in the list - */ - outb(next, WAITING_SCBH + base); - } - else - { - /* - * Select the scb that pointed to us and update its next pointer. - */ - outb(prev, SCBPTR + base); - outb(next, SCB_NEXT_WAITING + base); - } - /* - * Update the tail pointer - */ - if (inb(WAITING_SCBT + base) == scb->position) - { - outb(prev, WAITING_SCBT + base); - } - - /* - * Point us back at the original scb position - * and inform the SCSI system that the command - * has been aborted. - */ - outb(curscb, SCBPTR + base); - scb->state |= SCB_ABORTED; - scb->cmd->result = (DID_RESET << 16); - aic7xxx_done(p, scb); - -#ifdef AIC7XXX_DEBUG_ABORT - printk ("aic7xxx: (abort_waiting_scb) target/channel %d/%c, prev %d, " - "to_scb %d, next %d\n", target, channel, prev, timedout_scb, next); -#endif - return (next); -} - -/*+F************************************************************************* - * Function: - * aic7xxx_reset_device - * - * Description: - * The device at the given target/channel has been reset. Abort - * all active and queued scbs for that target/channel. - *-F*************************************************************************/ -static int -aic7xxx_reset_device(struct aic7xxx_host *p, int target, char channel, - unsigned char timedout_scb) -{ - int base = p->base; - struct aic7xxx_scb *scb; - unsigned char active_scb; - int i = 0; - int found = 0; - - /* - * Restore this when we're done - */ - active_scb = inb(SCBPTR + base); - -#ifdef AIC7XXX_DEBUG_ABORT - printk ("aic7xxx: (reset_device) target/channel %d/%c, to_scb %d, " - "active_scb %d\n", target, channel, timedout_scb, active_scb); -#endif - /* - * Search the QINFIFO. - */ - { - int saved_queue[AIC7XXX_MAXSCB]; - int queued = inb(QINCNT + base); - - for (i = 0; i < (queued - found); i++) - { - saved_queue[i] = inb(QINFIFO + base); - scb = &(p->scb_array[saved_queue[i]]); - if (aic7xxx_match_scb(scb, target, channel)) - { - /* - * We found an scb that needs to be aborted. - */ - scb->state |= SCB_ABORTED; - scb->cmd->result = (DID_RESET << 16); - aic7xxx_done(p, scb); - outb(scb->position, SCBPTR + base); - outb(0, SCBARRAY + base); - i--; - found++; - } - } - /* - * Now put the saved scbs back. - */ - for (queued = 0; queued < i; queued++) - { - outb(saved_queue[queued], QINFIFO + base); - } - } - - /* - * Search waiting for selection list. - */ - { - unsigned char next, prev; - - next = inb(WAITING_SCBH + base); /* Start at head of list. */ - prev = SCB_LIST_NULL; - - while (next != SCB_LIST_NULL) - { - scb = &(p->scb_array[next]); - /* - * Select the SCB. - */ - if (aic7xxx_match_scb(scb, target, channel)) - { - next = aic7xxx_abort_waiting_scb(p, scb, prev, timedout_scb); - found++; - } - else - { - outb(scb->position, SCBPTR + base); - prev = next; - next = inb(SCB_NEXT_WAITING + base); - } - } - } - - /* - * Go through the entire SCB array now and look for - * commands for this target that are active. These - * are other (most likely tagged) commands that - * were disconnected when the reset occured. - */ - for (i = 0; i < p->numscb; i++) - { - scb = &(p->scb_array[i]); - if ((scb->state & SCB_ACTIVE) && aic7xxx_match_scb(scb, target, channel)) - { - /* - * Ensure the target is "free" - */ - aic7xxx_unbusy_target(target, channel, base); - outb(scb->position, SCBPTR + base); - outb(0, SCBARRAY + base); - scb->state |= SCB_ABORTED; - scb->cmd->result = (DID_RESET << 16); - aic7xxx_done(p, scb); - found++; - } - } - - outb(active_scb, SCBPTR + base); - return (found); -} - -/*+F************************************************************************* - * Function: - * aic7xxx_reset_current_bus - * - * Description: - * Reset the current SCSI bus. - *-F*************************************************************************/ -static void -aic7xxx_reset_current_bus(int base) -{ -#ifdef AIC7XXX_DEBUG_ABORT - printk ("aic7xxx: (reset_current_bus)\n"); -#endif - outb(SCSIRSTO, SCSISEQ + base); - udelay(1000); - outb(0, SCSISEQ + base); -} - -/*+F************************************************************************* - * Function: - * aic7xxx_reset_channel - * - * Description: - * Reset the channel. - *-F*************************************************************************/ -static int -aic7xxx_reset_channel(struct aic7xxx_host *p, char channel, - unsigned char timedout_scb) -{ - int base = p->base; - unsigned char sblkctl; - char cur_channel; - unsigned long offset, offset_max; - int found; - -#ifdef AIC7XXX_DEBUG_ABORT - printk ("aic7xxx: (reset_channel) channel %c, to_scb %d\n", - channel, timedout_scb); -#endif - /* - * Clean up all the state information for the - * pending transactions on this bus. - */ - found = aic7xxx_reset_device(p, ALL_TARGETS, channel, timedout_scb); - - if (channel == 'B') - { - p->needsdtr |= (p->needsdtr_copy & 0xFF00); - p->sdtr_pending &= 0x00FF; - outb(0, ACTIVE_B + base); - offset = TARG_SCRATCH + base + 8; - offset_max = TARG_SCRATCH + base + 16; - } - else - { - if (p->bus_type == AIC_WIDE) - { - p->needsdtr = p->needsdtr_copy; - p->needwdtr = p->needwdtr_copy; - p->sdtr_pending = 0x0; - p->wdtr_pending = 0x0; - outb(0, ACTIVE_A + base); - outb(0, ACTIVE_B + base); - offset = TARG_SCRATCH + base; - offset_max = TARG_SCRATCH + base + 16; - } - else - { - p->needsdtr |= (p->needsdtr_copy & 0x00FF); - p->sdtr_pending &= 0xFF00; - outb(0, ACTIVE_A + base); - offset = TARG_SCRATCH + base; - offset_max = TARG_SCRATCH + base + 8; - } - } - while (offset < offset_max) - { - /* - * Revert to async/narrow transfers - * until we renegotiate. - */ - u_char targ_scratch; - targ_scratch = inb(offset); - targ_scratch &= SXFR; - outb(targ_scratch, offset); - offset++; - } - - /* - * Reset the bus and unpause/restart the controller - */ - - /* - * Case 1: Command for another bus is active - */ - sblkctl = inb(SBLKCTL + base); - cur_channel = (sblkctl & SELBUSB) ? 'B' : 'A'; - if (cur_channel != channel) - { -#ifdef AIC7XXX_DEBUG_ABORT - printk ("aic7xxx: (reset_channel) Stealthily resetting channel %c\n", - channel); -#endif - /* - * Stealthily reset the other bus without upsetting the current bus - */ - outb(sblkctl ^ SELBUSB, SBLKCTL + base); - aic7xxx_reset_current_bus(base); - outb(sblkctl, SBLKCTL + base); - - UNPAUSE_SEQUENCER(p); - } - /* - * Case 2: A command from this bus is active or we're idle - */ - else - { -#ifdef AIC7XXX_DEBUG_ABORT - printk ("aic7xxx: (reset_channel) Resetting current channel %c\n", - channel); -#endif - aic7xxx_reset_current_bus(base); - RESTART_SEQUENCER(p); - } - - return found; -} - -/*+F************************************************************************* - * Function: - * aic7xxx_isr - * - * Description: - * SCSI controller interrupt handler. - * - * NOTE: Since we declared this using SA_INTERRUPT, interrupts should - * be disabled all through this function unless we say otherwise. - *-F*************************************************************************/ -static void -aic7xxx_isr(int irq, struct pt_regs * regs) -{ - int base, intstat; - struct aic7xxx_host *p; - struct aic7xxx_scb *scb; - unsigned char ha_flags; - short transfer; - unsigned char scsi_id, bus_width; - unsigned char offset, rate, scratch, scratch_offset; - unsigned char max_offset, rej_byte; - unsigned short target_mask; - char channel; - void *addr; - int actual; - int scb_index; - Scsi_Cmnd *cmd; - - p = (struct aic7xxx_host *) aic7xxx_boards[irq]->hostdata; - - /* - * Search for the host with a pending interrupt. If we can't find - * one, then we've encountered a spurious interrupt. - */ - while ((p != NULL) && !(inb(INTSTAT + p->base) & INT_PEND)) - { - if (p->next == NULL) - { - p = NULL; - } - else - { - p = (struct aic7xxx_host *) p->next->hostdata; - } - } - - if (p == NULL) - { - if (aic7xxx_spurious_count == 1) - { - aic7xxx_spurious_count = 2; - printk("aic7xxx: (aic7xxx_isr) Encountered spurious interrupt.\n"); - return; - } - else - { - /* - * The best we can do is to set p back to head of list and process - * the erroneous interrupt - most likely a BRKADRINT. - */ - p = (struct aic7xxx_host *) aic7xxx_boards[irq]->hostdata; - } - } - - /* - * Keep track of interrupts for /proc/scsi - */ - p->isr_count++; - - if (!p->a_scanned && (p->isr_count == 1)) - { - /* - * We must only have one card at this IRQ and it must have been - * added to the board data before the spurious interrupt occurred. - * It is sufficient that we check isr_count and not the spurious - * interrupt count. - */ - printk("aic7xxx: (aic7xxx_isr) Encountered spurious interrupt.\n"); - return; - } - - base = p->base; - /* - * Handle all the interrupt sources - especially for SCSI - * interrupts, we won't get a second chance at them. - */ - intstat = inb(INTSTAT + base); - - if (intstat & BRKADRINT) - { - int i; - unsigned char errno = inb(ERROR + base); - - printk("aic7xxx: (aic7xxx_isr) BRKADRINT error(0x%x):\n", errno); - for (i = 0; i < NUMBER(hard_error); i++) - { - if (errno & hard_error[i].errno) - { - printk(" %s\n", hard_error[i].errmesg); - } - } - - panic("aic7xxx: (aic7xxx_isr) BRKADRINT, error(0x%x) seqaddr(0x%x).\n", - inb(ERROR + base), (inb(SEQADDR1 + base) << 8) | inb(SEQADDR0 + base)); - } - - if (intstat & SEQINT) - { - /* - * Although the sequencer is paused immediately on - * a SEQINT, an interrupt for a SCSIINT condition will - * unpaused the sequencer before this point. - */ - PAUSE_SEQUENCER(p); - - scsi_id = (inb(SCSIID + base) >> 4) & 0x0F; - scratch_offset = scsi_id; - channel = 'A'; - if (inb(SBLKCTL + base) & SELBUSB) - { - channel = 'B'; - scratch_offset += 8; - } - target_mask = (0x01 << scratch_offset); - - switch (intstat & SEQINT_MASK) - { - case BAD_PHASE: - panic("aic7xxx: (aic7xxx_isr) Unknown scsi bus phase.\n"); - break; - - case SEND_REJECT: - rej_byte = inb(REJBYTE + base); - if ((rej_byte & 0xF0) == 0x20) - { - scb_index = inb(SCBPTR + base); - scb = &(p->scb_array[scb_index]); - printk("aic7xxx: Warning - Tagged message received without identify." - "Disabling tagged commands for target %d channel %c.\n", - scsi_id, channel); - scb->cmd->device->tagged_supported = 0; - scb->cmd->device->tagged_queue = 0; - } - else - { - debug("aic7xxx: Warning - Rejecting unknown message (0x%x) received " - "from target %d channel %c.\n", rej_byte, scsi_id, channel); - } - break; - - case NO_IDENT: - panic("aic7xxx: Target %d, channel %c, did not send an IDENTIFY " - "message. SAVED_TCL(0x%x).\n", - scsi_id, channel, inb(SAVED_TCL + base)); - break; - - case NO_MATCH: - printk("aic7xxx: No active SCB for reconnecting target %d, " - "channel %c - Issuing ABORT. SAVED_TCL(0x%x).\n", - scsi_id, channel, inb(SAVED_TCL + base)); - aic7xxx_unbusy_target(scsi_id, channel, base); - outb(0, SCBARRAY + base); - outb(CLRSELTIMEO, CLRSINT1 + base); - RESTART_SEQUENCER(p); - break; - - case SDTR_MSG: - /* - * Help the sequencer to translate the negotiated - * transfer rate. Transfer is 1/4 the period - * in ns as is returned by the sync negotiation - * message. So, we must multiply by four. - */ - transfer = (inb(ARG_1 + base) << 2); - offset = inb(ACCUM + base); - scratch = inb(TARG_SCRATCH + base + scratch_offset); - /* - * The maximum offset for a wide device is 0x08; for a - * 8-bit bus device the maximum offset is 0x0F. - */ - if (scratch & WIDEXFER) - { - max_offset = 0x08; - } - else - { - max_offset = 0x0F; - } - aic7xxx_scsirate(p, &rate, transfer, MIN(offset, max_offset), - scsi_id, channel); - /* - * Preserve the wide transfer flag. - */ - scratch = rate | (scratch & WIDEXFER); - outb(scratch, TARG_SCRATCH + base + scratch_offset); - outb(scratch, SCSIRATE + base); - if ((scratch & 0x0F) == 0) - { /* - * The requested rate was so low that asynchronous transfers - * are faster (not to mention the controller won't support - * them), so we issue a reject to ensure we go to asynchronous - * transfers. - */ - outb(SEND_REJ, RETURN_1 + base); - } - else - { - /* - * See if we initiated Sync Negotiation - */ - if (p->sdtr_pending & target_mask) - { - /* - * Don't send an SDTR back to the target. - */ - outb(0, RETURN_1 + base); - } - else - { - /* - * Send our own SDTR in reply. - */ - printk("aic7xxx: Sending SDTR!!\n"); - outb(SEND_SDTR, RETURN_1 + base); - } - } - /* - * Clear the flags. - */ - p->needsdtr &= ~target_mask; - p->sdtr_pending &= ~target_mask; - break; - - case WDTR_MSG: - { - bus_width = inb(ARG_1 + base); - printk("aic7xxx: Received MSG_WDTR, Target %d, channel %c " - "needwdtr(0x%x).\n", scsi_id, channel, p->needwdtr); - scratch = inb(TARG_SCRATCH + base + scratch_offset); - - if (p->wdtr_pending & target_mask) - { - /* - * Don't send an WDTR back to the target, since we asked first. - */ - outb(0, RETURN_1 + base); - switch (bus_width) - { - case BUS_8_BIT: - scratch &= 0x7F; - break; - - case BUS_16_BIT: - printk("aic7xxx: Target %d, channel %c, using 16 bit " - "transfers.\n", scsi_id, channel); - scratch |= 0x80; - break; - - case BUS_32_BIT: - outb(SEND_REJ, RETURN_1 + base); - printk("aic7xxx: Target %d, channel %c, requesting 32 bit " - "transfers, rejecting...\n", scsi_id, channel); - break; - } - } - else - { - /* - * Send our own WDTR in reply. - */ - printk("aic7xxx: Will send WDTR!!\n"); - switch (bus_width) - { - case BUS_8_BIT: - scratch &= 0x7F; - break; - - case BUS_32_BIT: - /* - * Negotiate 16 bits. - */ - bus_width = BUS_16_BIT; - /* Yes, we mean to fall thru here. */ - - case BUS_16_BIT: - printk("aic7xxx: Target %d, channel %c, using 16 bit " - "transfers.\n", scsi_id, channel); - scratch |= 0x80; - break; - } - outb(bus_width | SEND_WDTR, RETURN_1 + base); - } - p->needwdtr &= ~target_mask; - p->wdtr_pending &= ~target_mask; - outb(scratch, TARG_SCRATCH + base + scratch_offset); - outb(scratch, SCSIRATE + base); - break; - } - - case REJECT_MSG: - { - /* - * What we care about here is if we had an - * outstanding SDTR or WDTR message for this - * target. If we did, this is a signal that - * the target is refusing negotiation. - */ - - scratch = inb(TARG_SCRATCH + base + scratch_offset); - - if (p->wdtr_pending & target_mask) - { - /* - * note 8bit xfers and clear flag - */ - scratch &= 0x7F; - p->needwdtr &= ~target_mask; - p->wdtr_pending &= ~target_mask; - printk("aic7xxx: Target %d, channel %c, refusing WIDE negotiation. " - "Using 8 bit transfers.\n", scsi_id, channel); - } - else - { - if (p->sdtr_pending & target_mask) - { - /* - * note asynch xfers and clear flag - */ - scratch &= 0xF0; - p->needsdtr &= ~target_mask; - p->sdtr_pending &= ~target_mask; - printk("aic7xxx: Target %d, channel %c, refusing synchronous " - "negotiation. Using asynchronous transfers.\n", - scsi_id, channel); - } - /* - * Otherwise, we ignore it. - */ - } - outb(scratch, TARG_SCRATCH + base + scratch_offset); - outb(scratch, SCSIRATE + base); - break; - } - - case BAD_STATUS: - scb_index = inb(SCBPTR + base); - scb = &(p->scb_array[scb_index]); - outb(0, RETURN_1 + base); /* CHECK_CONDITION may change this */ - if (!(scb->state & SCB_ACTIVE) || (scb->cmd == NULL)) - { - printk("aic7xxx: Referenced SCB not valid during SEQINT(0x%x) " - "scb(%d) state(0x%x) cmd(0x%x).\n", - intstat, scb_index, scb->state, (unsigned int) scb->cmd); - } - else - { - cmd = scb->cmd; - aic7xxx_getscb(p, scb); - aic7xxx_status(cmd) = scb->target_status; - - cmd->result |= scb->target_status; - - switch (status_byte(scb->target_status)) - { - case GOOD: - printk("aic7xxx: Interrupted for status of GOOD???\n"); - break; - - case CHECK_CONDITION: - if ((aic7xxx_error(cmd) == 0) && !(cmd->flags & WAS_SENSE)) - { - unsigned char tcl; - unsigned char control; - void *req_buf; - - tcl = scb->target_channel_lun; - - /* - * Send a sense command to the requesting target. - */ - cmd->flags |= WAS_SENSE; - memcpy((void *) scb->sense_cmd, (void *) generic_sense, - sizeof(generic_sense)); - - scb->sense_cmd[1] = (cmd->lun << 5); - scb->sense_cmd[4] = sizeof(cmd->sense_buffer); - - scb->sense_sg.address = (char *) &cmd->sense_buffer; - scb->sense_sg.length = sizeof(cmd->sense_buffer); - req_buf = &scb->sense_sg; - cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]); - control = scb->control; - - memset(scb, 0, SCB_PIO_TRANSFER_SIZE); - scb->control = control & DISCENB; - scb->target_channel_lun = tcl; - addr = scb->sense_cmd; - scb->SCSI_cmd_length = COMMAND_SIZE(scb->sense_cmd[0]); - memcpy(scb->SCSI_cmd_pointer, &addr, - sizeof(scb->SCSI_cmd_pointer)); - scb->SG_segment_count = 1; - memcpy(scb->SG_list_pointer, &req_buf, - sizeof(scb->SG_list_pointer)); - scb->data_count = scb->sense_sg.length; - memcpy(scb->data_pointer, &(scb->sense_sg.address), 4); - - aic7xxx_putscb(p, scb); - outb(SCB_LIST_NULL, SCB_NEXT_WAITING + base); - /* - * Ensure that the target is "BUSY" so we don't get overlapping - * commands if we happen to be doing tagged I/O. - */ - aic7xxx_busy_target(scsi_id, channel, base); - - aic7xxx_add_waiting_scb(base, scb, LIST_HEAD); - outb(SEND_SENSE, RETURN_1 + base); - } /* first time sense, no errors */ - - cmd->flags &= ~ASKED_FOR_SENSE; - if (aic7xxx_error(cmd) == 0) - { - aic7xxx_error(cmd) = DID_RETRY_COMMAND; - } - break; - - case BUSY: - printk("aic7xxx: Target busy.\n"); - if (!aic7xxx_error(cmd)) - { - aic7xxx_error(cmd) = DID_BUS_BUSY; - } - break; - - case QUEUE_FULL: - printk("aic7xxx: Queue full.\n"); - if (!aic7xxx_error(cmd)) - { - aic7xxx_error(cmd) = DID_RETRY_COMMAND; - } - break; - - default: - printk("aic7xxx: Unexpected target status(0x%x).\n", - scb->target_status); - if (!aic7xxx_error(cmd)) - { - aic7xxx_error(cmd) = DID_RETRY_COMMAND; - } - break; - } /* end switch */ - } /* end else of */ - break; - - case RESIDUAL: - scb_index = inb(SCBPTR + base); - scb = &(p->scb_array[scb_index]); - if (!(scb->state & SCB_ACTIVE) || (scb->cmd == NULL)) - { - printk("aic7xxx: Referenced SCB not valid during SEQINT(0x%x) " - "scb(%d) state(0x%x) cmd(0x%x).\n", - intstat, scb_index, scb->state, (unsigned int) scb->cmd); - } - else - { - cmd = scb->cmd; - /* - * Don't destroy valid residual information with - * residual coming from a check sense operation. - */ - if (!(cmd->flags & WAS_SENSE)) - { - /* - * We had an underflow. At this time, there's only - * one other driver that bothers to check for this, - * and cmd->underflow seems to be set rather half- - * heartedly in the higher-level SCSI code. - */ - actual = aic7xxx_length(cmd, scb->residual_SG_segment_count); - - actual -= (inb(SCB_RESID_DCNT2 + base) << 16) | - (inb(SCB_RESID_DCNT1 + base) << 8) | - inb(SCB_RESID_DCNT0 + base); - - if (actual < cmd->underflow) - { - printk("aic7xxx: Target %d underflow - " - "Wanted (at least) (%u) got(%u) count(%d).\n", - cmd->target, cmd->underflow, actual, - inb(SCB_RESID_SGCNT + base)); - aic7xxx_error(cmd) = DID_RETRY_COMMAND; - aic7xxx_status(cmd) = scb->target_status; - } - } - } - break; - - case ABORT_TAG: - scb_index = inb(SCBPTR + base); - scb = &(p->scb_array[scb_index]); - if (!(scb->state & SCB_ACTIVE) || (scb->cmd == NULL)) - { - printk("aic7xxx: Referenced SCB not valid during SEQINT(0x%x) " - "scb(%d) state(0x%x) cmd(0x%x)\n", - intstat, scb_index, scb->state, (unsigned int) scb->cmd); - } - else - { - cmd = scb->cmd; - /* - * We didn't receive a valid tag back from the target - * on a reconnect. - */ - printk("aic7xxx: Invalid tag received on target %d, channel %c, " - "lun %d - Sending ABORT_TAG.\n", - scsi_id, channel, cmd->lun & 0x07); - - cmd->result = (DID_RETRY_COMMAND << 16); - aic7xxx_done(p, scb); - } - break; - - case AWAITING_MSG: - scb_index = inb(SCBPTR + base); - scb = &(p->scb_array[scb_index]); - if (!(scb->state & SCB_ACTIVE) || (scb->cmd == NULL)) - { - printk("aic7xxx: Referenced SCB not valid during SEQINT(0x%x) " - "scb(%d) state(0x%x) cmd(0x%x).\n", - intstat, scb_index, scb->state, (unsigned int) scb->cmd); - } - else - { - /* - * This SCB had a zero length command, informing the sequencer - * that we wanted to send a special message to this target. - * We only do this for BUS_DEVICE_RESET messages currently. - */ - if (scb->state & SCB_DEVICE_RESET) - { -#ifdef AIC7XXX_DEBUG_ABORT - printk ("aic7xxx: (isr) sending bus device reset to target %d\n", - scsi_id); -#endif - outb(MSG_BUS_DEVICE_RESET, MSG0 + base); - outb(1, MSG_LEN + base); - } - else - { - panic("aic7xxx: AWAITING_SCB for an SCB that does " - "not have a waiting message.\n"); - } - } - break; - - case IMMEDDONE: - scb_index = inb(SCBPTR + base); - scb = &(p->scb_array[scb_index]); -#ifdef AIC7XXX_DEBUG_ABORT - printk ("aic7xxx: (isr) received IMMEDDONE for target %d, scb %d, state %d\n", - scsi_id, scb_index, scb->state); -#endif - if (scb->state & SCB_DEVICE_RESET) - { - int found; - - /* - * Go back to async/narrow transfers and renogiate. - */ - aic7xxx_unbusy_target(scsi_id, channel, base); - p->needsdtr |= (p->needsdtr_copy & target_mask); - p->needwdtr |= (p->needwdtr_copy & target_mask); - p->sdtr_pending &= ~target_mask; - p->wdtr_pending &= ~target_mask; - scratch = inb(TARG_SCRATCH + base + scratch_offset); - scratch &= SXFR; - outb(scratch, TARG_SCRATCH + base + scratch_offset); - found = aic7xxx_reset_device(p, (int) scsi_id, channel, SCB_LIST_NULL); - } - else - { - panic("aic7xxx: Immediate complete for unknown operation.\n"); - } - break; - -#if AIC7XXX_NOT_YET - /* XXX Fill these in later */ - case MESG_BUFFER_BUSY: - break; - case MSGIN_PHASEMIS: - break; -#endif - - case PARITY_ERROR: - { - scb_index = inb(SCBPTR + base); - scb = &(p->scb_array[scb_index]); - if (!(scb->state & SCB_ACTIVE) || (scb->cmd == NULL)) - { - printk("aic7xxx: Referenced SCB not valid during SEQINT(0x%x) " - "scb(%d) state(0x%x) cmd(0x%x).\n", - intstat, scb_index, scb->state, (unsigned int) scb->cmd); - } - else - { - char *phase; - unsigned char mesg_out = MSG_NOP; - unsigned char lastphase = inb(LASTPHASE + base); - - cmd = scb->cmd; - switch (lastphase) - { - case P_DATAOUT: - phase = "Data-Out"; - break; - case P_DATAIN: - phase = "Data-In"; - mesg_out = MSG_INITIATOR_DET_ERROR; - break; - case P_COMMAND: - phase = "Command"; - break; - case P_MESGOUT: - phase = "Message-Out"; - break; - case P_STATUS: - phase = "Status"; - mesg_out = MSG_INITIATOR_DET_ERROR; - break; - case P_MESGIN: - phase = "Message-In"; - mesg_out = MSG_MSG_PARITY_ERROR; - break; - default: - phase = "unknown"; - break; - } - - /* - * A parity error has occurred during a data - * transfer phase. Flag it and continue. - */ - printk("aic7xxx: Parity error during phase %s on target %d, " - "channel %d, lun %d.\n", phase, - cmd->target, cmd->channel & 0x01, cmd->lun & 0x07); - - /* - * We've set the hardware to assert ATN if we get a parity - * error on "in" phases, so all we need to do is stuff the - * message buffer with the appropriate message. In phases - * have set mesg_out to something other than MSG_NOP. - */ - if (mesg_out != MSG_NOP) - { - outb(mesg_out, MSG0 + base); - outb(1, MSG_LEN + base); - aic7xxx_error(cmd) = DID_PARITY; - } - else - { - /* - * Should we allow the target to make this decision for us? - */ - aic7xxx_error(cmd) = DID_RETRY_COMMAND; - } - } - break; - } - default: /* unknown */ - debug("aic7xxx: SEQINT, INTSTAT(0x%x) SCSISIGI(0x%x).\n", - intstat, inb(SCSISIGI + base)); - break; - } - - outb(CLRSEQINT, CLRINT + base); - UNPAUSE_SEQUENCER(p); - } - - if (intstat & SCSIINT) - { - int status = inb(SSTAT1 + base); - scsi_id = (inb(SCSIID + base) >> 4) & 0x0F; - channel = 'A'; - if (inb(SBLKCTL + base) & SELBUSB) - { - channel = 'B'; - } - - scb_index = inb(SCBPTR + base); - scb = &(p->scb_array[scb_index]); - if (!(scb->state & SCB_ACTIVE) || (scb->cmd == NULL)) - { - printk("aic7xxx: No command for SCB (SCSIINT).\n"); - /* - * Turn off the interrupt and set status - * to zero, so that it falls through the - * reset of the SCSIINT code. - */ - outb(status, CLRSINT1 + base); - UNPAUSE_SEQUENCER(p); - outb(CLRSCSIINT, CLRINT + base); - scb = NULL; - } - else - { - cmd = scb->cmd; - - /* - * Only the SCSI Status 1 register has information - * about exceptional conditions that we'd have a - * SCSIINT about; anything in SSTAT0 will be handled - * by the sequencer. Note that there can be multiple - * bits set. - */ - if (status & SELTO) - { - unsigned char waiting; - - /* - * Hardware selection timer has expired. Turn - * off SCSI selection sequence. - */ - outb(ENRSELI, SCSISEQ + base); - cmd->result = (DID_TIME_OUT << 16); - /* - * Clear an pending messages for the timed out - * target and mark the target as free. - */ - ha_flags = inb(FLAGS + base); - outb(0, MSG_LEN + base); - aic7xxx_unbusy_target(scsi_id, channel, base); - - outb(0, SCBARRAY + base); - - /* - * Shut off the offending interrupt sources, reset - * the sequencer address to zero and unpause it, - * then call the high-level SCSI completion routine. - * - * WARNING! This is a magic sequence! After many - * hours of guesswork, turning off the SCSI interrupts - * in CLRSINT? does NOT clear the SCSIINT bit in - * INTSTAT. By writing to the (undocumented, unused - * according to the AIC-7770 manual) third bit of - * CLRINT, you can clear INTSTAT. But, if you do it - * while the sequencer is paused, you get a BRKADRINT - * with an Illegal Host Address status, so the - * sequencer has to be restarted first. - */ - outb(CLRSELTIMEO, CLRSINT1 + base); - - outb(CLRSCSIINT, CLRINT + base); - - /* - * Shift the waiting for selection queue forward - */ - waiting = inb(WAITING_SCBH + base); - outb(waiting, SCBPTR + base); - waiting = inb(SCB_NEXT_WAITING + base); - outb(waiting, WAITING_SCBH + base); - - RESTART_SEQUENCER(p); - aic7xxx_done(p, scb); -#if 0 - printk("aic7xxx: SELTO SCB(%d) state(0x%x) cmd(0x%x).\n", - scb->position, scb->state, (unsigned int) scb->cmd); -#endif - } - else - { - if (!(status & BUSFREE)) - { - /* - * We don't know what's going on. Turn off the - * interrupt source and try to continue. - */ - printk("aic7xxx: SSTAT1(0x%x).\n", status); - outb(status, CLRSINT1 + base); - UNPAUSE_SEQUENCER(p); - outb(CLRSCSIINT, CLRINT + base); - } - } - } /* else */ - } - - if (intstat & CMDCMPLT) - { - int complete; - - /* - * The sequencer will continue running when it - * issues this interrupt. There may be >1 commands - * finished, so loop until we've processed them all. - */ - do { - complete = inb(QOUTFIFO + base); - - scb = &(p->scb_array[complete]); - if (!(scb->state & SCB_ACTIVE) || (scb->cmd == NULL)) - { - printk("aic7xxx: Warning - No command for SCB %d (CMDCMPLT).\n" - " QOUTCNT(%d) SCB state(0x%x) cmd(0x%x) pos(%d).\n", - complete, inb(QOUTFIFO + base), - scb->state, (unsigned int) scb->cmd, scb->position); - outb(CLRCMDINT, CLRINT + base); - continue; - } - cmd = scb->cmd; - - if ((cmd->flags & WAS_SENSE) && !(cmd->flags & ASKED_FOR_SENSE)) - { - /* - * Got sense information. - */ - cmd->flags &= ASKED_FOR_SENSE; - } -#if 0 - printk("aic7xxx: (complete) State(%d) cmd(0x%x) free(0x%x).\n", - scb->state, (unsigned int) scb->cmd, (unsigned int) p->free_scb); -#endif - - /* - * Clear interrupt status before checking - * the output queue again. This eliminates - * a race condition whereby a command could - * complete between the queue poll and the - * interrupt clearing, so notification of the - * command being complete never made it back - * up to the kernel. - */ - outb(CLRCMDINT, CLRINT + base); - aic7xxx_done(p, scb); -#if 0 - if (scb != &p->scb_array[scb->position]) - { - printk("aic7xxx: (complete) Address mismatch, pos(%d).\n", scb->position); - } - printk("aic7xxx: (complete) State(%d) cmd(0x%x) free(0x%x).\n", - scb->state, (unsigned int) scb->cmd, (unsigned int) p->free_scb); -#endif - -#ifdef AIC7XXX_PROC_STATS - /* - * XXX: we should actually know how much actually transferred - * XXX: for each command, but apparently that's too difficult. - */ - actual = aic7xxx_length(cmd, 0); - if (!(cmd->flags & WAS_SENSE) && (actual > 0)) - { - struct aic7xxx_xferstats *sp; - long *ptr; - int x; - - sp = &p->stats[cmd->channel & 0x01][cmd->target & 0x0F][cmd->lun & 0x07]; - sp->xfers++; - - if (cmd->request.cmd == WRITE) - { - sp->w_total++; - sp->w_total512 += (actual >> 9); - ptr = sp->w_bins; - } - else - { - sp->r_total++; - sp->r_total512 += (actual >> 9); - ptr = sp->r_bins; - } - for (x = 9; x <= 17; x++) - { - if (actual < (1 << x)) - { - ptr[x - 9]++; - break; - } - } - if (x > 17) - { - ptr[x - 9]++; - } - } -#endif /* AIC7XXX_PROC_STATS */ - - } while (inb(QOUTCNT + base)); - } -} - -/*+F************************************************************************* - * Function: - * aic7xxx_probe - * - * Description: - * Probing for EISA boards: it looks like the first two bytes - * are a manufacturer code - three characters, five bits each: - * - * BYTE 0 BYTE 1 BYTE 2 BYTE 3 - * ?1111122 22233333 PPPPPPPP RRRRRRRR - * - * The characters are baselined off ASCII '@', so add that value - * to each to get the real ASCII code for it. The next two bytes - * appear to be a product and revision number, probably vendor- - * specific. This is what is being searched for at each port, - * and what should probably correspond to the ID= field in the - * ECU's .cfg file for the card - if your card is not detected, - * make sure your signature is listed in the array. - * - * The fourth byte's lowest bit seems to be an enabled/disabled - * flag (rest of the bits are reserved?). - *-F*************************************************************************/ -static aha_type -aic7xxx_probe(int slot, int base) -{ - int i; - unsigned char buf[4]; - - static struct { - int n; - unsigned char signature[sizeof(buf)]; - aha_type type; - } AIC7xxx[] = { - { 4, { 0x04, 0x90, 0x77, 0x71 }, AIC_7771 }, /* host adapter 274x */ - { 4, { 0x04, 0x90, 0x77, 0x70 }, AIC_7770 }, /* motherboard 7770 */ - { 4, { 0x04, 0x90, 0x77, 0x56 }, AIC_284x }, /* 284x, BIOS enabled */ - { 4, { 0x04, 0x90, 0x77, 0x57 }, AIC_284x } /* 284x, BIOS disabled */ - }; - - /* - * The VL-bus cards need to be primed by - * writing before a signature check. - */ - for (i = 0; i < sizeof(buf); i++) - { - outb(0x80 + i, base); - buf[i] = inb(base + i); - } - - for (i = 0; i < NUMBER(AIC7xxx); i++) - { - /* - * Signature match on enabled card? - */ - if (!memcmp(buf, AIC7xxx[i].signature, AIC7xxx[i].n)) - { - if (inb(base + 4) & 1) - { - return (AIC7xxx[i].type); - } - - printk("aic7xxx: Disabled at slot %d, ignored.\n", slot); - } - } - - return (AIC_NONE); -} - -/*+F************************************************************************* - * Function: - * read_2840_seeprom - * - * Description: - * Reads the 2840 serial EEPROM and returns 1 if successful and 0 if - * not successful. - * - * See read_seeprom (for the 2940) for the instruction set of the 93C46 - * chip. - * - * The 2840 interface to the 93C46 serial EEPROM is through the - * STATUS_2840 and SEECTL_2840 registers. The CS_2840, CK_2840, and - * DO_2840 bits of the SEECTL_2840 register are connected to the chip - * select, clock, and data out lines respectively of the serial EEPROM. - * The DI_2840 bit of the STATUS_2840 is connected to the data in line - * of the serial EEPROM. The EEPROM_TF bit of STATUS_2840 register is - * useful in that it gives us an 800 nsec timer. After a read from the - * SEECTL_2840 register the timing flag is cleard and goes high 800 nsec - * later. - * - *-F*************************************************************************/ -static int -read_2840_seeprom(int base, struct seeprom_config *sc) -{ - int i = 0, k = 0; - unsigned char temp; - unsigned short checksum = 0; - unsigned short *seeprom = (unsigned short *) sc; - struct seeprom_cmd { - unsigned char len; - unsigned char bits[3]; - }; - struct seeprom_cmd seeprom_read = {3, {1, 1, 0}}; - -#define CLOCK_PULSE(p) \ - while ((inb(STATUS_2840 + base) & EEPROM_TF) == 0) \ - { \ - ; /* Do nothing */ \ - } \ - (void) inb(SEECTL_2840 + base); - - /* - * Read the first 32 registers of the seeprom. For the 2840, - * the 93C46 SEEPROM is a 1024-bit device with 64 16-bit registers - * but only the first 32 are used by Adaptec BIOS. The loop - * will range from 0 to 31. - */ - for (k = 0; k < (sizeof(*sc) / 2); k++) - { - /* - * Send chip select for one clock cycle. - */ - outb(CK_2840 | CS_2840, SEECTL_2840 + base); - CLOCK_PULSE(base); - - /* - * Now we're ready to send the read command followed by the - * address of the 16-bit register we want to read. - */ - for (i = 0; i < seeprom_read.len; i++) - { - temp = CS_2840 | seeprom_read.bits[i]; - outb(temp, SEECTL_2840 + base); - CLOCK_PULSE(base); - temp = temp ^ CK_2840; - outb(temp, SEECTL_2840 + base); - CLOCK_PULSE(base); - } - /* - * Send the 6 bit address (MSB first, LSB last). - */ - for (i = 5; i >= 0; i--) - { - temp = k; - temp = (temp >> i) & 1; /* Mask out all but lower bit. */ - temp = CS_2840 | temp; - outb(temp, SEECTL_2840 + base); - CLOCK_PULSE(base); - temp = temp ^ CK_2840; - outb(temp, SEECTL_2840 + base); - CLOCK_PULSE(base); - } - - /* - * Now read the 16 bit register. An initial 0 precedes the - * register contents which begins with bit 15 (MSB) and ends - * with bit 0 (LSB). The initial 0 will be shifted off the - * top of our word as we let the loop run from 0 to 16. - */ - for (i = 0; i <= 16; i++) - { - temp = CS_2840; - outb(temp, SEECTL_2840 + base); - CLOCK_PULSE(base); - temp = temp ^ CK_2840; - seeprom[k] = (seeprom[k] << 1) | (inb(STATUS_2840 + base) & DI_2840); - outb(temp, SEECTL_2840 + base); - CLOCK_PULSE(base); - } - /* - * The serial EEPROM has a checksum in the last word. Keep a - * running checksum for all words read except for the last - * word. We'll verify the checksum after all words have been - * read. - */ - if (k < (sizeof(*sc) / 2) - 1) - { - checksum = checksum + seeprom[k]; - } - - /* - * Reset the chip select for the next command cycle. - */ - outb(0, SEECTL_2840 + base); - CLOCK_PULSE(base); - outb(CK_2840, SEECTL_2840 + base); - CLOCK_PULSE(base); - outb(0, SEECTL_2840 + base); - CLOCK_PULSE(base); - } - -#if 0 - printk("Computed checksum 0x%x, checksum read 0x%x\n", checksum, sc->checksum); - printk("Serial EEPROM:"); - for (k = 0; k < (sizeof(*sc) / 2); k++) - { - if (((k % 8) == 0) && (k != 0)) - { - printk("\n "); - } - printk(" 0x%x", seeprom[k]); - } - printk("\n"); -#endif - - if (checksum != sc->checksum) - { - printk("aic7xxx: SEEPROM checksum error, ignoring SEEPROM settings.\n"); - return (0); - } - - return (1); -#undef CLOCK_PULSE -} - -/*+F************************************************************************* - * Function: - * read_seeprom - * - * Description: - * Reads the serial EEPROM and returns 1 if successful and 0 if - * not successful. - * - * The instruction set of the 93C46 chip is as follows: - * - * Start OP - * Function Bit Code Address Data Description - * ------------------------------------------------------------------- - * READ 1 10 A5 - A0 Reads data stored in memory, - * starting at specified address - * EWEN 1 00 11XXXX Write enable must preceed - * all programming modes - * ERASE 1 11 A5 - A0 Erase register A5A4A3A2A1A0 - * WRITE 1 01 A5 - A0 D15 - D0 Writes register - * ERAL 1 00 10XXXX Erase all registers - * WRAL 1 00 01XXXX D15 - D0 Writes to all registers - * EWDS 1 00 00XXXX Disables all programming - * instructions - * *Note: A value of X for address is a don't care condition. - * - * The 93C46 has a four wire interface: clock, chip select, data in, and - * data out. In order to perform one of the above functions, you need - * to enable the chip select for a clock period (typically a minimum of - * 1 usec, with the clock high and low a minimum of 750 and 250 nsec - * respectively. While the chip select remains high, you can clock in - * the instructions (above) starting with the start bit, followed by the - * OP code, Address, and Data (if needed). For the READ instruction, the - * requested 16-bit register contents is read from the data out line but - * is preceded by an initial zero (leading 0, followed by 16-bits, MSB - * first). The clock cycling from low to high initiates the next data - * bit to be sent from the chip. - * - * The 7870 interface to the 93C46 serial EEPROM is through the SEECTL - * register. After successful arbitration for the memory port, the - * SEECS bit of the SEECTL register is connected to the chip select. - * The SEECK, SEEDO, and SEEDI are connected to the clock, data out, - * and data in lines respectively. The SEERDY bit of SEECTL is useful - * in that it gives us an 800 nsec timer. After a write to the SEECTL - * register, the SEERDY goes high 800 nsec later. The one exception - * to this is when we first request access to the memory port. The - * SEERDY goes high to signify that access has been granted and, for - * this case, has no implied timing. - * - *-F*************************************************************************/ -static int -read_seeprom(int base, int offset, struct seeprom_config *sc) -{ - int i = 0, k; - unsigned long timeout; - unsigned char temp; - unsigned short checksum = 0; - unsigned short *seeprom = (unsigned short *) sc; - struct seeprom_cmd { - unsigned char len; - unsigned char bits[3]; - }; - struct seeprom_cmd seeprom_read = {3, {1, 1, 0}}; - -#define CLOCK_PULSE(p) \ - while ((inb(SEECTL + base) & SEERDY) == 0) \ - { \ - ; /* Do nothing */ \ - } - - /* - * Request access of the memory port. When access is - * granted, SEERDY will go high. We use a 1 second - * timeout which should be near 1 second more than - * is needed. Reason: after the 7870 chip reset, there - * should be no contention. - */ - outb(SEEMS, SEECTL + base); - timeout = jiffies + 100; /* 1 second timeout */ - while ((jiffies < timeout) && ((inb(SEECTL + base) & SEERDY) == 0)) - { - ; /* Do nothing! Wait for access to be granted. */ - } - if ((inb(SEECTL + base) & SEERDY) == 0) - { - outb(0, SEECTL + base); - return (0); - } - - /* - * Read the first 32 registers of the seeprom. For the 7870, - * the 93C46 SEEPROM is a 1024-bit device with 64 16-bit registers - * but only the first 32 are used by Adaptec BIOS. The loop - * will range from 0 to 31. - */ - for (k = 0; k < (sizeof(*sc) / 2); k++) - { - /* - * Send chip select for one clock cycle. - */ - outb(SEEMS | SEECK | SEECS, SEECTL + base); - CLOCK_PULSE(base); - - /* - * Now we're ready to send the read command followed by the - * address of the 16-bit register we want to read. - */ - for (i = 0; i < seeprom_read.len; i++) - { - temp = SEEMS | SEECS | (seeprom_read.bits[i] << 1); - outb(temp, SEECTL + base); - CLOCK_PULSE(base); - temp = temp ^ SEECK; - outb(temp, SEECTL + base); - CLOCK_PULSE(base); - } - /* - * Send the 6 bit address (MSB first, LSB last). - */ - for (i = 5; i >= 0; i--) - { - temp = k + offset; - temp = (temp >> i) & 1; /* Mask out all but lower bit. */ - temp = SEEMS | SEECS | (temp << 1); - outb(temp, SEECTL + base); - CLOCK_PULSE(base); - temp = temp ^ SEECK; - outb(temp, SEECTL + base); - CLOCK_PULSE(base); - } - - /* - * Now read the 16 bit register. An initial 0 precedes the - * register contents which begins with bit 15 (MSB) and ends - * with bit 0 (LSB). The initial 0 will be shifted off the - * top of our word as we let the loop run from 0 to 16. - */ - for (i = 0; i <= 16; i++) - { - temp = SEEMS | SEECS; - outb(temp, SEECTL + base); - CLOCK_PULSE(base); - temp = temp ^ SEECK; - seeprom[k] = (seeprom[k] << 1) | (inb(SEECTL + base) & SEEDI); - outb(temp, SEECTL + base); - CLOCK_PULSE(base); - } - - /* - * The serial EEPROM has a checksum in the last word. Keep a - * running checksum for all words read except for the last - * word. We'll verify the checksum after all words have been - * read. - */ - if (k < (sizeof(*sc) / 2) - 1) - { - checksum = checksum + seeprom[k]; - } - - /* - * Reset the chip select for the next command cycle. - */ - outb(SEEMS, SEECTL + base); - CLOCK_PULSE(base); - outb(SEEMS | SEECK, SEECTL + base); - CLOCK_PULSE(base); - outb(SEEMS, SEECTL + base); - CLOCK_PULSE(base); - } - - /* - * Release access to the memory port and the serial EEPROM. - */ - outb(0, SEECTL + base); - -#if 0 - printk("Computed checksum 0x%x, checksum read 0x%x\n", checksum, sc->checksum); - printk("Serial EEPROM:"); - for (k = 0; k < (sizeof(*sc) / 2); k++) - { - if (((k % 8) == 0) && (k != 0)) - { - printk("\n "); - } - printk(" 0x%x", seeprom[k]); - } - printk("\n"); -#endif - - if (checksum != sc->checksum) - { - printk("aic7xxx: SEEPROM checksum error, ignoring SEEPROM settings.\n"); - return (0); - } - - return (1); -#undef CLOCK_PULSE -} - -/*+F************************************************************************* - * Function: - * detect_maxscb - * - * Description: - * Return the maximum number of SCB's allowed for a given controller. - *-F*************************************************************************/ -static int -detect_maxscb(aha_type type, int base, int walk_scbs) -{ - unsigned char sblkctl_reg, scb_byte; - int maxscb = 0, i; - - switch (type) - { - case AIC_7770: - case AIC_7771: - case AIC_284x: - /* - * Check for Rev C or E boards. Rev E boards can supposedly have - * more than 4 SCBs, while the Rev C boards are limited to 4 SCBs. - * Until we know how to access more than 4 SCBs for the Rev E chips, - * we limit them, along with the Rev C chips, to 4 SCBs. - * - * The Rev E boards have a read/write autoflush bit in the - * SBLKCTL register, while in the Rev C boards it is read only. - */ - sblkctl_reg = inb(SBLKCTL + base) ^ AUTOFLUSHDIS; - outb(sblkctl_reg, SBLKCTL + base); - if (inb(SBLKCTL + base) == sblkctl_reg) - { - /* - * We detected a Rev E board. - */ - printk("aic7xxx: %s Rev E and subsequent.\n", board_names[type]); - outb(sblkctl_reg ^ AUTOFLUSHDIS, SBLKCTL + base); - maxscb = 4; - } - else - { - printk("aic7xxx: %s Rev C and previous.\n", board_names[type]); - maxscb = 4; - } - break; - - case AIC_7850: - maxscb = 3; - break; - - case AIC_7870: - case AIC_7871: - case AIC_7874: - case AIC_7880: - case AIC_7881: - case AIC_7884: - maxscb = 16; - break; - - case AIC_7872: - case AIC_7873: - case AIC_7882: - case AIC_7883: - /* - * Is suppose to have 255 SCBs, but we'll walk the SCBs - * looking for more if external RAM is detected. - */ - maxscb = 16; - break; - - case AIC_NONE: - /* - * This should never happen... But just in case. - */ - break; - } - - if (walk_scbs) - { - /* - * This adapter has external SCB memory. - * Walk the SCBs to determine how many there are. - */ - i = 0; - while (i < AIC7XXX_MAXSCB) - { - outb(i, SCBPTR + base); - scb_byte = ~(inb(SCBARRAY + base)); /* complement the byte */ - outb(scb_byte, SCBARRAY + base); /* write it back out */ - if (inb(SCBARRAY + base) != scb_byte) - { - break; - } - i++; - } - maxscb = i; - - printk("aic7xxx: Using %d SCB's after checking for SCB memory.\n", maxscb); - } - else - { - printk("aic7xxx: Using %d SCB's; No SCB memory check.\n", maxscb); - } - - return (maxscb); -} - -/*+F************************************************************************* - * Function: - * aic7xxx_register - * - * Description: - * Register a Adaptec aic7xxx chip SCSI controller with the kernel. - *-F*************************************************************************/ -static int -aic7xxx_register(Scsi_Host_Template *template, - struct aic7xxx_host_config *config) -{ - int i; - unsigned char sblkctl; - int max_targets; - int found = 1, base; - int bios_disabled = FALSE; - unsigned char target_settings; - unsigned char scsi_conf, host_conf; - int have_seeprom = FALSE; - struct Scsi_Host *host; - struct aic7xxx_host *p; - struct seeprom_config sc; - - base = config->base; - - /* - * Lock out other contenders for our i/o space. - */ - request_region(MINREG + base, MAXREG - MINREG, "aic7xxx"); - - switch (config->type) - { - case AIC_7770: - case AIC_7771: - /* - * For some 274x boards, we must clear the CHIPRST bit - * and pause the sequencer. For some reason, this makes - * the driver work. For 284x boards, we give it a - * CHIPRST just like the 294x boards. - * - * Use the BIOS settings to determine the interrupt - * trigger type (level or edge) and use this value - * for pausing and unpausing the sequencer. - */ - config->unpause = (inb(HCNTRL + base) & IRQMS) | INTEN; - config->pause = config->unpause | PAUSE; - config->extended = aic7xxx_extended; - - outb(config->pause | CHIPRST, HCNTRL + base); - aic7xxx_delay(1); - if (inb(HCNTRL + base) & CHIPRST) - { - printk("aic7xxx: Chip reset not cleared; clearing manually.\n"); - } - outb(config->pause, HCNTRL + base); - - /* - * Just to be on the safe side with the 274x, we will re-read the irq - * since there was some issue about resetting the board. - */ - config->irq = inb(INTDEF + base) & 0x0F; - if ((inb(HA_274_BIOSCTRL + base) & BIOSMODE) == BIOSDISABLED) - { - bios_disabled = TRUE; - } - host_conf = inb(HOSTCONF + base); - config->busrtime = host_conf & 0x3C; - /* XXX Is this valid for motherboard based controllers? */ - /* Setup the FIFO threshold and the bus off time */ - outb(host_conf & DFTHRSH, BUSSPD + base); - outb((host_conf << 2) & BOFF, BUSTIME + base); - - /* - * A reminder until this can be detected automatically. - */ - printk("aic7xxx: Extended translation %sabled.\n", - config->extended ? "en" : "dis"); - break; - - case AIC_284x: - outb(CHIPRST, HCNTRL + base); - config->unpause = UNPAUSE_284X; - config->pause = REQ_PAUSE; /* DWG would like to be like the rest */ - aic7xxx_delay(1); - outb(config->pause, HCNTRL + base); - - config->extended = aic7xxx_extended; - config->irq = inb(INTDEF + base) & 0x0F; - if ((inb(HA_274_BIOSCTRL + base) & BIOSMODE) == BIOSDISABLED) - { - bios_disabled = TRUE; - } - host_conf = inb(HOSTCONF + base); - - printk("aic7xxx: Reading SEEPROM..."); - have_seeprom = read_2840_seeprom(base, &sc); - if (!have_seeprom) - { - printk("aic7xxx: Unable to read SEEPROM.\n"); - config->busrtime = host_conf & 0x3C; - } - else - { - printk("done.\n"); - config->extended = ((sc.bios_control & CF284XEXTEND) >> 5); - config->scsi_id = (sc.brtime_id & CFSCSIID); - config->parity = (sc.adapter_control & CFSPARITY) ? - AIC_ENABLED : AIC_DISABLED; - config->low_term = (sc.adapter_control & CF284XSTERM) ? - AIC_ENABLED : AIC_DISABLED; - /* - * XXX - Adaptec *does* make 284x wide controllers, but the - * documents do not say where the high byte termination - * enable bit is located. For now, we'll just assume - * that it's in the same place as for the 2940 card. - */ - config->high_term = (sc.adapter_control & CFWSTERM) ? - AIC_ENABLED : AIC_DISABLED; - config->busrtime = ((sc.brtime_id & CFBRTIME) >> 8); - } - /* XXX Is this valid for motherboard based controllers? */ - /* Setup the FIFO threshold and the bus off time */ - outb(host_conf & DFTHRSH, BUSSPD + base); - outb((host_conf << 2) & BOFF, BUSTIME + base); - - printk("aic7xxx: Extended translation %sabled.\n", - config->extended ? "en" : "dis"); - break; - - case AIC_7850: - case AIC_7870: - case AIC_7871: - case AIC_7872: - case AIC_7873: - case AIC_7874: - case AIC_7880: - case AIC_7881: - case AIC_7882: - case AIC_7883: - case AIC_7884: - outb(CHIPRST, HCNTRL + base); - config->unpause = UNPAUSE_294X; - config->pause = config->unpause | PAUSE; - aic7xxx_delay(1); - outb(config->pause, HCNTRL + base); - - config->extended = aic7xxx_extended; - config->scsi_id = 7; - - printk("aic7xxx: Reading SEEPROM..."); - have_seeprom = read_seeprom(base, config->chan_num * (sizeof(sc) / 2), &sc); - if (!have_seeprom) - { - printk("aic7xxx: Unable to read SEEPROM.\n"); - } - else - { - printk("done.\n"); - config->extended = ((sc.bios_control & CFEXTEND) >> 7); - config->scsi_id = (sc.brtime_id & CFSCSIID); - config->parity = (sc.adapter_control & CFSPARITY) ? - AIC_ENABLED : AIC_DISABLED; - config->low_term = (sc.adapter_control & CFSTERM) ? - AIC_ENABLED : AIC_DISABLED; - config->high_term = (sc.adapter_control & CFWSTERM) ? - AIC_ENABLED : AIC_DISABLED; - config->busrtime = ((sc.brtime_id & CFBRTIME) >> 8); - if (((config->type == AIC_7880) || (config->type == AIC_7882) || - (config->type == AIC_7883) || (config->type == AIC_7884)) && - (sc.adapter_control & CFULTRAEN)) - { - printk ("aic7xxx: Enabling support for Ultra SCSI speed.\n"); - config->ultra_enabled = TRUE; - } - } - - /* - * XXX - force data fifo threshold to 100%. Why does this - * need to be done? - * - * We don't know where this is set in the SEEPROM or by the BIOS, - * so we default it to 100%. - */ - outb(config->scsi_id | DFTHRSH_100, SCSICONF + base); - outb(DFTHRSH_100, DSPCISTATUS + base); - - /* - * In case we are a wide card, place scsi ID in second conf byte. - */ - outb(config->scsi_id, (SCSICONF + base + 1)); - - printk("aic7xxx: Extended translation %sabled.\n", - config->extended ? "en" : "dis"); - break; - - default: - panic("aic7xxx: (aic7xxx_register) Internal error.\n"); - } - - config->maxscb = detect_maxscb(config->type, base, config->walk_scbs); - - if (config->chip_type == AIC_777x) - { - if (config->pause & IRQMS) - { - printk("aic7xxx: Using level sensitive interrupts.\n"); - } - else - { - printk("aic7xxx: Using edge triggered interrupts.\n"); - } - } - - /* - * Read the bus type from the SBLKCTL register. Set the FLAGS - * register in the sequencer for twin and wide bus cards. - */ - sblkctl = inb(SBLKCTL + base); - switch (sblkctl & SELBUS_MASK) - { - case SELNARROW: /* narrow/normal bus */ - config->scsi_id = inb(SCSICONF + base) & 0x07; - config->bus_type = AIC_SINGLE; - outb(SINGLE_BUS, FLAGS + base); - break; - - case SELWIDE: /* Wide bus */ - config->scsi_id = inb(SCSICONF + base + 1) & 0x0F; - config->bus_type = AIC_WIDE; - printk("aic7xxx: Enabling wide channel of %s-Wide.\n", - board_names[config->type]); - outb(WIDE_BUS, FLAGS + base); - break; - - case SELBUSB: /* Twin bus */ - config->scsi_id = inb(SCSICONF + base) & 0x07; -#ifdef AIC7XXX_TWIN_SUPPORT - config->scsi_id_b = inb(SCSICONF + base + 1) & 0x07; - config->bus_type = AIC_TWIN; - printk("aic7xxx: Enabled channel B of %s-Twin.\n", - board_names[config->type]); - outb(TWIN_BUS, FLAGS + base); -#else - config->bus_type = AIC_SINGLE; - printk("aic7xxx: Channel B of %s-Twin will be ignored.\n", - board_names[config->type]); - outb(0, FLAGS + base); -#endif - break; - - default: - printk("aic7xxx: Unsupported type 0x%x, please " - "mail deang@ims.com\n", inb(SBLKCTL + base)); - outb(0, FLAGS + base); - return (0); - } - - /* - * For the 294x cards, clearing DIAGLEDEN and DIAGLEDON, will - * take the card out of diagnostic mode and make the host adatper - * LED follow bus activity (will not always be on). - */ - outb(sblkctl & ~(DIAGLEDEN | DIAGLEDON), SBLKCTL + base); - - /* - * The IRQ level in i/o port 4 maps directly onto the real - * IRQ number. If it's ok, register it with the kernel. - * - * NB. the Adaptec documentation says the IRQ number is only - * in the lower four bits; the ECU information shows the - * high bit being used as well. Which is correct? - * - * The PCI cards get their interrupt from PCI BIOS. - */ - if ((config->chip_type == AIC_777x) && ((config->irq < 9) || (config->irq > 15))) - { - printk("aic7xxx: Host adapter uses unsupported IRQ level, ignoring.\n"); - return (0); - } - - /* - * Check the IRQ to see if it is shared by another aic7xxx - * controller. If it is and sharing of IRQs is not defined, - * then return 0 hosts found. If sharing of IRQs is allowed - * or the IRQ is not shared by another host adapter, then - * proceed. - */ -#ifndef AIC7XXX_SHARE_IRQS - if (aic7xxx_boards[config->irq] != NULL) - { - printk("aic7xxx: Sharing of IRQ's is not configured.\n"); - return (0); - } -#endif - - /* - * Print out debugging information before re-enabling - * the card - a lot of registers on it can't be read - * when the sequencer is active. - */ - debug_config(config); - - /* - * Before registry, make sure that the offsets of the - * struct scatterlist are what the sequencer will expect, - * otherwise disable scatter-gather altogether until someone - * can fix it. This is important since the sequencer will - * DMA elements of the SG array in while executing commands. - */ - if (template->sg_tablesize != SG_NONE) - { - struct scatterlist sg; - - if (SG_STRUCT_CHECK(sg)) - { - printk("aic7xxx: Warning - Kernel scatter-gather structures changed, " - "disabling it.\n"); - template->sg_tablesize = SG_NONE; - } - } - - /* - * Register each "host" and fill in the returned Scsi_Host - * structure as best we can. Some of the parameters aren't - * really relevant for bus types beyond ISA, and none of the - * high-level SCSI code looks at it anyway. Why are the fields - * there? Also save the pointer so that we can find the - * information when an IRQ is triggered. - */ - host = scsi_register(template, sizeof(struct aic7xxx_host)); - host->can_queue = config->maxscb; - host->cmd_per_lun = AIC7XXX_CMDS_PER_LUN; - host->this_id = config->scsi_id; - host->irq = config->irq; - if (config->bus_type == AIC_WIDE) - { - host->max_id = 16; - } - if (config->bus_type == AIC_TWIN) - { - host->max_channel = 1; - } - - p = (struct aic7xxx_host *) host->hostdata; - - /* - * Initialize the scb array by setting the state to free. - */ - for (i = 0; i < AIC7XXX_MAXSCB; i++) - { - p->scb_array[i].state = SCB_FREE; - p->scb_array[i].next = NULL; - p->scb_array[i].cmd = NULL; - } - - p->isr_count = 0; - p->a_scanned = FALSE; - p->b_scanned = FALSE; - p->base = base; - p->maxscb = config->maxscb; - p->numscb = 0; - p->extended = config->extended; - p->type = config->type; - p->chip_type = config->chip_type; - p->ultra_enabled = config->ultra_enabled; - p->chan_num = config->chan_num; - p->bus_type = config->bus_type; - p->have_seeprom = have_seeprom; - p->seeprom = sc; - p->free_scb = NULL; - p->next = NULL; - - p->unpause = config->unpause; - p->pause = config->pause; - - if (aic7xxx_boards[config->irq] == NULL) - { - /* - * Warning! This must be done before requesting the irq. It is - * possible for some boards to raise an interrupt as soon as - * they are enabled. So when we request the irq from the Linux - * kernel, an interrupt is triggered immediately. Therefore, we - * must ensure the board data is correctly set before the request. - */ - aic7xxx_boards[config->irq] = host; - - /* - * Register IRQ with the kernel. - */ - if (request_irq(config->irq, aic7xxx_isr, SA_INTERRUPT, "aic7xxx")) - { - printk("aic7xxx: Couldn't register IRQ %d, ignoring.\n", config->irq); - aic7xxx_boards[config->irq] = NULL; - return (0); - } - } - else - { - /* - * We have found a host adapter sharing an IRQ of a previously - * registered host adapter. Add this host adapter's Scsi_Host - * to the beginning of the linked list of hosts at the same IRQ. - */ - p->next = aic7xxx_boards[config->irq]; - aic7xxx_boards[config->irq] = host; - } - - /* - * Load the sequencer program, then re-enable the board - - * resetting the AIC-7770 disables it, leaving the lights - * on with nobody home. On the PCI bus you *may* be home, - * but then your mailing address is dynamically assigned - * so no one can find you anyway :-) - */ - printk("aic7xxx: Downloading sequencer code..."); - aic7xxx_loadseq(base); - - /* - * Set Fast Mode and Enable the board - */ - outb(FASTMODE, SEQCTL + base); - - if (p->chip_type == AIC_777x) - { - outb(ENABLE, BCTL + base); - } - - printk("done.\n"); - - /* - * Set the SCSI Id, SXFRCTL0, SXFRCTL1, and SIMODE1, for both channels - */ - if (p->bus_type == AIC_TWIN) - { - /* - * Select Channel B. - */ - outb((sblkctl & ~SELBUS_MASK) | SELBUSB, SBLKCTL + base); - - outb(config->scsi_id_b, SCSIID + base); - scsi_conf = inb(SCSICONF + base + 1) & (ENSPCHK | STIMESEL); - outb(scsi_conf | ENSTIMER | ACTNEGEN | STPWEN, SXFRCTL1 + base); - outb(ENSELTIMO , SIMODE1 + base); - if (p->ultra_enabled) - { - outb(DFON | SPIOEN | ULTRAEN, SXFRCTL0 + base); - } - else - { - outb(DFON | SPIOEN, SXFRCTL0 + base); - } - - /* - * Select Channel A - */ - outb((sblkctl & ~SELBUS_MASK) | SELNARROW, SBLKCTL + base); - } - outb(config->scsi_id, SCSIID + base); - scsi_conf = inb(SCSICONF + base) & (ENSPCHK | STIMESEL); - outb(scsi_conf | ENSTIMER | ACTNEGEN | STPWEN, SXFRCTL1 + base); - outb(ENSELTIMO , SIMODE1 + base); - if (p->ultra_enabled) - { - outb(DFON | SPIOEN | ULTRAEN, SXFRCTL0 + base); - } - else - { - outb(DFON | SPIOEN, SXFRCTL0 + base); - } - - /* - * Look at the information that board initialization or the board - * BIOS has left us. In the lower four bits of each target's - * scratch space any value other than 0 indicates that we should - * initiate synchronous transfers. If it's zero, the user or the - * BIOS has decided to disable synchronous negotiation to that - * target so we don't activate the needsdtr flag. - */ - p->needsdtr_copy = 0x0; - p->sdtr_pending = 0x0; - p->needwdtr_copy = 0x0; - p->wdtr_pending = 0x0; - if (p->bus_type == AIC_SINGLE) - { - max_targets = 8; - } - else - { - max_targets = 16; - } - - /* - * Grab the disconnection disable table and invert it for our needs - */ - if (have_seeprom) - { - p->discenable = 0x0; - } - else - { - if (bios_disabled) - { - printk("aic7xxx : Host adapter BIOS disabled. Using default SCSI " - "device parameters.\n"); - p->discenable = 0xFFFF; - } - else - { - p->discenable = ~((inb(DISC_DSB + base + 1) << 8) | - inb(DISC_DSB + base)); - } - } - - for (i = 0; i < max_targets; i++) - { - if (have_seeprom) - { - target_settings = ((sc.device_flags[i] & CFXFER) << 4); - if (sc.device_flags[i] & CFSYNCH) - { - p->needsdtr_copy |= (0x01 << i); - } - if (sc.device_flags[i] & CFWIDEB) - { - p->needwdtr_copy |= (0x01 << i); - } - if (sc.device_flags[i] & CFDISC) - { - p->discenable |= (0x01 << i); - } - } - else - { - if (bios_disabled) - { - target_settings = 0; /* 10 MHz */ - p->needsdtr_copy |= (0x01 << i); - p->needwdtr_copy |= (0x01 << i); - } - else - { - target_settings = inb(TARG_SCRATCH + base + i); - if (target_settings & 0x0F) - { - p->needsdtr_copy |= (0x01 << i); - /* - * Default to asynchronous transfers (0 offset) - */ - target_settings &= 0xF0; - } - if (target_settings & 0x80) - { - p->needwdtr_copy |= (0x01 << i); - target_settings &= 0x7F; - } - } - } - outb(target_settings, (TARG_SCRATCH + base + i)); - } - - /* - * If we are not wide, forget WDTR. This makes the driver - * work on some cards that don't leave these fields cleared - * when BIOS is not installed. - */ - if (p->bus_type != AIC_WIDE) - { - p->needwdtr = 0; - } - p->needsdtr = p->needsdtr_copy; - p->needwdtr = p->needwdtr_copy; -#if 0 - printk("NeedSdtr = 0x%x, 0x%x\n", p->needsdtr_copy, p->needsdtr); - printk("NeedWdtr = 0x%x, 0x%x\n", p->needwdtr_copy, p->needwdtr); -#endif - - /* - * Clear the control byte for every SCB so that the sequencer - * doesn't get confused and think that one of them is valid - */ - for (i = 0; i < config->maxscb; i++) - { - outb(i, SCBPTR + base); - outb(0, SCBARRAY + base); - } - - /* - * For reconnecting targets, the sequencer code needs to - * know how many SCBs it has to search through. - */ - outb(config->maxscb, SCBCOUNT + base); - - /* - * 2s compliment of SCBCOUNT - */ - i = p->maxscb; - outb(-i & 0xff, COMP_SCBCOUNT + base); - - /* - * Clear the active flags - no targets are busy. - */ - outb(0, ACTIVE_A + base); - outb(0, ACTIVE_B + base); - - /* - * We don't have any waiting selections - */ - outb(SCB_LIST_NULL, WAITING_SCBH + base); - outb(SCB_LIST_NULL, WAITING_SCBT + base); - - /* - * Reset the SCSI bus. Is this necessary? - * There may be problems for a warm boot without resetting - * the SCSI bus. Either BIOS settings in scratch RAM - * will not get reinitialized, or devices may stay at - * previous negotiated settings (SDTR and WDTR) while - * the driver will think that no negotiations have been - * performed. - * - * Some devices need a long time to "settle" after a SCSI - * bus reset. - */ - - if (!aic7xxx_no_reset) - { - printk("aic7xxx: Resetting the SCSI bus..."); - if (p->bus_type == AIC_TWIN) - { - /* - * Select Channel B. - */ - outb((sblkctl & ~SELBUS_MASK) | SELBUSB, SBLKCTL + base); - - outb(SCSIRSTO, SCSISEQ + base); - udelay(1000); - outb(0, SCSISEQ + base); - - /* - * Select Channel A. - */ - outb((sblkctl & ~SELBUS_MASK) | SELNARROW, SBLKCTL + base); - } - - outb(SCSIRSTO, SCSISEQ + base); - udelay(1000); - outb(0, SCSISEQ + base); - - aic7xxx_delay(AIC7XXX_RESET_DELAY); - - printk("done.\n"); - } - - /* - * Unpause the sequencer before returning and enable - * interrupts - we shouldn't get any until the first - * command is sent to us by the high-level SCSI code. - */ - UNPAUSE_SEQUENCER(p); - return (found); -} - -/*+F************************************************************************* - * Function: - * aic7xxx_detect - * - * Description: - * Try to detect and register an Adaptec 7770 or 7870 SCSI controller. - *-F*************************************************************************/ -int -aic7xxx_detect(Scsi_Host_Template *template) -{ - int found = 0, slot, base; - unsigned char irq = 0; - int i; - struct aic7xxx_host_config config; - - template->proc_dir = &proc_scsi_aic7xxx; - config.chan_num = 0; - - /* - * Since we may allow sharing of IRQs, it is imperative - * that we "null-out" the aic7xxx_boards array. It is - * not guaranteed to be initialized to 0 (NULL). We use - * a NULL entry to indicate that no prior hosts have - * been found/registered for that IRQ. - */ - for (i = 0; i <= MAXIRQ; i++) - { - aic7xxx_boards[i] = NULL; - } - - /* - * Initialize the spurious count to 0. - */ - aic7xxx_spurious_count = 0; - - /* - * EISA/VL-bus card signature probe. - */ - for (slot = MINSLOT; slot <= MAXSLOT; slot++) - { - base = SLOTBASE(slot) + MINREG; - - if (check_region(MINREG + base, MAXREG - MINREG)) - { - /* - * Some other driver has staked a - * claim to this i/o region already. - */ - continue; - } - - config.type = aic7xxx_probe(slot, HID0 + base); - if (config.type != AIC_NONE) - { - /* - * We found a card, allow 1 spurious interrupt. - */ - aic7xxx_spurious_count = 1; - - /* - * We "find" a AIC-7770 if we locate the card - * signature and we can set it up and register - * it with the kernel without incident. - */ - config.chip_type = AIC_777x; - config.base = base; - config.irq = irq; - config.parity = AIC_UNKNOWN; - config.low_term = AIC_UNKNOWN; - config.high_term = AIC_UNKNOWN; - config.busrtime = 0; - config.walk_scbs = FALSE; - config.ultra_enabled = FALSE; - found += aic7xxx_register(template, &config); - - /* - * Disallow spurious interrupts. - */ - aic7xxx_spurious_count = 0; - } - } - -#ifdef CONFIG_PCI - /* - * PCI-bus probe. - */ - if (pcibios_present()) - { - struct - { - unsigned short vendor_id; - unsigned short device_id; - aha_type card_type; - aha_chip_type chip_type; - } const aic7xxx_pci_devices[] = { - {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7850, AIC_7850, AIC_785x}, - {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7870, AIC_7870, AIC_787x}, - {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7871, AIC_7871, AIC_787x}, - {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7872, AIC_7872, AIC_787x}, - {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7873, AIC_7873, AIC_787x}, - {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7874, AIC_7874, AIC_787x}, - {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7880, AIC_7880, AIC_788x}, - {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7881, AIC_7881, AIC_788x}, - {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7882, AIC_7882, AIC_788x}, - {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7883, AIC_7883, AIC_788x}, - {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7884, AIC_7884, AIC_788x} - }; - - int error; - int done = 0; - unsigned int io_port; - unsigned short index = 0; - unsigned char pci_bus, pci_device_fn; - unsigned int csize_lattime; - unsigned int class_revid; - unsigned int devconfig; - char rev_id[] = {'B', 'C', 'D'}; - - for (i = 0; i < NUMBER(aic7xxx_pci_devices); i++) - { - done = FALSE; - while (!done) - { - if (pcibios_find_device(aic7xxx_pci_devices[i].vendor_id, - aic7xxx_pci_devices[i].device_id, - index, &pci_bus, &pci_device_fn)) - { - done = TRUE; - } - else /* Found an Adaptec PCI device. */ - { - config.type = aic7xxx_pci_devices[i].card_type; - config.chip_type = aic7xxx_pci_devices[i].chip_type; - config.chan_num = 0; - config.walk_scbs = FALSE; - switch (config.type) - { - case AIC_7872: /* 3940 */ - case AIC_7882: /* 3940-Ultra */ - config.walk_scbs = TRUE; - config.chan_num = number_of_39xxs & 0x1; /* Has 2 controllers */ - number_of_39xxs++; - if (number_of_39xxs == 2) - { - number_of_39xxs = 0; /* To be consistent with 3985. */ - } - break; - - case AIC_7873: /* 3985 */ - case AIC_7883: /* 3985-Ultra */ - config.chan_num = number_of_39xxs & 0x3; /* Has 3 controllers */ - number_of_39xxs++; - if (number_of_39xxs == 3) - { - number_of_39xxs = 0; - } - break; - - default: - break; - } - - /* - * Read esundry information from PCI BIOS. - */ - error = pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_0, &io_port); - error += pcibios_read_config_byte(pci_bus, pci_device_fn, - PCI_INTERRUPT_LINE, &irq); - - /* - * Ensure that we are using good values for the PCI burst size - * and latency timer. - */ - error += pcibios_read_config_dword(pci_bus, pci_device_fn, - CSIZE_LATTIME, &csize_lattime); - if ((csize_lattime & CACHESIZE) == 0) - { - /* Default to 8DWDs - what's the PCI define for this? */ - csize_lattime |= 8; - } - if((csize_lattime & LATTIME) == 0) - { - /* Default to 64 PCLKS (is this a good value?) */ - /* This may also be availble in the SEEPROM?? */ - csize_lattime |= (64 << 8); - } - pcibios_write_config_dword(pci_bus, pci_device_fn, - CSIZE_LATTIME, csize_lattime); - printk("aic7xxx: BurstLen = %d DWDs, Latency Timer = %d PCLKS\n", - (int) (csize_lattime & CACHESIZE), - (csize_lattime >> 8) & 0x000000ff); - - error += pcibios_read_config_dword(pci_bus, pci_device_fn, - CLASS_PROGIF_REVID, &class_revid); - if ((class_revid & DEVREVID) < 3) - { - printk("aic7xxx: %s Rev %c.\n", board_names[config.type], - rev_id[class_revid & DEVREVID]); - } - - error += pcibios_read_config_dword(pci_bus, pci_device_fn, - DEVCONFIG, &devconfig); - if (error) - { - panic("aic7xxx: (aic7xxx_detect) Error %d reading PCI registers.\n", - error); - } - - printk("aic7xxx: devconfig = 0x%x.\n", devconfig); - - /* - * The first bit of PCI_BASE_ADDRESS_0 is always set, so - * we mask it off. - */ - base = io_port & 0xfffffffe; - - /* - * I don't think we need to bother with allowing - * spurious interrupts for the 787x/7850, but what - * the hey. - */ - aic7xxx_spurious_count = 1; - - config.base = base; - config.irq = irq; - config.parity = AIC_UNKNOWN; - config.low_term = AIC_UNKNOWN; - config.high_term = AIC_UNKNOWN; - config.busrtime = 0; - config.ultra_enabled = FALSE; - if (devconfig & RAMPSM) - { - /* - * External SRAM present. Have the probe walk the SCBs to see - * how much SRAM we have and set the number of SCBs accordingly. - * We have to turn off SCBRAMSEL to access the external SCB - * SRAM. - * - * It seems that early versions of the aic7870 didn't use these - * bits, hence the hack for the 3940 above. I would guess that - * recent 3940s using later aic7870 or aic7880 chips do actually - * set RAMPSM. - * - * The documentation isn't clear, but it sounds like the value - * written to devconfig must not have RAMPSM set. The second - * sixteen bits of the register are R/O anyway, so it shouldn't - * affect RAMPSM either way. - */ - printk ("aic7xxx: External RAM detected. Enabling RAM access.\n"); - devconfig &= ~(RAMPSM | SCBRAMSEL); - pcibios_write_config_dword(pci_bus, pci_device_fn, - DEVCONFIG, devconfig); - config.walk_scbs = TRUE; - } - found += aic7xxx_register(template, &config); - - /* - * Disable spurious interrupts. - */ - aic7xxx_spurious_count = 0; - - index++; - } /* Found an Adaptec PCI device. */ - } - } - } -#endif CONFIG_PCI - - template->name = aic7xxx_info(NULL); - return (found); -} - - -/*+F************************************************************************* - * Function: - * aic7xxx_buildscb - * - * Description: - * Build a SCB. - *-F*************************************************************************/ -static void -aic7xxx_buildscb(struct aic7xxx_host *p, - Scsi_Cmnd *cmd, - struct aic7xxx_scb *scb) -{ - void *addr; - unsigned short mask; - struct scatterlist *sg; - - /* - * Setup the control byte if we need negotiation and have not - * already requested it. - */ -#ifdef AIC7XXX_TAGGED_QUEUEING - if (cmd->device->tagged_supported) - { - if (cmd->device->tagged_queue == 0) - { - printk("aic7xxx: Enabling tagged queuing for target %d, " - "channel %d.\n", cmd->target, cmd->channel); - cmd->device->tagged_queue = 1; - cmd->device->current_tag = 1; /* enable tagging */ - } - cmd->tag = cmd->device->current_tag; - cmd->device->current_tag++; - scb->control |= TAG_ENB; - } -#endif - mask = (0x01 << (cmd->target | (cmd->channel << 3))); - if (p->discenable & mask) - { - scb->control |= DISCENB; - } - if ((p->needwdtr & mask) && !(p->wdtr_pending & mask)) - { - p->wdtr_pending |= mask; - scb->control |= NEEDWDTR; -#if 0 - printk("aic7xxx: Sending WDTR request to target %d.\n", cmd->target); -#endif - } - else - { - if ((p->needsdtr & mask) && !(p->sdtr_pending & mask)) - { - p->sdtr_pending |= mask; - scb->control |= NEEDSDTR; -#if 0 - printk("aic7xxx: Sending SDTR request to target %d.\n", cmd->target); -#endif - } - } - -#if 0 - printk("aic7xxx: (build_scb) Target %d, cmd(0x%x) size(%u) wdtr(0x%x) " - "mask(0x%x).\n", - cmd->target, cmd->cmnd[0], cmd->cmd_len, p->needwdtr, mask); -#endif - scb->target_channel_lun = ((cmd->target << 4) & 0xF0) | - ((cmd->channel & 0x01) << 3) | (cmd->lun & 0x07); - - /* - * The interpretation of request_buffer and request_bufflen - * changes depending on whether or not use_sg is zero; a - * non-zero use_sg indicates the number of elements in the - * scatter-gather array. - */ - - /* - * XXX - this relies on the host data being stored in a - * little-endian format. - */ - addr = cmd->cmnd; - scb->SCSI_cmd_length = cmd->cmd_len; - memcpy(scb->SCSI_cmd_pointer, &addr, sizeof(scb->SCSI_cmd_pointer)); - - if (cmd->use_sg) - { - scb->SG_segment_count = cmd->use_sg; - memcpy(scb->SG_list_pointer, &cmd->request_buffer, - sizeof(scb->SG_list_pointer)); - memcpy(&sg, &cmd->request_buffer, sizeof(sg)); - memcpy(scb->data_pointer, &(sg[0].address), sizeof(scb->data_pointer)); - scb->data_count = sg[0].length; -#if 0 - debug("aic7xxx: (build_scb) SG segs(%d), length(%u), sg[0].length(%d).\n", - cmd->use_sg, aic7xxx_length(cmd, 0), scb->data_count); -#endif - } - else - { -#if 0 - debug("aic7xxx: (build_scb) Creating scatterlist, addr(0x%lx) length(%d).\n", - (unsigned long) cmd->request_buffer, cmd->request_bufflen); -#endif - if (cmd->request_bufflen == 0) - { - /* - * In case the higher level SCSI code ever tries to send a zero - * length command, ensure the SCB indicates no data. The driver - * will interpret a zero length command as a Bus Device Reset. - */ - scb->SG_segment_count = 0; - memset(scb->SG_list_pointer, 0, sizeof(scb->SG_list_pointer)); - memset(scb->data_pointer, 0, sizeof(scb->data_pointer)); - scb->data_count = 0; - } - else - { - scb->SG_segment_count = 1; - scb->sg.address = (char *) cmd->request_buffer; - scb->sg.length = cmd->request_bufflen; - addr = &scb->sg; - memcpy(scb->SG_list_pointer, &addr, sizeof(scb->SG_list_pointer)); - scb->data_count = scb->sg.length; - memcpy(scb->data_pointer, &cmd->request_buffer, sizeof(scb->data_pointer)); - } - } -} - -/*+F************************************************************************* - * Function: - * aic7xxx_queue - * - * Description: - * Queue a SCB to the controller. - *-F*************************************************************************/ -int -aic7xxx_queue(Scsi_Cmnd *cmd, void (*fn)(Scsi_Cmnd *)) -{ - long flags; - struct aic7xxx_host *p; - struct aic7xxx_scb *scb; - - p = (struct aic7xxx_host *) cmd->host->hostdata; - - /* - * Check to see if channel was scanned. - */ - if (!p->a_scanned && (cmd->channel == 0)) - { - printk("aic7xxx: Scanning channel A for devices.\n"); - p->a_scanned = TRUE; - } - else - { - if (!p->b_scanned && (cmd->channel == 1)) - { - printk("aic7xxx: Scanning channel B for devices.\n"); - p->b_scanned = TRUE; - } - } - -#if 0 - debug("aic7xxx: (queue) cmd(0x%x) size(%u), target %d, channel %d, lun %d.\n", - cmd->cmnd[0], cmd->cmd_len, cmd->target, cmd->channel, - cmd->lun & 0x07); -#endif - - /* - * This is a critical section, since we don't want the - * interrupt routine mucking with the host data or the - * card. Since the kernel documentation is vague on - * whether or not we are in a cli/sti pair already, save - * the flags to be on the safe side. - */ - save_flags(flags); - cli(); - - /* - * Find a free slot in the SCB array to load this command - * into. Since can_queue is set to the maximum number of - * SCBs for the card, we should always find one. - * - * First try to find an scb in the free list. If there are - * none in the free list, then check the current number of - * of scbs and take an unused one from the scb array. - */ - scb = p->free_scb; - if (scb != NULL) - { /* found one in the free list */ - p->free_scb = scb->next; /* remove and update head of list */ - /* - * Warning! For some unknown reason, the scb at the head - * of the free list is not the same address that it should - * be. That's why we set the scb pointer taken by the - * position in the array. The scb at the head of the list - * should match this address, but it doesn't. - */ - scb = &(p->scb_array[scb->position]); - scb->control = 0; - scb->state = SCB_ACTIVE; - } - else - { - if (p->numscb >= p->maxscb) - { - panic("aic7xxx: (aic7xxx_queue) Couldn't find a free SCB.\n"); - } - else - { - /* - * Initialize the scb within the scb array. The - * position within the array is the position on - * the board that it will be loaded. - */ - scb = &(p->scb_array[p->numscb]); - memset(scb, 0, sizeof(*scb)); - - scb->position = p->numscb; - p->numscb++; - scb->state = SCB_ACTIVE; - } - } - - scb->cmd = cmd; - aic7xxx_position(cmd) = scb->position; -#if 0 - debug_scb(scb); -#endif; - - /* - * Construct the SCB beforehand, so the sequencer is - * paused a minimal amount of time. - */ - aic7xxx_buildscb(p, cmd, scb); - -#if 0 - if (scb != &p->scb_array[scb->position]) - { - printk("aic7xxx: (queue) Address of SCB by position does not match SCB " - "address.\n"); - } - printk("aic7xxx: (queue) SCB pos(%d) cmdptr(0x%x) state(%d) freescb(0x%x)\n", - scb->position, (unsigned int) scb->cmd, - scb->state, (unsigned int) p->free_scb); -#endif - /* - * Pause the sequencer so we can play with its registers - - * wait for it to acknowledge the pause. - * - * XXX - should the interrupts be left on while doing this? - */ - PAUSE_SEQUENCER(p); - - /* - * Save the SCB pointer and put our own pointer in - this - * selects one of the four banks of SCB registers. Load - * the SCB, then write its pointer into the queue in FIFO - * and restore the saved SCB pointer. - */ - aic7xxx_putscb(p, scb); - outb(scb->position, QINFIFO + p->base); - - /* - * Make sure the Scsi_Cmnd pointer is saved, the struct it - * points to is set up properly, and the parity error flag - * is reset, then unpause the sequencer and watch the fun - * begin. - */ - cmd->scsi_done = fn; - aic7xxx_error(cmd) = DID_OK; - aic7xxx_status(cmd) = 0; - cmd->result = 0; - memset(&cmd->sense_buffer, 0, sizeof(cmd->sense_buffer)); - - UNPAUSE_SEQUENCER(p); -#if 0 - printk("aic7xxx: (queue) After - cmd(0x%lx) scb->cmd(0x%lx) pos(%d).\n", - (long) cmd, (long) scb->cmd, scb->position); -#endif; - restore_flags(flags); - return (0); -} - -/*+F************************************************************************* - * Function: - * aic7xxx_abort_scb - * - * Description: - * Abort an scb. If the scb has not previously been aborted, then - * we attempt to send a BUS_DEVICE_RESET message to the target. If - * the scb has previously been unsuccessfully aborted, then we will - * reset the channel and have all devices renegotiate. Returns an - * enumerated type that indicates the status of the operation. - *-F*************************************************************************/ -static aha_abort_reset_type -aic7xxx_abort_scb(struct aic7xxx_host *p, struct aic7xxx_scb *scb, - unsigned char errcode) -{ - int base = p->base; - int found = FALSE; - aha_abort_reset_type scb_status = ABORT_RESET_SUCCESS; - char channel = scb->target_channel_lun & SELBUSB ? 'B': 'A'; - - /* - * Ensure that the card doesn't do anything - * behind our back. - */ - PAUSE_SEQUENCER(p); - -#ifdef AIC7XXX_DEBUG_ABORT - printk ("aic7xxx: (abort_scb) scb %d, scb_aborted 0x%x\n", - scb->position, (scb->state & SCB_ABORTED)); -#endif - /* - * First, determine if we want to do a bus reset or simply a bus device - * reset. If this is the first time that a transaction has timed out, - * just schedule a bus device reset. Otherwise, we reset the bus and - * abort all pending I/Os on that bus. - */ - if (scb->state & SCB_ABORTED) - { - /* - * Been down this road before. Do a full bus reset. - */ - found = aic7xxx_reset_channel(p, channel, scb->position); - } - else - { - unsigned char active_scb, control; - struct aic7xxx_scb *active_scbp; - - /* - * Send a Bus Device Reset Message: - * The target we select to send the message to may be entirely - * different than the target pointed to by the scb that timed - * out. If the command is in the QINFIFO or the waiting for - * selection list, its not tying up the bus and isn't responsible - * for the delay so we pick off the active command which should - * be the SCB selected by SCBPTR. If its disconnected or active, - * we device reset the target scbp points to. Although it may - * be that this target is not responsible for the delay, it may - * may also be that we're timing out on a command that just takes - * too much time, so we try the bus device reset there first. - */ - active_scb = inb(SCBPTR + base); - active_scbp = &(p->scb_array[active_scb]); - control = inb(SCBARRAY + base); - - /* - * Test to see if scbp is disconnected - */ - outb(scb->position, SCBPTR + base); - if (inb(SCBARRAY + base) & DISCONNECTED) - { -#ifdef AIC7XXX_DEBUG_ABORT - printk ("aic7xxx: (abort_scb) scb %d is disconnected.\n", scb->position); -#endif - scb->state |= (SCB_DEVICE_RESET | SCB_ABORTED); - scb->SG_segment_count = 0; - memset(scb->SG_list_pointer, 0, sizeof(scb->SG_list_pointer)); - memset(scb->data_pointer, 0, sizeof(scb->data_pointer)); - scb->data_count = 0; - aic7xxx_putscb(p, scb); - aic7xxx_error(scb->cmd) = errcode; - scb_status = ABORT_RESET_PENDING; - aic7xxx_add_waiting_scb(base, scb, LIST_SECOND); - UNPAUSE_SEQUENCER(p); - } - else - { - /* - * Is the active SCB really active? - */ - if (active_scbp->state & SCB_ACTIVE) - { - unsigned char msg_len = inb(MSG_LEN + base); - if (msg_len != 0) - { -#ifdef AIC7XXX_DEBUG_ABORT - printk ("aic7xxx: (abort_scb) scb is active, needs DMA, " - "msg_len is non-zero.\n"); -#endif - /* - * If we're in a message phase, tacking on another message - * may confuse the target totally. The bus is probably wedged, - * so reset the channel. - */ - channel = (active_scbp->target_channel_lun & SELBUSB) ? 'B': 'A'; - aic7xxx_reset_channel(p, channel, scb->position); - } - else - { -#ifdef AIC7XXX_DEBUG_ABORT - printk ("aic7xxx: (abort_scb) scb is active, needs DMA, " - "msg_len is zero.\n"); -#endif - /* - * Load the message buffer and assert attention. - */ - active_scbp->state |= (SCB_DEVICE_RESET | SCB_ABORTED); - outb(1, MSG_LEN + base); - outb(MSG_BUS_DEVICE_RESET, MSG0 + base); - if (active_scbp->target_channel_lun != scb->target_channel_lun) - { - /* - * XXX - We would like to increment the timeout on scb, but - * access to that routine is denied because it is hidden - * in scsi.c. If we were able to do this, it would give - * scb a new lease on life. - */ - ; - } - aic7xxx_error(scb->cmd) = errcode; - scb_status = ABORT_RESET_PENDING; - UNPAUSE_SEQUENCER(p); - } - } - else - { -#ifdef AIC7XXX_DEBUG_ABORT - printk ("aic7xxx: (abort_scb) no active command.\n"); -#endif - /* - * No active command to single out, so reset - * the bus for the timed out target. - */ - aic7xxx_reset_channel(p, channel, scb->position); - } - } - } - return (scb_status); -} - -/*+F************************************************************************* - * Function: - * aic7xxx_abort_reset - * - * Description: - * Abort or reset the current SCSI command(s). Returns an enumerated - * type that indicates the status of the operation. - *-F*************************************************************************/ -static aha_abort_reset_type -aic7xxx_abort_reset(Scsi_Cmnd *cmd, unsigned char errcode) -{ - struct aic7xxx_scb *scb; - struct aic7xxx_host *p; - long flags; - aha_abort_reset_type scb_status = ABORT_RESET_SUCCESS; - - p = (struct aic7xxx_host *) cmd->host->hostdata; - scb = &(p->scb_array[aic7xxx_position(cmd)]); - - save_flags(flags); - cli(); - -#ifdef AIC7XXX_DEBUG_ABORT - printk ("aic7xxx: (abort_reset) scb state 0x%x\n", scb->state); -#endif - - if (scb->state & SCB_ACTIVE) - { - if (scb->state & SCB_IMMED) - { - /* - * Don't know how set the number of retries to 0. - */ - /* cmd->retries = 0; */ - aic7xxx_error(cmd) = errcode; - aic7xxx_done(p, scb); - } - else - { - /* - * Abort the operation. - */ - scb_status = aic7xxx_abort_scb(p, scb, errcode); - } - } - else - { - /* - * The scb is not active and must have completed after the timeout - * check in scsi.c and before we check the scb state above. For - * this case we return SCSI_ABORT_NOT_RUNNING (if abort was called) - * or SCSI_RESET_SUCCESS (if reset was called). - */ -#ifdef AIC7XXX_DEBUG_ABORT - printk ("aic7xxx: (abort_reset) called with no active scb, errcode 0x%x\n", - errcode); -#endif - scb_status = ABORT_RESET_INACTIVE; - /* - * According to the comments in scsi.h and Michael Neuffer, if we do not - * have an active command for abort or reset, we should not call the - * command done function. Unfortunately, this hangs the system for me - * unless we *do* call the done function. - * - * XXX - Revisit this sometime! - */ - cmd->result = errcode << 16; - cmd->scsi_done(cmd); - } - restore_flags(flags); - return (scb_status); -} - - -/*+F************************************************************************* - * Function: - * aic7xxx_abort - * - * Description: - * Abort the current SCSI command(s). - *-F*************************************************************************/ -int -aic7xxx_abort(Scsi_Cmnd *cmd) -{ -#ifdef AIC7XXX_DEBUG_ABORT - printk ("aic7xxx: (abort) target/channel %d/%d\n", cmd->target, cmd->channel); -#endif - - switch (aic7xxx_abort_reset(cmd, DID_ABORT)) - { - case ABORT_RESET_INACTIVE: - return (SCSI_ABORT_NOT_RUNNING); - break; - case ABORT_RESET_PENDING: - return (SCSI_ABORT_PENDING); - break; - case ABORT_RESET_SUCCESS: - default: - return (SCSI_ABORT_SUCCESS); - break; - } -} - -/*+F************************************************************************* - * Function: - * aic7xxx_reset - * - * Description: - * Resetting the bus always succeeds - is has to, otherwise the - * kernel will panic! Try a surgical technique - sending a BUS - * DEVICE RESET message - on the offending target before pulling - * the SCSI bus reset line. - *-F*************************************************************************/ -int -aic7xxx_reset(Scsi_Cmnd *cmd) -{ -#ifdef AIC7XXX_DEBUG_ABORT - printk ("aic7xxx: (reset) target/channel %d/%d\n", cmd->target, cmd->channel); -#endif - - switch (aic7xxx_abort_reset(cmd, DID_RESET)) - { - case ABORT_RESET_PENDING: - return (SCSI_RESET_PENDING); - break; - case ABORT_RESET_INACTIVE: - case ABORT_RESET_SUCCESS: - default: - return (SCSI_RESET_SUCCESS); - break; - } -} - -/*+F************************************************************************* - * Function: - * aic7xxx_biosparam - * - * Description: - * Return the disk geometry for the given SCSI device. - *-F*************************************************************************/ -int -aic7xxx_biosparam(Disk *disk, kdev_t dev, int geom[]) -{ - int heads, sectors, cylinders; - struct aic7xxx_host *p; - - p = (struct aic7xxx_host *) disk->device->host->hostdata; - - /* - * XXX - if I could portably find the card's configuration - * information, then this could be autodetected instead - * of left to a boot-time switch. - */ - heads = 64; - sectors = 32; - cylinders = disk->capacity / (heads * sectors); - - if (p->extended && cylinders > 1024) - { - heads = 255; - sectors = 63; - cylinders = disk->capacity / (255 * 63); - } - - geom[0] = heads; - geom[1] = sectors; - geom[2] = cylinders; - - return (0); -} - -#ifdef MACH -#include "aic7xxx_proc.src" -#else -#include "aic7xxx_proc.c" -#endif - -#ifdef MODULE -/* Eventually this will go into an include file, but this will be later */ -Scsi_Host_Template driver_template = AIC7XXX; - -#include "scsi_module.c" -#endif - -/* - * Overrides for Emacs so that we almost follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 2 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -2 - * c-argdecl-indent: 2 - * c-label-offset: -2 - * c-continued-statement-offset: 2 - * c-continued-brace-offset: 0 - * indent-tabs-mode: nil - * tab-width: 8 - * End: - */ - diff --git a/i386/i386at/gpl/linux/scsi/aic7xxx.h b/i386/i386at/gpl/linux/scsi/aic7xxx.h deleted file mode 100644 index 76d4d962..00000000 --- a/i386/i386at/gpl/linux/scsi/aic7xxx.h +++ /dev/null @@ -1,67 +0,0 @@ -/*+M************************************************************************* - * Adaptec 274x/284x/294x device driver for Linux. - * - * Copyright (c) 1994 John Aycock - * The University of Calgary Department of Computer Science. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to - * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - * - * $Id: aic7xxx.h,v 1.1.1.1 1997/02/25 21:27:47 thomas Exp $ - *-M*************************************************************************/ -#ifndef _aic7xxx_h -#define _aic7xxx_h - -#define AIC7XXX_H_VERSION "$Revision: 1.1.1.1 $" - -/* - * Scsi_Host_Template (see hosts.h) for AIC-7770/AIC-7870 - some fields - * to do with card config are filled in after the card is detected. - */ -#define AIC7XXX { \ - NULL, \ - NULL, \ - NULL, \ - aic7xxx_proc_info, \ - NULL, \ - aic7xxx_detect, \ - NULL, \ - aic7xxx_info, \ - NULL, \ - aic7xxx_queue, \ - aic7xxx_abort, \ - aic7xxx_reset, \ - NULL, \ - aic7xxx_biosparam, \ - -1, /* max simultaneous cmds */\ - -1, /* scsi id of host adapter */\ - SG_ALL, /* max scatter-gather cmds */\ - 2, /* cmds per lun (linked cmds) */\ - 0, /* number of 7xxx's present */\ - 0, /* no memory DMA restrictions */\ - ENABLE_CLUSTERING \ -} - -extern int aic7xxx_queue(Scsi_Cmnd *, void (*)(Scsi_Cmnd *)); -extern int aic7xxx_biosparam(Disk *, kdev_t, int[]); -extern int aic7xxx_detect(Scsi_Host_Template *); -extern int aic7xxx_command(Scsi_Cmnd *); -extern int aic7xxx_abort(Scsi_Cmnd *); -extern int aic7xxx_reset(Scsi_Cmnd *); - -extern const char *aic7xxx_info(struct Scsi_Host *); - -extern int aic7xxx_proc_info(char *, char **, off_t, int, int, int); - -#endif /* _aic7xxx_h */ diff --git a/i386/i386at/gpl/linux/scsi/aic7xxx_proc.src b/i386/i386at/gpl/linux/scsi/aic7xxx_proc.src deleted file mode 100644 index 65996822..00000000 --- a/i386/i386at/gpl/linux/scsi/aic7xxx_proc.src +++ /dev/null @@ -1,271 +0,0 @@ -/*+M************************************************************************* - * Adaptec 274x/284x/294x device driver proc support for Linux. - * - * Copyright (c) 1995 Dean W. Gehnert - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to - * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - * - * ---------------------------------------------------------------- - * o Modified from the EATA /proc support. - * o Additional support for device block statistics provided by - * Matthew Jacob. - * - * Dean W. Gehnert, deang@ims.com, 08/30/95 - * - * $Id: aic7xxx_proc.src,v 1.1.1.1 1997/02/25 21:27:47 thomas Exp $ - *-M*************************************************************************/ - -#define BLS buffer + len + size -#define HDRB \ -" < 512 512-1K 1-2K 2-4K 4-8K 8-16K 16-32K 32-64K 64-128K >128K" - -#ifdef PROC_DEBUG -extern int vsprintf(char *, const char *, va_list); - -static void -proc_debug(const char *fmt, ...) -{ - va_list ap; - char buf[256]; - - va_start(ap, fmt); - vsprintf(buf, fmt, ap); - printk(buf); - va_end(ap); -} -#else /* PROC_DEBUG */ -# define proc_debug(fmt, args...) -#endif /* PROC_DEBUG */ - -/*+F************************************************************************* - * Function: - * aic7xxx_set_info - * - * Description: - * Set parameters for the driver from the /proc filesystem. - *-F*************************************************************************/ -int -aic7xxx_set_info(char *buffer, int length, struct Scsi_Host *HBAptr) -{ - proc_debug("aic7xxx_set_info(): %s\n", buffer); - return (-ENOSYS); /* Currently this is a no-op */ -} - -/*+F************************************************************************* - * Function: - * aic7xxx_proc_info - * - * Description: - * Return information to handle /proc support for the driver. - *-F*************************************************************************/ -int -aic7xxx_proc_info(char *buffer, char **start, off_t offset, int length, - int hostno, int inout) -{ - struct Scsi_Host *HBAptr; - struct aic7xxx_host *p; - static u8 buff[512]; - int i; - int size = 0; - int len = 0; - off_t begin = 0; - off_t pos = 0; - static char *bus_name[] = {"Single", "Twin", "Wide"}; - - HBAptr = NULL; - for (i = 0; i < NUMBER(aic7xxx_boards); i++) - { - if ((HBAptr = aic7xxx_boards[i]) != NULL) - { - if (HBAptr->host_no == hostno) - { - break; - } - - while ((HBAptr->hostdata != NULL) && - ((HBAptr = ((struct aic7xxx_host *) HBAptr->hostdata)->next) != NULL)) - { - if (HBAptr->host_no == hostno) - { - break; break; - } - } - - HBAptr = NULL; - } - } - - if (HBAptr == NULL) - { - size += sprintf(BLS, "Can't find adapter for host number %d\n", hostno); - len += size; pos = begin + len; size = 0; - goto stop_output; - } - - if (inout == TRUE) /* Has data been written to the file? */ - { - return (aic7xxx_set_info(buffer, length, HBAptr)); - } - - if (offset == 0) - { - memset(buff, 0, sizeof(buff)); - } - - p = (struct aic7xxx_host *) HBAptr->hostdata; - - size += sprintf(BLS, "Adaptec AIC7xxx driver version: "); - size += sprintf(BLS, "%s/", rcs_version(AIC7XXX_C_VERSION)); - size += sprintf(BLS, "%s/", rcs_version(AIC7XXX_H_VERSION)); - size += sprintf(BLS, "%s\n", rcs_version(AIC7XXX_SEQ_VER)); - len += size; pos = begin + len; size = 0; - - size += sprintf(BLS, "\n"); - size += sprintf(BLS, "Compile Options:\n"); -#ifdef AIC7XXX_RESET_DELAY - size += sprintf(BLS, " AIC7XXX_RESET_DELAY : %d\n", AIC7XXX_RESET_DELAY); -#endif -#ifdef AIC7XXX_TWIN_SUPPORT - size += sprintf(BLS, " AIC7XXX_TWIN_SUPPORT : Enabled\n"); -#else - size += sprintf(BLS, " AIC7XXX_TWIN_SUPPORT : Disabled\n"); -#endif -#ifdef AIC7XXX_TAGGED_QUEUEING - size += sprintf(BLS, " AIC7XXX_TAGGED_QUEUEING: Enabled\n"); -#else - size += sprintf(BLS, " AIC7XXX_TAGGED_QUEUEING: Disabled\n"); -#endif -#ifdef AIC7XXX_SHARE_IRQS - size += sprintf(BLS, " AIC7XXX_SHARE_IRQS : Enabled\n"); -#else - size += sprintf(BLS, " AIC7XXX_SHARE_IRQS : Disabled\n"); -#endif -#ifdef AIC7XXX_PROC_STATS - size += sprintf(BLS, " AIC7XXX_PROC_STATS : Enabled\n"); -#else - size += sprintf(BLS, " AIC7XXX_PROC_STATS : Disabled\n"); -#endif - len += size; pos = begin + len; size = 0; - - size += sprintf(BLS, "\n"); - size += sprintf(BLS, "Adapter Configuration:\n"); - size += sprintf(BLS, " SCSI Adapter: %s\n", board_names[p->type]); - size += sprintf(BLS, " Host Bus: %s\n", bus_name[p->bus_type]); - size += sprintf(BLS, " Base IO: %#.4x\n", p->base); - size += sprintf(BLS, " IRQ: %d\n", HBAptr->irq); - size += sprintf(BLS, " SCB: %d (%d)\n", p->numscb, p->maxscb); - size += sprintf(BLS, " Interrupts: %d", p->isr_count); - if (p->chip_type == AIC_777x) - { - size += sprintf(BLS, " %s\n", - (p->pause & IRQMS) ? "(Level Sensitive)" : "(Edge Triggered)"); - } - else - { - size += sprintf(BLS, "\n"); - } - size += sprintf(BLS, " Serial EEPROM: %s\n", - p->have_seeprom ? "True" : "False"); - size += sprintf(BLS, " Pause/Unpause: %#.2x/%#.2x\n", p->pause, - p->unpause); - size += sprintf(BLS, " Extended Translation: %sabled\n", - p->extended ? "En" : "Dis"); - size += sprintf(BLS, " SCSI Bus Reset: %sabled\n", - aic7xxx_no_reset ? "Dis" : "En"); - size += sprintf(BLS, " Ultra SCSI: %sabled\n", - p->ultra_enabled ? "En" : "Dis"); - len += size; pos = begin + len; size = 0; - -#ifdef AIC7XXX_PROC_STATS - { - struct aic7xxx_xferstats *sp; - int channel, target, lun; - - /* - * XXX: Need to fix this to avoid overflow... - */ - size += sprintf(BLS, "\n"); - size += sprintf(BLS, "Statistics:\n"); - for (channel = 0; channel < 2; channel++) - { - for (target = 0; target < 16; target++) - { - for (lun = 0; lun < 8; lun++) - { - sp = &p->stats[channel][target][lun]; - if (sp->xfers == 0) - { - continue; - } - size += sprintf(BLS, "CHAN#%c (TGT %d LUN %d):\n", - 'A' + channel, target, lun); - size += sprintf(BLS, "nxfers %ld (%ld read;%ld written)\n", - sp->xfers, sp->r_total, sp->w_total); - size += sprintf(BLS, "blks(512) rd=%ld; blks(512) wr=%ld\n", - sp->r_total512, sp->w_total512); - size += sprintf(BLS, "%s\n", HDRB); - size += sprintf(BLS, " Reads:"); - size += sprintf(BLS, "%6ld %6ld %6ld %6ld ", sp->r_bins[0], - sp->r_bins[1], sp->r_bins[2], sp->r_bins[3]); - size += sprintf(BLS, "%6ld %6ld %6ld %6ld ", sp->r_bins[4], - sp->r_bins[5], sp->r_bins[6], sp->r_bins[7]); - size += sprintf(BLS, "%6ld %6ld\n", sp->r_bins[8], - sp->r_bins[9]); - size += sprintf(BLS, "Writes:"); - size += sprintf(BLS, "%6ld %6ld %6ld %6ld ", sp->w_bins[0], - sp->w_bins[1], sp->w_bins[2], sp->w_bins[3]); - size += sprintf(BLS, "%6ld %6ld %6ld %6ld ", sp->w_bins[4], - sp->w_bins[5], sp->w_bins[6], sp->w_bins[7]); - size += sprintf(BLS, "%6ld %6ld\n", sp->w_bins[8], - sp->w_bins[9]); - size += sprintf(BLS, "\n"); - } - } - } - len += size; pos = begin + len; size = 0; - } -#endif /* AIC7XXX_PROC_STATS */ - -stop_output: - proc_debug("2pos: %ld offset: %ld len: %d\n", pos, offset, len); - *start = buffer + (offset - begin); /* Start of wanted data */ - len -= (offset - begin); /* Start slop */ - if (len > length) - { - len = length; /* Ending slop */ - } - proc_debug("3pos: %ld offset: %ld len: %d\n", pos, offset, len); - - return (len); -} - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 2 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -2 - * c-argdecl-indent: 2 - * c-label-offset: -2 - * c-continued-statement-offset: 2 - * c-continued-brace-offset: 0 - * indent-tabs-mode: nil - * tab-width: 8 - * End: - */ diff --git a/i386/i386at/gpl/linux/scsi/aic7xxx_reg.h b/i386/i386at/gpl/linux/scsi/aic7xxx_reg.h deleted file mode 100644 index 4a7f612c..00000000 --- a/i386/i386at/gpl/linux/scsi/aic7xxx_reg.h +++ /dev/null @@ -1,746 +0,0 @@ -/*+M************************************************************************* - * Adaptec AIC7xxx register and scratch ram definitions. - * - * Copyright (c) 1994, 1995, 1996 Justin T. Gibbs. - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to - * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - * - * $Id: aic7xxx_reg.h,v 1.1.1.1 1997/02/25 21:27:47 thomas Exp $ - *-M*************************************************************************/ - -/* - * This header is shared by the sequencer code and the kernel level driver. - * - * All page numbers refer to the Adaptec AIC-7770 Data Book availible from - * Adaptec's Technical Documents Department 1-800-934-2766 - */ - -/* - * SCSI Sequence Control (p. 3-11). - * Each bit, when set starts a specific SCSI sequence on the bus - */ -#define SCSISEQ 0x000 -#define TEMODEO 0x80 -#define ENSELO 0x40 -#define ENSELI 0x20 -#define ENRSELI 0x10 -#define ENAUTOATNO 0x08 -#define ENAUTOATNI 0x04 -#define ENAUTOATNP 0x02 -#define SCSIRSTO 0x01 - -/* - * SCSI Transfer Control 0 Register (pp. 3-13). - * Controls the SCSI module data path. - */ -#define SXFRCTL0 0x001 -#define DFON 0x80 -#define DFPEXP 0x40 -#define ULTRAEN 0x20 -#define CLRSTCNT 0x10 -#define SPIOEN 0x08 -#define SCAMEN 0x04 -#define CLRCHN 0x02 -/* UNUSED 0x01 */ - -/* - * SCSI Transfer Control 1 Register (pp. 3-14,15). - * Controls the SCSI module data path. - */ -#define SXFRCTL1 0x002 -#define BITBUCKET 0x80 -#define SWRAPEN 0x40 -#define ENSPCHK 0x20 -#define STIMESEL 0x18 -#define ENSTIMER 0x04 -#define ACTNEGEN 0x02 -#define STPWEN 0x01 /* Powered Termination */ - -/* - * SCSI Control Signal Read Register (p. 3-15). - * Reads the actual state of the SCSI bus pins - */ -#define SCSISIGI 0x003 -#define CDI 0x80 -#define IOI 0x40 -#define MSGI 0x20 -#define ATNI 0x10 -#define SELI 0x08 -#define BSYI 0x04 -#define REQI 0x02 -#define ACKI 0x01 - -/* - * Possible phases in SCSISIGI - */ -#define PHASE_MASK 0xe0 -#define P_DATAOUT 0x00 -#define P_DATAIN 0x40 -#define P_COMMAND 0x80 -#define P_MESGOUT 0xa0 -#define P_STATUS 0xc0 -#define P_MESGIN 0xe0 -/* - * SCSI Contol Signal Write Register (p. 3-16). - * Writing to this register modifies the control signals on the bus. Only - * those signals that are allowed in the current mode (Initiator/Target) are - * asserted. - */ -#define SCSISIGO 0x003 -#define CDO 0x80 -#define IOO 0x40 -#define MSGO 0x20 -#define ATNO 0x10 -#define SELO 0x08 -#define BSYO 0x04 -#define REQO 0x02 -#define ACKO 0x01 - -/* - * SCSI Rate Control (p. 3-17). - * Contents of this register determine the Synchronous SCSI data transfer - * rate and the maximum synchronous Req/Ack offset. An offset of 0 in the - * SOFS (3:0) bits disables synchronous data transfers. Any offset value - * greater than 0 enables synchronous transfers. - */ -#define SCSIRATE 0x004 -#define WIDEXFER 0x80 /* Wide transfer control */ -#define SXFR 0x70 /* Sync transfer rate */ -#define SOFS 0x0f /* Sync offset */ - -/* - * SCSI ID (p. 3-18). - * Contains the ID of the board and the current target on the - * selected channel. - */ -#define SCSIID 0x005 -#define TID 0xf0 /* Target ID mask */ -#define OID 0x0f /* Our ID mask */ - -/* - * SCSI Latched Data (p. 3-19). - * Read/Write latchs used to transfer data on the SCSI bus during - * Automatic or Manual PIO mode. SCSIDATH can be used for the - * upper byte of a 16bit wide asyncronouse data phase transfer. - */ -#define SCSIDATL 0x006 -#define SCSIDATH 0x007 - -/* - * SCSI Transfer Count (pp. 3-19,20) - * These registers count down the number of bytes transfered - * across the SCSI bus. The counter is decremented only once - * the data has been safely transfered. SDONE in SSTAT0 is - * set when STCNT goes to 0 - */ -#define STCNT 0x008 -#define STCNT0 0x008 -#define STCNT1 0x009 -#define STCNT2 0x00a - -/* - * Clear SCSI Interrupt 0 (p. 3-20) - * Writing a 1 to a bit clears the associated SCSI Interrupt in SSTAT0. - */ -#define CLRSINT0 0x00b -#define CLRSELDO 0x40 -#define CLRSELDI 0x20 -#define CLRSELINGO 0x10 -#define CLRSWRAP 0x08 -/* UNUSED 0x04 */ -#define CLRSPIORDY 0x02 -/* UNUSED 0x01 */ - -/* - * SCSI Status 0 (p. 3-21) - * Contains one set of SCSI Interrupt codes - * These are most likely of interest to the sequencer - */ -#define SSTAT0 0x00b -#define TARGET 0x80 /* Board acting as target */ -#define SELDO 0x40 /* Selection Done */ -#define SELDI 0x20 /* Board has been selected */ -#define SELINGO 0x10 /* Selection In Progress */ -#define SWRAP 0x08 /* 24bit counter wrap */ -#define SDONE 0x04 /* STCNT = 0x000000 */ -#define SPIORDY 0x02 /* SCSI PIO Ready */ -#define DMADONE 0x01 /* DMA transfer completed */ - -/* - * Clear SCSI Interrupt 1 (p. 3-23) - * Writing a 1 to a bit clears the associated SCSI Interrupt in SSTAT1. - */ -#define CLRSINT1 0x00c -#define CLRSELTIMEO 0x80 -#define CLRATNO 0x40 -#define CLRSCSIRSTI 0x20 -/* UNUSED 0x10 */ -#define CLRBUSFREE 0x08 -#define CLRSCSIPERR 0x04 -#define CLRPHASECHG 0x02 -#define CLRREQINIT 0x01 - -/* - * SCSI Status 1 (p. 3-24) - */ -#define SSTAT1 0x00c -#define SELTO 0x80 -#define ATNTARG 0x40 -#define SCSIRSTI 0x20 -#define PHASEMIS 0x10 -#define BUSFREE 0x08 -#define SCSIPERR 0x04 -#define PHASECHG 0x02 -#define REQINIT 0x01 - -/* - * SCSI Interrupt Mode 1 (pp. 3-28,29) - * Setting any bit will enable the corresponding function - * in SIMODE1 to interrupt via the IRQ pin. - */ -#define SIMODE1 0x011 -#define ENSELTIMO 0x80 -#define ENATNTARG 0x40 -#define ENSCSIRST 0x20 -#define ENPHASEMIS 0x10 -#define ENBUSFREE 0x08 -#define ENSCSIPERR 0x04 -#define ENPHASECHG 0x02 -#define ENREQINIT 0x01 - -/* - * SCSI Data Bus (High) (p. 3-29) - * This register reads data on the SCSI Data bus directly. - */ -#define SCSIBUSL 0x012 -#define SCSIBUSH 0x013 - -/* - * SCSI/Host Address (p. 3-30) - * These registers hold the host address for the byte about to be - * transfered on the SCSI bus. They are counted up in the same - * manner as STCNT is counted down. SHADDR should always be used - * to determine the address of the last byte transfered since HADDR - * can be squewed by write ahead. - */ -#define SHADDR 0x014 -#define SHADDR0 0x014 -#define SHADDR1 0x015 -#define SHADDR2 0x016 -#define SHADDR3 0x017 - -/* - * Selection/Reselection ID (p. 3-31) - * Upper four bits are the device id. The ONEBIT is set when the re/selecting - * device did not set its own ID. - */ -#define SELID 0x019 -#define SELID_MASK 0xf0 -#define ONEBIT 0x08 -/* UNUSED 0x07 */ - -/* - * SCSI Block Control (p. 3-32) - * Controls Bus type and channel selection. In a twin channel configuration - * addresses 0x00-0x1e are gated to the appropriate channel based on this - * register. SELWIDE allows for the coexistence of 8bit and 16bit devices - * on a wide bus. - */ -#define SBLKCTL 0x01f -#define DIAGLEDEN 0x80 /* Aic78X0 only */ -#define DIAGLEDON 0x40 /* Aic78X0 only */ -#define AUTOFLUSHDIS 0x20 -/* UNUSED 0x10 */ -#define SELBUS_MASK 0x0a -#define SELBUSB 0x08 -/* UNUSED 0x04 */ -#define SELWIDE 0x02 -/* UNUSED 0x01 */ -#define SELNARROW 0x00 - -/* - * Sequencer Control (p. 3-33) - * Error detection mode and speed configuration - */ -#define SEQCTL 0x060 -#define PERRORDIS 0x80 -#define PAUSEDIS 0x40 -#define FAILDIS 0x20 -#define FASTMODE 0x10 -#define BRKADRINTEN 0x08 -#define STEP 0x04 -#define SEQRESET 0x02 -#define LOADRAM 0x01 - -/* - * Sequencer RAM Data (p. 3-34) - * Single byte window into the Scratch Ram area starting at the address - * specified by SEQADDR0 and SEQADDR1. To write a full word, simply write - * four bytes in sucessesion. The SEQADDRs will increment after the most - * significant byte is written - */ -#define SEQRAM 0x061 - -/* - * Sequencer Address Registers (p. 3-35) - * Only the first bit of SEQADDR1 holds addressing information - */ -#define SEQADDR0 0x062 -#define SEQADDR1 0x063 -#define SEQADDR1_MASK 0x01 - -/* - * Accumulator - * We cheat by passing arguments in the Accumulator up to the kernel driver - */ -#define ACCUM 0x064 - -#define SINDEX 0x065 -#define DINDEX 0x066 -#define ALLZEROS 0x06a -#define NONE 0x06a -#define SINDIR 0x06c -#define DINDIR 0x06d -#define FUNCTION1 0x06e - -/* - * Host Address (p. 3-48) - * This register contains the address of the byte about - * to be transfered across the host bus. - */ -#define HADDR 0x088 -#define HADDR0 0x088 -#define HADDR1 0x089 -#define HADDR2 0x08a -#define HADDR3 0x08b - -#define HCNT 0x08c -#define HCNT0 0x08c -#define HCNT1 0x08d -#define HCNT2 0x08e - -/* - * SCB Pointer (p. 3-49) - * Gate one of the four SCBs into the SCBARRAY window. - */ -#define SCBPTR 0x090 - -/* - * Board Control (p. 3-43) - */ -#define BCTL 0x084 -/* RSVD 0xf0 */ -#define ACE 0x08 /* Support for external processors */ -/* RSVD 0x06 */ -#define ENABLE 0x01 - -/* - * On the aic78X0 chips, Board Control is replaced by the DSCommand - * register (p. 4-64) - */ -#define DSCOMMAND 0x084 -#define CACHETHEN 0x80 /* Cache Threshold enable */ -#define DPARCKEN 0x40 /* Data Parity Check Enable */ -#define MPARCKEN 0x20 /* Memory Parity Check Enable */ -#define EXTREQLCK 0x10 /* External Request Lock */ - -/* - * Bus On/Off Time (p. 3-44) - */ -#define BUSTIME 0x085 -#define BOFF 0xf0 -#define BON 0x0f -#define BOFF_60BCLKS 0xf0 - -/* - * Bus Speed (p. 3-45) - */ -#define BUSSPD 0x086 -#define DFTHRSH 0xc0 -#define STBOFF 0x38 -#define STBON 0x07 -#define DFTHRSH_100 0xc0 - -/* - * Host Control (p. 3-47) R/W - * Overal host control of the device. - */ -#define HCNTRL 0x087 -/* UNUSED 0x80 */ -#define POWRDN 0x40 -/* UNUSED 0x20 */ -#define SWINT 0x10 -#define IRQMS 0x08 -#define PAUSE 0x04 -#define INTEN 0x02 -#define CHIPRST 0x01 - -/* - * Interrupt Status (p. 3-50) - * Status for system interrupts - */ -#define INTSTAT 0x091 -#define SEQINT_MASK 0xf1 /* SEQINT Status Codes */ -#define BAD_PHASE 0x01 /* unknown scsi bus phase */ -#define SEND_REJECT 0x11 /* sending a message reject */ -#define NO_IDENT 0x21 /* no IDENTIFY after reconnect*/ -#define NO_MATCH 0x31 /* no cmd match for reconnect */ -#define SDTR_MSG 0x41 /* SDTR message recieved */ -#define WDTR_MSG 0x51 /* WDTR message recieved */ -#define REJECT_MSG 0x61 /* Reject message recieved */ -#define BAD_STATUS 0x71 /* Bad status from target */ -#define RESIDUAL 0x81 /* Residual byte count != 0 */ -#define ABORT_TAG 0x91 /* Sent an ABORT_TAG message */ -#define AWAITING_MSG 0xa1 /* - * Kernel requested to specify - * a message to this target - * (command was null), so tell - * it that it can fill the - * message buffer. - */ -#define IMMEDDONE 0xb1 /* - * An immediate command has - * completed - */ -#define MSG_BUFFER_BUSY 0xc1 /* - * Sequencer wants to use the - * message buffer, but it - * already contains a message - */ -#define MSGIN_PHASEMIS 0xd1 /* - * Target changed phase on us - * when we were expecting - * another msgin byte. - */ -#define PARITY_ERROR 0xe1 /* - * Sequencer detected a parity - * error. - */ -#define BRKADRINT 0x08 -#define SCSIINT 0x04 -#define CMDCMPLT 0x02 -#define SEQINT 0x01 -#define INT_PEND (BRKADRINT | SEQINT | SCSIINT | CMDCMPLT) - -/* - * Hard Error (p. 3-53) - * Reporting of catastrophic errors. You usually cannot recover from - * these without a full board reset. - */ -#define ERROR 0x092 -/* UNUSED 0xf0 */ -#define PARERR 0x08 -#define ILLOPCODE 0x04 -#define ILLSADDR 0x02 -#define ILLHADDR 0x01 - -/* - * Clear Interrupt Status (p. 3-52) - */ -#define CLRINT 0x092 -#define CLRBRKADRINT 0x08 -#define CLRSCSIINT 0x04 -#define CLRCMDINT 0x02 -#define CLRSEQINT 0x01 - -#define DFCNTRL 0x093 -#define WIDEODD 0x40 -#define SCSIEN 0x20 -#define SDMAEN 0x10 -#define SDMAENACK 0x10 -#define HDMAEN 0x08 -#define HDMAENACK 0x08 -#define DIRECTION 0x04 -#define FIFOFLUSH 0x02 -#define FIFORESET 0x01 - -#define DFSTATUS 0x094 -#define HDONE 0x08 -#define FIFOEMP 0x01 - -#define DFDAT 0x099 - -/* - * SCB Auto Increment (p. 3-59) - * Byte offset into the SCB Array and an optional bit to allow auto - * incrementing of the address during download and upload operations - */ -#define SCBCNT 0x09a -#define SCBAUTO 0x80 -#define SCBCNT_MASK 0x1f - -/* - * Queue In FIFO (p. 3-60) - * Input queue for queued SCBs (commands that the seqencer has yet to start) - */ -#define QINFIFO 0x09b - -/* - * Queue In Count (p. 3-60) - * Number of queued SCBs - */ -#define QINCNT 0x09c - -/* - * Queue Out FIFO (p. 3-61) - * Queue of SCBs that have completed and await the host - */ -#define QOUTFIFO 0x09d - -/* - * Queue Out Count (p. 3-61) - * Number of queued SCBs in the Out FIFO - */ -#define QOUTCNT 0x09e - -/* - * SCB Definition (p. 5-4) - * The two reserved bytes at SCBARRAY+1[23] are expected to be set to - * zero. Bit 3 in SCBARRAY+0 is used as an internal flag to indicate - * whether or not to DMA an SCB from host ram. This flag prevents the - * "re-fetching" of transactions that are requed because the target is - * busy with another command. We also use bits 6 & 7 to indicate whether - * or not to initiate SDTR or WDTR repectively when starting this command. - */ -#define SCBARRAY 0x0a0 -#define SCB_CONTROL 0x0a0 -#define NEEDWDTR 0x80 -#define DISCENB 0x40 -#define TAG_ENB 0x20 -#define NEEDSDTR 0x10 -#define DISCONNECTED 0x04 -#define SCB_TAG_TYPE 0x03 -#define SCB_TCL 0x0a1 -#define SCB_TARGET_STATUS 0x0a2 -#define SCB_SGCOUNT 0x0a3 -#define SCB_SGPTR 0x0a4 -#define SCB_SGPTR0 0x0a4 -#define SCB_SGPTR1 0x0a5 -#define SCB_SGPTR2 0x0a6 -#define SCB_SGPTR3 0x0a7 -#define SCB_RESID_SGCNT 0x0a8 -#define SCB_RESID_DCNT 0x0a9 -#define SCB_RESID_DCNT0 0x0a9 -#define SCB_RESID_DCNT1 0x0aa -#define SCB_RESID_DCNT2 0x0ab -#define SCB_DATAPTR 0x0ac -#define SCB_DATAPTR0 0x0ac -#define SCB_DATAPTR1 0x0ad -#define SCB_DATAPTR2 0x0ae -#define SCB_DATAPTR3 0x0af -#define SCB_DATACNT 0x0b0 -#define SCB_DATACNT0 0x0b0 -#define SCB_DATACNT1 0x0b1 -#define SCB_DATACNT2 0x0b2 -/* UNUSED - QUAD PADDING 0x0b3 */ -#define SCB_CMDPTR 0x0b4 -#define SCB_CMDPTR0 0x0b4 -#define SCB_CMDPTR1 0x0b5 -#define SCB_CMDPTR2 0x0b6 -#define SCB_CMDPTR3 0x0b7 -#define SCB_CMDLEN 0x0b8 -#define SCB_NEXT_WAITING 0x0b9 - -#ifdef linux -#define SG_SIZEOF 0x0c /* sizeof(struct scatterlist) */ -#else -#define SG_SIZEOF 0x08 /* sizeof(struct ahc_dma) */ -#endif - -/* --------------------- AHA-2840-only definitions -------------------- */ - -#define SEECTL_2840 0x0c0 -/* UNUSED 0xf8 */ -#define CS_2840 0x04 -#define CK_2840 0x02 -#define DO_2840 0x01 - -#define STATUS_2840 0x0c1 -#define EEPROM_TF 0x80 -#define BIOS_SEL 0x60 -#define ADSEL 0x1e -#define DI_2840 0x01 - -/* --------------------- AIC-7870-only definitions -------------------- */ - -#define DSPCISTATUS 0x086 - -/* - * Serial EEPROM Control (p. 4-92 in 7870 Databook) - * Controls the reading and writing of an external serial 1-bit - * EEPROM Device. In order to access the serial EEPROM, you must - * first set the SEEMS bit that generates a request to the memory - * port for access to the serial EEPROM device. When the memory - * port is not busy servicing another request, it reconfigures - * to allow access to the serial EEPROM. When this happens, SEERDY - * gets set high to verify that the memory port access has been - * granted. - * - * After successful arbitration for the memory port, the SEECS bit of - * the SEECTL register is connected to the chip select. The SEECK, - * SEEDO, and SEEDI are connected to the clock, data out, and data in - * lines respectively. The SEERDY bit of SEECTL is useful in that it - * gives us an 800 nsec timer. After a write to the SEECTL register, - * the SEERDY goes high 800 nsec later. The one exception to this is - * when we first request access to the memory port. The SEERDY goes - * high to signify that access has been granted and, for this case, has - * no implied timing. - * - * See 93cx6.c for detailed information on the protocol necessary to - * read the serial EEPROM. - */ -#define SEECTL 0x01e -#define EXTARBACK 0x80 -#define EXTARBREQ 0x40 -#define SEEMS 0x20 -#define SEERDY 0x10 -#define SEECS 0x08 -#define SEECK 0x04 -#define SEEDO 0x02 -#define SEEDI 0x01 - -/* ---------------------- Scratch RAM Offsets ------------------------- */ -/* These offsets are either to values that are initialized by the board's - * BIOS or are specified by the sequencer code. - * - * The host adapter card (at least the BIOS) uses 20-2f for SCSI - * device information, 32-33 and 5a-5f as well. As it turns out, the - * BIOS trashes 20-2f, writing the synchronous negotiation results - * on top of the BIOS values, so we re-use those for our per-target - * scratchspace (actually a value that can be copied directly into - * SCSIRATE). The kernel driver will enable synchronous negotiation - * for all targets that have a value other than 0 in the lower four - * bits of the target scratch space. This should work regardless of - * whether the bios has been installed. - */ - -/* - * 1 byte per target starting at this address for configuration values - */ -#define TARG_SCRATCH 0x020 - -/* - * The sequencer will stick the frist byte of any rejected message here so - * we can see what is getting thrown away. - */ -#define REJBYTE 0x031 - -/* - * Bit vector of targets that have disconnection disabled. - */ -#define DISC_DSB 0x032 -#define DISC_DSB_A 0x032 -#define DISC_DSB_B 0x033 - -/* - * Length of pending message - */ -#define MSG_LEN 0x034 - -#define MSG0 0x035 -#define COMP_MSG0 0xcb /* 2's complement of MSG0 */ -#define MSG1 0x036 -#define MSG2 0x037 -#define MSG3 0x038 -#define MSG4 0x039 -#define MSG5 0x03a - -/* - * These are offsets into the card's scratch ram. Some of the values are - * specified in the AHA2742 technical reference manual and are initialized - * by the BIOS at boot time. - */ -#define LASTPHASE 0x049 -#define ARG_1 0x04a -#define RETURN_1 0x04a -#define SEND_SENSE 0x80 -#define SEND_WDTR 0x80 -#define SEND_SDTR 0x80 -#define SEND_REJ 0x40 - -#define SIGSTATE 0x04b - -#define DMAPARAMS 0x04c /* Parameters for DMA Logic */ - -#define SG_COUNT 0x04d -#define SG_NEXT 0x04e /* working value of SG pointer */ -#define SG_NEXT0 0x04e -#define SG_NEXT1 0x04f -#define SG_NEXT2 0x050 -#define SG_NEXT3 0x051 - -#define SCBCOUNT 0x052 /* - * Number of SCBs supported by - * this card. - */ -#define FLAGS 0x053 -#define SINGLE_BUS 0x00 -#define TWIN_BUS 0x01 -#define WIDE_BUS 0x02 -#define DPHASE 0x04 -#define MAXOFFSET 0x08 -#define IDENTIFY_SEEN 0x40 -#define RESELECTED 0x80 - -#define ACTIVE_A 0x054 -#define ACTIVE_B 0x055 -#define SAVED_TCL 0x056 /* - * Temporary storage for the - * target/channel/lun of a - * reconnecting target - */ -#define WAITING_SCBH 0x057 /* - * head of list of SCBs awaiting - * selection - */ -#define WAITING_SCBT 0x058 /* - * tail of list of SCBs awaiting - * selection - */ -#define COMP_SCBCOUNT 0x059 -#define SCB_LIST_NULL 0xff - -#define SCSICONF 0x05a -#define HOSTCONF 0x05d - -#define HA_274_BIOSCTRL 0x05f -#define BIOSMODE 0x30 -#define BIOSDISABLED 0x30 - -/* Message codes */ -#define MSG_EXTENDED 0x01 -#define MSG_SDTR 0x01 -#define MSG_WDTR 0x03 -#define MSG_SDPTRS 0x02 -#define MSG_RDPTRS 0x03 -#define MSG_DISCONNECT 0x04 -#define MSG_INITIATOR_DET_ERROR 0x05 -#define MSG_ABORT 0x06 -#define MSG_REJECT 0x07 -#define MSG_NOP 0x08 -#define MSG_MSG_PARITY_ERROR 0x09 -#define MSG_BUS_DEVICE_RESET 0x0c -#define MSG_SIMPLE_TAG 0x20 -#define MSG_IDENTIFY 0x80 - -/* WDTR Message values */ -#define BUS_8_BIT 0x00 -#define BUS_16_BIT 0x01 -#define BUS_32_BIT 0x02 - -#define MAX_OFFSET_8BIT 0x0f -#define MAX_OFFSET_16BIT 0x08 - diff --git a/i386/i386at/gpl/linux/scsi/aic7xxx_seq.h b/i386/i386at/gpl/linux/scsi/aic7xxx_seq.h deleted file mode 100644 index d08f7d81..00000000 --- a/i386/i386at/gpl/linux/scsi/aic7xxx_seq.h +++ /dev/null @@ -1,374 +0,0 @@ -#define AIC7XXX_SEQ_VER "$Id: aic7xxx_seq.h,v 1.1.1.1 1997/02/25 21:27:47 thomas Exp $" - 0x10, 0x6a, 0x00, 0x00, - 0x01, 0x53, 0x05, 0x1e, - 0x08, 0x1f, 0x1f, 0x04, - 0x20, 0x0b, 0x32, 0x1a, - 0x08, 0x1f, 0x1f, 0x04, - 0x20, 0x0b, 0x32, 0x1a, - 0xff, 0x57, 0x12, 0x18, - 0xff, 0x9c, 0x01, 0x1e, - 0xff, 0x9b, 0x90, 0x02, - 0xff, 0xa1, 0x6e, 0x02, - 0xff, 0x6e, 0x64, 0x02, - 0x88, 0xa1, 0x14, 0x1e, - 0x00, 0x55, 0x10, 0x1a, - 0x20, 0xa0, 0x17, 0x1a, - 0x00, 0x55, 0x55, 0x00, - 0x00, 0x65, 0x17, 0x10, - 0xff, 0x90, 0x9b, 0x02, - 0x00, 0x65, 0x01, 0x10, - 0xff, 0x57, 0x90, 0x02, - 0x00, 0x65, 0x19, 0x10, - 0x00, 0x54, 0x10, 0x1a, - 0x20, 0xa0, 0x17, 0x1a, - 0x00, 0x54, 0x54, 0x00, - 0xff, 0x57, 0xb9, 0x02, - 0xff, 0x90, 0x57, 0x02, - 0xf7, 0x1f, 0x65, 0x02, - 0x08, 0xa1, 0x64, 0x02, - 0x00, 0x65, 0x65, 0x00, - 0xff, 0x65, 0x1f, 0x02, - 0x00, 0xa1, 0x1f, 0x17, - 0x58, 0x6a, 0x00, 0x00, - 0xff, 0xb8, 0x22, 0x1a, - 0xa1, 0x6a, 0x91, 0x00, - 0x00, 0x65, 0x30, 0x10, - 0x40, 0xa0, 0x64, 0x02, - 0x07, 0xa1, 0x35, 0x02, - 0x00, 0x35, 0x35, 0x00, - 0x80, 0x35, 0x35, 0x00, - 0x01, 0x6a, 0x34, 0x00, - 0xb0, 0xa0, 0x30, 0x1e, - 0x36, 0x6a, 0x66, 0x00, - 0x20, 0xa0, 0x2e, 0x1e, - 0x23, 0xa0, 0x64, 0x02, - 0xff, 0x64, 0x6d, 0x02, - 0xff, 0x90, 0x6d, 0x02, - 0xcb, 0x66, 0x34, 0x06, - 0x90, 0xa0, 0x30, 0x1e, - 0x00, 0x66, 0x51, 0x17, - 0x40, 0x0b, 0x37, 0x1a, - 0x20, 0x0b, 0x30, 0x1e, - 0xff, 0x6a, 0x34, 0x02, - 0x00, 0x19, 0x1f, 0x17, - 0x03, 0x53, 0x53, 0x02, - 0x80, 0x53, 0x53, 0x00, - 0x00, 0x65, 0x39, 0x10, - 0x03, 0x53, 0x53, 0x02, - 0xff, 0xb9, 0x57, 0x02, - 0x02, 0x01, 0x01, 0x00, - 0x00, 0x65, 0x4d, 0x17, - 0xff, 0x6c, 0x04, 0x02, - 0x02, 0x6a, 0x00, 0x00, - 0x08, 0x6a, 0x0c, 0x00, - 0x60, 0x6a, 0x0b, 0x00, - 0x08, 0x0c, 0x04, 0x1b, - 0x01, 0x0c, 0x3f, 0x1e, - 0x04, 0x0c, 0x44, 0x1e, - 0x04, 0x0c, 0x0c, 0x00, - 0xe1, 0x6a, 0x91, 0x00, - 0xe0, 0x03, 0x64, 0x02, - 0xff, 0x64, 0x49, 0x02, - 0xff, 0x64, 0x03, 0x02, - 0x00, 0x6a, 0x4e, 0x1c, - 0x40, 0x64, 0x54, 0x1c, - 0x80, 0x64, 0x81, 0x1c, - 0xa0, 0x64, 0x90, 0x1c, - 0xc0, 0x64, 0x8e, 0x1c, - 0xe0, 0x64, 0xa4, 0x1c, - 0x01, 0x6a, 0x91, 0x00, - 0x7d, 0x6a, 0x4c, 0x00, - 0x00, 0x65, 0x55, 0x10, - 0xff, 0xa9, 0x08, 0x02, - 0xff, 0xaa, 0x09, 0x02, - 0xff, 0xab, 0x0a, 0x02, - 0x00, 0x65, 0x59, 0x10, - 0x79, 0x6a, 0x4c, 0x00, - 0x00, 0x65, 0x23, 0x17, - 0x04, 0x53, 0x50, 0x1a, - 0x00, 0x65, 0x31, 0x17, - 0x04, 0x53, 0x53, 0x00, - 0x01, 0x4d, 0x5b, 0x18, - 0xbf, 0x4c, 0x4c, 0x02, - 0x00, 0x4c, 0x17, 0x17, - 0x04, 0x0b, 0x7c, 0x1e, - 0xff, 0x4d, 0x4d, 0x06, - 0xff, 0x4d, 0x7c, 0x1e, - 0xff, 0x6a, 0x64, 0x02, - 0x0c, 0x4e, 0x4e, 0x06, - 0x00, 0x4f, 0x4f, 0x08, - 0xff, 0x6a, 0x8e, 0x02, - 0xff, 0x6a, 0x8d, 0x02, - 0x0c, 0x6a, 0x8c, 0x00, - 0xff, 0x4e, 0x88, 0x02, - 0xff, 0x4f, 0x89, 0x02, - 0xff, 0x50, 0x8a, 0x02, - 0xff, 0x51, 0x8b, 0x02, - 0x0d, 0x93, 0x93, 0x00, - 0x08, 0x94, 0x6a, 0x1e, - 0x40, 0x93, 0x93, 0x02, - 0x08, 0x93, 0x6c, 0x1a, - 0xff, 0x99, 0x88, 0x02, - 0xff, 0x99, 0x89, 0x02, - 0xff, 0x99, 0x8a, 0x02, - 0xff, 0x99, 0x8b, 0x02, - 0xff, 0x99, 0x6a, 0x02, - 0xff, 0x99, 0x6a, 0x02, - 0xff, 0x99, 0x6a, 0x02, - 0xff, 0x99, 0x6a, 0x02, - 0xff, 0x99, 0x8c, 0x02, - 0xff, 0x99, 0x8d, 0x02, - 0xff, 0x99, 0x8e, 0x02, - 0xff, 0x8c, 0x08, 0x02, - 0xff, 0x8d, 0x09, 0x02, - 0xff, 0x8e, 0x0a, 0x02, - 0x10, 0x0c, 0x59, 0x1e, - 0xff, 0x08, 0xa9, 0x02, - 0xff, 0x09, 0xaa, 0x02, - 0xff, 0x0a, 0xab, 0x02, - 0xff, 0x4d, 0xa8, 0x02, - 0x00, 0x65, 0x3f, 0x10, - 0x00, 0x65, 0x23, 0x17, - 0xff, 0xb4, 0x88, 0x02, - 0xff, 0xb5, 0x89, 0x02, - 0xff, 0xb6, 0x8a, 0x02, - 0xff, 0xb7, 0x8b, 0x02, - 0xff, 0xb8, 0x8c, 0x02, - 0xff, 0x6a, 0x8d, 0x02, - 0xff, 0x6a, 0x8e, 0x02, - 0xff, 0x8c, 0x08, 0x02, - 0xff, 0x8d, 0x09, 0x02, - 0xff, 0x8e, 0x0a, 0x02, - 0x3d, 0x6a, 0x17, 0x17, - 0x00, 0x65, 0x3f, 0x10, - 0xa2, 0x6a, 0x12, 0x17, - 0x00, 0x65, 0xb0, 0x10, - 0xff, 0x34, 0x92, 0x1a, - 0x08, 0x6a, 0x07, 0x17, - 0x35, 0x6a, 0x65, 0x00, - 0xff, 0x34, 0x66, 0x02, - 0x10, 0x0c, 0xa1, 0x1a, - 0x02, 0x0b, 0x94, 0x1e, - 0x01, 0x66, 0x98, 0x18, - 0x40, 0x6a, 0x0c, 0x00, - 0xff, 0x66, 0x66, 0x06, - 0x02, 0x0b, 0x0b, 0x00, - 0xff, 0x6c, 0x06, 0x02, - 0xff, 0x66, 0x94, 0x1a, - 0x08, 0x0c, 0xa2, 0x1a, - 0x01, 0x0c, 0x9c, 0x1e, - 0x10, 0x0c, 0xa2, 0x1a, - 0x10, 0x03, 0x03, 0x00, - 0x00, 0x65, 0x3f, 0x10, - 0x40, 0x6a, 0x0c, 0x00, - 0xff, 0x6a, 0x34, 0x02, - 0x00, 0x65, 0x3f, 0x10, - 0x64, 0x6a, 0x12, 0x17, - 0xff, 0x64, 0x31, 0x02, - 0x80, 0x64, 0xe4, 0x1a, - 0x04, 0x64, 0xde, 0x1c, - 0x02, 0x64, 0xe0, 0x1c, - 0x00, 0x6a, 0xb2, 0x1c, - 0x03, 0x64, 0xe2, 0x1c, - 0x01, 0x64, 0xc5, 0x1c, - 0x07, 0x64, 0x02, 0x1d, - 0x10, 0x03, 0x03, 0x00, - 0x11, 0x6a, 0x91, 0x00, - 0x07, 0x6a, 0x07, 0x17, - 0x00, 0x65, 0x14, 0x17, - 0x00, 0x65, 0x3f, 0x10, - 0xff, 0xa8, 0xb4, 0x1e, - 0x81, 0x6a, 0x91, 0x00, - 0xff, 0xa2, 0xb8, 0x1e, - 0x71, 0x6a, 0x91, 0x00, - 0x80, 0x4a, 0xb8, 0x18, - 0x00, 0x65, 0xb0, 0x10, - 0x20, 0xa0, 0xbf, 0x1a, - 0xff, 0xa1, 0x6e, 0x02, - 0xff, 0x6e, 0x64, 0x02, - 0x88, 0xa1, 0xbe, 0x1e, - 0x00, 0x55, 0x55, 0x04, - 0x00, 0x65, 0xbf, 0x10, - 0x00, 0x54, 0x54, 0x04, - 0xff, 0xb8, 0xc2, 0x1a, - 0xb1, 0x6a, 0x91, 0x00, - 0x00, 0x65, 0x00, 0x10, - 0xff, 0x90, 0x9d, 0x02, - 0x02, 0x6a, 0x91, 0x00, - 0x00, 0x65, 0xb0, 0x10, - 0x4a, 0x6a, 0x0e, 0x17, - 0x64, 0x6a, 0x0e, 0x17, - 0x01, 0x64, 0xd4, 0x1c, - 0x03, 0x64, 0xca, 0x1c, - 0x00, 0x65, 0xad, 0x10, - 0x02, 0x4a, 0xad, 0x18, - 0x4a, 0x6a, 0x0e, 0x17, - 0x51, 0x6a, 0x91, 0x00, - 0xff, 0x4a, 0xb0, 0x1e, - 0x40, 0x4a, 0xad, 0x1c, - 0x7f, 0x4a, 0x4a, 0x02, - 0x35, 0x6a, 0x66, 0x00, - 0x35, 0x6a, 0x62, 0x17, - 0x10, 0x03, 0x03, 0x00, - 0x00, 0x65, 0xb0, 0x10, - 0x03, 0x4a, 0xad, 0x18, - 0x4a, 0x6a, 0x0e, 0x17, - 0x64, 0x6a, 0x0e, 0x17, - 0x41, 0x6a, 0x91, 0x00, - 0xff, 0x4a, 0xb0, 0x1e, - 0x40, 0x4a, 0xad, 0x1c, - 0x35, 0x6a, 0x66, 0x00, - 0x35, 0x6a, 0x53, 0x17, - 0x10, 0x03, 0x03, 0x00, - 0x00, 0x65, 0xb0, 0x10, - 0x04, 0xa0, 0xa0, 0x00, - 0x00, 0x65, 0xb0, 0x10, - 0x00, 0x65, 0x40, 0x17, - 0x00, 0x65, 0xb0, 0x10, - 0xfb, 0x53, 0x53, 0x02, - 0x00, 0x65, 0xb0, 0x10, - 0x78, 0x64, 0xad, 0x1a, - 0x07, 0x64, 0x64, 0x02, - 0x00, 0x19, 0x56, 0x00, - 0xf7, 0x56, 0x56, 0x02, - 0x08, 0x1f, 0x64, 0x02, - 0x00, 0x56, 0x56, 0x00, - 0x00, 0x65, 0x14, 0x17, - 0x08, 0x0c, 0xf0, 0x1a, - 0x01, 0x0c, 0xeb, 0x1e, - 0x10, 0x0c, 0xf0, 0x1a, - 0x64, 0x6a, 0x12, 0x17, - 0x20, 0x64, 0xf4, 0x1c, - 0x00, 0x6a, 0x26, 0x17, - 0xfb, 0xa0, 0xa0, 0x02, - 0x40, 0x53, 0x53, 0x00, - 0x00, 0x65, 0x3f, 0x10, - 0x4a, 0x6a, 0x0e, 0x17, - 0xff, 0x59, 0x64, 0x02, - 0x00, 0x4a, 0x65, 0x06, - 0x00, 0x65, 0xfe, 0x12, - 0xff, 0x4a, 0x90, 0x02, - 0xff, 0x56, 0x64, 0x02, - 0x00, 0xa1, 0xfe, 0x18, - 0x20, 0xa0, 0xfe, 0x1e, - 0x00, 0x65, 0x14, 0x17, - 0x00, 0x65, 0xf1, 0x10, - 0x10, 0x03, 0x03, 0x00, - 0x91, 0x6a, 0x91, 0x00, - 0x0d, 0x6a, 0x07, 0x17, - 0x00, 0x65, 0xb0, 0x10, - 0x61, 0x6a, 0x91, 0x00, - 0x00, 0x65, 0xb0, 0x10, - 0x40, 0x6a, 0x0c, 0x00, - 0xff, 0xb8, 0xb8, 0x1e, - 0x00, 0x65, 0x00, 0x10, - 0x50, 0x6a, 0x60, 0x00, - 0xff, 0x34, 0x0b, 0x1f, - 0x10, 0x6a, 0x60, 0x00, - 0xc1, 0x6a, 0x91, 0x00, - 0x01, 0x6a, 0x34, 0x00, - 0xff, 0x65, 0x35, 0x02, - 0x10, 0x6a, 0x60, 0x01, - 0x02, 0x0b, 0x0b, 0x00, - 0xff, 0x06, 0x6a, 0x02, - 0x10, 0x0c, 0x15, 0x1b, - 0x02, 0x0b, 0x10, 0x1f, - 0xff, 0x65, 0x66, 0x02, - 0xff, 0x12, 0x6d, 0x03, - 0xff, 0x06, 0x6a, 0x03, - 0xd1, 0x6a, 0x91, 0x00, - 0x00, 0x65, 0x3f, 0x10, - 0xff, 0x65, 0x93, 0x02, - 0x01, 0x0b, 0x1a, 0x1b, - 0x10, 0x0c, 0x18, 0x1f, - 0x04, 0x65, 0x1c, 0x1b, - 0x01, 0x94, 0x1b, 0x1f, - 0x40, 0x93, 0x93, 0x02, - 0x38, 0x93, 0x1d, 0x1b, - 0xff, 0x6a, 0x6a, 0x03, - 0xf0, 0x65, 0x65, 0x02, - 0x0f, 0x05, 0x64, 0x02, - 0x00, 0x65, 0x65, 0x00, - 0xff, 0x65, 0x05, 0x03, - 0x80, 0x53, 0x74, 0x1f, - 0x40, 0x53, 0x74, 0x1b, - 0x21, 0x6a, 0x91, 0x01, - 0xff, 0x56, 0x64, 0x02, - 0xff, 0x65, 0x90, 0x02, - 0x00, 0xa1, 0x2b, 0x19, - 0x04, 0xa0, 0x2b, 0x1f, - 0xff, 0x6a, 0x6a, 0x03, - 0x01, 0x65, 0x65, 0x06, - 0xff, 0x52, 0x64, 0x02, - 0x00, 0x65, 0x26, 0x19, - 0x31, 0x6a, 0x91, 0x00, - 0x06, 0x6a, 0x07, 0x17, - 0x10, 0x03, 0x03, 0x01, - 0xff, 0xac, 0x88, 0x02, - 0xff, 0xad, 0x89, 0x02, - 0xff, 0xae, 0x8a, 0x02, - 0xff, 0xaf, 0x8b, 0x02, - 0xff, 0xb0, 0x8c, 0x02, - 0xff, 0xb1, 0x8d, 0x02, - 0xff, 0xb2, 0x8e, 0x02, - 0xff, 0x8c, 0x08, 0x02, - 0xff, 0x8d, 0x09, 0x02, - 0xff, 0x8e, 0x0a, 0x02, - 0xff, 0xa3, 0x4d, 0x02, - 0xff, 0xa4, 0x4e, 0x02, - 0xff, 0xa5, 0x4f, 0x02, - 0xff, 0xa6, 0x50, 0x02, - 0xff, 0xa7, 0x51, 0x03, - 0x04, 0x53, 0x74, 0x1f, - 0xff, 0x4d, 0xa3, 0x02, - 0xff, 0x4e, 0xa4, 0x02, - 0xff, 0x4f, 0xa5, 0x02, - 0xff, 0x50, 0xa6, 0x02, - 0xff, 0x51, 0xa7, 0x02, - 0xff, 0x14, 0xac, 0x02, - 0xff, 0x15, 0xad, 0x02, - 0xff, 0x16, 0xae, 0x02, - 0xff, 0x17, 0xaf, 0x02, - 0xff, 0xa9, 0xb0, 0x02, - 0xff, 0xaa, 0xb1, 0x02, - 0xff, 0xab, 0xb2, 0x03, - 0x4c, 0x05, 0x64, 0x0a, - 0x08, 0x1f, 0x50, 0x1f, - 0x08, 0x64, 0x64, 0x00, - 0x20, 0x64, 0x65, 0x07, - 0x80, 0xa0, 0x61, 0x1b, - 0x08, 0x53, 0x53, 0x00, - 0x01, 0x6a, 0x6d, 0x00, - 0x03, 0x6a, 0x6d, 0x00, - 0x01, 0x6a, 0x6d, 0x00, - 0x00, 0x65, 0x67, 0x17, - 0xff, 0x4a, 0x6d, 0x02, - 0x08, 0x53, 0x5b, 0x1b, - 0x0f, 0x6c, 0x6d, 0x02, - 0xcb, 0x66, 0x34, 0x07, - 0x08, 0x53, 0x53, 0x04, - 0x80, 0x04, 0x5f, 0x1b, - 0x0f, 0x6a, 0x6d, 0x00, - 0x00, 0x65, 0x5a, 0x11, - 0x08, 0x6a, 0x6d, 0x00, - 0x00, 0x65, 0x5a, 0x11, - 0x01, 0x6a, 0x4a, 0x00, - 0x01, 0x6a, 0x6d, 0x00, - 0x02, 0x6a, 0x6d, 0x00, - 0x03, 0x6a, 0x6d, 0x00, - 0xff, 0x4a, 0x6d, 0x02, - 0xcb, 0x66, 0x34, 0x07, - 0x00, 0x65, 0x4d, 0x17, - 0x4c, 0x6c, 0x64, 0x0a, - 0xff, 0x65, 0x65, 0x06, - 0x07, 0x64, 0x64, 0x02, - 0xff, 0x6a, 0x4a, 0x02, - 0x0f, 0x64, 0x70, 0x1f, - 0x19, 0x4a, 0x4a, 0x06, - 0xff, 0x64, 0x64, 0x06, - 0x00, 0x65, 0x6c, 0x11, - 0x2e, 0x4a, 0x4a, 0x0a, - 0x19, 0x4a, 0x4a, 0x06, - 0x20, 0x01, 0x74, 0x1f, - 0x1f, 0x4a, 0x4a, 0x0a, - 0xff, 0x6a, 0x6a, 0x03, diff --git a/i386/i386at/gpl/linux/scsi/constants.c b/i386/i386at/gpl/linux/scsi/constants.c deleted file mode 100644 index 07f071b2..00000000 --- a/i386/i386at/gpl/linux/scsi/constants.c +++ /dev/null @@ -1,649 +0,0 @@ -/* - * ASCII values for a number of symbolic constants, printing functions, - * etc. - */ - -/* - * Don't import our own symbols, as this would severely mess up our - * symbol tables. - */ -#define _SCSI_SYMS_VER_ -#define __NO_VERSION__ -#include <linux/module.h> - -#include <linux/config.h> -#include <linux/blk.h> -#include <linux/kernel.h> -#include "scsi.h" -#include "hosts.h" - -#define CONST_COMMAND 0x01 -#define CONST_STATUS 0x02 -#define CONST_SENSE 0x04 -#define CONST_XSENSE 0x08 -#define CONST_CMND 0x10 -#define CONST_MSG 0x20 -#define CONST_HOST 0x40 -#define CONST_DRIVER 0x80 - -static const char unknown[] = "UNKNOWN"; - -#ifdef CONFIG_SCSI_CONSTANTS -#ifdef CONSTANTS -#undef CONSTANTS -#endif -#define CONSTANTS (CONST_COMMAND | CONST_STATUS | CONST_SENSE | CONST_XSENSE \ - | CONST_CMND | CONST_MSG | CONST_HOST | CONST_DRIVER) -#endif - -#if (CONSTANTS & CONST_COMMAND) -static const char * group_0_commands[] = { -/* 00-03 */ "Test Unit Ready", "Rezero Unit", unknown, "Request Sense", -/* 04-07 */ "Format Unit", "Read Block Limits", unknown, "Reasssign Blocks", -/* 08-0d */ "Read (6)", unknown, "Write (6)", "Seek (6)", unknown, unknown, -/* 0e-12 */ unknown, "Read Reverse", "Write Filemarks", "Space", "Inquiry", -/* 13-16 */ unknown, "Recover Buffered Data", "Mode Select", "Reserve", -/* 17-1b */ "Release", "Copy", "Erase", "Mode Sense", "Start/Stop Unit", -/* 1c-1d */ "Receive Diagnostic", "Send Diagnostic", -/* 1e-1f */ "Prevent/Allow Medium Removal", unknown, -}; - - -static const char *group_1_commands[] = { -/* 20-22 */ unknown, unknown, unknown, -/* 23-28 */ unknown, unknown, "Read Capacity", unknown, unknown, "Read (10)", -/* 29-2d */ unknown, "Write (10)", "Seek (10)", unknown, unknown, -/* 2e-31 */ "Write Verify","Verify", "Search High", "Search Equal", -/* 32-34 */ "Search Low", "Set Limits", "Prefetch or Read Position", -/* 35-37 */ "Synchronize Cache","Lock/Unlock Cache", "Read Defect Data", -/* 38-3c */ "Medium Scan", "Compare","Copy Verify", "Write Buffer", "Read Buffer", -/* 3d-3f */ "Update Block", "Read Long", "Write Long", -}; - - -static const char *group_2_commands[] = { -/* 40-41 */ "Change Definition", "Write Same", -/* 42-48 */ unknown, unknown, unknown, unknown, unknown, unknown, unknown, -/* 49-4f */ unknown, unknown, unknown, "Log Select", "Log Sense", unknown, unknown, -/* 50-55 */ unknown, unknown, unknown, unknown, unknown, "Mode Select (10)", -/* 56-5b */ unknown, unknown, unknown, unknown, "Mode Sense (10)", unknown, -/* 5c-5f */ unknown, unknown, unknown, -}; - - - -#define group(opcode) (((opcode) >> 5) & 7) - -#define RESERVED_GROUP 0 -#define VENDOR_GROUP 1 -#define NOTEXT_GROUP 2 - -static const char **commands[] = { - group_0_commands, group_1_commands, group_2_commands, - (const char **) RESERVED_GROUP, (const char **) RESERVED_GROUP, - (const char **) NOTEXT_GROUP, (const char **) VENDOR_GROUP, - (const char **) VENDOR_GROUP -}; - -static const char reserved[] = "RESERVED"; -static const char vendor[] = "VENDOR SPECIFIC"; - -static void print_opcode(int opcode) { - const char **table = commands[ group(opcode) ]; - switch ((unsigned long) table) { - case RESERVED_GROUP: - printk("%s(0x%02x) ", reserved, opcode); - break; - case NOTEXT_GROUP: - printk("%s(0x%02x) ", unknown, opcode); - break; - case VENDOR_GROUP: - printk("%s(0x%02x) ", vendor, opcode); - break; - default: - printk("%s ",table[opcode & 0x1f]); - } -} -#else /* CONST & CONST_COMMAND */ -static void print_opcode(int opcode) { - printk("0x%02x ", opcode); -} -#endif - -void print_command (unsigned char *command) { - int i,s; - print_opcode(command[0]); - for ( i = 1, s = COMMAND_SIZE(command[0]); i < s; ++i) - printk("%02x ", command[i]); - printk("\n"); -} - -#if (CONSTANTS & CONST_STATUS) -static const char * statuses[] = { -/* 0-4 */ "Good", "Check Condition", "Condition Good", unknown, "Busy", -/* 5-9 */ unknown, unknown, unknown, "Intermediate Good", unknown, -/* a-d */ "Intermediate Good", unknown, "Reservation Conflict", unknown, -/* e-f */ unknown, unknown, -}; -#endif - -void print_status (int status) { - status = (status >> 1) & 0xf; -#if (CONSTANTS & CONST_STATUS) - printk("%s ",statuses[status]); -#else - printk("0x%0x ", status); -#endif -} - -#if (CONSTANTS & CONST_XSENSE) -#define D 0x001 /* DIRECT ACCESS DEVICE (disk) */ -#define T 0x002 /* SEQUENTIAL ACCESS DEVICE (tape) */ -#define L 0x004 /* PRINTER DEVICE */ -#define P 0x008 /* PROCESSOR DEVICE */ -#define W 0x010 /* WRITE ONCE READ MULTIPLE DEVICE */ -#define R 0x020 /* READ ONLY (CD-ROM) DEVICE */ -#define S 0x040 /* SCANNER DEVICE */ -#define O 0x080 /* OPTICAL MEMORY DEVICE */ -#define M 0x100 /* MEDIA CHANGER DEVICE */ -#define C 0x200 /* COMMUNICATION DEVICE */ - -struct error_info{ - unsigned char code1, code2; - unsigned short int devices; - const char * text; -}; - -struct error_info2{ - unsigned char code1, code2_min, code2_max; - unsigned short int devices; - const char * text; -}; - -static struct error_info2 additional2[] = -{ - {0x40,0x00,0x7f,D,"Ram failure (%x)"}, - {0x40,0x80,0xff,D|T|L|P|W|R|S|O|M|C,"Diagnostic failure on component (%x)"}, - {0x41,0x00,0xff,D,"Data path failure (%x)"}, - {0x42,0x00,0xff,D,"Power-on or self-test failure (%x)"}, - {0, 0, 0, 0, NULL} -}; - -static struct error_info additional[] = -{ - {0x00,0x01,T,"Filemark detected"}, - {0x00,0x02,T|S,"End-of-partition/medium detected"}, - {0x00,0x03,T,"Setmark detected"}, - {0x00,0x04,T|S,"Beginning-of-partition/medium detected"}, - {0x00,0x05,T|S,"End-of-data detected"}, - {0x00,0x06,D|T|L|P|W|R|S|O|M|C,"I/O process terminated"}, - {0x00,0x11,R,"Audio play operation in progress"}, - {0x00,0x12,R,"Audio play operation paused"}, - {0x00,0x13,R,"Audio play operation successfully completed"}, - {0x00,0x14,R,"Audio play operation stopped due to error"}, - {0x00,0x15,R,"No current audio status to return"}, - {0x01,0x00,D|W|O,"No index/sector signal"}, - {0x02,0x00,D|W|R|O|M,"No seek complete"}, - {0x03,0x00,D|T|L|W|S|O,"Peripheral device write fault"}, - {0x03,0x01,T,"No write current"}, - {0x03,0x02,T,"Excessive write errors"}, - {0x04,0x00,D|T|L|P|W|R|S|O|M|C, - "Logical unit not ready, cause not reportable"}, - {0x04,0x01,D|T|L|P|W|R|S|O|M|C, - "Logical unit is in process of becoming ready"}, - {0x04,0x02,D|T|L|P|W|R|S|O|M|C, - "Logical unit not ready, initializing command required"}, - {0x04,0x03,D|T|L|P|W|R|S|O|M|C, - "Logical unit not ready, manual intervention required"}, - {0x04,0x04,D|T|L|O,"Logical unit not ready, format in progress"}, - {0x05,0x00,D|T|L|W|R|S|O|M|C,"Logical unit does not respond to selection"}, - {0x06,0x00,D|W|R|O|M,"No reference position found"}, - {0x07,0x00,D|T|L|W|R|S|O|M,"Multiple peripheral devices selected"}, - {0x08,0x00,D|T|L|W|R|S|O|M|C,"Logical unit communication failure"}, - {0x08,0x01,D|T|L|W|R|S|O|M|C,"Logical unit communication time-out"}, - {0x08,0x02,D|T|L|W|R|S|O|M|C,"Logical unit communication parity error"}, - {0x09,0x00,D|T|W|R|O,"Track following error"}, - {0x09,0x01,W|R|O,"Tracking servo failure"}, - {0x09,0x02,W|R|O,"Focus servo failure"}, - {0x09,0x03,W|R|O,"Spindle servo failure"}, - {0x0A,0x00,D|T|L|P|W|R|S|O|M|C,"Error log overflow"}, - {0x0C,0x00,T|S,"Write error"}, - {0x0C,0x01,D|W|O,"Write error recovered with auto reallocation"}, - {0x0C,0x02,D|W|O,"Write error - auto reallocation failed"}, - {0x10,0x00,D|W|O,"Id crc or ecc error"}, - {0x11,0x00,D|T|W|R|S|O,"Unrecovered read error"}, - {0x11,0x01,D|T|W|S|O,"Read retries exhausted"}, - {0x11,0x02,D|T|W|S|O,"Error too long to correct"}, - {0x11,0x03,D|T|W|S|O,"Multiple read errors"}, - {0x11,0x04,D|W|O,"Unrecovered read error - auto reallocate failed"}, - {0x11,0x05,W|R|O,"L-ec uncorrectable error"}, - {0x11,0x06,W|R|O,"Circ unrecovered error"}, - {0x11,0x07,W|O,"Data resynchronization error"}, - {0x11,0x08,T,"Incomplete block read"}, - {0x11,0x09,T,"No gap found"}, - {0x11,0x0A,D|T|O,"Miscorrected error"}, - {0x11,0x0B,D|W|O,"Unrecovered read error - recommend reassignment"}, - {0x11,0x0C,D|W|O,"Unrecovered read error - recommend rewrite the data"}, - {0x12,0x00,D|W|O,"Address mark not found for id field"}, - {0x13,0x00,D|W|O,"Address mark not found for data field"}, - {0x14,0x00,D|T|L|W|R|S|O,"Recorded entity not found"}, - {0x14,0x01,D|T|W|R|O,"Record not found"}, - {0x14,0x02,T,"Filemark or setmark not found"}, - {0x14,0x03,T,"End-of-data not found"}, - {0x14,0x04,T,"Block sequence error"}, - {0x15,0x00,D|T|L|W|R|S|O|M,"Random positioning error"}, - {0x15,0x01,D|T|L|W|R|S|O|M,"Mechanical positioning error"}, - {0x15,0x02,D|T|W|R|O,"Positioning error detected by read of medium"}, - {0x16,0x00,D|W|O,"Data synchronization mark error"}, - {0x17,0x00,D|T|W|R|S|O,"Recovered data with no error correction applied"}, - {0x17,0x01,D|T|W|R|S|O,"Recovered data with retries"}, - {0x17,0x02,D|T|W|R|O,"Recovered data with positive head offset"}, - {0x17,0x03,D|T|W|R|O,"Recovered data with negative head offset"}, - {0x17,0x04,W|R|O,"Recovered data with retries and/or circ applied"}, - {0x17,0x05,D|W|R|O,"Recovered data using previous sector id"}, - {0x17,0x06,D|W|O,"Recovered data without ecc - data auto-reallocated"}, - {0x17,0x07,D|W|O,"Recovered data without ecc - recommend reassignment"}, - {0x18,0x00,D|T|W|R|O,"Recovered data with error correction applied"}, - {0x18,0x01,D|W|R|O,"Recovered data with error correction and retries applied"}, - {0x18,0x02,D|W|R|O,"Recovered data - data auto-reallocated"}, - {0x18,0x03,R,"Recovered data with circ"}, - {0x18,0x04,R,"Recovered data with lec"}, - {0x18,0x05,D|W|R|O,"Recovered data - recommend reassignment"}, - {0x19,0x00,D|O,"Defect list error"}, - {0x19,0x01,D|O,"Defect list not available"}, - {0x19,0x02,D|O,"Defect list error in primary list"}, - {0x19,0x03,D|O,"Defect list error in grown list"}, - {0x1A,0x00,D|T|L|P|W|R|S|O|M|C,"Parameter list length error"}, - {0x1B,0x00,D|T|L|P|W|R|S|O|M|C,"Synchronous data transfer error"}, - {0x1C,0x00,D|O,"Defect list not found"}, - {0x1C,0x01,D|O,"Primary defect list not found"}, - {0x1C,0x02,D|O,"Grown defect list not found"}, - {0x1D,0x00,D|W|O,"Miscompare during verify operation"}, - {0x1E,0x00,D|W|O,"Recovered id with ecc correction"}, - {0x20,0x00,D|T|L|P|W|R|S|O|M|C,"Invalid command operation code"}, - {0x21,0x00,D|T|W|R|O|M,"Logical block address out of range"}, - {0x21,0x01,M,"Invalid element address"}, - {0x22,0x00,D,"Illegal function (should use 20 00, 24 00, or 26 00)"}, - {0x24,0x00,D|T|L|P|W|R|S|O|M|C,"Invalid field in cdb"}, - {0x25,0x00,D|T|L|P|W|R|S|O|M|C,"Logical unit not supported"}, - {0x26,0x00,D|T|L|P|W|R|S|O|M|C,"Invalid field in parameter list"}, - {0x26,0x01,D|T|L|P|W|R|S|O|M|C,"Parameter not supported"}, - {0x26,0x02,D|T|L|P|W|R|S|O|M|C,"Parameter value invalid"}, - {0x26,0x03,D|T|L|P|W|R|S|O|M|C,"Threshold parameters not supported"}, - {0x27,0x00,D|T|W|O,"Write protected"}, - {0x28,0x00,D|T|L|P|W|R|S|O|M|C,"Not ready to ready transition (medium may have changed)"}, - {0x28,0x01,M,"Import or export element accessed"}, - {0x29,0x00,D|T|L|P|W|R|S|O|M|C,"Power on, reset, or bus device reset occurred"}, - {0x2A,0x00,D|T|L|W|R|S|O|M|C,"Parameters changed"}, - {0x2A,0x01,D|T|L|W|R|S|O|M|C,"Mode parameters changed"}, - {0x2A,0x02,D|T|L|W|R|S|O|M|C,"Log parameters changed"}, - {0x2B,0x00,D|T|L|P|W|R|S|O|C,"Copy cannot execute since host cannot disconnect"}, - {0x2C,0x00,D|T|L|P|W|R|S|O|M|C,"Command sequence error"}, - {0x2C,0x01,S,"Too many windows specified"}, - {0x2C,0x02,S,"Invalid combination of windows specified"}, - {0x2D,0x00,T,"Overwrite error on update in place"}, - {0x2F,0x00,D|T|L|P|W|R|S|O|M|C,"Commands cleared by another initiator"}, - {0x30,0x00,D|T|W|R|O|M,"Incompatible medium installed"}, - {0x30,0x01,D|T|W|R|O,"Cannot read medium - unknown format"}, - {0x30,0x02,D|T|W|R|O,"Cannot read medium - incompatible format"}, - {0x30,0x03,D|T,"Cleaning cartridge installed"}, - {0x31,0x00,D|T|W|O,"Medium format corrupted"}, - {0x31,0x01,D|L|O,"Format command failed"}, - {0x32,0x00,D|W|O,"No defect spare location available"}, - {0x32,0x01,D|W|O,"Defect list update failure"}, - {0x33,0x00,T,"Tape length error"}, - {0x36,0x00,L,"Ribbon, ink, or toner failure"}, - {0x37,0x00,D|T|L|W|R|S|O|M|C,"Rounded parameter"}, - {0x39,0x00,D|T|L|W|R|S|O|M|C,"Saving parameters not supported"}, - {0x3A,0x00,D|T|L|W|R|S|O|M,"Medium not present"}, - {0x3B,0x00,T|L,"Sequential positioning error"}, - {0x3B,0x01,T,"Tape position error at beginning-of-medium"}, - {0x3B,0x02,T,"Tape position error at end-of-medium"}, - {0x3B,0x03,L,"Tape or electronic vertical forms unit not ready"}, - {0x3B,0x04,L,"Slew failure"}, - {0x3B,0x05,L,"Paper jam"}, - {0x3B,0x06,L,"Failed to sense top-of-form"}, - {0x3B,0x07,L,"Failed to sense bottom-of-form"}, - {0x3B,0x08,T,"Reposition error"}, - {0x3B,0x09,S,"Read past end of medium"}, - {0x3B,0x0A,S,"Read past beginning of medium"}, - {0x3B,0x0B,S,"Position past end of medium"}, - {0x3B,0x0C,S,"Position past beginning of medium"}, - {0x3B,0x0D,M,"Medium destination element full"}, - {0x3B,0x0E,M,"Medium source element empty"}, - {0x3D,0x00,D|T|L|P|W|R|S|O|M|C,"Invalid bits in identify message"}, - {0x3E,0x00,D|T|L|P|W|R|S|O|M|C,"Logical unit has not self-configured yet"}, - {0x3F,0x00,D|T|L|P|W|R|S|O|M|C,"Target operating conditions have changed"}, - {0x3F,0x01,D|T|L|P|W|R|S|O|M|C,"Microcode has been changed"}, - {0x3F,0x02,D|T|L|P|W|R|S|O|M|C,"Changed operating definition"}, - {0x3F,0x03,D|T|L|P|W|R|S|O|M|C,"Inquiry data has changed"}, - {0x43,0x00,D|T|L|P|W|R|S|O|M|C,"Message error"}, - {0x44,0x00,D|T|L|P|W|R|S|O|M|C,"Internal target failure"}, - {0x45,0x00,D|T|L|P|W|R|S|O|M|C,"Select or reselect failure"}, - {0x46,0x00,D|T|L|P|W|R|S|O|M|C,"Unsuccessful soft reset"}, - {0x47,0x00,D|T|L|P|W|R|S|O|M|C,"Scsi parity error"}, - {0x48,0x00,D|T|L|P|W|R|S|O|M|C,"Initiator detected error message received"}, - {0x49,0x00,D|T|L|P|W|R|S|O|M|C,"Invalid message error"}, - {0x4A,0x00,D|T|L|P|W|R|S|O|M|C,"Command phase error"}, - {0x4B,0x00,D|T|L|P|W|R|S|O|M|C,"Data phase error"}, - {0x4C,0x00,D|T|L|P|W|R|S|O|M|C,"Logical unit failed self-configuration"}, - {0x4E,0x00,D|T|L|P|W|R|S|O|M|C,"Overlapped commands attempted"}, - {0x50,0x00,T,"Write append error"}, - {0x50,0x01,T,"Write append position error"}, - {0x50,0x02,T,"Position error related to timing"}, - {0x51,0x00,T|O,"Erase failure"}, - {0x52,0x00,T,"Cartridge fault"}, - {0x53,0x00,D|T|L|W|R|S|O|M,"Media load or eject failed"}, - {0x53,0x01,T,"Unload tape failure"}, - {0x53,0x02,D|T|W|R|O|M,"Medium removal prevented"}, - {0x54,0x00,P,"Scsi to host system interface failure"}, - {0x55,0x00,P,"System resource failure"}, - {0x57,0x00,R,"Unable to recover table-of-contents"}, - {0x58,0x00,O,"Generation does not exist"}, - {0x59,0x00,O,"Updated block read"}, - {0x5A,0x00,D|T|L|P|W|R|S|O|M,"Operator request or state change input (unspecified)"}, - {0x5A,0x01,D|T|W|R|O|M,"Operator medium removal request"}, - {0x5A,0x02,D|T|W|O,"Operator selected write protect"}, - {0x5A,0x03,D|T|W|O,"Operator selected write permit"}, - {0x5B,0x00,D|T|L|P|W|R|S|O|M,"Log exception"}, - {0x5B,0x01,D|T|L|P|W|R|S|O|M,"Threshold condition met"}, - {0x5B,0x02,D|T|L|P|W|R|S|O|M,"Log counter at maximum"}, - {0x5B,0x03,D|T|L|P|W|R|S|O|M,"Log list codes exhausted"}, - {0x5C,0x00,D|O,"Rpl status change"}, - {0x5C,0x01,D|O,"Spindles synchronized"}, - {0x5C,0x02,D|O,"Spindles not synchronized"}, - {0x60,0x00,S,"Lamp failure"}, - {0x61,0x00,S,"Video acquisition error"}, - {0x61,0x01,S,"Unable to acquire video"}, - {0x61,0x02,S,"Out of focus"}, - {0x62,0x00,S,"Scan head positioning error"}, - {0x63,0x00,R,"End of user area encountered on this track"}, - {0x64,0x00,R,"Illegal mode for this track"}, - {0, 0, 0, NULL} -}; -#endif - -#if (CONSTANTS & CONST_SENSE) -static const char *snstext[] = { - "None","Recovered Error","Not Ready","Medium Error","Hardware Error", - "Illegal Request","Unit Attention","Data Protect","Blank Check", - "Key=9","Copy Aborted","Aborted Command","End-Of-Medium", - "Volume Overflow", "Miscompare", "Key=15"}; -#endif - - -/* Print sense information */ -void print_sense(const char * devclass, Scsi_Cmnd * SCpnt) -{ - int i, s; - int sense_class, valid, code; - unsigned char * sense_buffer = SCpnt->sense_buffer; - const char * error = NULL; - - sense_class = (sense_buffer[0] >> 4) & 0x07; - code = sense_buffer[0] & 0xf; - valid = sense_buffer[0] & 0x80; - - if (sense_class == 7) { - s = sense_buffer[7] + 8; - if(s > sizeof(SCpnt->sense_buffer)) s = sizeof(SCpnt->sense_buffer); - - if (!valid) - printk("extra data not valid "); - - if (sense_buffer[2] & 0x80) printk( "FMK "); - if (sense_buffer[2] & 0x40) printk( "EOM "); - if (sense_buffer[2] & 0x20) printk( "ILI "); - - switch (code) { - case 0x0: - error = "Current"; - break; - case 0x1: - error = "Deferred"; - break; - default: - error = "Invalid"; - } - - printk("%s error ", error); - -#if (CONSTANTS & CONST_SENSE) - printk( "%s%s: sense key %s\n", devclass, - kdevname(SCpnt->request.rq_dev), snstext[sense_buffer[2] & 0x0f]); -#else - printk("%s%s: sns = %2x %2x\n", devclass, - kdevname(SCpnt->request.rq_dev), sense_buffer[0], sense_buffer[2]); -#endif - - /* Check to see if additional sense information is available */ - if(sense_buffer[7] + 7 < 13 || - (sense_buffer[12] == 0 && sense_buffer[13] == 0)) goto done; - -#if (CONSTANTS & CONST_XSENSE) - for(i=0; additional[i].text; i++) - if(additional[i].code1 == sense_buffer[12] && - additional[i].code2 == sense_buffer[13]) - printk("Additional sense indicates %s\n", additional[i].text); - - for(i=0; additional2[i].text; i++) - if(additional2[i].code1 == sense_buffer[12] && - additional2[i].code2_min >= sense_buffer[13] && - additional2[i].code2_max <= sense_buffer[13]) { - printk("Additional sense indicates "); - printk(additional2[i].text, sense_buffer[13]); - printk("\n"); - }; -#else - printk("ASC=%2x ASCQ=%2x\n", sense_buffer[12], sense_buffer[13]); -#endif - } else { - -#if (CONSTANTS & CONST_SENSE) - if (sense_buffer[0] < 15) - printk("%s%s: old sense key %s\n", devclass, - kdevname(SCpnt->request.rq_dev), snstext[sense_buffer[0] & 0x0f]); - else -#endif - printk("%s%s: sns = %2x %2x\n", devclass, - kdevname(SCpnt->request.rq_dev), sense_buffer[0], sense_buffer[2]); - - printk("Non-extended sense class %d code 0x%0x ", sense_class, code); - s = 4; - } - - done: -#if !(CONSTANTS & CONST_SENSE) - printk("Raw sense data:"); - for (i = 0; i < s; ++i) - printk("0x%02x ", sense_buffer[i]); - printk("\n"); -#endif - return; -} - -#if (CONSTANTS & CONST_MSG) -static const char *one_byte_msgs[] = { -/* 0x00 */ "Command Complete", NULL, "Save Pointers", -/* 0x03 */ "Restore Pointers", "Disconnect", "Initiator Error", -/* 0x06 */ "Abort", "Message Reject", "Nop", "Message Parity Error", -/* 0x0a */ "Linked Command Complete", "Linked Command Complete w/flag", -/* 0x0c */ "Bus device reset", "Abort Tag", "Clear Queue", -/* 0x0f */ "Initiate Recovery", "Release Recovery" -}; - -#define NO_ONE_BYTE_MSGS (sizeof(one_byte_msgs) / sizeof (const char *)) - -static const char *two_byte_msgs[] = { -/* 0x20 */ "Simple Queue Tag", "Head of Queue Tag", "Ordered Queue Tag" -/* 0x23 */ "Ignore Wide Residue" -}; - -#define NO_TWO_BYTE_MSGS (sizeof(two_byte_msgs) / sizeof (const char *)) - -static const char *extended_msgs[] = { -/* 0x00 */ "Modify Data Pointer", "Synchronous Data Transfer Request", -/* 0x02 */ "SCSI-I Extended Identify", "Wide Data Transfer Request" -}; - -#define NO_EXTENDED_MSGS (sizeof(two_byte_msgs) / sizeof (const char *)) -#endif /* (CONSTANTS & CONST_MSG) */ - -int print_msg (const unsigned char *msg) { - int len = 0, i; - if (msg[0] == EXTENDED_MESSAGE) { - len = 3 + msg[1]; -#if (CONSTANTS & CONST_MSG) - if (msg[2] < NO_EXTENDED_MSGS) - printk ("%s ", extended_msgs[msg[2]]); - else - printk ("Extended Message, reserved code (0x%02x) ", (int) msg[2]); - switch (msg[2]) { - case EXTENDED_MODIFY_DATA_POINTER: - printk("pointer = %d", (int) (msg[3] << 24) | (msg[4] << 16) | - (msg[5] << 8) | msg[6]); - break; - case EXTENDED_SDTR: - printk("period = %d ns, offset = %d", (int) msg[3] * 4, (int) - msg[4]); - break; - case EXTENDED_WDTR: - printk("width = 2^%d bytes", msg[3]); - break; - default: - for (i = 2; i < len; ++i) - printk("%02x ", msg[i]); - } -#else - for (i = 0; i < len; ++i) - printk("%02x ", msg[i]); -#endif - /* Identify */ - } else if (msg[0] & 0x80) { -#if (CONSTANTS & CONST_MSG) - printk("Identify disconnect %sallowed %s %d ", - (msg[0] & 0x40) ? "" : "not ", - (msg[0] & 0x20) ? "target routine" : "lun", - msg[0] & 0x7); -#else - printk("%02x ", msg[0]); -#endif - len = 1; - /* Normal One byte */ - } else if (msg[0] < 0x1f) { -#if (CONSTANTS & CONST_MSG) - if (msg[0] < NO_ONE_BYTE_MSGS) - printk(one_byte_msgs[msg[0]]); - else - printk("reserved (%02x) ", msg[0]); -#else - printk("%02x ", msg[0]); -#endif - len = 1; - /* Two byte */ - } else if (msg[0] <= 0x2f) { -#if (CONSTANTS & CONST_MSG) - if ((msg[0] - 0x20) < NO_TWO_BYTE_MSGS) - printk("%s %02x ", two_byte_msgs[msg[0] - 0x20], - msg[1]); - else - printk("reserved two byte (%02x %02x) ", - msg[0], msg[1]); -#else - printk("%02x %02x", msg[0], msg[1]); -#endif - len = 2; - } else -#if (CONSTANTS & CONST_MSG) - printk(reserved); -#else - printk("%02x ", msg[0]); -#endif - return len; -} - -void print_Scsi_Cmnd (Scsi_Cmnd *cmd) { - printk("scsi%d : destination target %d, lun %d\n", - cmd->host->host_no, - cmd->target, - cmd->lun); - printk(" command = "); - print_command (cmd->cmnd); -} - -#if (CONSTANTS & CONST_HOST) -static const char * hostbyte_table[]={ -"DID_OK", "DID_NO_CONNECT", "DID_BUS_BUSY", "DID_TIME_OUT", "DID_BAD_TARGET", -"DID_ABORT", "DID_PARITY", "DID_ERROR", "DID_RESET", "DID_BAD_INTR",NULL}; - -void print_hostbyte(int scsiresult) -{ static int maxcode=0; - int i; - - if(!maxcode) { - for(i=0;hostbyte_table[i];i++) ; - maxcode=i-1; - } - printk("Hostbyte=0x%02x",host_byte(scsiresult)); - if(host_byte(scsiresult)>maxcode) { - printk("is invalid "); - return; - } - printk("(%s) ",hostbyte_table[host_byte(scsiresult)]); -} -#else -void print_hostbyte(int scsiresult) -{ printk("Hostbyte=0x%02x ",host_byte(scsiresult)); -} -#endif - -#if (CONSTANTS & CONST_DRIVER) -static const char * driverbyte_table[]={ -"DRIVER_OK", "DRIVER_BUSY", "DRIVER_SOFT", "DRIVER_MEDIA", "DRIVER_ERROR", -"DRIVER_INVALID", "DRIVER_TIMEOUT", "DRIVER_HARD",NULL }; - -static const char * driversuggest_table[]={"SUGGEST_OK", -"SUGGEST_RETRY", "SUGGEST_ABORT", "SUGGEST_REMAP", "SUGGEST_DIE", -unknown,unknown,unknown, "SUGGEST_SENSE",NULL}; - - -void print_driverbyte(int scsiresult) -{ static int driver_max=0,suggest_max=0; - int i,dr=driver_byte(scsiresult)&DRIVER_MASK, - su=(driver_byte(scsiresult)&SUGGEST_MASK)>>4; - - if(!driver_max) { - for(i=0;driverbyte_table[i];i++) ; - driver_max=i; - for(i=0;driversuggest_table[i];i++) ; - suggest_max=i; - } - printk("Driverbyte=0x%02x",driver_byte(scsiresult)); - printk("(%s,%s) ", - dr<driver_max ? driverbyte_table[dr]:"invalid", - su<suggest_max ? driversuggest_table[su]:"invalid"); -} -#else -void print_driverbyte(int scsiresult) -{ printk("Driverbyte=0x%02x ",driver_byte(scsiresult)); -} -#endif - -/* - * Overrides for Emacs so that we almost follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 4 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -4 - * c-argdecl-indent: 4 - * c-label-offset: -4 - * c-continued-statement-offset: 4 - * c-continued-brace-offset: 0 - * indent-tabs-mode: nil - * tab-width: 8 - * End: - */ diff --git a/i386/i386at/gpl/linux/scsi/constants.h b/i386/i386at/gpl/linux/scsi/constants.h deleted file mode 100644 index e10527ea..00000000 --- a/i386/i386at/gpl/linux/scsi/constants.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _CONSTANTS_H -#define _CONSTANTS_H -extern int print_msg(unsigned char *); -extern void print_status(int); -extern void print_Scsi_Cmnd (Scsi_Cmnd *); -#endif /* def _CONSTANTS_H */ diff --git a/i386/i386at/gpl/linux/scsi/eata.c b/i386/i386at/gpl/linux/scsi/eata.c deleted file mode 100644 index 29000332..00000000 --- a/i386/i386at/gpl/linux/scsi/eata.c +++ /dev/null @@ -1,1099 +0,0 @@ -/* - * eata.c - Low-level driver for EATA/DMA SCSI host adapters. - * - * 6 Jul 1995 rev. 2.01 for linux 1.3.7 - * Update required by the new /proc/scsi support. - * - * 11 Mar 1995 rev. 2.00 for linux 1.2.0 - * Fixed a bug which prevented media change detection for removable - * disk drives. - * - * 23 Feb 1995 rev. 1.18 for linux 1.1.94 - * Added a check for scsi_register returning NULL. - * - * 11 Feb 1995 rev. 1.17 for linux 1.1.91 - * Now DEBUG_RESET is disabled by default. - * Register a board even if it does not assert DMA protocol support - * (DPT SK2011B does not report correctly the dmasup bit). - * - * 9 Feb 1995 rev. 1.16 for linux 1.1.90 - * Use host->wish_block instead of host->block. - * New list of Data Out SCSI commands. - * - * 8 Feb 1995 rev. 1.15 for linux 1.1.89 - * Cleared target_time_out counter while performing a reset. - * All external symbols renamed to avoid possible name conflicts. - * - * 28 Jan 1995 rev. 1.14 for linux 1.1.86 - * Added module support. - * Log and do a retry when a disk drive returns a target status - * different from zero on a recovered error. - * - * 24 Jan 1995 rev. 1.13 for linux 1.1.85 - * Use optimized board configuration, with a measured performance - * increase in the range 10%-20% on i/o throughput. - * - * 16 Jan 1995 rev. 1.12 for linux 1.1.81 - * Fix mscp structure comments (no functional change). - * Display a message if check_region detects a port address - * already in use. - * - * 17 Dec 1994 rev. 1.11 for linux 1.1.74 - * Use the scsicam_bios_param routine. This allows an easy - * migration path from disk partition tables created using - * different SCSI drivers and non optimal disk geometry. - * - * 15 Dec 1994 rev. 1.10 for linux 1.1.74 - * Added support for ISA EATA boards (DPT PM2011, DPT PM2021). - * The host->block flag is set for all the detected ISA boards. - * The detect routine no longer enforces LEVEL triggering - * for EISA boards, it just prints a warning message. - * - * 30 Nov 1994 rev. 1.09 for linux 1.1.68 - * Redo i/o on target status CHECK_CONDITION for TYPE_DISK only. - * Added optional support for using a single board at a time. - * - * 18 Nov 1994 rev. 1.08 for linux 1.1.64 - * Forces sg_tablesize = 64 and can_queue = 64 if these - * values are not correctly detected (DPT PM2012). - * - * 14 Nov 1994 rev. 1.07 for linux 1.1.63 Final BETA release. - * 04 Aug 1994 rev. 1.00 for linux 1.1.39 First BETA release. - * - * - * This driver is based on the CAM (Common Access Method Committee) - * EATA (Enhanced AT Bus Attachment) rev. 2.0A, using DMA protocol. - * - * Copyright (C) 1994, 1995 Dario Ballabio (dario@milano.europe.dg.com) - * - */ - -/* - * - * Here is a brief description of the DPT SCSI host adapters. - * All these boards provide an EATA/DMA compatible programming interface - * and are fully supported by this driver: - * - * PM2011B/9X - Entry Level ISA - * PM2021A/9X - High Performance ISA - * PM2012A Old EISA - * PM2012B Old EISA - * PM2022A/9X - Entry Level EISA - * PM2122A/9X - High Performance EISA - * PM2322A/9X - Extra High Performance EISA - * - * The DPT PM2001 provides only the EATA/PIO interface and hence is not - * supported by this driver. - * - * This code has been tested with up to 3 Distributed Processing Technology - * PM2122A/9X (DPT SCSI BIOS v002.D1, firmware v05E.0) eisa controllers, - * no on board cache and no RAID option. - * BIOS must be enabled on the first board and must be disabled for all other - * boards. - * Support is provided for any number of DPT PM2122 eisa boards. - * All boards should be configured at the same IRQ level. - * Multiple IRQ configurations are supported too. - * Boards can be located in any eisa slot (1-15) and are named EATA0, - * EATA1,... in increasing eisa slot number. ISA boards are detected - * after the eisa slot probes. - * - * The IRQ for EISA boards should be _level_ triggered (not _edge_ triggered). - * This is a requirement in order to support multiple boards on the same IRQ. - * - * Other eisa configuration parameters are: - * - * COMMAND QUEUING : ENABLED - * COMMAND TIMEOUT : ENABLED - * CACHE : DISABLED - * - * In order to support multiple ISA boards in a reliable way, - * the driver sets host->wish_block = TRUE for all ISA boards. - */ - -#if defined(MODULE) -#include <linux/module.h> -#include <linux/version.h> -#endif - -#include <linux/string.h> -#include <linux/sched.h> -#include <linux/kernel.h> -#include <linux/ioport.h> -#include <asm/io.h> -#include <asm/system.h> -#include <linux/proc_fs.h> -#include <linux/blk.h> -#include "scsi.h" -#include "hosts.h" -#include "sd.h" -#include <asm/dma.h> -#include <asm/irq.h> -#include "linux/in.h" -#include "eata.h" -#include<linux/stat.h> - -struct proc_dir_entry proc_scsi_eata2x = { - PROC_SCSI_EATA2X, 6, "eata2x", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - -/* Subversion values */ -#define ISA 0 -#define ESA 1 - -#undef FORCE_CONFIG - -#undef DEBUG_DETECT -#undef DEBUG_INTERRUPT -#undef DEBUG_STATISTICS -#undef DEBUG_RESET - -#define MAX_TARGET 8 -#define MAX_IRQ 16 -#define MAX_BOARDS 18 -#define MAX_MAILBOXES 64 -#define MAX_SGLIST 64 -#define MAX_CMD_PER_LUN 2 - -#define FALSE 0 -#define TRUE 1 -#define FREE 0 -#define IN_USE 1 -#define LOCKED 2 -#define IN_RESET 3 -#define IGNORE 4 -#define NO_IRQ 0xff -#define NO_DMA 0xff -#define MAXLOOP 200000 - -#define REG_CMD 7 -#define REG_STATUS 7 -#define REG_AUX_STATUS 8 -#define REG_DATA 0 -#define REG_DATA2 1 -#define REG_SEE 6 -#define REG_LOW 2 -#define REG_LM 3 -#define REG_MID 4 -#define REG_MSB 5 -#define REGION_SIZE 9 -#define EISA_RANGE 0xf000 -#define BSY_ASSERTED 0x80 -#define DRQ_ASSERTED 0x08 -#define ABSY_ASSERTED 0x01 -#define IRQ_ASSERTED 0x02 -#define READ_CONFIG_PIO 0xf0 -#define SET_CONFIG_PIO 0xf1 -#define SEND_CP_PIO 0xf2 -#define RECEIVE_SP_PIO 0xf3 -#define TRUNCATE_XFR_PIO 0xf4 -#define RESET_PIO 0xf9 -#define READ_CONFIG_DMA 0xfd -#define SET_CONFIG_DMA 0xfe -#define SEND_CP_DMA 0xff -#define ASOK 0x00 -#define ASST 0x01 - -#define ARRAY_SIZE(arr) (sizeof (arr) / sizeof (arr)[0]) - -/* "EATA", in Big Endian format */ -#define EATA_SIGNATURE 0x41544145 - -/* Number of valid bytes in the board config structure for EATA 2.0x */ -#define EATA_2_0A_SIZE 28 -#define EATA_2_0B_SIZE 30 - -/* Board info structure */ -struct eata_info { - ulong data_len; /* Number of valid bytes after this field */ - ulong sign; /* ASCII "EATA" signature */ - unchar :4, /* unused low nibble */ - version:4; /* EATA version, should be 0x1 */ - unchar ocsena:1, /* Overlap Command Support Enabled */ - tarsup:1, /* Target Mode Supported */ - :2, - dmasup:1, /* DMA Supported */ - drqvld:1, /* DRQ Index (DRQX) is valid */ - ata:1, /* This is an ATA device */ - haaval:1; /* Host Adapter Address Valid */ - ushort cp_pad_len; /* Number of pad bytes after cp_len */ - unchar host_addr[3]; /* Host Adapter SCSI ID for channels 2, 1, 0 */ - unchar reserved; - ulong cp_len; /* Number of valid bytes in cp */ - ulong sp_len; /* Number of valid bytes in sp */ - ushort queue_size; /* Max number of cp that can be queued */ - ushort unused; - ushort scatt_size; /* Max number of entries in scatter/gather table */ - unchar irq:4, /* Interrupt Request assigned to this controller */ - irq_tr:1, /* 0 for edge triggered, 1 for level triggered */ - second:1, /* 1 if this is a secondary (not primary) controller */ - drqx:2; /* DRQ Index (0=DMA0, 1=DMA7, 2=DMA6, 3=DMA5) */ - unchar sync; /* 1 if scsi target id 7...0 is running sync scsi */ - - /* Structure extension defined in EATA 2.0B */ - unchar isaena:1, /* ISA i/o addressing is disabled/enabled */ - forcaddr:1, /* Port address has been forced */ - :6; - unchar max_id:5, /* Max number of SCSI target IDs */ - max_chan:3; /* Max SCSI channel number on this board */ - - ushort ipad[249]; - }; - -/* Board config structure */ -struct eata_config { - ushort len; /* Number of bytes following this field */ - unchar edis:1, /* Disable EATA interface after config command */ - ocena:1, /* Overlapped Commands Enabled */ - mdpena:1, /* Transfer all Modified Data Pointer Messages */ - tarena:1, /* Target Mode Enabled for this controller */ - :4; - unchar cpad[511]; - }; - -/* Returned status packet structure */ -struct mssp { - unchar adapter_status:7, /* State related to current command */ - eoc:1; /* End Of Command (1 = command completed) */ - unchar target_status; /* SCSI status received after data transfer */ - unchar unused[2]; - ulong inv_res_len; /* Number of bytes not transferred */ - Scsi_Cmnd *SCpnt; /* Address set in cp */ - char mess[12]; - }; - -/* MailBox SCSI Command Packet */ -struct mscp { - unchar sreset:1, /* SCSI Bus Reset Signal should be asserted */ - init:1, /* Re-initialize controller and self test */ - reqsen:1, /* Transfer Request Sense Data to addr using DMA */ - sg:1, /* Use Scatter/Gather */ - :1, - interp:1, /* The controller interprets cp, not the target */ - dout:1, /* Direction of Transfer is Out (Host to Target) */ - din:1; /* Direction of Transfer is In (Target to Host) */ - unchar sense_len; /* Request Sense Length */ - unchar unused[4]; - unchar phsunit:1, /* Send to Target Physical Unit (bypass RAID) */ - notused:7; - unchar target; /* SCSI Target ID */ - unchar lun:3, /* LUN */ - :2, - luntar:1, /* This cp is for Target (not LUN) */ - dispri:1, /* Disconnect Privilege granted */ - one:1; /* 1 */ - unchar mess[3]; /* Massage to/from Target */ - unchar cdb[12]; /* Command Descriptor Block */ - ulong data_len; /* If sg=0 Data Length, if sg=1 sglist length */ - Scsi_Cmnd *SCpnt; /* Address to be returned is sp */ - ulong data_address; /* If sg=0 Data Address, if sg=1 sglist address */ - ulong sp_addr; /* Address where sp is DMA'ed when cp completes */ - ulong sense_addr; /* Address where Sense Data is DMA'ed on error */ - - struct sg_list { - unsigned int address; /* Segment Address */ - unsigned int num_bytes; /* Segment Length */ - } sglist[MAX_SGLIST]; - - unsigned int index; /* cp index */ - }; - -struct hostdata { - struct mscp cp[MAX_MAILBOXES]; /* Mailboxes for this board */ - unsigned int cp_stat[MAX_MAILBOXES]; /* FREE, IN_USE, LOCKED, IN_RESET */ - unsigned int last_cp_used; /* Index of last mailbox used */ - unsigned int iocount; /* Total i/o done for this board */ - unsigned int multicount; /* Total ... in second ihdlr loop */ - int board_number; /* Number of this board */ - char board_name[16]; /* Name of this board */ - char board_id[256]; /* data from INQUIRY on this board */ - int in_reset; /* True if board is doing a reset */ - int target_time_out[MAX_TARGET]; /* N. of timeout errors on target */ - int target_reset[MAX_TARGET]; /* If TRUE redo operation on target */ - unsigned char subversion; /* Bus type, either ISA or ESA */ - unsigned char protocol_rev; /* EATA 2.0 rev., 'A' or 'B' or 'C' */ - struct mssp sp[MAX_MAILBOXES]; /* Returned status for this board */ - }; - -static struct Scsi_Host * sh[MAX_BOARDS + 1]; -static const char* driver_name = "EATA"; -static unsigned int irqlist[MAX_IRQ], calls[MAX_IRQ]; - -#define HD(board) ((struct hostdata *) &sh[board]->hostdata) -#define BN(board) (HD(board)->board_name) - -static void eata2x_interrupt_handler(int, struct pt_regs *); -static int do_trace = FALSE; - -static inline unchar wait_on_busy(ushort iobase) { - unsigned int loop = MAXLOOP; - - while (inb(iobase + REG_AUX_STATUS) & ABSY_ASSERTED) - if (--loop == 0) return TRUE; - - return FALSE; -} - -static inline unchar do_dma (ushort iobase, unsigned int addr, unchar cmd) { - - if (wait_on_busy(iobase)) return TRUE; - - if (addr) { - outb((char) addr, iobase + REG_LOW); - outb((char) (addr >> 8), iobase + REG_LM); - outb((char) (addr >> 16), iobase + REG_MID); - outb((char) (addr >> 24), iobase + REG_MSB); - } - - outb(cmd, iobase + REG_CMD); - return FALSE; -} - -static inline unchar read_pio (ushort iobase, ushort *start, ushort *end) { - unsigned int loop = MAXLOOP; - ushort *p; - - for (p = start; p <= end; p++) { - - while (!(inb(iobase + REG_STATUS) & DRQ_ASSERTED)) - if (--loop == 0) return TRUE; - - loop = MAXLOOP; - *p = inw(iobase); - } - - return FALSE; -} - -static inline int port_detect(ushort *port_base, unsigned int j, - Scsi_Host_Template * tpnt) { - unsigned char irq, dma_channel, subversion; - unsigned char protocol_rev; - struct eata_info info; - const char *board_status; - - /* Allowed DMA channels for ISA (0 indicates reserved) */ - unsigned char dma_channel_table[4] = { 5, 6, 7, 0 }; - - char name[16]; - - sprintf(name, "%s%d", driver_name, j); - - if(check_region(*port_base, REGION_SIZE)) { - printk("%s: address 0x%03x in use, skipping probe.\n", - name, *port_base); - return FALSE; - } - - if (do_dma(*port_base, 0, READ_CONFIG_PIO)) return FALSE; - - /* Read the info structure */ - if (read_pio(*port_base, (ushort *)&info, (ushort *)&info.ipad[0])) - return FALSE; - - /* Check the controller "EATA" signature */ - if (info.sign != EATA_SIGNATURE) return FALSE; - - if (ntohl(info.data_len) < EATA_2_0A_SIZE) { - printk("%s: config structure size (%ld bytes) too short, detaching.\n", - name, ntohl(info.data_len)); - return FALSE; - } - else if (ntohl(info.data_len) == EATA_2_0A_SIZE) - protocol_rev = 'A'; - else if (ntohl(info.data_len) == EATA_2_0B_SIZE) - protocol_rev = 'B'; - else - protocol_rev = 'C'; - - if (protocol_rev != 'A' && info.max_chan > 0) - printk("%s: warning, only scsi channel 0 is supported.\n", name); - - irq = info.irq; - - if (*port_base & EISA_RANGE) { - - if (!info.haaval || info.ata || info.drqvld) { - printk("%s: unusable EISA board found (%d%d%d), detaching.\n", - name, info.haaval, info.ata, info.drqvld); - return FALSE; - } - - subversion = ESA; - dma_channel = NO_DMA; - } - else { - - if (!info.haaval || info.ata || !info.drqvld) { - printk("%s: unusable ISA board found (%d%d%d), detaching.\n", - name, info.haaval, info.ata, info.drqvld); - return FALSE; - } - - subversion = ISA; - dma_channel = dma_channel_table[3 - info.drqx]; - } - - if (!info.dmasup) - printk("%s: warning, DMA protocol support not asserted.\n", name); - - if (subversion == ESA && !info.irq_tr) - printk("%s: warning, LEVEL triggering is suggested for IRQ %u.\n", - name, irq); - - if (info.second) - board_status = "Sec."; - else - board_status = "Prim."; - - /* Board detected, allocate its IRQ if not already done */ - if ((irq >= MAX_IRQ) || ((irqlist[irq] == NO_IRQ) && request_irq - (irq, eata2x_interrupt_handler, SA_INTERRUPT, driver_name))) { - printk("%s: unable to allocate IRQ %u, detaching.\n", name, irq); - return FALSE; - } - - if (subversion == ISA && request_dma(dma_channel, driver_name)) { - printk("%s: unable to allocate DMA channel %u, detaching.\n", - name, dma_channel); - free_irq(irq); - return FALSE; - } - -#if defined (FORCE_CONFIG) - { - struct eata_config config; - - /* Set board configuration */ - memset((char *)&config, 0, sizeof(struct eata_config)); - config.len = (ushort) htons((ushort)510); - config.ocena = TRUE; - - if (do_dma(*port_base, (unsigned int)&config, SET_CONFIG_DMA)) { - printk("%s: busy timeout sending configuration, detaching.\n", name); - return FALSE; - } - } -#endif - - sh[j] = scsi_register(tpnt, sizeof(struct hostdata)); - - if (sh[j] == NULL) { - printk("%s: unable to register host, detaching.\n", name); - - if (irqlist[irq] == NO_IRQ) free_irq(irq); - - if (subversion == ISA) free_dma(dma_channel); - - return FALSE; - } - - sh[j]->io_port = *port_base; - sh[j]->n_io_port = REGION_SIZE; - sh[j]->dma_channel = dma_channel; - sh[j]->irq = irq; - sh[j]->sg_tablesize = (ushort) ntohs(info.scatt_size); - sh[j]->this_id = (ushort) info.host_addr[3]; - sh[j]->can_queue = (ushort) ntohs(info.queue_size); - sh[j]->cmd_per_lun = MAX_CMD_PER_LUN; - - /* Register the I/O space that we use */ - request_region(sh[j]->io_port, REGION_SIZE, driver_name); - - memset(HD(j), 0, sizeof(struct hostdata)); - HD(j)->subversion = subversion; - HD(j)->protocol_rev = protocol_rev; - HD(j)->board_number = j; - irqlist[irq] = j; - - if (HD(j)->subversion == ESA) - sh[j]->unchecked_isa_dma = FALSE; - else { - sh[j]->wish_block = TRUE; - sh[j]->unchecked_isa_dma = TRUE; - disable_dma(dma_channel); - clear_dma_ff(dma_channel); - set_dma_mode(dma_channel, DMA_MODE_CASCADE); - enable_dma(dma_channel); - } - - strcpy(BN(j), name); - - printk("%s: 2.0%c, %s, ID %d, PORT 0x%03x, IRQ %u, DMA %u, SG %d, "\ - "Mbox %d, CmdLun %d.\n", BN(j), HD(j)->protocol_rev, board_status, - sh[j]->this_id, sh[j]->io_port, sh[j]->irq, sh[j]->dma_channel, - sh[j]->sg_tablesize, sh[j]->can_queue, sh[j]->cmd_per_lun); - - /* DPT PM2012 does not allow to detect sg_tablesize correctly */ - if (sh[j]->sg_tablesize > MAX_SGLIST || sh[j]->sg_tablesize < 2) { - printk("%s: detect, forcing to use %d SG lists.\n", BN(j), MAX_SGLIST); - sh[j]->sg_tablesize = MAX_SGLIST; - } - - /* DPT PM2012 does not allow to detect can_queue correctly */ - if (sh[j]->can_queue > MAX_MAILBOXES || sh[j]->can_queue < 2) { - printk("%s: detect, forcing to use %d Mbox.\n", BN(j), MAX_MAILBOXES); - sh[j]->can_queue = MAX_MAILBOXES; - } - -#if defined (DEBUG_DETECT) - if (protocol_rev != 'A') - printk("%s: EATA 2.0%c, isaena %u, forcaddr %u, max_id %u,"\ - " max_chan %u.\n", name, protocol_rev, info.isaena, - info.forcaddr, info.max_id, info.max_chan); - - printk("%s: Version 0x%x, SYNC 0x%x, infol %ld, cpl %ld spl %ld.\n", - name, info.version, info.sync, ntohl(info.data_len), - ntohl(info.cp_len), ntohl(info.sp_len)); -#endif - - return TRUE; -} - -int eata2x_detect (Scsi_Host_Template * tpnt) { - unsigned int j = 0, k, flags; - - ushort io_port[] = { - 0x1c88, 0x2c88, 0x3c88, 0x4c88, 0x5c88, 0x6c88, 0x7c88, 0x8c88, - 0x9c88, 0xac88, 0xbc88, 0xcc88, 0xdc88, 0xec88, 0xfc88, - 0x1f0, 0x170, 0x330, 0x230, 0x0 - }; - - ushort *port_base = io_port; - - tpnt->proc_dir = &proc_scsi_eata2x; - - save_flags(flags); - cli(); - - for (k = 0; k < MAX_IRQ; k++) { - irqlist[k] = NO_IRQ; - calls[k] = 0; - } - - for (k = 0; k < MAX_BOARDS + 1; k++) sh[k] = NULL; - - while (*port_base) { - - if (j < MAX_BOARDS && port_detect(port_base, j, tpnt)) j++; - - port_base++; - } - - if (j > 0) - printk("EATA/DMA 2.0x: Copyright (C) 1994, 1995 Dario Ballabio.\n"); - - restore_flags(flags); - return j; -} - -static inline void build_sg_list(struct mscp *cpp, Scsi_Cmnd *SCpnt) { - unsigned int k; - struct scatterlist * sgpnt; - - sgpnt = (struct scatterlist *) SCpnt->request_buffer; - - for (k = 0; k < SCpnt->use_sg; k++) { - cpp->sglist[k].address = htonl((unsigned int) sgpnt[k].address); - cpp->sglist[k].num_bytes = htonl((unsigned int) sgpnt[k].length); - } - - cpp->data_address = htonl((unsigned int) cpp->sglist); - cpp->data_len = htonl((SCpnt->use_sg * sizeof(struct sg_list))); -} - -int eata2x_queuecommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { - unsigned int i, j, k, flags; - struct mscp *cpp; - struct mssp *spp; - - static const unsigned char data_out_cmds[] = { - 0x0a, 0x2a, 0x15, 0x55, 0x04, 0x07, 0x0b, 0x10, 0x16, 0x18, 0x1d, - 0x24, 0x2b, 0x2e, 0x30, 0x31, 0x32, 0x38, 0x39, 0x3a, 0x3b, 0x3d, - 0x3f, 0x40, 0x41, 0x4c, 0xaa, 0xae, 0xb0, 0xb1, 0xb2, 0xb6, 0xea - }; - - save_flags(flags); - cli(); - /* j is the board number */ - j = ((struct hostdata *) SCpnt->host->hostdata)->board_number; - - if (!done) panic("%s: qcomm, pid %ld, null done.\n", BN(j), SCpnt->pid); - - /* i is the mailbox number, look for the first free mailbox - starting from last_cp_used */ - i = HD(j)->last_cp_used + 1; - - for (k = 0; k < sh[j]->can_queue; k++, i++) { - - if (i >= sh[j]->can_queue) i = 0; - - if (HD(j)->cp_stat[i] == FREE) { - HD(j)->last_cp_used = i; - break; - } - } - - if (k == sh[j]->can_queue) { - printk("%s: qcomm, no free mailbox, resetting.\n", BN(j)); - - if (HD(j)->in_reset) - printk("%s: qcomm, already in reset.\n", BN(j)); - else if (eata2x_reset(SCpnt) == SCSI_RESET_SUCCESS) - panic("%s: qcomm, SCSI_RESET_SUCCESS.\n", BN(j)); - - SCpnt->result = DID_BUS_BUSY << 16; - SCpnt->host_scribble = NULL; - printk("%s: qcomm, pid %ld, DID_BUS_BUSY, done.\n", BN(j), SCpnt->pid); - restore_flags(flags); - done(SCpnt); - return 0; - } - - /* Set pointer to control packet structure */ - cpp = &HD(j)->cp[i]; - - memset(cpp, 0, sizeof(struct mscp)); - - /* Set pointer to status packet structure */ - spp = &HD(j)->sp[i]; - - memset(spp, 0, sizeof(struct mssp)); - - /* The EATA protocol uses Big Endian format, while Intel is Little Endian */ - cpp->sp_addr = htonl((unsigned int) spp); - - SCpnt->scsi_done = done; - cpp->index = i; - SCpnt->host_scribble = (unsigned char *) &cpp->index; - - if (do_trace) printk("%s: qcomm, mbox %d, target %d, pid %ld.\n", - BN(j), i, SCpnt->target, SCpnt->pid); - - for (k = 0; k < ARRAY_SIZE(data_out_cmds); k++) - if (SCpnt->cmnd[0] == data_out_cmds[k]) { - cpp->dout = TRUE; - break; - } - - cpp->din = !cpp->dout; - cpp->reqsen = TRUE; - cpp->dispri = TRUE; - cpp->one = TRUE; - cpp->target = SCpnt->target; - cpp->lun = SCpnt->lun; - cpp->SCpnt = SCpnt; - cpp->sense_addr = htonl((unsigned int) SCpnt->sense_buffer); - cpp->sense_len = sizeof SCpnt->sense_buffer; - - if (SCpnt->use_sg) { - cpp->sg = TRUE; - build_sg_list(cpp, SCpnt); - } - else { - cpp->data_address = htonl((unsigned int) SCpnt->request_buffer); - cpp->data_len = htonl(SCpnt->request_bufflen); - } - - memcpy(cpp->cdb, SCpnt->cmnd, SCpnt->cmd_len); - - /* Send control packet to the board */ - if (do_dma(sh[j]->io_port, (unsigned int) cpp, SEND_CP_DMA)) { - SCpnt->result = DID_ERROR << 16; - SCpnt->host_scribble = NULL; - printk("%s: qcomm, target %d, pid %ld, adapter busy, DID_ERROR, done.\n", - BN(j), SCpnt->target, SCpnt->pid); - restore_flags(flags); - done(SCpnt); - return 0; - } - - HD(j)->cp_stat[i] = IN_USE; - restore_flags(flags); - return 0; -} - -int eata2x_abort (Scsi_Cmnd *SCarg) { - unsigned int i, j, flags; - - save_flags(flags); - cli(); - j = ((struct hostdata *) SCarg->host->hostdata)->board_number; - - if (SCarg->host_scribble == NULL) { - printk("%s: abort, target %d, pid %ld inactive.\n", - BN(j), SCarg->target, SCarg->pid); - restore_flags(flags); - return SCSI_ABORT_NOT_RUNNING; - } - - i = *(unsigned int *)SCarg->host_scribble; - printk("%s: abort, mbox %d, target %d, pid %ld.\n", - BN(j), i, SCarg->target, SCarg->pid); - - if (i >= sh[j]->can_queue) - panic("%s: abort, invalid SCarg->host_scribble.\n", BN(j)); - - if (wait_on_busy(sh[j]->io_port)) { - printk("%s: abort, timeout error.\n", BN(j)); - restore_flags(flags); - return SCSI_ABORT_ERROR; - } - - if (HD(j)->cp_stat[i] == FREE) { - printk("%s: abort, mbox %d is free.\n", BN(j), i); - restore_flags(flags); - return SCSI_ABORT_NOT_RUNNING; - } - - if (HD(j)->cp_stat[i] == IN_USE) { - printk("%s: abort, mbox %d is in use.\n", BN(j), i); - - if (SCarg != HD(j)->cp[i].SCpnt) - panic("%s: abort, mbox %d, SCarg %p, cp SCpnt %p.\n", - BN(j), i, SCarg, HD(j)->cp[i].SCpnt); - - restore_flags(flags); - return SCSI_ABORT_SNOOZE; - } - - if (HD(j)->cp_stat[i] == IN_RESET) { - printk("%s: abort, mbox %d is in reset.\n", BN(j), i); - restore_flags(flags); - return SCSI_ABORT_ERROR; - } - - if (HD(j)->cp_stat[i] == LOCKED) { - printk("%s: abort, mbox %d is locked.\n", BN(j), i); - restore_flags(flags); - return SCSI_ABORT_NOT_RUNNING; - } - restore_flags(flags); - panic("%s: abort, mbox %d, invalid cp_stat.\n", BN(j), i); -} - -int eata2x_reset (Scsi_Cmnd *SCarg) { - unsigned int i, j, flags, time, k, limit = 0; - int arg_done = FALSE; - Scsi_Cmnd *SCpnt; - - save_flags(flags); - cli(); - j = ((struct hostdata *) SCarg->host->hostdata)->board_number; - printk("%s: reset, enter, target %d, pid %ld.\n", - BN(j), SCarg->target, SCarg->pid); - - if (SCarg->host_scribble == NULL) - printk("%s: reset, pid %ld inactive.\n", BN(j), SCarg->pid); - - if (HD(j)->in_reset) { - printk("%s: reset, exit, already in reset.\n", BN(j)); - restore_flags(flags); - return SCSI_RESET_ERROR; - } - - if (wait_on_busy(sh[j]->io_port)) { - printk("%s: reset, exit, timeout error.\n", BN(j)); - restore_flags(flags); - return SCSI_RESET_ERROR; - } - - for (k = 0; k < MAX_TARGET; k++) HD(j)->target_reset[k] = TRUE; - - for (k = 0; k < MAX_TARGET; k++) HD(j)->target_time_out[k] = 0; - - for (i = 0; i < sh[j]->can_queue; i++) { - - if (HD(j)->cp_stat[i] == FREE) continue; - - if (HD(j)->cp_stat[i] == LOCKED) { - HD(j)->cp_stat[i] = FREE; - printk("%s: reset, locked mbox %d forced free.\n", BN(j), i); - continue; - } - - SCpnt = HD(j)->cp[i].SCpnt; - HD(j)->cp_stat[i] = IN_RESET; - printk("%s: reset, mbox %d in reset, pid %ld.\n", - BN(j), i, SCpnt->pid); - - if (SCpnt == NULL) - panic("%s: reset, mbox %d, SCpnt == NULL.\n", BN(j), i); - - if (SCpnt->host_scribble == NULL) - panic("%s: reset, mbox %d, garbled SCpnt.\n", BN(j), i); - - if (*(unsigned int *)SCpnt->host_scribble != i) - panic("%s: reset, mbox %d, index mismatch.\n", BN(j), i); - - if (SCpnt->scsi_done == NULL) - panic("%s: reset, mbox %d, SCpnt->scsi_done == NULL.\n", BN(j), i); - - if (SCpnt == SCarg) arg_done = TRUE; - } - - if (do_dma(sh[j]->io_port, 0, RESET_PIO)) { - printk("%s: reset, cannot reset, timeout error.\n", BN(j)); - restore_flags(flags); - return SCSI_RESET_ERROR; - } - - printk("%s: reset, board reset done, enabling interrupts.\n", BN(j)); - -#if defined (DEBUG_RESET) - do_trace = TRUE; -#endif - - HD(j)->in_reset = TRUE; - sti(); - time = jiffies; - while (jiffies < (time + 100) && limit++ < 100000000); - cli(); - printk("%s: reset, interrupts disabled, loops %d.\n", BN(j), limit); - - for (i = 0; i < sh[j]->can_queue; i++) { - - /* Skip mailboxes already set free by interrupt */ - if (HD(j)->cp_stat[i] != IN_RESET) continue; - - SCpnt = HD(j)->cp[i].SCpnt; - SCpnt->result = DID_RESET << 16; - SCpnt->host_scribble = NULL; - - /* This mailbox is still waiting for its interrupt */ - HD(j)->cp_stat[i] = LOCKED; - - printk("%s, reset, mbox %d locked, DID_RESET, pid %ld done.\n", - BN(j), i, SCpnt->pid); - restore_flags(flags); - SCpnt->scsi_done(SCpnt); - cli(); - } - - HD(j)->in_reset = FALSE; - do_trace = FALSE; - restore_flags(flags); - - if (arg_done) { - printk("%s: reset, exit, success.\n", BN(j)); - return SCSI_RESET_SUCCESS; - } - else { - printk("%s: reset, exit, wakeup.\n", BN(j)); - return SCSI_RESET_PUNT; - } -} - -static void eata2x_interrupt_handler(int irq, struct pt_regs * regs) { - Scsi_Cmnd *SCpnt; - unsigned int i, j, k, flags, status, tstatus, loops, total_loops = 0; - struct mssp *spp; - struct mscp *cpp; - - save_flags(flags); - cli(); - - if (irqlist[irq] == NO_IRQ) { - printk("%s, ihdlr, irq %d, unexpected interrupt.\n", driver_name, irq); - restore_flags(flags); - return; - } - - if (do_trace) printk("%s: ihdlr, enter, irq %d, calls %d.\n", - driver_name, irq, calls[irq]); - - /* Service all the boards configured on this irq */ - for (j = 0; sh[j] != NULL; j++) { - - if (sh[j]->irq != irq) continue; - - loops = 0; - - /* Loop until all interrupts for a board are serviced */ - while (inb(sh[j]->io_port + REG_AUX_STATUS) & IRQ_ASSERTED) { - total_loops++; - loops++; - - if (do_trace) printk("%s: ihdlr, start service, count %d.\n", - BN(j), HD(j)->iocount); - - /* Read the status register to clear the interrupt indication */ - inb(sh[j]->io_port + REG_STATUS); - - /* Service all mailboxes of this board */ - for (i = 0; i < sh[j]->can_queue; i++) { - spp = &HD(j)->sp[i]; - - /* Check if this mailbox has completed the operation */ - if (spp->eoc == FALSE) continue; - - spp->eoc = FALSE; - - if (HD(j)->cp_stat[i] == IGNORE) { - HD(j)->cp_stat[i] = FREE; - continue; - } - else if (HD(j)->cp_stat[i] == LOCKED) { - HD(j)->cp_stat[i] = FREE; - printk("%s: ihdlr, mbox %d unlocked, count %d.\n", - BN(j), i, HD(j)->iocount); - continue; - } - else if (HD(j)->cp_stat[i] == FREE) { - printk("%s: ihdlr, mbox %d is free, count %d.\n", - BN(j), i, HD(j)->iocount); - continue; - } - else if (HD(j)->cp_stat[i] == IN_RESET) - printk("%s: ihdlr, mbox %d is in reset.\n", BN(j), i); - else if (HD(j)->cp_stat[i] != IN_USE) - panic("%s: ihdlr, mbox %d, invalid cp_stat.\n", BN(j), i); - - HD(j)->cp_stat[i] = FREE; - cpp = &HD(j)->cp[i]; - SCpnt = spp->SCpnt; - - if (SCpnt == NULL) - panic("%s: ihdlr, mbox %d, SCpnt == NULL.\n", BN(j), i); - - if (SCpnt != cpp->SCpnt) - panic("%s: ihdlr, mbox %d, sp SCpnt %p, cp SCpnt %p.\n", - BN(j), i, SCpnt, cpp->SCpnt); - - if (SCpnt->host_scribble == NULL) - panic("%s: ihdlr, mbox %d, pid %ld, SCpnt %p garbled.\n", - BN(j), i, SCpnt->pid, SCpnt); - - if (*(unsigned int *)SCpnt->host_scribble != i) - panic("%s: ihdlr, mbox %d, pid %ld, index mismatch %d,"\ - " irq %d.\n", BN(j), i, SCpnt->pid, - *(unsigned int *)SCpnt->host_scribble, irq); - - tstatus = status_byte(spp->target_status); - - switch (spp->adapter_status) { - case ASOK: /* status OK */ - - /* Forces a reset if a disk drive keeps returning BUSY */ - if (tstatus == BUSY && SCpnt->device->type != TYPE_TAPE) - status = DID_ERROR << 16; - - /* If there was a bus reset, redo operation on each target */ - else if (tstatus != GOOD - && SCpnt->device->type == TYPE_DISK - && HD(j)->target_reset[SCpnt->target]) - status = DID_BUS_BUSY << 16; - - /* Works around a flaw in scsi.c */ - else if (tstatus == CHECK_CONDITION - && SCpnt->device->type == TYPE_DISK - && (SCpnt->sense_buffer[2] & 0xf) == RECOVERED_ERROR) - status = DID_BUS_BUSY << 16; - - else - status = DID_OK << 16; - - if (tstatus == GOOD) - HD(j)->target_reset[SCpnt->target] = FALSE; - - if (spp->target_status && SCpnt->device->type == TYPE_DISK) - printk("%s: ihdlr, target %d:%d, pid %ld, target_status "\ - "0x%x, sense key 0x%x.\n", BN(j), - SCpnt->target, SCpnt->lun, SCpnt->pid, - spp->target_status, SCpnt->sense_buffer[2]); - - HD(j)->target_time_out[SCpnt->target] = 0; - - break; - case ASST: /* Selection Time Out */ - case 0x02: /* Command Time Out */ - - if (HD(j)->target_time_out[SCpnt->target] > 1) - status = DID_ERROR << 16; - else { - status = DID_TIME_OUT << 16; - HD(j)->target_time_out[SCpnt->target]++; - } - - break; - case 0x03: /* SCSI Bus Reset Received */ - case 0x04: /* Initial Controller Power-up */ - - if (SCpnt->device->type != TYPE_TAPE) - status = DID_BUS_BUSY << 16; - else - status = DID_ERROR << 16; - - for (k = 0; k < MAX_TARGET; k++) - HD(j)->target_reset[k] = TRUE; - - break; - case 0x07: /* Bus Parity Error */ - case 0x0c: /* Controller Ram Parity */ - case 0x05: /* Unexpected Bus Phase */ - case 0x06: /* Unexpected Bus Free */ - case 0x08: /* SCSI Hung */ - case 0x09: /* Unexpected Message Reject */ - case 0x0a: /* SCSI Bus Reset Stuck */ - case 0x0b: /* Auto Request-Sense Failed */ - default: - status = DID_ERROR << 16; - break; - } - - SCpnt->result = status | spp->target_status; - HD(j)->iocount++; - - if (loops > 1) HD(j)->multicount++; - -#if defined (DEBUG_INTERRUPT) - if (SCpnt->result || do_trace) -#else - if ((spp->adapter_status != ASOK && HD(j)->iocount > 1000) || - (spp->adapter_status != ASOK && - spp->adapter_status != ASST && HD(j)->iocount <= 1000) || - do_trace) -#endif - printk("%s: ihdlr, mbox %d, err 0x%x:%x,"\ - " target %d:%d, pid %ld, count %d.\n", - BN(j), i, spp->adapter_status, spp->target_status, - SCpnt->target, SCpnt->lun, SCpnt->pid, HD(j)->iocount); - - /* Set the command state to inactive */ - SCpnt->host_scribble = NULL; - - restore_flags(flags); - SCpnt->scsi_done(SCpnt); - cli(); - - } /* Mailbox loop */ - - } /* Multiple command loop */ - - } /* Boards loop */ - - calls[irq]++; - - if (total_loops == 0) - printk("%s: ihdlr, irq %d, no command completed, calls %d.\n", - driver_name, irq, calls[irq]); - - if (do_trace) printk("%s: ihdlr, exit, irq %d, calls %d.\n", - driver_name, irq, calls[irq]); - -#if defined (DEBUG_STATISTICS) - if ((calls[irq] % 100000) == 10000) - for (j = 0; sh[j] != NULL; j++) - printk("%s: ihdlr, calls %d, count %d, multi %d.\n", BN(j), - calls[(sh[j]->irq)], HD(j)->iocount, HD(j)->multicount); -#endif - - restore_flags(flags); - return; -} - -#if defined(MODULE) -Scsi_Host_Template driver_template = EATA; - -#include "scsi_module.c" -#endif diff --git a/i386/i386at/gpl/linux/scsi/eata.h b/i386/i386at/gpl/linux/scsi/eata.h deleted file mode 100644 index aabcc806..00000000 --- a/i386/i386at/gpl/linux/scsi/eata.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * eata.h - used by the low-level driver for EATA/DMA SCSI host adapters. - * - */ -#ifndef _EATA_H -#define _EATA_H - -#include <linux/scsicam.h> - -int eata2x_detect(Scsi_Host_Template *); -int eata2x_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); -int eata2x_abort(Scsi_Cmnd *); -int eata2x_reset(Scsi_Cmnd *); - -#define EATA_VERSION "2.01.00" - - -#define EATA { \ - NULL, /* Ptr for modules */ \ - NULL, /* usage count for modules */ \ - NULL, \ - NULL, \ - "EATA/DMA 2.0x rev. " EATA_VERSION " ", \ - eata2x_detect, \ - NULL, /* Release */ \ - NULL, \ - NULL, \ - eata2x_queuecommand, \ - eata2x_abort, \ - eata2x_reset, \ - NULL, \ - scsicam_bios_param, \ - 0, /* can_queue, reset by detect */ \ - 7, /* this_id, reset by detect */ \ - 0, /* sg_tablesize, reset by detect */ \ - 0, /* cmd_per_lun, reset by detect */ \ - 0, /* number of boards present */ \ - 1, /* unchecked isa dma, reset by detect */ \ - ENABLE_CLUSTERING \ - } -#endif diff --git a/i386/i386at/gpl/linux/scsi/eata_dma.c b/i386/i386at/gpl/linux/scsi/eata_dma.c deleted file mode 100644 index da9e3daa..00000000 --- a/i386/i386at/gpl/linux/scsi/eata_dma.c +++ /dev/null @@ -1,1375 +0,0 @@ -/************************************************************ - * * - * Linux EATA SCSI driver * - * * - * based on the CAM document CAM/89-004 rev. 2.0c, * - * DPT's driver kit, some internal documents and source, * - * and several other Linux scsi drivers and kernel docs. * - * * - * The driver currently: * - * -supports all ISA based EATA-DMA boards * - * -supports all EISA based EATA-DMA boards * - * -supports all PCI based EATA-DMA boards * - * -supports multiple HBAs with & without IRQ sharing * - * -supports all SCSI channels on multi channel boards * - * -needs identical IDs on all channels of a HBA * - * -can be loaded as module * - * -displays statistical and hardware information * - * in /proc/scsi/eata_dma * - * -provides rudimentary latency measurement * - * possibilities via /proc/scsi/eata_dma/<hostnum> * - * * - * (c)1993,94,95 Michael Neuffer * - * neuffer@goofy.zdv.uni-mainz.de * - * * - * This program is free software; you can redistribute it * - * and/or modify it under the terms of the GNU General * - * Public License as published by the Free Software * - * Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be * - * useful, but WITHOUT ANY WARRANTY; without even the * - * implied warranty of MERCHANTABILITY or FITNESS FOR A * - * PARTICULAR PURPOSE. See the GNU General Public License * - * for more details. * - * * - * You should have received a copy of the GNU General * - * Public License along with this kernel; if not, write to * - * the Free Software Foundation, Inc., 675 Mass Ave, * - * Cambridge, MA 02139, USA. * - * * - * I have to thank DPT for their excellent support. I took * - * me almost a year and a stopover at their HQ, on my first * - * trip to the USA, to get it, but since then they've been * - * very helpful and tried to give me all the infos and * - * support I need. * - * * - * Thanks also to Greg Hosler who did a lot of testing and * - * found quite a number of bugs during the development. * - ************************************************************ - * last change: 95/11/29 OS: Linux 1.3.45 * - ************************************************************/ - -/* Look in eata_dma.h for configuration and revision information */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/string.h> -#include <linux/ioport.h> -#include <linux/malloc.h> -#include <linux/in.h> -#include <linux/bios32.h> -#include <linux/pci.h> -#include <linux/proc_fs.h> -#include <asm/byteorder.h> -#include <asm/types.h> -#include <asm/io.h> -#include <asm/dma.h> -#include <linux/blk.h> -#include "scsi.h" -#include "sd.h" -#include "hosts.h" -#include <linux/scsicam.h> -#include "eata_dma.h" -#include "eata_dma_proc.h" - -#include <linux/stat.h> -#include <linux/config.h> /* for CONFIG_PCI */ - -struct proc_dir_entry proc_scsi_eata_dma = { - PROC_SCSI_EATA, 8, "eata_dma", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - -static u32 ISAbases[] = -{0x1F0, 0x170, 0x330, 0x230}; -static unchar EISAbases[] = -{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; -static uint registered_HBAs = 0; -static struct Scsi_Host *last_HBA = NULL; -static struct Scsi_Host *first_HBA = NULL; -static unchar reg_IRQ[] = -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; -static unchar reg_IRQL[] = -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; -static struct eata_sp *status = 0; /* Statuspacket array */ -static void *dma_scratch = 0; - -static struct eata_register *fake_int_base; -static int fake_int_result; -static int fake_int_happened; - -static ulong int_counter = 0; -static ulong queue_counter = 0; - -void eata_scsi_done (Scsi_Cmnd * scmd) -{ - scmd->request.rq_status = RQ_SCSI_DONE; - - if (scmd->request.sem != NULL) - up(scmd->request.sem); - - return; -} - -void eata_fake_int_handler(s32 irq, struct pt_regs * regs) -{ - fake_int_result = inb((ulong)fake_int_base + HA_RSTATUS); - fake_int_happened = TRUE; - DBG(DBG_INTR3, printk("eata_fake_int_handler called irq%d base %p" - " res %#x\n", irq, fake_int_base, fake_int_result)); - return; -} - -#ifdef MACH -#include "eata_dma_proc.src" -#else -#include "eata_dma_proc.c" -#endif - -#ifdef MODULE -int eata_release(struct Scsi_Host *sh) -{ - uint i; - if (sh->irq && reg_IRQ[sh->irq] == 1) free_irq(sh->irq); - else reg_IRQ[sh->irq]--; - - scsi_init_free((void *)status, 512); - scsi_init_free((void *)dma_scratch, 512); - for (i = 0; i < sh->can_queue; i++){ /* Free all SG arrays */ - if(SD(sh)->ccb[i].sg_list != NULL) - scsi_init_free((void *) SD(sh)->ccb[i].sg_list, - sh->sg_tablesize * sizeof(struct eata_sg_list)); - } - - if (SD(sh)->channel == 0) { - if (sh->dma_channel != BUSMASTER) free_dma(sh->dma_channel); - if (sh->io_port && sh->n_io_port) - release_region(sh->io_port, sh->n_io_port); - } - return(TRUE); -} -#endif - - -void eata_int_handler(int irq, struct pt_regs * regs) -{ - uint i, result = 0; - uint hba_stat, scsi_stat, eata_stat; - Scsi_Cmnd *cmd; - struct eata_ccb *cp; - struct eata_sp *sp; - uint base; - ulong flags; - uint x; - struct Scsi_Host *sh; - - save_flags(flags); - cli(); - - for (x = 1, sh = first_HBA; x <= registered_HBAs; x++, sh = SD(sh)->next) { - if (sh->irq != irq) - continue; - - while(inb((uint)sh->base + HA_RAUXSTAT) & HA_AIRQ) { - - int_counter++; - - sp = &SD(sh)->sp; - cp = sp->ccb; - - if(cp == NULL) { - eata_stat = inb((uint)sh->base + HA_RSTATUS); - printk("eata_dma: int_handler, Spurious IRQ %d " - "received. CCB pointer not set.\n", irq); - break; - } - - cmd = cp->cmd; - base = (uint) cmd->host->base; - hba_stat = sp->hba_stat; - - scsi_stat = (sp->scsi_stat >> 1) & 0x1f; - - if (sp->EOC == FALSE) { - eata_stat = inb(base + HA_RSTATUS); - printk("eata_dma: int_handler, board: %x cmd %lx returned " - "unfinished.\nEATA: %x HBA: %x SCSI: %x spadr %lx " - "spadrirq %lx, irq%d\n", base, (long)cp, eata_stat, - hba_stat, scsi_stat,(long)&status, (long)&status[irq], - irq); - DBG(DBG_DELAY, DEL2(800)); - break; - } - - if (cp->status == LOCKED) { - cp->status = FREE; - eata_stat = inb(base + HA_RSTATUS); - printk("eata_dma: int_handler, freeing locked queueslot\n"); - DBG(DBG_INTR && DBG_DELAY, DEL2(800)); - break; - } - - eata_stat = inb(base + HA_RSTATUS); - DBG(DBG_INTR, printk("IRQ %d received, base %#.4x, pid %ld, " - "target: %x, lun: %x, ea_s: %#.2x, hba_s: " - "%#.2x \n", irq, base, cmd->pid, cmd->target, - cmd->lun, eata_stat, hba_stat)); - - switch (hba_stat) { - case HA_NO_ERROR: /* NO Error */ - if (scsi_stat == CONDITION_GOOD - && cmd->device->type == TYPE_DISK - && (HD(cmd)->t_state[cp->cp_channel][cp->cp_id] == RESET)) - result = DID_BUS_BUSY << 16; - else if (scsi_stat == GOOD) { - HD(cmd)->t_state[cp->cp_channel][cp->cp_id] = OK; - if(HD(cmd)->do_latency == TRUE && cp->timestamp) { - uint time; - time = jiffies - cp->timestamp; - if((cp->rw_latency) == TRUE) { /* was WRITE */ - if(HD(cmd)->writes_lat[cp->sizeindex][1] > time) - HD(cmd)->writes_lat[cp->sizeindex][1] = time; - if(HD(cmd)->writes_lat[cp->sizeindex][2] < time) - HD(cmd)->writes_lat[cp->sizeindex][2] = time; - HD(cmd)->writes_lat[cp->sizeindex][3] += time; - HD(cmd)->writes_lat[cp->sizeindex][0]++; - } else { - if(HD(cmd)->reads_lat[cp->sizeindex][1] > time) - HD(cmd)->reads_lat[cp->sizeindex][1] = time; - if(HD(cmd)->reads_lat[cp->sizeindex][2] < time) - HD(cmd)->reads_lat[cp->sizeindex][2] = time; - HD(cmd)->reads_lat[cp->sizeindex][3] += time; - HD(cmd)->reads_lat[cp->sizeindex][0]++; - } - } - } - else if (scsi_stat == CHECK_CONDITION - && cmd->device->type == TYPE_DISK - && (cmd->sense_buffer[2] & 0xf) == RECOVERED_ERROR) - result = DID_BUS_BUSY << 16; - else - result = DID_OK << 16; - HD(cmd)->t_timeout[cp->cp_channel][cp->cp_id] = OK; - break; - case HA_ERR_SEL_TO: /* Selection Timeout */ - result = DID_BAD_TARGET << 16; - break; - case HA_ERR_CMD_TO: /* Command Timeout */ - if (HD(cmd)->t_timeout[cp->cp_channel][cp->cp_id] > 1) - result = DID_ERROR << 16; - else { - result = DID_TIME_OUT << 16; - HD(cmd)->t_timeout[cp->cp_channel][cp->cp_id]++; - } - break; - case HA_ERR_RESET: /* SCSI Bus Reset Received */ - case HA_INIT_POWERUP: /* Initial Controller Power-up */ - if (cmd->device->type != TYPE_TAPE) - result = DID_BUS_BUSY << 16; - else - result = DID_ERROR << 16; - - for (i = 0; i < MAXTARGET; i++) - HD(cmd)->t_state[cp->cp_channel][i] = RESET; - break; - case HA_UNX_BUSPHASE: /* Unexpected Bus Phase */ - case HA_UNX_BUS_FREE: /* Unexpected Bus Free */ - case HA_BUS_PARITY: /* Bus Parity Error */ - case HA_SCSI_HUNG: /* SCSI Hung */ - case HA_UNX_MSGRJCT: /* Unexpected Message Reject */ - case HA_RESET_STUCK: /* SCSI Bus Reset Stuck */ - case HA_RSENSE_FAIL: /* Auto Request-Sense Failed */ - case HA_PARITY_ERR: /* Controller Ram Parity */ - default: - result = DID_ERROR << 16; - break; - } - cmd->result = result | (scsi_stat << 1); - -#if DBG_INTR2 - if (scsi_stat || result || hba_stat || eata_stat != 0x50 - || cmd->scsi_done == NULL || cmd->device->id == 7) - printk("HBA: %d, channel %d, id: %d, lun %d, pid %ld:\n" - "eata_stat %#x, hba_stat %#.2x, scsi_stat %#.2x, " - "sense_key: %#x, result: %#.8x\n", x, - cmd->device->channel, cmd->device->id, cmd->device->lun, - cmd->pid, eata_stat, hba_stat, scsi_stat, - cmd->sense_buffer[2] & 0xf, cmd->result); - DBG(DBG_INTR&&DBG_DELAY,DEL2(800)); -#endif - - cp->status = FREE; /* now we can release the slot */ - cmd->scsi_done(cmd); - } - } - restore_flags(flags); - - return; -} - -inline int eata_send_command(u32 addr, u32 base, u8 command) -{ - long loop = R_LIMIT; - - while (inb(base + HA_RAUXSTAT) & HA_ABUSY) - if (--loop == 0) - return(FALSE); - - /* And now the address in nice little byte chunks */ - outb( addr & 0x000000ff, base + HA_WDMAADDR); - outb((addr & 0x0000ff00) >> 8, base + HA_WDMAADDR + 1); - outb((addr & 0x00ff0000) >> 16, base + HA_WDMAADDR + 2); - outb((addr & 0xff000000) >> 24, base + HA_WDMAADDR + 3); - outb(command, base + HA_WCOMMAND); - return(TRUE); -} - -#if 0 -inline int eata_send_immediate(u32 addr, u32 base, u8 cmnd, u8 cmnd2, u8 id, - u8 lun) -{ - if(addr){ - outb( addr & 0x000000ff, base + HA_WDMAADDR); - outb((addr & 0x0000ff00) >> 8, base + HA_WDMAADDR + 1); - outb((addr & 0x00ff0000) >> 16, base + HA_WDMAADDR + 2); - outb((addr & 0xff000000) >> 24, base + HA_WDMAADDR + 3); - } else { - outb(id, base + HA_WSUBCODE); - outb(lun, base + HA_WSUBLUN); - } - - outb(cmnd2, base + HA_WCOMMAND2); - outb(cmnd, base + HA_WCOMMAND); - return(TRUE); -} -#endif - -int eata_queue(Scsi_Cmnd * cmd, void (* done) (Scsi_Cmnd *)) -{ - unsigned int i, x, y; - u32 flags; - hostdata *hd; - struct Scsi_Host *sh; - struct eata_ccb *cp; - struct scatterlist *sl; - - save_flags(flags); - cli(); - - queue_counter++; - - hd = HD(cmd); - sh = cmd->host; - - /* check for free slot */ - for (y = hd->last_ccb + 1, x = 0; x < sh->can_queue; x++, y++) { - if (y >= sh->can_queue) - y = 0; - if (hd->ccb[y].status == FREE) - break; - } - - hd->last_ccb = y; - - if (x >= sh->can_queue) { - uint z; - - printk(KERN_EMERG "eata_dma: run out of queue slots cmdno:%ld" - " intrno: %ld, can_queue: %d, x: %d, y: %d\n", - queue_counter, int_counter, sh->can_queue, x, y); - printk(KERN_EMERG "Status of queueslots:"); - for(z = 0; z < sh->can_queue; z +=2) { - switch(hd->ccb[z].status) { - case FREE: - printk(KERN_EMERG "Slot %2d is FREE \t", z); - break; - case USED: - printk(KERN_EMERG "Slot %2d is USED \t", z); - break; - case LOCKED: - printk(KERN_EMERG "Slot %2d is LOCKED\t", z); - break; - default: - printk(KERN_EMERG "Slot %2d is UNKNOWN\t", z); - } - panic("\nSystem halted.\n"); - } - } - cp = &hd->ccb[y]; - - memset(cp, 0, sizeof(struct eata_ccb) - sizeof(struct eata_sg_list *)); - - cp->status = USED; /* claim free slot */ - - DBG(DBG_QUEUE, printk("eata_queue pid %ld, target: %x, lun: %x, y %d\n", - cmd->pid, cmd->target, cmd->lun, y)); - DBG(DBG_QUEUE && DBG_DELAY, DEL2(250)); - - if(hd->do_latency == TRUE) { - int x, z; - short *sho; - long *lon; - x = 0; /* just to keep GCC quiet */ - if (cmd->cmnd[0] == WRITE_6 || cmd->cmnd[0] == WRITE_10 || - cmd->cmnd[0] == WRITE_12 || cmd->cmnd[0] == READ_6 || - cmd->cmnd[0] == READ_10 || cmd->cmnd[0] == READ_12) { - - cp->timestamp = jiffies; /* For latency measurements */ - switch(cmd->cmnd[0]) { - case WRITE_6: - case READ_6: - x = cmd->cmnd[4]/2; - break; - case WRITE_10: - case READ_10: - sho = (short *) &cmd->cmnd[7]; - x = ntohs(*sho)/2; - break; - case WRITE_12: - case READ_12: - lon = (long *) &cmd->cmnd[6]; - x = ntohl(*lon)/2; - break; - } - - for(z = 0; (x > (1 << z)) && (z <= 11); z++) - /* nothing */; - cp->sizeindex = z; - if (cmd->cmnd[0] == WRITE_6 || cmd->cmnd[0] == WRITE_10 || - cmd->cmnd[0] == WRITE_12){ - cp->rw_latency = TRUE; - } - } - } - cmd->scsi_done = (void *)done; - - switch (cmd->cmnd[0]) { - case CHANGE_DEFINITION: case COMPARE: case COPY: - case COPY_VERIFY: case LOG_SELECT: case MODE_SELECT: - case MODE_SELECT_10: case SEND_DIAGNOSTIC: case WRITE_BUFFER: - case FORMAT_UNIT: case REASSIGN_BLOCKS: case RESERVE: - case SEARCH_EQUAL: case SEARCH_HIGH: case SEARCH_LOW: - case WRITE_6: case WRITE_10: case WRITE_VERIFY: - case UPDATE_BLOCK: case WRITE_LONG: case WRITE_SAME: - case SEARCH_HIGH_12: case SEARCH_EQUAL_12: case SEARCH_LOW_12: - case WRITE_12: case WRITE_VERIFY_12: case SET_WINDOW: - case MEDIUM_SCAN: case SEND_VOLUME_TAG: - case 0xea: /* alternate number for WRITE LONG */ - cp->DataOut = TRUE; /* Output mode */ - break; - case TEST_UNIT_READY: - default: - cp->DataIn = TRUE; /* Input mode */ - } - - /* FIXME: This will will have to be changed once the midlevel driver - * allows different HBA IDs on every channel. - */ - if (cmd->target == sh->this_id) - cp->Interpret = TRUE; /* Interpret command */ - - if (cmd->use_sg) { - cp->scatter = TRUE; /* SG mode */ - if (cp->sg_list == NULL) { - cp->sg_list = kmalloc(sh->sg_tablesize * sizeof(struct eata_sg_list), - GFP_ATOMIC | GFP_DMA); - } - if (cp->sg_list == NULL) - panic("eata_dma: Run out of DMA memory for SG lists !\n"); - cp->cp_dataDMA = htonl(virt_to_bus(cp->sg_list)); - - cp->cp_datalen = htonl(cmd->use_sg * sizeof(struct eata_sg_list)); - sl=(struct scatterlist *)cmd->request_buffer; - for(i = 0; i < cmd->use_sg; i++, sl++){ - cp->sg_list[i].data = htonl(virt_to_bus(sl->address)); - cp->sg_list[i].len = htonl((u32) sl->length); - } - } else { - cp->scatter = FALSE; - cp->cp_datalen = htonl(cmd->request_bufflen); - cp->cp_dataDMA = htonl(virt_to_bus(cmd->request_buffer)); - } - - cp->Auto_Req_Sen = TRUE; - cp->cp_reqDMA = htonl(virt_to_bus(cmd->sense_buffer)); - cp->reqlen = sizeof(cmd->sense_buffer); - - cp->cp_id = cmd->target; - cp->cp_channel = cmd->channel; - cp->cp_lun = cmd->lun; - cp->cp_dispri = TRUE; - cp->cp_identify = TRUE; - memcpy(cp->cp_cdb, cmd->cmnd, cmd->cmd_len); - - cp->cp_statDMA = htonl(virt_to_bus(&(hd->sp))); - - cp->cp_viraddr = cp; /* This will be passed thru, so we don't need to - * convert it */ - cp->cmd = cmd; - cmd->host_scribble = (char *)&hd->ccb[y]; - - if(eata_send_command((u32) cp, (u32) sh->base, EATA_CMD_DMA_SEND_CP) == FALSE) { - cmd->result = DID_BUS_BUSY << 16; - DBG(DBG_QUEUE && DBG_ABNORM, - printk("eata_queue target %d, pid %ld, HBA busy, " - "returning DID_BUS_BUSY\n",cmd->target, cmd->pid)); - done(cmd); - cp->status = FREE; - restore_flags(flags); - return(0); - } - DBG(DBG_QUEUE, printk("Queued base %#.4x pid: %ld target: %x lun: %x " - "slot %d irq %d\n", (s32)sh->base, cmd->pid, - cmd->target, cmd->lun, y, sh->irq)); - DBG(DBG_QUEUE && DBG_DELAY, DEL2(200)); - restore_flags(flags); - return(0); -} - - -int eata_abort(Scsi_Cmnd * cmd) -{ - ulong loop = R_LIMIT; - ulong flags; - - save_flags(flags); - cli(); - - DBG(DBG_ABNORM, printk("eata_abort called pid: %ld target: %x lun: %x" - " reason %x\n", cmd->pid, cmd->target, cmd->lun, - cmd->abort_reason)); - DBG(DBG_ABNORM && DBG_DELAY, DEL2(500)); - - while (inb((u32)(cmd->host->base) + HA_RAUXSTAT) & HA_ABUSY) { - if (--loop == 0) { - printk("eata_dma: abort, timeout error.\n"); - restore_flags(flags); - DBG(DBG_ABNORM && DBG_DELAY, DEL2(500)); - return (SCSI_ABORT_ERROR); - } - } - if (CD(cmd)->status == RESET) { - restore_flags(flags); - printk("eata_dma: abort, command reset error.\n"); - DBG(DBG_ABNORM && DBG_DELAY, DEL2(500)); - return (SCSI_ABORT_ERROR); - } - if (CD(cmd)->status == LOCKED) { - restore_flags(flags); - DBG(DBG_ABNORM, printk("eata_dma: abort, queue slot locked.\n")); - DBG(DBG_ABNORM && DBG_DELAY, DEL2(500)); - return (SCSI_ABORT_NOT_RUNNING); - } - if (CD(cmd)->status == USED) { - DBG(DBG_ABNORM, printk("Returning: SCSI_ABORT_BUSY\n")); - restore_flags(flags); - return (SCSI_ABORT_BUSY); /* SNOOZE */ - } - if (CD(cmd)->status == FREE) { - DBG(DBG_ABNORM, printk("Returning: SCSI_ABORT_NOT_RUNNING\n")); - restore_flags(flags); - return (SCSI_ABORT_NOT_RUNNING); - } - restore_flags(flags); - panic("eata_dma: abort: invalid slot status\n"); -} - -int eata_reset(Scsi_Cmnd * cmd) -{ - ushort x, z; - ulong time, limit = 0; - ulong loop = R_LIMIT; - ulong flags; - unchar success = FALSE; - Scsi_Cmnd *sp; - - save_flags(flags); - cli(); - - DBG(DBG_ABNORM, printk("eata_reset called pid:%ld target: %x lun: %x" - " reason %x\n", cmd->pid, cmd->target, cmd->lun, - cmd->abort_reason)); - - if (HD(cmd)->state == RESET) { - printk("eata_reset: exit, already in reset.\n"); - restore_flags(flags); - DBG(DBG_ABNORM && DBG_DELAY, DEL2(500)); - return (SCSI_RESET_ERROR); - } - - while (inb((u32)(cmd->host->base) + HA_RAUXSTAT) & HA_ABUSY) - if (--loop == 0) { - printk("eata_reset: exit, timeout error.\n"); - restore_flags(flags); - DBG(DBG_ABNORM && DBG_DELAY, DEL2(500)); - return (SCSI_RESET_ERROR); - } - - for (x = 0; x < MAXCHANNEL; x++) { - for (z = 0; z < MAXTARGET; z++) { - HD(cmd)->t_state[x][z] = RESET; - HD(cmd)->t_timeout[x][z] = NO_TIMEOUT; - } - } - - for (x = 0; x < cmd->host->can_queue; x++) { - if (HD(cmd)->ccb[x].status == FREE) - continue; - - if (HD(cmd)->ccb[x].status == LOCKED) { - HD(cmd)->ccb[x].status = FREE; - printk("eata_reset: locked slot %d forced free.\n", x); - DBG(DBG_ABNORM && DBG_DELAY, DEL2(500)); - continue; - } - sp = HD(cmd)->ccb[x].cmd; - HD(cmd)->ccb[x].status = RESET; - printk("eata_reset: slot %d in reset, pid %ld.\n", x, sp->pid); - DBG(DBG_ABNORM && DBG_DELAY, DEL2(500)); - - if (sp == NULL) - panic("eata_reset: slot %d, sp==NULL.\n", x); - DBG(DBG_ABNORM && DBG_DELAY, DEL2(500)); - - if (sp == cmd) - success = TRUE; - } - - /* hard reset the HBA */ - inb((u32) (cmd->host->base) + HA_RSTATUS); /* This might cause trouble */ - eata_send_command(0, (u32) cmd->host->base, EATA_CMD_RESET); - - DBG(DBG_ABNORM, printk("eata_reset: board reset done, enabling interrupts.\n")); - HD(cmd)->state = RESET; - - restore_flags(flags); - - time = jiffies; - while (jiffies < (time + (3 * HZ)) || limit++ < 10000000) - /* As time goes by... */; - - save_flags(flags); - cli(); - - DBG(DBG_ABNORM, printk("eata_reset: interrupts disabled, loops %ld.\n", - limit)); - DBG(DBG_ABNORM && DBG_DELAY, DEL2(500)); - - for (x = 0; x < cmd->host->can_queue; x++) { - - /* Skip slots already set free by interrupt */ - if (HD(cmd)->ccb[x].status != RESET) - continue; - - sp = HD(cmd)->ccb[x].cmd; - sp->result = DID_RESET << 16; - - /* This mailbox is still waiting for its interrupt */ - HD(cmd)->ccb[x].status = LOCKED; - - printk("eata_reset: slot %d locked, DID_RESET, pid %ld done.\n", - x, sp->pid); - DBG(DBG_ABNORM && DBG_DELAY, DEL2(500)); - restore_flags(flags); - sp->scsi_done(sp); - cli(); - } - - HD(cmd)->state = FALSE; - restore_flags(flags); - - if (success) { - DBG(DBG_ABNORM, printk("eata_reset: exit, success.\n")); - DBG(DBG_ABNORM && DBG_DELAY, DEL2(500)); - return (SCSI_RESET_SUCCESS); - } else { - DBG(DBG_ABNORM, printk("eata_reset: exit, wakeup.\n")); - DBG(DBG_ABNORM && DBG_DELAY, DEL2(500)); - return (SCSI_RESET_PUNT); - } -} - -char * get_board_data(u32 base, u32 irq, u32 id) -{ - struct eata_ccb *cp; - struct eata_sp *sp; - static char *buff; - ulong i; - ulong limit = 0; - - cp = (struct eata_ccb *) scsi_init_malloc(sizeof(struct eata_ccb), - GFP_ATOMIC | GFP_DMA); - sp = (struct eata_sp *) scsi_init_malloc(sizeof(struct eata_sp), - GFP_ATOMIC | GFP_DMA); - - buff = dma_scratch; - - memset(cp, 0, sizeof(struct eata_ccb)); - memset(sp, 0, sizeof(struct eata_sp)); - memset(buff, 0, 256); - - cp->DataIn = TRUE; - cp->Interpret = TRUE; /* Interpret command */ - cp->cp_dispri = TRUE; - cp->cp_identify = TRUE; - - cp->cp_datalen = htonl(56); - cp->cp_dataDMA = htonl(virt_to_bus(buff)); - cp->cp_statDMA = htonl(virt_to_bus(sp)); - cp->cp_viraddr = cp; - - cp->cp_id = id; - cp->cp_lun = 0; - - cp->cp_cdb[0] = INQUIRY; - cp->cp_cdb[1] = 0; - cp->cp_cdb[2] = 0; - cp->cp_cdb[3] = 0; - cp->cp_cdb[4] = 56; - cp->cp_cdb[5] = 0; - - fake_int_base = (struct eata_register *) base; - fake_int_result = FALSE; - fake_int_happened = FALSE; - - eata_send_command((u32) cp, (u32) base, EATA_CMD_DMA_SEND_CP); - - i = jiffies + (3 * HZ); - while (fake_int_happened == FALSE && jiffies <= i) - barrier(); - - DBG(DBG_INTR3, printk("fake_int_result: %#x hbastat %#x scsistat %#x," - " buff %p sp %p\n", - fake_int_result, (u32) (sp->hba_stat /*& 0x7f*/), - (u32) sp->scsi_stat, buff, sp)); - - scsi_init_free((void *)cp, sizeof(struct eata_ccb)); - scsi_init_free((void *)sp, sizeof(struct eata_sp)); - - if ((fake_int_result & HA_SERROR) || jiffies > i){ - /* hard reset the HBA */ - inb((u32) (base) + HA_RSTATUS); - eata_send_command(0, base, EATA_CMD_RESET); - i = jiffies; - while (jiffies < (i + (3 * HZ)) && limit++ < 10000000) - barrier(); - return (NULL); - } else - return (buff); -} - -int check_blink_state(long base) -{ - ushort loops = 10; - u32 blinkindicator; - u32 state = 0x12345678; - u32 oldstate = 0; - - blinkindicator = htonl(0x54504442); - while ((loops--) && (state != oldstate)) { - oldstate = state; - state = inl((uint) base + 1); - } - - DBG(DBG_BLINK, printk("Did Blink check. Status: %d\n", - (state == oldstate) && (state == blinkindicator))); - - if ((state == oldstate) && (state == blinkindicator)) - return(TRUE); - else - return (FALSE); -} - -int get_conf_PIO(u32 base, struct get_conf *buf) -{ - ulong loop = R_LIMIT; - u16 *p; - - if(check_region(base, 9)) - return (FALSE); - - memset(buf, 0, sizeof(struct get_conf)); - - while (inb(base + HA_RSTATUS) & HA_SBUSY) - if (--loop == 0) - return (FALSE); - - DBG(DBG_PIO && DBG_PROBE, - printk("Issuing PIO READ CONFIG to HBA at %#x\n", base)); - eata_send_command(0, base, EATA_CMD_PIO_READ_CONFIG); - - loop = R_LIMIT; - for (p = (u16 *) buf; - (long)p <= ((long)buf + (sizeof(struct get_conf) / 2)); p++) { - while (!(inb(base + HA_RSTATUS) & HA_SDRQ)) - if (--loop == 0) - return (FALSE); - - loop = R_LIMIT; - *p = inw(base + HA_RDATA); - } - - if (!(inb(base + HA_RSTATUS) & HA_SERROR)) { /* Error ? */ - if (htonl(EATA_SIGNATURE) == buf->signature) { - DBG(DBG_PIO&&DBG_PROBE, printk("EATA Controller found at %x " - "EATA Level: %x\n", (uint) base, - (uint) (buf->version))); - - while (inb(base + HA_RSTATUS) & HA_SDRQ) - inw(base + HA_RDATA); - return (TRUE); - } - } else { - DBG(DBG_PROBE, printk("eata_dma: get_conf_PIO, error during transfer " - "for HBA at %lx\n", (long)base)); - } - return (FALSE); -} - -void print_config(struct get_conf *gc) -{ - printk("LEN: %d ver:%d OCS:%d TAR:%d TRNXFR:%d MORES:%d DMAS:%d\n", - (u32) ntohl(gc->len), gc->version, - gc->OCS_enabled, gc->TAR_support, gc->TRNXFR, gc->MORE_support, - gc->DMA_support); - printk("DMAV:%d HAAV:%d SCSIID0:%d ID1:%d ID2:%d QUEUE:%d SG:%d SEC:%d\n", - gc->DMA_valid, gc->HAA_valid, gc->scsi_id[3], gc->scsi_id[2], - gc->scsi_id[1], ntohs(gc->queuesiz), ntohs(gc->SGsiz), gc->SECOND); - printk("IRQ:%d IRQT:%d DMAC:%d FORCADR:%d SG_64K:%d SG_UAE:%d MID:%d " - "MCH:%d MLUN:%d\n", - gc->IRQ, gc->IRQ_TR, (8 - gc->DMA_channel) & 7, gc->FORCADR, - gc->SG_64K, gc->SG_UAE, gc->MAX_ID, gc->MAX_CHAN, gc->MAX_LUN); - printk("RIDQ:%d PCI:%d EISA:%d\n", - gc->ID_qest, gc->is_PCI, gc->is_EISA); - DBG(DPT_DEBUG, DELAY(14)); -} - -short register_HBA(u32 base, struct get_conf *gc, Scsi_Host_Template * tpnt, - u8 bustype) -{ - ulong size = 0; - unchar dma_channel = 0; - char *buff = 0; - unchar bugs = 0; - struct Scsi_Host *sh; - hostdata *hd; - int x; - - - DBG(DBG_REGISTER, print_config(gc)); - - if (gc->DMA_support == FALSE) { - printk("The EATA HBA at %#.4x does not support DMA.\n" - "Please use the EATA-PIO driver.\n", base); - return (FALSE); - } - if(gc->HAA_valid == FALSE || ntohl(gc->len) < 0x22) - gc->MAX_CHAN = 0; - - if (reg_IRQ[gc->IRQ] == FALSE) { /* Interrupt already registered ? */ - if (!request_irq(gc->IRQ, (void *) eata_fake_int_handler, SA_INTERRUPT, - "eata_dma")){ - reg_IRQ[gc->IRQ]++; - if (!gc->IRQ_TR) - reg_IRQL[gc->IRQ] = TRUE; /* IRQ is edge triggered */ - } else { - printk("Couldn't allocate IRQ %d, Sorry.", gc->IRQ); - return (FALSE); - } - } else { /* More than one HBA on this IRQ */ - if (reg_IRQL[gc->IRQ] == TRUE) { - printk("Can't support more than one HBA on this IRQ,\n" - " if the IRQ is edge triggered. Sorry.\n"); - return (FALSE); - } else - reg_IRQ[gc->IRQ]++; - } - - /* if gc->DMA_valid it must be an ISA HBA and we have to register it */ - dma_channel = BUSMASTER; - if (gc->DMA_valid) { - if (request_dma(dma_channel = (8 - gc->DMA_channel) & 7, "eata_dma")) { - printk("Unable to allocate DMA channel %d for ISA HBA at %#.4x.\n", - dma_channel, base); - reg_IRQ[gc->IRQ]--; - if (reg_IRQ[gc->IRQ] == 0) - free_irq(gc->IRQ); - if (gc->IRQ_TR == FALSE) - reg_IRQL[gc->IRQ] = FALSE; - return (FALSE); - } - } - -#if !(NEWSTUFF) - if (bustype != IS_EISA && bustype != IS_ISA) -#endif - buff = get_board_data(base, gc->IRQ, gc->scsi_id[3]); - - if (buff == NULL) { -#if !(NEWSTUFF) - if (bustype == IS_EISA || bustype == IS_ISA) { - bugs = bugs || BROKEN_INQUIRY; - } else { -#endif - if (gc->DMA_support == FALSE) - printk("HBA at %#.4x doesn't support DMA. Sorry\n", base); - else - printk("HBA at %#.4x does not react on INQUIRY. Sorry.\n", - base); - if (gc->DMA_valid) - free_dma(dma_channel); - reg_IRQ[gc->IRQ]--; - if (reg_IRQ[gc->IRQ] == 0) - free_irq(gc->IRQ); - if (gc->IRQ_TR == FALSE) - reg_IRQL[gc->IRQ] = FALSE; - return (FALSE); -#if !(NEWSTUFF) - } -#endif - } - - if (gc->DMA_support == FALSE && buff != NULL) - printk("HBA %.12sat %#.4x doesn't set the DMA_support flag correctly.\n", - &buff[16], base); - - request_region(base, 9, "eata_dma"); /* We already checked the - * availability, so this - * should not fail. - */ - - if(ntohs(gc->queuesiz) == 0) { - gc->queuesiz = ntohs(64); - printk("Warning: Queue size has to be corrected. Assuming 64 queueslots\n" - " This might be a PM2012B with a defective Firmware\n"); - } - - size = sizeof(hostdata) + ((sizeof(struct eata_ccb) + sizeof(long)) - * ntohs(gc->queuesiz)); - - DBG(DBG_REGISTER, printk("scsi_register size: %ld\n", size)); - - sh = scsi_register(tpnt, size); - - if(sh == NULL) { - if (gc->DMA_valid) - free_dma(dma_channel); - - reg_IRQ[gc->IRQ]--; - if (reg_IRQ[gc->IRQ] == 0) - free_irq(gc->IRQ); - if (gc->IRQ_TR == FALSE) - reg_IRQL[gc->IRQ] = FALSE; - return (FALSE); - } - - hd = SD(sh); - - memset(hd->ccb, 0, sizeof(struct eata_ccb) * ntohs(gc->queuesiz)); - memset(hd->reads, 0, sizeof(u32) * 26); - - hd->broken_INQUIRY = (bugs & BROKEN_INQUIRY); - - if(hd->broken_INQUIRY == TRUE) { - strcpy(SD(sh)->vendor, "DPT"); - strcpy(SD(sh)->name, "??????????"); - strcpy(SD(sh)->revision, "???.?"); - } else { - strncpy(SD(sh)->vendor, &buff[8], 8); - SD(sh)->vendor[8] = 0; - strncpy(SD(sh)->name, &buff[16], 17); - SD(sh)->name[17] = 0; - SD(sh)->revision[0] = buff[32]; - SD(sh)->revision[1] = buff[33]; - SD(sh)->revision[2] = buff[34]; - SD(sh)->revision[3] = '.'; - SD(sh)->revision[4] = buff[35]; - SD(sh)->revision[5] = 0; - } - - switch (ntohl(gc->len)) { - case 0x1c: - SD(sh)->EATA_revision = 'a'; - break; - case 0x1e: - SD(sh)->EATA_revision = 'b'; - break; - case 0x22: - SD(sh)->EATA_revision = 'c'; - break; - case 0x24: - SD(sh)->EATA_revision = 'z'; - default: - SD(sh)->EATA_revision = '?'; - } - - if(ntohl(gc->len) >= 0x22) { - if (gc->is_PCI == TRUE) - hd->bustype = IS_PCI; - else if (gc->is_EISA == TRUE) - hd->bustype = IS_EISA; - else - hd->bustype = IS_ISA; - } else if(hd->broken_INQUIRY == FALSE) { - if (buff[21] == '4') - hd->bustype = IS_PCI; - else if (buff[21] == '2') - hd->bustype = IS_EISA; - else - hd->bustype = IS_ISA; - } else - hd->bustype = bustype; - - if(ntohl(gc->len) >= 0x22) { - sh->max_id = gc->MAX_ID + 1; - sh->max_lun = gc->MAX_LUN + 1; - } else { - sh->max_id = 8; - sh->max_lun = 8; - } - - hd->channel = gc->MAX_CHAN; - sh->max_channel = gc->MAX_CHAN; - sh->unique_id = base; - sh->base = (char *) base; - sh->io_port = base; - sh->n_io_port = 9; - sh->irq = gc->IRQ; - sh->dma_channel = dma_channel; - - /* FIXME: - * SCSI midlevel code should support different HBA ids on every channel - */ - sh->this_id = gc->scsi_id[3]; - sh->can_queue = ntohs(gc->queuesiz); - - if (gc->OCS_enabled == TRUE) { - if(hd->bustype != IS_ISA) - sh->cmd_per_lun = sh->can_queue/C_P_L_DIV; - else - sh->cmd_per_lun = 8; /* We artificially limit this to conserve - * memory, which would be needed for ISA - * bounce buffers */ - } else - sh->cmd_per_lun = 1; - - /* FIXME: - * SG should be allocated more dynamically - */ - /* - * If we are using a ISA board, we can't use extended SG, - * because we would need exessive amounts of memory for - * bounce buffers. - */ - if (gc->SG_64K == TRUE && ntohs(gc->SGsiz) == 64 && hd->bustype != IS_ISA){ - sh->sg_tablesize = SG_SIZE_BIG; - sh->use_clustering = FALSE; - } else { - sh->sg_tablesize = ntohs(gc->SGsiz); - sh->use_clustering = TRUE; - if (sh->sg_tablesize > SG_SIZE || sh->sg_tablesize == 0) { - sh->sg_tablesize = SG_SIZE; - if (ntohs(gc->SGsiz) == 0) - printk("Warning: SG size had to be corrected.\n" - "This might be a PM2012 with a defective Firmware\n"); - } - } - - if (gc->SECOND) - hd->primary = FALSE; - else - hd->primary = TRUE; - - sh->wish_block = FALSE; - - if (hd->bustype != IS_ISA) { - sh->unchecked_isa_dma = FALSE; - } else { - sh->unchecked_isa_dma = TRUE; /* We're doing ISA DMA */ - } - - for(x = 0; x <= 11; x++){ /* Initialize min. latency */ - hd->writes_lat[x][1] = 0xffffffff; - hd->reads_lat[x][1] = 0xffffffff; - } - - hd->next = NULL; /* build a linked list of all HBAs */ - hd->prev = last_HBA; - if(hd->prev != NULL) - SD(hd->prev)->next = sh; - last_HBA = sh; - if (first_HBA == NULL) - first_HBA = sh; - registered_HBAs++; - - return (TRUE); -} - - -void find_EISA(struct get_conf *buf, Scsi_Host_Template * tpnt) -{ - u32 base; - int i; - -#if CHECKPAL - u8 pal1, pal2, pal3; -#endif - - for (i = 0; i < MAXEISA; i++) { - if (EISAbases[i] == TRUE) { /* Still a possibility ? */ - - base = 0x1c88 + (i * 0x1000); -#if CHECKPAL - pal1 = inb((u16)base - 8); - pal2 = inb((u16)base - 7); - pal3 = inb((u16)base - 6); - - if (((pal1 == DPT_ID1) && (pal2 == DPT_ID2)) || - ((pal1 == NEC_ID1) && (pal2 == NEC_ID2) && (pal3 == NEC_ID3))|| - ((pal1 == ATT_ID1) && (pal2 == ATT_ID2) && (pal3 == ATT_ID3))){ - DBG(DBG_PROBE, printk("EISA EATA id tags found: %x %x %x \n", - (int)pal1, (int)pal2, (int)pal3)); -#endif - if (get_conf_PIO(base, buf) == TRUE) { - if (buf->IRQ) { - DBG(DBG_EISA, printk("Registering EISA HBA\n")); - register_HBA(base, buf, tpnt, IS_EISA); - } else - printk("eata_dma: No valid IRQ. HBA removed from list\n"); - } else { - if (check_blink_state(base)) - printk("HBA is in BLINK state. Consult your HBAs " - "Manual to correct this.\n"); - } - /* Nothing found here so we take it from the list */ - EISAbases[i] = 0; -#if CHECKPAL - } -#endif - } - } - return; -} - -void find_ISA(struct get_conf *buf, Scsi_Host_Template * tpnt) -{ - int i; - - for (i = 0; i < MAXISA; i++) { - if (ISAbases[i]) { - if (get_conf_PIO(ISAbases[i],buf) == TRUE){ - DBG(DBG_ISA, printk("Registering ISA HBA\n")); - register_HBA(ISAbases[i], buf, tpnt, IS_ISA); - } else { - if (check_blink_state(ISAbases[i])) - printk("HBA is in BLINK state. Consult your HBAs " - "Manual to correct this.\n"); - } - ISAbases[i] = 0; - } - } - return; -} - -void find_PCI(struct get_conf *buf, Scsi_Host_Template * tpnt) -{ - -#ifndef CONFIG_PCI - printk("eata_dma: kernel PCI support not enabled. Skipping scan for PCI HBAs.\n"); -#else - - u8 pci_bus, pci_device_fn; - static s16 pci_index = 0; /* Device index to PCI BIOS calls */ - u32 base = 0; - u16 com_adr; - u16 rev_device; - u32 error, i, x; - u8 pal1, pal2, pal3; - - if (pcibios_present()) { - for (i = 0; i <= MAXPCI; ++i, ++pci_index) { - if (pcibios_find_device(PCI_VENDOR_ID_DPT, PCI_DEVICE_ID_DPT, - pci_index, &pci_bus, &pci_device_fn)) - break; - DBG(DBG_PROBE && DBG_PCI, - printk("eata_dma: find_PCI, HBA at bus %d, device %d," - " function %d, index %d\n", (s32)pci_bus, - (s32)((pci_device_fn & 0xf8) >> 3), - (s32)(pci_device_fn & 7), pci_index)); - - if (!(error = pcibios_read_config_word(pci_bus, pci_device_fn, - PCI_CLASS_DEVICE, &rev_device))) { - if (rev_device == PCI_CLASS_STORAGE_SCSI) { - if (!(error = pcibios_read_config_word(pci_bus, - pci_device_fn, PCI_COMMAND, - (u16 *) & com_adr))) { - if (!((com_adr & PCI_COMMAND_IO) && - (com_adr & PCI_COMMAND_MASTER))) { - printk("eata_dma: find_PCI, HBA has IO or BUSMASTER mode disabled\n"); - continue; - } - } else - printk("eata_dma: find_PCI, error %x while reading " - "PCI_COMMAND\n", error); - } else - printk("eata_dma: find_PCI, DEVICECLASSID %x didn't match\n", - rev_device); - } else { - printk("eata_dma: find_PCI, error %x while reading PCI_CLASS_BASE\n", - error); - continue; - } - - if (!(error = pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_0, (int *) &base))){ - - /* Check if the address is valid */ - if (base & 0x01) { - base &= 0xfffffffe; - /* EISA tag there ? */ - pal1 = inb(base); - pal2 = inb(base + 1); - pal3 = inb(base + 2); - if (((pal1 == DPT_ID1) && (pal2 == DPT_ID2)) || - ((pal1 == NEC_ID1) && (pal2 == NEC_ID2) && - (pal3 == NEC_ID3)) || - ((pal1 == ATT_ID1) && (pal2 == ATT_ID2) && - (pal3 == ATT_ID3))) - base += 0x08; - else - base += 0x10; /* Now, THIS is the real address */ - - if (base != 0x1f8) { - /* We didn't find it in the primary search */ - if (get_conf_PIO(base, buf) == TRUE) { - - /* OK. We made it till here, so we can go now - * and register it. We only have to check and - * eventually remove it from the EISA and ISA list - */ - DBG(DBG_PCI, printk("Registering PCI HBA\n")); - register_HBA(base, buf, tpnt, IS_PCI); - - if (base < 0x1000) { - for (x = 0; x < MAXISA; ++x) { - if (ISAbases[x] == base) { - ISAbases[x] = 0; - break; - } - } - } else if ((base & 0x0fff) == 0x0c88) - EISAbases[(base >> 12) & 0x0f] = 0; - continue; /* break; */ - } else if (check_blink_state(base) == TRUE) { - printk("eata_dma: HBA is in BLINK state.\n" - "Consult your HBAs Manual to correct this.\n"); - } - } - } - } else { - printk("eata_dma: error %x while reading " - "PCI_BASE_ADDRESS_0\n", error); - } - } - } else { - printk("eata_dma: No BIOS32 extensions present. This driver release " - "still depends on it.\n" - " Skipping scan for PCI HBAs. \n"); - } -#endif /* #ifndef CONFIG_PCI */ - return; -} - -int eata_detect(Scsi_Host_Template * tpnt) -{ - struct Scsi_Host *HBA_ptr; - struct get_conf gc; - int i; - - DBG((DBG_PROBE && DBG_DELAY) || DPT_DEBUG, - printk("Using lots of delays to let you read the debugging output\n")); - - tpnt->proc_dir = &proc_scsi_eata_dma; - - status = scsi_init_malloc(512, GFP_ATOMIC | GFP_DMA); - dma_scratch = scsi_init_malloc(512, GFP_ATOMIC | GFP_DMA); - - if(status == NULL || dma_scratch == NULL) { - printk("eata_dma: can't allocate enough memory to probe for hosts !\n"); - return(0); - } - - find_PCI(&gc, tpnt); - - find_EISA(&gc, tpnt); - - find_ISA(&gc, tpnt); - - for (i = 0; i <= MAXIRQ; i++) { /* Now that we know what we have, we */ - if (reg_IRQ[i]){ /* exchange the interrupt handler which */ - free_irq(i); /* we used for probing with the real one */ - request_irq(i, (void *)(eata_int_handler), SA_INTERRUPT, "eata_dma"); - } - } - HBA_ptr = first_HBA; - - if (registered_HBAs != 0) { - printk("EATA (Extended Attachment) driver version: %d.%d%s\n" - "developed in co-operation with DPT\n" - "(c) 1993-95 Michael Neuffer, neuffer@goofy.zdv.uni-mainz.de\n", - VER_MAJOR, VER_MINOR, VER_SUB); - printk("Registered HBAs:"); - printk("\nHBA no. Boardtype: Revis: EATA: Bus: BaseIO: IRQ: DMA: Ch: " - "ID: Pr: QS: SG: CPL:\n"); - for (i = 1; i <= registered_HBAs; i++) { - printk("scsi%-2d: %.10s v%s 2.0%c %s %#.4x %2d", - HBA_ptr->host_no, SD(HBA_ptr)->name, SD(HBA_ptr)->revision, - SD(HBA_ptr)->EATA_revision, (SD(HBA_ptr)->bustype == 'P')? - "PCI ":(SD(HBA_ptr)->bustype == 'E')?"EISA":"ISA ", - (u32) HBA_ptr->base, HBA_ptr->irq); - if(HBA_ptr->dma_channel != BUSMASTER) - printk(" %2x ", HBA_ptr->dma_channel); - else - printk(" %s", "BMST"); - printk(" %d %d %c %2d %2d %2d\n", SD(HBA_ptr)->channel, - HBA_ptr->this_id, (SD(HBA_ptr)->primary == TRUE)?'Y':'N', - HBA_ptr->can_queue, HBA_ptr->sg_tablesize, HBA_ptr->cmd_per_lun); - HBA_ptr = SD(HBA_ptr)->next; - } - } else { - scsi_init_free((void *)status, 512); - } - - scsi_init_free((void *)dma_scratch, 512); - - DBG(DPT_DEBUG, DELAY(12)); - - return(registered_HBAs); -} - -#ifdef MODULE -/* Eventually this will go into an include file, but this will be later */ -Scsi_Host_Template driver_template = EATA_DMA; -#include "scsi_module.c" -#endif - -/* - * Overrides for Emacs so that we almost follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 4 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -4 - * c-argdecl-indent: 4 - * c-label-offset: -4 - * c-continued-statement-offset: 4 - * c-continued-brace-offset: 0 - * tab-width: 8 - * End: - */ diff --git a/i386/i386at/gpl/linux/scsi/eata_dma.h b/i386/i386at/gpl/linux/scsi/eata_dma.h deleted file mode 100644 index 41504673..00000000 --- a/i386/i386at/gpl/linux/scsi/eata_dma.h +++ /dev/null @@ -1,119 +0,0 @@ -/******************************************************** -* Header file for eata_dma.c Linux EATA-DMA SCSI driver * -* (c) 1993,94,95 Michael Neuffer * -********************************************************* -* last change: 95/07/18 * -********************************************************/ - - -#ifndef _EATA_DMA_H -#define _EATA_DMA_H - -#ifndef HOSTS_C - -#include "eata_generic.h" - - -#define VER_MAJOR 2 -#define VER_MINOR 5 -#define VER_SUB "8a" - - -/************************************************************************ - * Here you can switch parts of the code on and of * - ************************************************************************/ - -#define CHECKPAL 0 /* EISA pal checking on/off */ -#define NEWSTUFF 0 /* Some changes for ISA/EISA boards */ - -/************************************************************************ - * Debug options. * - * Enable DEBUG and whichever options you require. * - ************************************************************************/ -#define DEBUG_EATA 1 /* Enable debug code. */ -#define DPT_DEBUG 0 /* Bobs special */ -#define DBG_DELAY 0 /* Build in delays so debug messages can be - * be read before they vanish of the top of - * the screen! */ -#define DBG_PROBE 0 /* Debug probe routines. */ -#define DBG_PCI 0 /* Trace PCI routines */ -#define DBG_EISA 0 /* Trace EISA routines */ -#define DBG_ISA 0 /* Trace ISA routines */ -#define DBG_BLINK 0 /* Trace Blink check */ -#define DBG_PIO 0 /* Trace get_config_PIO */ -#define DBG_COM 0 /* Trace command call */ -#define DBG_QUEUE 0 /* Trace command queueing. */ -#define DBG_QUEUE2 0 /* Trace command queueing SG. */ -#define DBG_INTR 0 /* Trace interrupt service routine. */ -#define DBG_INTR2 0 /* Trace interrupt service routine. */ -#define DBG_INTR3 0 /* Trace get_board_data interrupts. */ -#define DBG_PROC 0 /* Debug proc-fs related statistics */ -#define DBG_PROC_WRITE 0 -#define DBG_REGISTER 0 /* */ -#define DBG_ABNORM 1 /* Debug abnormal actions (reset, abort)*/ - -#if DEBUG_EATA -#define DBG(x, y) if ((x)) {y;} -#else -#define DBG(x, y) -#endif - -#endif /* !HOSTS_C */ - -int eata_detect(Scsi_Host_Template *); -const char *eata_info(struct Scsi_Host *); -int eata_command(Scsi_Cmnd *); -int eata_queue(Scsi_Cmnd *, void (* done)(Scsi_Cmnd *)); -int eata_abort(Scsi_Cmnd *); -int eata_reset(Scsi_Cmnd *); -int eata_proc_info(char *, char **, off_t, int, int, int); -#ifdef MODULE -int eata_release(struct Scsi_Host *); -#else -#define eata_release NULL -#endif - -#include <linux/scsicam.h> - -#define EATA_DMA { \ - NULL, NULL, \ - NULL, /* proc_dir_entry */ \ - eata_proc_info, /* procinfo */ \ - "EATA (Extended Attachment) HBA driver", \ - eata_detect, \ - eata_release, \ - NULL, NULL, \ - eata_queue, \ - eata_abort, \ - eata_reset, \ - NULL, /* Slave attach */ \ - scsicam_bios_param, \ - 0, /* Canqueue */ \ - 0, /* this_id */ \ - 0, /* sg_tablesize */ \ - 0, /* cmd_per_lun */ \ - 0, /* present */ \ - 1, /* True if ISA */ \ - ENABLE_CLUSTERING } - - -#endif /* _EATA_DMA_H */ - -/* - * Overrides for Emacs so that we almost follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 4 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -4 - * c-argdecl-indent: 4 - * c-label-offset: -4 - * c-continued-statement-offset: 4 - * c-continued-brace-offset: 0 - * indent-tabs-mode: nil - * tab-width: 8 - * End: - */ diff --git a/i386/i386at/gpl/linux/scsi/eata_dma_proc.h b/i386/i386at/gpl/linux/scsi/eata_dma_proc.h deleted file mode 100644 index d49f348e..00000000 --- a/i386/i386at/gpl/linux/scsi/eata_dma_proc.h +++ /dev/null @@ -1,260 +0,0 @@ - -struct lun_map { - __u8 id:5, - chan:3; - __u8 lun; -}; - -typedef struct emul_pp { - __u8 p_code:6, - null:1, - p_save:1; - __u8 p_length; - __u16 cylinder; - __u8 heads; - __u8 sectors; - __u8 null2; - __u8 s_lunmap:4, - ems:1; - __u16 drive_type; /* In Little Endian ! */ - struct lun_map lunmap[4]; -}emulpp; - - -/* Log Sense pages */ - -typedef struct log_sheader { - __u8 page_code, - reserved; - __u16 length; -}logsh; - - -/* Log Sense Statistics */ - -typedef struct read_command_statistics { - __u16 code; /* 0x01 */ - __u8 flags; - __u8 length; /* 0x24 */ - __u32 h_commands, - uncached, - la_cmds, - la_blks, - la_hits, - missed, - hits, - seq_la_blks, - seq_la_hits; -}r_cmd_stat; - -typedef struct write_command_statistics { - __u16 code; /* 0x03 */ - __u8 flags; - __u8 length; /* 0x28 */ - __u32 h_commands, - uncached, - thru, - bypass, - soft_err, - hits, - b_idle, - b_activ, - b_blks, - b_blks_clean; -}w_cmd_stat; - -typedef struct host_command_statistics { - __u16 code; /* 0x02, 0x04 */ - __u8 flags; - __u8 length; /* 0x30 */ - __u32 sizes[12]; -}hst_cmd_stat; - -typedef struct physical_command_statistics { - __u16 code; /* 0x06, 0x07 */ - __u8 flags; - __u8 length; /* 0x34 */ - __u32 sizes[13]; -}phy_cmd_stat; - -typedef struct misc_device_statistics { - __u16 code; /* 0x05 */ - __u8 flags; - __u8 length; /* 0x10 */ - __u32 disconnect, - pass_thru, - sg_commands, - stripe_boundary_crosses; -}msc_stats; - -/* Configuration Pages */ - -typedef struct controller_configuration { - __u16 code; /* 0x01 */ - __u8 flags; - __u8 length; /* 0x02 */ - __u8 intt:1, - sec:1, - csh:1, - key:1, - tmr:1, - srs:1, - nvr:1; - __u8 interrupt; -}coco; - -typedef struct controller_hardware_errors { - __u16 code; /* 0x02 */ - __u8 flags; - __u8 length; /* 0x02 */ - __u8 unused:1, - per:1; - __u8 interrupt; -}coher; - -typedef struct memory_map { - __u16 code; /* 0x03, 0x04 */ - __u8 flags; - __u8 length; /* 0x04 */ - __u32 memory_map; -}mema; - -typedef struct scsi_transfer { - __u16 code; /* 0x05 */ - __u8 flags; - __u8 length; /* 0x04 */ - __u8 offset, - period; - __u16 speed; -}scsitrans; - -typedef struct scsi_modes { - __u16 code; /* 0x06 */ - __u8 flags; - __u8 length; /* 0x02 */ - __u8 que:1, - cdis:1, - wtru:1, - dasd:1, - ncr:1, - awre:1; - __u8 reserved; -}scsimod; - -typedef struct host_bus { - __u16 code; /* 0x07 */ - __u8 flags; - __u8 length; /* 0x02 */ - __u8 speed:6, - pci:1, - eisa:1; - __u8 reserved; -}hobu; - -typedef struct scsi_bus { - __u16 code; /* 0x08 */ - __u8 flags; - __u8 length; /* 0x02 */ - __u8 speed:4, - res:1, - ext:1, - wide:1, - dif:1; - __u8 busnum; -}scbu; - -typedef struct board_type { - __u16 code; /* 0x09 */ - __u8 flags; - __u8 length; /* 0x04 */ - __u8 unused:1, - cmi:1, - dmi:1, - cm4k:1, - cm4:1, - dm4k:1, - dm4:1, - hba:1; - __u8 cpu_type, - cpu_speed; - __u8 sx1:1, - sx2:1, - unused2:4, - alrm:1, - srom:1; -}boty; - -typedef struct memory_config { - __u16 code; /* 0x0a */ - __u8 flags; - __u8 length; /* 0x04 */ - __u8 banksize[4]; -}memco; - -typedef struct firmware_info { - __u16 code; /* 0x0b */ - __u8 flags; - __u8 length; /* 0x04 */ - __u8 dnld:1, - bs528:1, - fmt:1, - fw528:1; - __u8 unused1, - fw_type, - unused; -}firm; - -typedef struct subsystem_info { - __u16 code; /* 0x0c */ - __u8 flags; - __u8 length; /* 0x02 */ - __u8 shlf:1, - swap:1, - noss:1; - __u8 reserved; -}subinf; - -typedef struct per_channel_info { - __u16 code; /* 0x0d */ - __u8 flags; - __u8 length; /* 0x02 */ - __u8 channel; - __u8 shlf:1, - swap:1, - noss:1, - srs:1, - que:1, - ext:1, - wide:1, - diff:1; -}pcinf; - -typedef struct array_limits { - __u16 code; /* 0x0e */ - __u8 flags; - __u8 length; /* 0x04 */ - __u8 max_groups, - raid0_drv, - raid35_drv, - unused; -}arrlim; - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 4 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -4 - * c-argdecl-indent: 4 - * c-label-offset: -4 - * c-continued-statement-offset: 4 - * c-continued-brace-offset: 0 - * indent-tabs-mode: nil - * tab-width: 8 - * End: - */ - diff --git a/i386/i386at/gpl/linux/scsi/eata_dma_proc.src b/i386/i386at/gpl/linux/scsi/eata_dma_proc.src deleted file mode 100644 index b4936a67..00000000 --- a/i386/i386at/gpl/linux/scsi/eata_dma_proc.src +++ /dev/null @@ -1,488 +0,0 @@ - -void swap_statistics(u8 *p) -{ - u32 y; - u32 *lp, h_lp; - u16 *sp, h_sp; - u8 *bp; - - lp = (u32 *)p; - sp = ((short *)lp) + 1; /* Convert Header */ - h_sp = *sp = ntohs(*sp); - lp++; - - do { - sp = (u16 *)lp; /* Convert SubHeader */ - *sp = ntohs(*sp); - bp = (u8 *) lp; - y = *(bp + 3); - lp++; - for (h_lp = (u32)lp; (u32)lp < h_lp + ((u32)*(bp + 3)); lp++) - *lp = ntohl(*lp); - }while ((u32)lp < ((u32)p) + 4 + h_sp); - -} - -/* - * eata_set_info - * buffer : pointer to the data that has been written to the hostfile - * length : number of bytes written to the hostfile - * HBA_ptr: pointer to the Scsi_Host struct - */ -int eata_set_info(char *buffer, int length, struct Scsi_Host *HBA_ptr) -{ - int orig_length = length; - - if (length >= 8 && strncmp(buffer, "eata_dma", 8) == 0) { - buffer += 9; - length -= 9; - if(length >= 8 && strncmp(buffer, "latency", 7) == 0) { - SD(HBA_ptr)->do_latency = TRUE; - return(orig_length); - } - - if(length >=10 && strncmp(buffer, "nolatency", 9) == 0) { - SD(HBA_ptr)->do_latency = FALSE; - return(orig_length); - } - - printk("Unknown command:%s length: %d\n", buffer, length); - } else - printk("Wrong Signature:%10s\n", buffer); - - return(-EINVAL); -} - -/* - * eata_proc_info - * inout : decides on the direction of the dataflow and the meaning of the - * variables - * buffer: If inout==FALSE data is beeing written to it else read from it - * *start: If inout==FALSE start of the valid data in the buffer - * offset: If inout==FALSE offset from the beginning of the imaginary file - * from which we start writing into the buffer - * length: If inout==FALSE max number of bytes to be written into the buffer - * else number of bytes in the buffer - */ -int eata_proc_info(char *buffer, char **start, off_t offset, int length, - int hostno, int inout) -{ - - Scsi_Device *scd, SDev; - struct Scsi_Host *HBA_ptr; - Scsi_Cmnd scmd; - char cmnd[10]; - static u8 buff[512]; - static u8 buff2[512]; - hst_cmd_stat *rhcs, *whcs; - coco *cc; - scsitrans *st; - scsimod *sm; - hobu *hb; - scbu *sb; - boty *bt; - memco *mc; - firm *fm; - subinf *si; - pcinf *pi; - arrlim *al; - int i, x; - int size, len = 0; - off_t begin = 0; - off_t pos = 0; - scd = NULL; - - HBA_ptr = first_HBA; - for (i = 1; i <= registered_HBAs; i++) { - if (HBA_ptr->host_no == hostno) - break; - HBA_ptr = SD(HBA_ptr)->next; - } - - if(inout == TRUE) /* Has data been writen to the file ? */ - return(eata_set_info(buffer, length, HBA_ptr)); - - if (offset == 0) - memset(buff, 0, sizeof(buff)); - - cc = (coco *) (buff + 0x148); - st = (scsitrans *)(buff + 0x164); - sm = (scsimod *) (buff + 0x16c); - hb = (hobu *) (buff + 0x172); - sb = (scbu *) (buff + 0x178); - bt = (boty *) (buff + 0x17e); - mc = (memco *) (buff + 0x186); - fm = (firm *) (buff + 0x18e); - si = (subinf *) (buff + 0x196); - pi = (pcinf *) (buff + 0x19c); - al = (arrlim *) (buff + 0x1a2); - - size = sprintf(buffer+len, "EATA (Extended Attachment) driver version: " - "%d.%d%s\n",VER_MAJOR, VER_MINOR, VER_SUB); - len += size; pos = begin + len; - size = sprintf(buffer + len, "queued commands: %10ld\n" - "processed interrupts:%10ld\n", queue_counter, int_counter); - len += size; pos = begin + len; - - size = sprintf(buffer + len, "\nscsi%-2d: HBA %.10s\n", - HBA_ptr->host_no, SD(HBA_ptr)->name); - len += size; - pos = begin + len; - size = sprintf(buffer + len, "Firmware revision: v%s\n", - SD(HBA_ptr)->revision); - len += size; - pos = begin + len; - size = sprintf(buffer + len, "Hardware Configuration:\n"); - len += size; - pos = begin + len; - - if(SD(HBA_ptr)->broken_INQUIRY == TRUE) { - if (HBA_ptr->dma_channel == BUSMASTER) - size = sprintf(buffer + len, "DMA: BUSMASTER\n"); - else - size = sprintf(buffer + len, "DMA: %d\n", HBA_ptr->dma_channel); - len += size; - pos = begin + len; - - size = sprintf(buffer + len, "Base IO : %#.4x\n", (u32) HBA_ptr->base); - len += size; - pos = begin + len; - - size = sprintf(buffer + len, "Host Bus: EISA\n"); - len += size; - pos = begin + len; - - } else { - memset(&SDev, 0, sizeof(Scsi_Device)); - memset(&scmd, 0, sizeof(Scsi_Cmnd)); - - SDev.host = HBA_ptr; - SDev.id = HBA_ptr->this_id; - SDev.lun = 0; - SDev.channel = 0; - - cmnd[0] = LOG_SENSE; - cmnd[1] = 0; - cmnd[2] = 0x33 + (3<<6); - cmnd[3] = 0; - cmnd[4] = 0; - cmnd[5] = 0; - cmnd[6] = 0; - cmnd[7] = 0x00; - cmnd[8] = 0x66; - cmnd[9] = 0; - - scmd.cmd_len = 10; - - scmd.host = HBA_ptr; - scmd.device = &SDev; - scmd.target = HBA_ptr->this_id; - scmd.lun = 0; - scmd.channel = 0; - scmd.use_sg = 0; - - /* - * Do the command and wait for it to finish. - */ - { - struct semaphore sem = MUTEX_LOCKED; - scmd.request.rq_status = RQ_SCSI_BUSY; - scmd.request.sem = &sem; - scsi_do_cmd (&scmd, cmnd, buff + 0x144, 0x66, - eata_scsi_done, 1 * HZ, 1); - down(&sem); - } - - size = sprintf(buffer + len, "IRQ: %2d, %s triggered\n", cc->interrupt, - (cc->intt == TRUE)?"level":"edge"); - len += size; - pos = begin + len; - if (HBA_ptr->dma_channel == 0xff) - size = sprintf(buffer + len, "DMA: BUSMASTER\n"); - else - size = sprintf(buffer + len, "DMA: %d\n", HBA_ptr->dma_channel); - len += size; - pos = begin + len; - size = sprintf(buffer + len, "CPU: MC680%02d %dMHz\n", bt->cpu_type, - bt->cpu_speed); - len += size; - pos = begin + len; - size = sprintf(buffer + len, "Base IO : %#.4x\n", (u32) HBA_ptr->base); - len += size; - pos = begin + len; - size = sprintf(buffer + len, "Host Bus: %s\n", - (SD(HBA_ptr)->bustype == IS_PCI)?"PCI ": - (SD(HBA_ptr)->bustype == IS_EISA)?"EISA":"ISA "); - - len += size; - pos = begin + len; - size = sprintf(buffer + len, "SCSI Bus:%s%s Speed: %sMB/sec. %s\n", - (sb->wide == TRUE)?" WIDE":"", - (sb->dif == TRUE)?" DIFFERENTIAL":"", - (sb->speed == 0)?"5":(sb->speed == 1)?"10":"20", - (sb->ext == TRUE)?"With external cable detection":""); - len += size; - pos = begin + len; - size = sprintf(buffer + len, "SCSI channel expansion Module: %s present\n", - (bt->sx1 == TRUE)?"SX1 (one channel)": - ((bt->sx2 == TRUE)?"SX2 (two channels)":"not")); - len += size; - pos = begin + len; - size = sprintf(buffer + len, "SmartRAID hardware: %spresent.\n", - (cc->srs == TRUE)?"":"not "); - len += size; - pos = begin + len; - size = sprintf(buffer + len, " Type: %s\n", - ((cc->key == TRUE)?((bt->dmi == TRUE)?"integrated" - :((bt->dm4 == TRUE)?"DM401X" - :(bt->dm4k == TRUE)?"DM4000" - :"-")) - :"-")); - len += size; - pos = begin + len; - - size = sprintf(buffer + len, " Max array groups: %d\n", - (al->code == 0x0e)?al->max_groups:7); - len += size; - pos = begin + len; - size = sprintf(buffer + len, " Max drives per RAID 0 array: %d\n", - (al->code == 0x0e)?al->raid0_drv:7); - len += size; - pos = begin + len; - size = sprintf(buffer + len, " Max drives per RAID 3/5 array: %d\n", - (al->code == 0x0e)?al->raid35_drv:7); - len += size; - pos = begin + len; - size = sprintf(buffer + len, "Cache Module: %spresent.\n", - (cc->csh)?"":"not "); - len += size; - pos = begin + len; - size = sprintf(buffer + len, " Type: %s\n", - ((cc->csh == TRUE)?((bt->cmi == TRUE)?"integrated" - :((bt->cm4 == TRUE)?"CM401X" - :((bt->cm4k == TRUE)?"CM4000" - :"-"))) - :"-")); - len += size; - pos = begin + len; - for (x = 0; x <= 3; x++) { - size = sprintf(buffer + len, " Bank%d: %dMB with%s ECC\n",x, - mc->banksize[x] & 0x7f, - (mc->banksize[x] & 0x80)?"":"out"); - len += size; - pos = begin + len; - } - size = sprintf(buffer + len, "Timer Mod.: %spresent\n", - (cc->tmr == TRUE)?"":"not "); - len += size; - pos = begin + len; - size = sprintf(buffer + len, "NVRAM : %spresent\n", - (cc->nvr == TRUE)?"":"not "); - len += size; - pos = begin + len; - size = sprintf(buffer + len, "SmartROM : %sabled\n", - (bt->srom == TRUE)?"dis":"en"); - len += size; - pos = begin + len; - size = sprintf(buffer + len, "Alarm : %s\n", - (bt->alrm == TRUE)?"on":"off"); - len += size; - pos = begin + len; - - if (pos < offset) { - len = 0; - begin = pos; - } - if (pos > offset + length) - goto stop_output; - - cmnd[0] = LOG_SENSE; - cmnd[1] = 0; - cmnd[2] = 0x32 + (3<<6); - cmnd[3] = 0; - cmnd[4] = 0; - cmnd[5] = 0; - cmnd[6] = 0; - cmnd[7] = 0x01; - cmnd[8] = 0x44; - cmnd[9] = 0; - - scmd.cmd_len = 10; - - /* - * Do the command and wait for it to finish. - */ - { - struct semaphore sem = MUTEX_LOCKED; - scmd.request.rq_status = RQ_SCSI_BUSY; - scmd.request.sem = &sem; - scsi_do_cmd (&scmd, cmnd, buff2, 0x144, - eata_scsi_done, 1 * HZ, 1); - down(&sem); - } - - swap_statistics(buff2); - rhcs = (hst_cmd_stat *)(buff2 + 0x2c); - whcs = (hst_cmd_stat *)(buff2 + 0x8c); - - for (x = 0; x <= 11; x++) { - SD(HBA_ptr)->reads[x] += rhcs->sizes[x]; - SD(HBA_ptr)->writes[x] += whcs->sizes[x]; - SD(HBA_ptr)->reads[12] += rhcs->sizes[x]; - SD(HBA_ptr)->writes[12] += whcs->sizes[x]; - } - size = sprintf(buffer + len, "Host<->Disk command statistics:\n" - " Reads: Writes:\n"); - len += size; - pos = begin + len; - for (x = 0; x <= 10; x++) { - size = sprintf(buffer+len,"%5dk:%12u %12u\n", 1 << x, - SD(HBA_ptr)->reads[x], - SD(HBA_ptr)->writes[x]); - len += size; - pos = begin + len; - } - size = sprintf(buffer+len,">1024k:%12u %12u\n", - SD(HBA_ptr)->reads[11], - SD(HBA_ptr)->writes[11]); - len += size; - pos = begin + len; - size = sprintf(buffer+len,"Sum :%12u %12u\n", - SD(HBA_ptr)->reads[12], - SD(HBA_ptr)->writes[12]); - len += size; - pos = begin + len; - } - - if (pos < offset) { - len = 0; - begin = pos; - } - if (pos > offset + length) - goto stop_output; - - if(SD(HBA_ptr)->do_latency == TRUE) { - size = sprintf(buffer + len, "Host Latency Command Statistics:\n" - "Current timer resolution: 10ms\n" - " Reads: Min:(ms) Max:(ms) Ave:(ms)\n"); - len += size; - pos = begin + len; - for (x = 0; x <= 10; x++) { - size = sprintf(buffer+len,"%5dk:%12u %12u %12u %12u\n", - 1 << x, - SD(HBA_ptr)->reads_lat[x][0], - (SD(HBA_ptr)->reads_lat[x][1] == 0xffffffff) - ? 0:(SD(HBA_ptr)->reads_lat[x][1] * 10), - SD(HBA_ptr)->reads_lat[x][2] * 10, - SD(HBA_ptr)->reads_lat[x][3] * 10 / - ((SD(HBA_ptr)->reads_lat[x][0]) - ? SD(HBA_ptr)->reads_lat[x][0]:1)); - len += size; - pos = begin + len; - } - size = sprintf(buffer+len,">1024k:%12u %12u %12u %12u\n", - SD(HBA_ptr)->reads_lat[11][0], - (SD(HBA_ptr)->reads_lat[11][1] == 0xffffffff) - ? 0:(SD(HBA_ptr)->reads_lat[11][1] * 10), - SD(HBA_ptr)->reads_lat[11][2] * 10, - SD(HBA_ptr)->reads_lat[11][3] * 10 / - ((SD(HBA_ptr)->reads_lat[x][0]) - ? SD(HBA_ptr)->reads_lat[x][0]:1)); - len += size; - pos = begin + len; - - if (pos < offset) { - len = 0; - begin = pos; - } - if (pos > offset + length) - goto stop_output; - - size = sprintf(buffer + len, - " Writes: Min:(ms) Max:(ms) Ave:(ms)\n"); - len += size; - pos = begin + len; - for (x = 0; x <= 10; x++) { - size = sprintf(buffer+len,"%5dk:%12u %12u %12u %12u\n", - 1 << x, - SD(HBA_ptr)->writes_lat[x][0], - (SD(HBA_ptr)->writes_lat[x][1] == 0xffffffff) - ? 0:(SD(HBA_ptr)->writes_lat[x][1] * 10), - SD(HBA_ptr)->writes_lat[x][2] * 10, - SD(HBA_ptr)->writes_lat[x][3] * 10 / - ((SD(HBA_ptr)->writes_lat[x][0]) - ? SD(HBA_ptr)->writes_lat[x][0]:1)); - len += size; - pos = begin + len; - } - size = sprintf(buffer+len,">1024k:%12u %12u %12u %12u\n", - SD(HBA_ptr)->writes_lat[11][0], - (SD(HBA_ptr)->writes_lat[11][1] == 0xffffffff) - ? 0:(SD(HBA_ptr)->writes_lat[x][1] * 10), - SD(HBA_ptr)->writes_lat[11][2] * 10, - SD(HBA_ptr)->writes_lat[11][3] * 10/ - ((SD(HBA_ptr)->writes_lat[x][0]) - ? SD(HBA_ptr)->writes_lat[x][0]:1)); - len += size; - pos = begin + len; - - if (pos < offset) { - len = 0; - begin = pos; - } - if (pos > offset + length) - goto stop_output; - } - -#if 0 - scd = scsi_devices; - - size = sprintf(buffer+len,"Attached devices: %s\n", (scd)?"":"none"); - len += size; - pos = begin + len; - - while (scd) { - if (scd->host == HBA_ptr) { - proc_print_scsidevice(scd, buffer, &size, len); - len += size; - pos = begin + len; - - if (pos < offset) { - len = 0; - begin = pos; - } - if (pos > offset + length) - goto stop_output; - } - scd = scd->next; - } -#endif - - stop_output: - DBG(DBG_PROC, printk("2pos: %ld offset: %ld len: %d\n", pos, offset, len)); - *start=buffer+(offset-begin); /* Start of wanted data */ - len-=(offset-begin); /* Start slop */ - if(len>length) - len = length; /* Ending slop */ - DBG(DBG_PROC, printk("3pos: %ld offset: %ld len: %d\n", pos, offset, len)); - - return (len); -} - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 4 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -4 - * c-argdecl-indent: 4 - * c-label-offset: -4 - * c-continued-statement-offset: 4 - * c-continued-brace-offset: 0 - * tab-width: 8 - * End: - */ diff --git a/i386/i386at/gpl/linux/scsi/eata_generic.h b/i386/i386at/gpl/linux/scsi/eata_generic.h deleted file mode 100644 index 4d9fc497..00000000 --- a/i386/i386at/gpl/linux/scsi/eata_generic.h +++ /dev/null @@ -1,397 +0,0 @@ -/******************************************************** -* Header file for eata_dma.c and eata_pio.c * -* Linux EATA SCSI drivers * -* (c) 1993,94,95 Michael Neuffer * -********************************************************* -* last change: 95/11/07 * -********************************************************/ - - -#ifndef _EATA_GENERIC_H -#define _EATA_GENERIC_H - - - -/********************************************* - * Misc. definitions * - *********************************************/ - -#ifndef TRUE -#define TRUE 1 -#endif -#ifndef FALSE -#define FALSE 0 -#endif - -#define min(a,b) ((a<b)?(a):(b)) - -#define R_LIMIT 0x20000 - -#define MAXISA 4 -#define MAXEISA 16 -#define MAXPCI 16 -#define MAXIRQ 16 -#define MAXTARGET 16 -#define MAXCHANNEL 3 - -#define IS_ISA 'I' -#define IS_EISA 'E' -#define IS_PCI 'P' - -#define BROKEN_INQUIRY 1 - -#define BUSMASTER 0xff -#define PIO 0xfe - -#define EATA_SIGNATURE 0x45415441 /* BIG ENDIAN coded "EATA" sig. */ - -#define DPT_ID1 0x12 -#define DPT_ID2 0x14 - -#define ATT_ID1 0x06 -#define ATT_ID2 0x94 -#define ATT_ID3 0x0 - -#define NEC_ID1 0x38 -#define NEC_ID2 0xa3 -#define NEC_ID3 0x82 - - -#define EATA_CP_SIZE 44 - -#define MAX_PCI_DEVICES 32 /* Maximum # Of Devices Per Bus */ -#define MAX_METHOD_2 16 /* Max Devices For Method 2 */ -#define MAX_PCI_BUS 16 /* Maximum # Of Busses Allowed */ - -#define SG_SIZE 64 -#define SG_SIZE_BIG 509 /* max. 509 elements, one 4k page */ - -#define C_P_L_DIV 2 /* 1 <= C_P_L_DIV <= 8 - * You can use this parameter to fine-tune - * the driver. Depending on the number of - * devices and their speed and ability to queue - * commands, you will get the best results with a - * value - * ~= numdevices-(devices_unable_to_queue_commands/2) - * The reason for this is that the disk driver - * tends to flood the queue, so that other - * drivers have problems to queue commands - * themselves. This can for example result in - * the effect that the tape stops during disk - * accesses. - */ - -#define FREE 0 -#define OK 0 -#define NO_TIMEOUT 0 -#define USED 1 -#define TIMEOUT 2 -#define RESET 4 -#define LOCKED 8 - -#define HD(cmd) ((hostdata *)&(cmd->host->hostdata)) -#define CD(cmd) ((struct eata_ccb *)(cmd->host_scribble)) -#define SD(host) ((hostdata *)&(host->hostdata)) - -#define DELAY(x) { __u32 i; i = jiffies + (x * HZ); while (jiffies < i) barrier(); } -#define DEL2(x) { __u32 i; for (i = 0; i < 0xffff * x; i++); } - -/*********************************************** - * EATA Command & Register definitions * - ***********************************************/ -#define PCI_REG_DPTconfig 0x40 -#define PCI_REG_PumpModeAddress 0x44 -#define PCI_REG_PumpModeData 0x48 -#define PCI_REG_ConfigParam1 0x50 -#define PCI_REG_ConfigParam2 0x54 - - -#define EATA_CMD_PIO_SETUPTEST 0xc6 -#define EATA_CMD_PIO_READ_CONFIG 0xf0 -#define EATA_CMD_PIO_SET_CONFIG 0xf1 -#define EATA_CMD_PIO_SEND_CP 0xf2 -#define EATA_CMD_PIO_RECEIVE_SP 0xf3 -#define EATA_CMD_PIO_TRUNC 0xf4 - -#define EATA_CMD_RESET 0xf9 -#define EATA_CMD_IMMEDIATE 0xfa - -#define EATA_CMD_DMA_READ_CONFIG 0xfd -#define EATA_CMD_DMA_SET_CONFIG 0xfe -#define EATA_CMD_DMA_SEND_CP 0xff - -#define ECS_EMULATE_SENSE 0xd4 - -#define EATA_GENERIC_ABORT 0x00 -#define EATA_SPECIFIC_RESET 0x01 -#define EATA_BUS_RESET 0x02 -#define EATA_SPECIFIC_ABORT 0x03 -#define EATA_QUIET_INTR 0x04 -#define EATA_COLD_BOOT_HBA 0x06 /* Only as a last resort */ -#define EATA_FORCE_IO 0x07 - - -#define HA_WCOMMAND 0x07 /* command register offset */ -#define HA_WCOMMAND2 0x06 /* immediate command offset */ -#define HA_WSUBCODE 0x05 -#define HA_WSUBLUN 0x04 -#define HA_WDMAADDR 0x02 /* DMA address LSB offset */ -#define HA_RAUXSTAT 0x08 /* aux status register offset*/ -#define HA_RSTATUS 0x07 /* status register offset */ -#define HA_RDATA 0x00 /* data register (16bit) */ - -#define HA_ABUSY 0x01 /* aux busy bit */ -#define HA_AIRQ 0x02 /* aux IRQ pending bit */ -#define HA_SERROR 0x01 /* pr. command ended in error*/ -#define HA_SMORE 0x02 /* more data soon to come */ -#define HA_SCORR 0x04 /* data corrected */ -#define HA_SDRQ 0x08 /* data request active */ -#define HA_SSC 0x10 /* seek complete */ -#define HA_SFAULT 0x20 /* write fault */ -#define HA_SREADY 0x40 /* drive ready */ -#define HA_SBUSY 0x80 /* drive busy */ -#define HA_SDRDY HA_SSC+HA_SREADY+HA_SDRQ - -/********************************************** - * Message definitions * - **********************************************/ - -#define HA_NO_ERROR 0x00 /* No Error */ -#define HA_ERR_SEL_TO 0x01 /* Selection Timeout */ -#define HA_ERR_CMD_TO 0x02 /* Command Timeout */ -#define HA_ERR_RESET 0x03 /* SCSI Bus Reset Received */ -#define HA_INIT_POWERUP 0x04 /* Initial Controller Power-up */ -#define HA_UNX_BUSPHASE 0x05 /* Unexpected Bus Phase */ -#define HA_UNX_BUS_FREE 0x06 /* Unexpected Bus Free */ -#define HA_BUS_PARITY 0x07 /* Bus Parity Error */ -#define HA_SCSI_HUNG 0x08 /* SCSI Hung */ -#define HA_UNX_MSGRJCT 0x09 /* Unexpected Message Rejected */ -#define HA_RESET_STUCK 0x0a /* SCSI Bus Reset Stuck */ -#define HA_RSENSE_FAIL 0x0b /* Auto Request-Sense Failed */ -#define HA_PARITY_ERR 0x0c /* Controller Ram Parity Error */ -#define HA_CP_ABORT_NA 0x0d /* Abort Message sent to non-active cmd */ -#define HA_CP_ABORTED 0x0e /* Abort Message sent to active cmd */ -#define HA_CP_RESET_NA 0x0f /* Reset Message sent to non-active cmd */ -#define HA_CP_RESET 0x10 /* Reset Message sent to active cmd */ -#define HA_ECC_ERR 0x11 /* Controller Ram ECC Error */ -#define HA_PCI_PARITY 0x12 /* PCI Parity Error */ -#define HA_PCI_MABORT 0x13 /* PCI Master Abort */ -#define HA_PCI_TABORT 0x14 /* PCI Target Abort */ -#define HA_PCI_STABORT 0x15 /* PCI Signaled Target Abort */ - -/********************************************** - * Other definitions * - **********************************************/ - -struct reg_bit { /* reading this one will clear the interrupt */ - __u8 error:1; /* previous command ended in an error */ - __u8 more:1; /* more DATA coming soon, poll BSY & DRQ (PIO) */ - __u8 corr:1; /* data read was successfully corrected with ECC*/ - __u8 drq:1; /* data request active */ - __u8 sc:1; /* seek complete */ - __u8 fault:1; /* write fault */ - __u8 ready:1; /* drive ready */ - __u8 busy:1; /* controller busy */ -}; - -struct reg_abit { /* reading this won't clear the interrupt */ - __u8 abusy:1; /* auxiliary busy */ - __u8 irq:1; /* set when drive interrupt is asserted */ - __u8 dummy:6; -}; - -struct eata_register { /* EATA register set */ - __u8 data_reg[2]; /* R, couldn't figure this one out */ - __u8 cp_addr[4]; /* W, CP address register */ - union { - __u8 command; /* W, command code: [read|set] conf, send CP*/ - struct reg_bit status; /* R, see register_bit1 */ - __u8 statusbyte; - } ovr; - struct reg_abit aux_stat; /* R, see register_bit2 */ -}; - -struct get_conf { /* Read Configuration Array */ - __u32 len; /* Should return 0x22, 0x24, etc */ - __u32 signature; /* Signature MUST be "EATA" */ - __u8 version2:4, - version:4; /* EATA Version level */ - __u8 OCS_enabled:1, /* Overlap Command Support enabled */ - TAR_support:1, /* SCSI Target Mode supported */ - TRNXFR:1, /* Truncate Transfer Cmd not necessary * - * Only used in PIO Mode */ - MORE_support:1, /* MORE supported (only PIO Mode) */ - DMA_support:1, /* DMA supported Driver uses only * - * this mode */ - DMA_valid:1, /* DRQ value in Byte 30 is valid */ - ATA:1, /* ATA device connected (not supported) */ - HAA_valid:1; /* Hostadapter Address is valid */ - - __u16 cppadlen; /* Number of pad bytes send after CD data * - * set to zero for DMA commands */ - __u8 scsi_id[4]; /* SCSI ID of controller 2-0 Byte 0 res. * - * if not, zero is returned */ - __u32 cplen; /* CP length: number of valid cp bytes */ - __u32 splen; /* Number of bytes returned after * - * Receive SP command */ - __u16 queuesiz; /* max number of queueable CPs */ - __u16 dummy; - __u16 SGsiz; /* max number of SG table entries */ - __u8 IRQ:4, /* IRQ used this HA */ - IRQ_TR:1, /* IRQ Trigger: 0=edge, 1=level */ - SECOND:1, /* This is a secondary controller */ - DMA_channel:2; /* DRQ index, DRQ is 2comp of DRQX */ - __u8 sync; /* device at ID 7 tru 0 is running in * - * synchronous mode, this will disappear */ - __u8 DSBLE:1, /* ISA i/o addressing is disabled */ - FORCADR:1, /* i/o address has been forced */ - SG_64K:1, - SG_UAE:1, - :4; - __u8 MAX_ID:5, /* Max number of SCSI target IDs */ - MAX_CHAN:3; /* Number of SCSI busses on HBA */ - __u8 MAX_LUN; /* Max number of LUNs */ - __u8 :3, - AUTOTRM:1, - M1_inst:1, - ID_qest:1, /* Raidnum ID is questionable */ - is_PCI:1, /* HBA is PCI */ - is_EISA:1; /* HBA is EISA */ - __u8 unused[478]; -}; - -struct eata_sg_list -{ - __u32 data; - __u32 len; -}; - -struct eata_ccb { /* Send Command Packet structure */ - - __u8 SCSI_Reset:1, /* Cause a SCSI Bus reset on the cmd */ - HBA_Init:1, /* Cause Controller to reinitialize */ - Auto_Req_Sen:1, /* Do Auto Request Sense on errors */ - scatter:1, /* Data Ptr points to a SG Packet */ - Resrvd:1, /* RFU */ - Interpret:1, /* Interpret the SCSI cdb of own use */ - DataOut:1, /* Data Out phase with command */ - DataIn:1; /* Data In phase with command */ - __u8 reqlen; /* Request Sense Length * - * Valid if Auto_Req_Sen=1 */ - __u8 unused[3]; - __u8 FWNEST:1, /* send cmd to phys RAID component */ - unused2:7; - __u8 Phsunit:1, /* physical unit on mirrored pair */ - I_AT:1, /* inhibit address translation */ - I_HBA_C:1, /* HBA inhibit caching */ - unused3:5; - - __u8 cp_id:5, /* SCSI Device ID of target */ - cp_channel:3; /* SCSI Channel # of HBA */ - __u8 cp_lun:3, - :2, - cp_luntar:1, /* CP is for target ROUTINE */ - cp_dispri:1, /* Grant disconnect privilege */ - cp_identify:1; /* Always TRUE */ - __u8 cp_msg1; /* Message bytes 0-3 */ - __u8 cp_msg2; - __u8 cp_msg3; - __u8 cp_cdb[12]; /* Command Descriptor Block */ - __u32 cp_datalen; /* Data Transfer Length * - * If scatter=1 len of sg package */ - void *cp_viraddr; /* address of this ccb */ - __u32 cp_dataDMA; /* Data Address, if scatter=1 * - * address of scatter packet */ - __u32 cp_statDMA; /* address for Status Packet */ - __u32 cp_reqDMA; /* Request Sense Address, used if * - * CP command ends with error */ - /* Additional CP info begins here */ - __u32 timestamp; /* Needed to measure command latency */ - __u32 timeout; - __u8 sizeindex; - __u8 rw_latency; - __u8 retries; - __u8 status; /* status of this queueslot */ - Scsi_Cmnd *cmd; /* address of cmd */ - struct eata_sg_list *sg_list; -}; - - -struct eata_sp { - __u8 hba_stat:7, /* HBA status */ - EOC:1; /* True if command finished */ - __u8 scsi_stat; /* Target SCSI status */ - __u8 reserved[2]; - __u32 residue_len; /* Number of bytes not transferred */ - struct eata_ccb *ccb; /* Address set in COMMAND PACKET */ - __u8 msg[12]; -}; - -typedef struct hstd { - __u8 vendor[9]; - __u8 name[18]; - __u8 revision[6]; - __u8 EATA_revision; - __u8 bustype; /* bustype of HBA */ - __u8 channel; /* # of avail. scsi channels */ - __u8 state; /* state of HBA */ - __u8 primary; /* true if primary */ - __u8 broken_INQUIRY:1; /* This is an EISA HBA with * - * broken INQUIRY */ - __u8 do_latency; /* Latency measurement flag */ - __u32 reads[13]; - __u32 writes[13]; - __u32 reads_lat[12][4]; - __u32 writes_lat[12][4]; - /* state of Target (RESET,..) */ - __u8 t_state[MAXCHANNEL][MAXTARGET]; - /* timeouts on target */ - __u32 t_timeout[MAXCHANNEL][MAXTARGET]; - __u32 last_ccb; /* Last used ccb */ - __u32 cplen; /* size of CP in words */ - __u16 cppadlen; /* pad length of cp in words */ - __u8 hostid; /* SCSI ID of HBA */ - __u8 devflags; /* bits set for detected devices */ - __u8 moresupport; /* HBA supports MORE flag */ - struct Scsi_Host *next; - struct Scsi_Host *prev; - struct eata_sp sp; /* status packet */ - struct eata_ccb ccb[0]; /* ccb array begins here */ -}hostdata; - -/* structure for max. 2 emulated drives */ -struct drive_geom_emul { - __u8 trans; /* translation flag 1=transl */ - __u8 channel; /* SCSI channel number */ - __u8 HBA; /* HBA number (prim/sec) */ - __u8 id; /* drive id */ - __u8 lun; /* drive lun */ - __u32 heads; /* number of heads */ - __u32 sectors; /* number of sectors */ - __u32 cylinder; /* number of cylinders */ -}; - -struct geom_emul { - __u8 bios_drives; /* number of emulated drives */ - struct drive_geom_emul drv[2]; /* drive structures */ -}; - -#endif /* _EATA_GENERIC_H */ - -/* - * Overrides for Emacs so that we almost follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 4 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -4 - * c-argdecl-indent: 4 - * c-label-offset: -4 - * c-continued-statement-offset: 4 - * c-continued-brace-offset: 0 - * tab-width: 8 - * End: - */ diff --git a/i386/i386at/gpl/linux/scsi/eata_pio.c b/i386/i386at/gpl/linux/scsi/eata_pio.c deleted file mode 100644 index 95248ae7..00000000 --- a/i386/i386at/gpl/linux/scsi/eata_pio.c +++ /dev/null @@ -1,1051 +0,0 @@ -/************************************************************ - * * - * Linux EATA SCSI PIO driver * - * * - * based on the CAM document CAM/89-004 rev. 2.0c, * - * DPT's driver kit, some internal documents and source, * - * and several other Linux scsi drivers and kernel docs. * - * * - * The driver currently: * - * -supports all EATA-PIO boards * - * -only supports DASD devices * - * * - * (c)1993,94,95 Michael Neuffer, Alfred Arnold * - * neuffer@goofy.zdv.uni-mainz.de * - * a.arnold@kfa-juelich.de * - * * - * This program is free software; you can redistribute it * - * and/or modify it under the terms of the GNU General * - * Public License as published by the Free Software * - * Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be * - * useful, but WITHOUT ANY WARRANTY; without even the * - * implied warranty of MERCHANTABILITY or FITNESS FOR A * - * PARTICULAR PURPOSE. See the GNU General Public License * - * for more details. * - * * - * You should have received a copy of the GNU General * - * Public License along with this kernel; if not, write to * - * the Free Software Foundation, Inc., 675 Mass Ave, * - * Cambridge, MA 02139, USA. * - * * - ************************************************************ - * last change: 95/08/04 OS: Linux 1.3.15 * - ************************************************************/ - -/* Look in eata_pio.h for configuration information */ - -#include <linux/module.h> - -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/string.h> -#include <linux/ioport.h> -#include <linux/malloc.h> -#include <linux/in.h> -#include <linux/bios32.h> -#include <linux/pci.h> -#include <linux/proc_fs.h> -#include <asm/io.h> -#include "eata_pio.h" -#include "eata_dma_proc.h" -#include "scsi.h" -#include "sd.h" - -#include <linux/stat.h> -#include <linux/config.h> /* for CONFIG_PCI */ - -struct proc_dir_entry proc_scsi_eata_pio = { - PROC_SCSI_EATA_PIO, 9, "eata_pio", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - -static uint ISAbases[MAXISA] = -{0x1F0, 0x170, 0x330, 0x230}; -static uint ISAirqs[MAXISA] = -{14,12,15,11}; -static unchar EISAbases[] = -{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; -static uint registered_HBAs = 0; -static struct Scsi_Host *last_HBA = NULL; -static struct Scsi_Host *first_HBA = NULL; -static unchar reg_IRQ[] = -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; -static unchar reg_IRQL[] = -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - -static ulong int_counter = 0; -static ulong queue_counter = 0; - -void hprint(const char *str) -{ - char *hptr =(char *) 0x000b0000; - char *hptr2=(char *) 0x000b00a0; - char *hptr3=(char *) 0x000b0f00; - int z; - - memmove(hptr,hptr2,24*80*2); - for (z=0; z<strlen(str); z++) - hptr3[z*2]=str[z]; - for (; z<80; z++) - hptr3[z*2]=' '; -} - -#ifdef MACH -#include "eata_pio_proc.src" -#else -#include "eata_pio_proc.c" -#endif - -#ifdef MODULE -int eata_pio_release(struct Scsi_Host *sh) -{ - if (sh->irq && reg_IRQ[sh->irq] == 1) free_irq(sh->irq); - else reg_IRQ[sh->irq]--; - if (SD(sh)->channel == 0) { - if (sh->io_port && sh->n_io_port) - release_region(sh->io_port, sh->n_io_port); - } - return(TRUE); -} -#endif - -void IncStat(Scsi_Pointer *SCp, uint Increment) -{ - SCp->ptr+=Increment; - if ((SCp->this_residual-=Increment)==0) - { - if ((--SCp->buffers_residual)==0) SCp->Status=FALSE; - else - { - SCp->buffer++; - SCp->ptr=SCp->buffer->address; - SCp->this_residual=SCp->buffer->length; - } - } -} - -void eata_pio_int_handler(int irq, struct pt_regs * regs) -{ - uint eata_stat = 0xfffff; - Scsi_Cmnd *cmd; - hostdata *hd; - struct eata_ccb *cp; - uint base; - ulong flags; - uint x,z; - struct Scsi_Host *sh; - ushort zwickel=0; - unchar stat,odd; - - save_flags(flags); - cli(); - - for (x = 1, sh = first_HBA; x <= registered_HBAs; x++, sh = SD(sh)->prev) { - if (sh->irq != irq) - continue; - if (inb((uint)sh->base + HA_RSTATUS) & HA_SBUSY) - continue; - - int_counter++; - - hd=SD(sh); - - cp = &hd->ccb[0]; - cmd = cp->cmd; - base = (uint) cmd->host->base; - - do - { - stat=inb(base+HA_RSTATUS); - if (stat&HA_SDRQ) - if (cp->DataIn) - { - z=256; odd=FALSE; - while ((cmd->SCp.Status)&&((z>0)||(odd))) - { - if (odd) - { - *(cmd->SCp.ptr)=zwickel>>8; - IncStat(&cmd->SCp,1); - odd=FALSE; - } - x=min(z,cmd->SCp.this_residual/2); - insw(base+HA_RDATA,cmd->SCp.ptr,x); - z-=x; - IncStat(&cmd->SCp,2*x); - if ((z>0)&&(cmd->SCp.this_residual==1)) - { - zwickel=inw(base+HA_RDATA); - *(cmd->SCp.ptr)=zwickel&0xff; - IncStat(&cmd->SCp,1); z--; - odd=TRUE; - } - } - while (z>0) { - zwickel=inw(base+HA_RDATA); - z--; - } - } - else /* cp->DataOut */ - { - odd=FALSE; z=256; - while ((cmd->SCp.Status)&&((z>0)||(odd))) - { - if (odd) - { - zwickel+=*(cmd->SCp.ptr)<<8; - IncStat(&cmd->SCp,1); - outw(zwickel,base+HA_RDATA); - z--; - odd=FALSE; - } - x=min(z,cmd->SCp.this_residual/2); - outsw(base+HA_RDATA,cmd->SCp.ptr,x); - z-=x; - IncStat(&cmd->SCp,2*x); - if ((z>0)&&(cmd->SCp.this_residual==1)) - { - zwickel=*(cmd->SCp.ptr); - zwickel&=0xff; - IncStat(&cmd->SCp,1); - odd=TRUE; - } - } - while (z>0||odd) { - outw(zwickel,base+HA_RDATA); - z--; - odd=FALSE; - } - } - } - while ((stat&HA_SDRQ)||((stat&HA_SMORE)&&hd->moresupport)); - - /* terminate handler if HBA goes busy again, i.e. transfers - * more data */ - - if (stat&HA_SBUSY) break; - - /* OK, this is quite stupid, but I haven't found any correct - * way to get HBA&SCSI status so far */ - - if (!(inb(base+HA_RSTATUS)&HA_SERROR)) - { - cmd->result=(DID_OK<<16); - hd->devflags|=(1<<cp->cp_id); - } - else if (hd->devflags&1<<cp->cp_id) - cmd->result=(DID_OK<<16)+0x02; - else cmd->result=(DID_NO_CONNECT<<16); - - if (cp->status == LOCKED) { - cp->status = FREE; - eata_stat = inb(base + HA_RSTATUS); - printk("eata_pio: int_handler, freeing locked queueslot\n"); - DBG(DBG_INTR&&DBG_DELAY,DEL2(800)); - restore_flags(flags); - return; - } - -#if DBG_INTR2 - if (stat != 0x50) - printk("stat: %#.2x, result: %#.8x\n", stat, cmd->result); - DBG(DBG_INTR&&DBG_DELAY,DEL2(800)); -#endif - - cp->status = FREE; /* now we can release the slot */ - - restore_flags(flags); - cmd->scsi_done(cmd); - save_flags(flags); - cli(); - } - restore_flags(flags); - - return; -} - -inline uint eata_pio_send_command(uint base, unchar command) -{ - uint loop = R_LIMIT; - - while (inb(base + HA_RSTATUS) & HA_SBUSY) - if (--loop == 0) - return(TRUE); - - outb(command, base + HA_WCOMMAND); - return(FALSE); -} - -int eata_pio_queue(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) -{ - uint x, y; - long flags; - uint base; - - hostdata *hd; - struct Scsi_Host *sh; - struct eata_ccb *cp; - - save_flags(flags); - cli(); - - queue_counter++; - - hd = HD(cmd); - sh = cmd->host; - base = (uint) sh->base; - - /* use only slot 0, as 2001 can handle only one cmd at a time */ - - y = x = 0; - - if (hd->ccb[y].status!=FREE) { - - DBG(DBG_QUEUE, printk("can_queue %d, x %d, y %d\n",sh->can_queue,x,y)); -#if DEBUG_EATA - panic("eata_pio: run out of queue slots cmdno:%ld intrno: %ld\n", - queue_counter, int_counter); -#else - panic("eata_pio: run out of queue slots....\n"); -#endif - } - - cp = &hd->ccb[y]; - - memset(cp, 0, sizeof(struct eata_ccb)); - memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer)); - - cp->status = USED; /* claim free slot */ - - DBG(DBG_QUEUE, printk("eata_pio_queue pid %ld, target: %x, lun: %x, y %d\n", - cmd->pid, cmd->target, cmd->lun, y)); - DBG(DBG_QUEUE && DBG_DELAY, DEL2(250)); - - cmd->scsi_done = (void *)done; - - switch (cmd->cmnd[0]) { - case CHANGE_DEFINITION: case COMPARE: case COPY: - case COPY_VERIFY: case LOG_SELECT: case MODE_SELECT: - case MODE_SELECT_10: case SEND_DIAGNOSTIC: case WRITE_BUFFER: - case FORMAT_UNIT: case REASSIGN_BLOCKS: case RESERVE: - case SEARCH_EQUAL: case SEARCH_HIGH: case SEARCH_LOW: - case WRITE_6: case WRITE_10: case WRITE_VERIFY: - case UPDATE_BLOCK: case WRITE_LONG: case WRITE_SAME: - case SEARCH_HIGH_12: case SEARCH_EQUAL_12: case SEARCH_LOW_12: - case WRITE_12: case WRITE_VERIFY_12: case SET_WINDOW: - case MEDIUM_SCAN: case SEND_VOLUME_TAG: - case 0xea: /* alternate number for WRITE LONG */ - cp->DataOut = TRUE; /* Output mode */ - break; - case TEST_UNIT_READY: - default: - cp->DataIn = TRUE; /* Input mode */ - } - - cp->Interpret = (cmd->target == hd->hostid); - cp->cp_datalen = htonl((ulong)cmd->request_bufflen); - cp->Auto_Req_Sen = FALSE; - cp->cp_reqDMA = htonl(0); - cp->reqlen = 0; - - cp->cp_id = cmd->target; - cp->cp_lun = cmd->lun; - cp->cp_dispri = FALSE; - cp->cp_identify = TRUE; - memcpy(cp->cp_cdb, cmd->cmnd, COMMAND_SIZE(*cmd->cmnd)); - - cp->cp_statDMA = htonl(0); - - cp->cp_viraddr = cp; - cp->cmd = cmd; - cmd->host_scribble = (char *)&hd->ccb[y]; - - if (cmd->use_sg == 0) - { - cmd->SCp.buffers_residual=1; - cmd->SCp.ptr = cmd->request_buffer; - cmd->SCp.this_residual = cmd->request_bufflen; - cmd->SCp.buffer = NULL; - } else { - cmd->SCp.buffer = cmd->request_buffer; - cmd->SCp.buffers_residual = cmd->use_sg; - cmd->SCp.ptr = cmd->SCp.buffer->address; - cmd->SCp.this_residual = cmd->SCp.buffer->length; - } - cmd->SCp.Status = (cmd->SCp.this_residual != 0); /* TRUE as long as bytes - * are to transfer */ - - if (eata_pio_send_command(base, EATA_CMD_PIO_SEND_CP)) - { - cmd->result = DID_BUS_BUSY << 16; - printk("eata_pio_queue target %d, pid %ld, HBA busy, returning " - "DID_BUS_BUSY, done.\n", cmd->target, cmd->pid); - done(cmd); - cp->status = FREE; - restore_flags(flags); - return (0); - } - while (!(inb(base + HA_RSTATUS) & HA_SDRQ)); - outsw(base + HA_RDATA, cp, hd->cplen); - outb(EATA_CMD_PIO_TRUNC, base + HA_WCOMMAND); - for (x = 0; x < hd->cppadlen; x++) outw(0, base + HA_RDATA); - - DBG(DBG_QUEUE,printk("Queued base %#.4lx pid: %ld target: %x lun: %x " - "slot %d irq %d\n", (long)sh->base, cmd->pid, - cmd->target, cmd->lun, y, sh->irq)); - DBG(DBG_QUEUE && DBG_DELAY, DEL2(200)); - - restore_flags(flags); - return (0); -} - -int eata_pio_abort(Scsi_Cmnd * cmd) -{ - ulong flags; - uint loop = R_LIMIT; - - save_flags(flags); - cli(); - - DBG(DBG_ABNORM, printk("eata_pio_abort called pid: %ld target: %x lun: %x" - " reason %x\n", cmd->pid, cmd->target, cmd->lun, - cmd->abort_reason)); - DBG(DBG_ABNORM && DBG_DELAY, DEL2(500)); - - - while (inb((uint)(cmd->host->base) + HA_RAUXSTAT) & HA_ABUSY) - if (--loop == 0) { - printk("eata_pio: abort, timeout error.\n"); - restore_flags(flags); - DBG(DBG_ABNORM && DBG_DELAY, DEL2(500)); - return (SCSI_ABORT_ERROR); - } - if (CD(cmd)->status == FREE) { - DBG(DBG_ABNORM, printk("Returning: SCSI_ABORT_NOT_RUNNING\n")); - restore_flags(flags); - return (SCSI_ABORT_NOT_RUNNING); - } - if (CD(cmd)->status == USED) { - DBG(DBG_ABNORM, printk("Returning: SCSI_ABORT_BUSY\n")); - restore_flags(flags); - return (SCSI_ABORT_BUSY); /* SNOOZE */ - } - if (CD(cmd)->status == RESET) { - restore_flags(flags); - printk("eata_pio: abort, command reset error.\n"); - DBG(DBG_ABNORM && DBG_DELAY, DEL2(500)); - return (SCSI_ABORT_ERROR); - } - if (CD(cmd)->status == LOCKED) { - restore_flags(flags); - DBG(DBG_ABNORM, printk("eata_pio: abort, queue slot locked.\n")); - DBG(DBG_ABNORM && DBG_DELAY, DEL2(500)); - return (SCSI_ABORT_NOT_RUNNING); - } - restore_flags(flags); - panic("eata_pio: abort: invalid slot status\n"); -} - -int eata_pio_reset(Scsi_Cmnd * cmd) -{ - uint x, z, time, limit = 0; - ulong flags; - unchar success = FALSE; - Scsi_Cmnd *sp; - - save_flags(flags); - cli(); - hprint("reset"); - DBG(DBG_ABNORM, printk("eata_pio_reset called pid:%ld target: %x lun: %x " - "reason %x\n", cmd->pid, cmd->target, cmd->lun, - cmd->abort_reason)); - - if (HD(cmd)->state == RESET) { - printk("eata_pio_reset: exit, already in reset.\n"); - restore_flags(flags); - DBG(DBG_ABNORM && DBG_DELAY, DEL2(500)); - return (SCSI_RESET_ERROR); - } - - for (z = 0; z < MAXTARGET; z++) { - HD(cmd)->t_state[0][z] = RESET; - HD(cmd)->t_timeout[0][z] = NO_TIMEOUT; - } - - /* force all slots to be free */ - - for (x = 0; x < cmd->host->can_queue; x++) { - - if (HD(cmd)->ccb[x].status == FREE) - continue; - - sp = HD(cmd)->ccb[x].cmd; - HD(cmd)->ccb[x].status = RESET; - printk("eata_pio_reset: slot %d in reset, pid %ld.\n", x, sp->pid); - DBG(DBG_ABNORM && DBG_DELAY, DEL2(500)); - - if (sp == NULL) - panic("eata_pio_reset: slot %d, sp==NULL.\n", x); - DBG(DBG_ABNORM && DBG_DELAY, DEL2(500)); - } - - /* hard reset the HBA */ - outb((uint) cmd->host->base+HA_WCOMMAND, EATA_CMD_RESET); - - DBG(DBG_ABNORM, printk("eata_pio_reset: board reset done.\n")); - HD(cmd)->state = RESET; - - time = jiffies; - while (jiffies < (time + (3 * HZ)) && limit++ < 10000000); - - DBG(DBG_ABNORM, printk("eata_pio_reset: interrupts disabled, loops %d.\n", limit)); - DBG(DBG_ABNORM && DBG_DELAY, DEL2(500)); - - for (x = 0; x < cmd->host->can_queue; x++) { - - /* Skip slots already set free by interrupt */ - if (HD(cmd)->ccb[x].status != RESET) - continue; - - sp = HD(cmd)->ccb[x].cmd; - sp->result = DID_RESET << 16; - - /* This mailbox is terminated */ - printk("eata_pio_reset: resetted ccb %d.\n",x); - HD(cmd)->ccb[x].status = FREE; - - restore_flags(flags); - sp->scsi_done(sp); - cli(); - } - - HD(cmd)->state = FALSE; - restore_flags(flags); - - if (success) { /* hmmm... */ - DBG(DBG_ABNORM, printk("eata_pio_reset: exit, success.\n")); - DBG(DBG_ABNORM && DBG_DELAY, DEL2(500)); - return (SCSI_RESET_SUCCESS); - } else { - DBG(DBG_ABNORM, printk("eata_pio_reset: exit, wakeup.\n")); - DBG(DBG_ABNORM && DBG_DELAY, DEL2(500)); - return (SCSI_RESET_PUNT); - } -} - -char * get_pio_board_data(ulong base, uint irq, uint id, ulong cplen, ushort cppadlen) -{ - struct eata_ccb cp; - static char buff[256]; - int z; - - memset(&cp, 0, sizeof(struct eata_ccb)); - memset(buff, 0, sizeof(buff)); - - cp.DataIn = TRUE; - cp.Interpret = TRUE; /* Interpret command */ - - cp.cp_datalen = htonl(254); - cp.cp_dataDMA = htonl(0); - - cp.cp_id = id; - cp.cp_lun = 0; - - cp.cp_cdb[0] = INQUIRY; - cp.cp_cdb[1] = 0; - cp.cp_cdb[2] = 0; - cp.cp_cdb[3] = 0; - cp.cp_cdb[4] = 254; - cp.cp_cdb[5] = 0; - - if (eata_pio_send_command((uint) base, EATA_CMD_PIO_SEND_CP)) - return (NULL); - while (!(inb(base + HA_RSTATUS) & HA_SDRQ)); - outsw(base + HA_RDATA, &cp, cplen); - outb(EATA_CMD_PIO_TRUNC, base + HA_WCOMMAND); - for (z = 0; z < cppadlen; z++) outw(0, base + HA_RDATA); - - while (inb(base + HA_RSTATUS) & HA_SBUSY); - if (inb(base + HA_RSTATUS) & HA_SERROR) - return (NULL); - else if (!(inb(base + HA_RSTATUS) & HA_SDRQ)) - return (NULL); - else - { - insw(base+HA_RDATA, &buff, 127); - while (inb(base + HA_RSTATUS)&HA_SDRQ) inw(base + HA_RDATA); - return (buff); - } -} - -int get_pio_conf_PIO(u32 base, struct get_conf *buf) -{ - ulong loop = R_LIMIT; - int z; - ushort *p; - - if(check_region(base, 9)) - return (FALSE); - - memset(buf, 0, sizeof(struct get_conf)); - - while (inb(base + HA_RSTATUS) & HA_SBUSY) - if (--loop == 0) - return (FALSE); - - DBG(DBG_PIO && DBG_PROBE, - printk("Issuing PIO READ CONFIG to HBA at %#x\n", base)); - eata_pio_send_command(base, EATA_CMD_PIO_READ_CONFIG); - - loop = R_LIMIT; - for (p = (ushort *) buf; - (long)p <= ((long)buf + (sizeof(struct get_conf) / 2)); p++) { - while (!(inb(base + HA_RSTATUS) & HA_SDRQ)) - if (--loop == 0) - return (FALSE); - - loop = R_LIMIT; - *p = inw(base + HA_RDATA); - } - if (!(inb(base + HA_RSTATUS) & HA_SERROR)) { /* Error ? */ - if (htonl(EATA_SIGNATURE) == buf->signature) { - DBG(DBG_PIO&&DBG_PROBE, printk("EATA Controller found at %#4x " - "EATA Level: %x\n", base, - (uint) (buf->version))); - - while (inb(base + HA_RSTATUS) & HA_SDRQ) - inw(base + HA_RDATA); - if(ALLOW_DMA_BOARDS == FALSE) { - for (z = 0; z < MAXISA; z++) - if (base == ISAbases[z]) { - buf->IRQ = ISAirqs[z]; - break; - } - } - return (TRUE); - } - } else { - DBG(DBG_PROBE, printk("eata_dma: get_conf_PIO, error during transfer " - "for HBA at %x\n", base)); - } - return (FALSE); -} - -void print_pio_config(struct get_conf *gc) -{ - printk("Please check values: (read config data)\n"); - printk("LEN: %d ver:%d OCS:%d TAR:%d TRNXFR:%d MORES:%d\n", - (uint) ntohl(gc->len), gc->version, - gc->OCS_enabled, gc->TAR_support, gc->TRNXFR, gc->MORE_support); - printk("HAAV:%d SCSIID0:%d ID1:%d ID2:%d QUEUE:%d SG:%d SEC:%d\n", - gc->HAA_valid, gc->scsi_id[3], gc->scsi_id[2], - gc->scsi_id[1], ntohs(gc->queuesiz), ntohs(gc->SGsiz), gc->SECOND); - printk("IRQ:%d IRQT:%d FORCADR:%d MCH:%d RIDQ:%d\n", - gc->IRQ, gc->IRQ_TR, gc->FORCADR, - gc->MAX_CHAN, gc->ID_qest); - DBG(DPT_DEBUG, DELAY(14)); -} - -static uint print_selftest(uint base) -{ - unchar buffer[512]; -#ifdef VERBOSE_SETUP - int z; -#endif - - printk("eata_pio: executing controller self test & setup...\n"); - while (inb(base + HA_RSTATUS) & HA_SBUSY); - outb(EATA_CMD_PIO_SETUPTEST, base + HA_WCOMMAND); - do { - while (inb(base + HA_RSTATUS) & HA_SBUSY) - /* nothing */ ; - if (inb(base + HA_RSTATUS) & HA_SDRQ) - { - insw(base + HA_RDATA, &buffer, 256); -#ifdef VERBOSE_SETUP - /* no beeps please... */ - for (z = 0; z < 511 && buffer[z]; z++) - if (buffer[z] != 7) printk("%c", buffer[z]); -#endif - } - } while (inb(base+HA_RSTATUS) & (HA_SBUSY|HA_SDRQ)); - - return (!(inb(base+HA_RSTATUS) & HA_SERROR)); -} - -int register_pio_HBA(long base, struct get_conf *gc, Scsi_Host_Template * tpnt) -{ - ulong size = 0; - char *buff; - ulong cplen; - ushort cppadlen; - struct Scsi_Host *sh; - hostdata *hd; - - DBG(DBG_REGISTER, print_pio_config(gc)); - - if (gc->DMA_support == TRUE) { - printk("HBA at %#.4lx supports DMA. Please use EATA-DMA driver.\n",base); - if(ALLOW_DMA_BOARDS == FALSE) - return (FALSE); - } - - if ((buff = get_pio_board_data((uint)base, gc->IRQ, gc->scsi_id[3], - cplen =(htonl(gc->cplen )+1)/2, - cppadlen=(htons(gc->cppadlen)+1)/2)) == NULL) - { - printk("HBA at %#lx didn't react on INQUIRY. Sorry.\n", (ulong) base); - return (FALSE); - } - - if (print_selftest(base) == FALSE && ALLOW_DMA_BOARDS == FALSE) - { - printk("HBA at %#lx failed while performing self test & setup.\n", - (ulong) base); - return (FALSE); - } - - if (!reg_IRQ[gc->IRQ]) { /* Interrupt already registered ? */ - if (!request_irq(gc->IRQ, eata_pio_int_handler, SA_INTERRUPT, - "EATA-PIO")){ - reg_IRQ[gc->IRQ]++; - if (!gc->IRQ_TR) - reg_IRQL[gc->IRQ] = TRUE; /* IRQ is edge triggered */ - } else { - printk("Couldn't allocate IRQ %d, Sorry.", gc->IRQ); - return (FALSE); - } - } else { /* More than one HBA on this IRQ */ - if (reg_IRQL[gc->IRQ] == TRUE) { - printk("Can't support more than one HBA on this IRQ,\n" - " if the IRQ is edge triggered. Sorry.\n"); - return (FALSE); - } else - reg_IRQ[gc->IRQ]++; - } - - request_region(base, 8, "eata_pio"); - - size = sizeof(hostdata) + (sizeof(struct eata_ccb) * ntohs(gc->queuesiz)); - - sh = scsi_register(tpnt, size); - hd = SD(sh); - - memset(hd->ccb, 0, (sizeof(struct eata_ccb) * ntohs(gc->queuesiz))); - memset(hd->reads, 0, sizeof(ulong) * 26); - - strncpy(SD(sh)->vendor, &buff[8], 8); - SD(sh)->vendor[8] = 0; - strncpy(SD(sh)->name, &buff[16], 17); - SD(sh)->name[17] = 0; - SD(sh)->revision[0] = buff[32]; - SD(sh)->revision[1] = buff[33]; - SD(sh)->revision[2] = buff[34]; - SD(sh)->revision[3] = '.'; - SD(sh)->revision[4] = buff[35]; - SD(sh)->revision[5] = 0; - - switch (ntohl(gc->len)) { - case 0x1c: - SD(sh)->EATA_revision = 'a'; - break; - case 0x1e: - SD(sh)->EATA_revision = 'b'; - break; - case 0x22: - SD(sh)->EATA_revision = 'c'; - break; - case 0x24: - SD(sh)->EATA_revision = 'z'; - default: - SD(sh)->EATA_revision = '?'; - } - - if(ntohl(gc->len) >= 0x22) { - if (gc->is_PCI == TRUE) - hd->bustype = IS_PCI; - else if (gc->is_EISA == TRUE) - hd->bustype = IS_EISA; - else - hd->bustype = IS_ISA; - } else { - if (buff[21] == '4') - hd->bustype = IS_PCI; - else if (buff[21] == '2') - hd->bustype = IS_EISA; - else - hd->bustype = IS_ISA; - } - - SD(sh)->cplen=cplen; - SD(sh)->cppadlen=cppadlen; - SD(sh)->hostid=gc->scsi_id[3]; - SD(sh)->devflags=1<<gc->scsi_id[3]; - SD(sh)->moresupport=gc->MORE_support; - sh->unique_id = base; - sh->base = (char *) base; - sh->io_port = base; - sh->n_io_port = 8; - sh->irq = gc->IRQ; - sh->dma_channel = PIO; - sh->this_id = gc->scsi_id[3]; - sh->can_queue = 1; - sh->cmd_per_lun = 1; - sh->sg_tablesize = SG_ALL; - - hd->channel = 0; - - sh->max_id = 8; - sh->max_lun = 8; - - if (gc->SECOND) - hd->primary = FALSE; - else - hd->primary = TRUE; - - sh->unchecked_isa_dma = FALSE; /* We can only do PIO */ - - hd->next = NULL; /* build a linked list of all HBAs */ - hd->prev = last_HBA; - if(hd->prev != NULL) - SD(hd->prev)->next = sh; - last_HBA = sh; - if (first_HBA == NULL) - first_HBA = sh; - registered_HBAs++; - return (1); -} - -void find_pio_ISA(struct get_conf *buf, Scsi_Host_Template * tpnt) -{ - int i; - - for (i = 0; i < MAXISA; i++) { - if (ISAbases[i]) { - if (get_pio_conf_PIO(ISAbases[i], buf) == TRUE){ - register_pio_HBA(ISAbases[i], buf, tpnt); - } - ISAbases[i] = 0; - } - } - return; -} - -void find_pio_EISA(struct get_conf *buf, Scsi_Host_Template * tpnt) -{ - u32 base; - int i; - -#if CHECKPAL - u8 pal1, pal2, pal3; -#endif - - for (i = 0; i < MAXEISA; i++) { - if (EISAbases[i] == TRUE) { /* Still a possibility ? */ - - base = 0x1c88 + (i * 0x1000); -#if CHECKPAL - pal1 = inb((u16)base - 8); - pal2 = inb((u16)base - 7); - pal3 = inb((u16)base - 6); - - if (((pal1 == 0x12) && (pal2 == 0x14)) || - ((pal1 == 0x38) && (pal2 == 0xa3) && (pal3 == 0x82)) || - ((pal1 == 0x06) && (pal2 == 0x94) && (pal3 == 0x24))) { - DBG(DBG_PROBE, printk("EISA EATA id tags found: %x %x %x \n", - (int)pal1, (int)pal2, (int)pal3)); -#endif - if (get_pio_conf_PIO(base, buf) == TRUE) { - DBG(DBG_PROBE && DBG_EISA, print_pio_config(buf)); - if (buf->IRQ) { - register_pio_HBA(base, buf, tpnt); - } else - printk("eata_dma: No valid IRQ. HBA removed from list\n"); - } - /* Nothing found here so we take it from the list */ - EISAbases[i] = 0; -#if CHECKPAL - } -#endif - } - } - return; -} - -void find_pio_PCI(struct get_conf *buf, Scsi_Host_Template * tpnt) -{ - -#ifndef CONFIG_PCI - printk("eata_pio: kernel PCI support not enabled. Skipping scan for PCI HBAs.\n"); -#else - - u8 pci_bus, pci_device_fn; - static s16 pci_index = 0; /* Device index to PCI BIOS calls */ - u32 base = 0; - u16 com_adr; - u16 rev_device; - u32 error, i, x; - - if (pcibios_present()) { - for (i = 0; i <= MAXPCI; ++i, ++pci_index) { - if (pcibios_find_device(PCI_VENDOR_ID_DPT, PCI_DEVICE_ID_DPT, - pci_index, &pci_bus, &pci_device_fn)) - break; - DBG(DBG_PROBE && DBG_PCI, - printk("eata_pio: HBA at bus %d, device %d," - " function %d, index %d\n", (s32)pci_bus, - (s32)((pci_device_fn & 0xf8) >> 3), - (s32)(pci_device_fn & 7), pci_index)); - - if (!(error = pcibios_read_config_word(pci_bus, pci_device_fn, - PCI_CLASS_DEVICE, &rev_device))) { - if (rev_device == PCI_CLASS_STORAGE_SCSI) { - if (!(error = pcibios_read_config_word(pci_bus, - pci_device_fn, PCI_COMMAND, - (u16 *) & com_adr))) { - if (!((com_adr & PCI_COMMAND_IO) && - (com_adr & PCI_COMMAND_MASTER))) { - printk("HBA has IO or BUSMASTER mode disabled\n"); - continue; - } - } else - printk("eata_pio: error %x while reading " - "PCI_COMMAND\n", error); - } else - printk("DEVICECLASSID %x didn't match\n", rev_device); - } else { - printk("eata_pio: error %x while reading PCI_CLASS_BASE\n", - error); - continue; - } - - if (!(error = pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_0, (int *) &base))){ - - /* Check if the address is valid */ - if (base & 0x01) { - base &= 0xfffffffe; - /* EISA tag there ? */ - if ((inb(base) == 0x12) && (inb(base + 1) == 0x14)) - continue; /* Jep, it's forced, so move on */ - base += 0x10; /* Now, THIS is the real address */ - if (base != 0x1f8) { - /* We didn't find it in the primary search */ - if (get_pio_conf_PIO(base, buf) == TRUE) { - if (buf->FORCADR) /* If the address is forced */ - continue; /* we'll find it later */ - - /* OK. We made it till here, so we can go now - * and register it. We only have to check and - * eventually remove it from the EISA and ISA list - */ - - register_pio_HBA(base, buf, tpnt); - - if (base < 0x1000) { - for (x = 0; x < MAXISA; ++x) { - if (ISAbases[x] == base) { - ISAbases[x] = 0; - break; - } - } - } else if ((base & 0x0fff) == 0x0c88) { - x = (base >> 12) & 0x0f; - EISAbases[x] = 0; - } - continue; /* break; */ - } - } - } - } else - printk("eata_pio: error %x while reading " - "PCI_BASE_ADDRESS_0\n", error); - } - } else - printk("eata_pio: No BIOS32 extensions present. This driver release " - "still depends on it.\n" - " Skipping scan for PCI HBAs.\n"); -#endif /* #ifndef CONFIG_PCI */ - return; -} - - -int eata_pio_detect(Scsi_Host_Template * tpnt) -{ - struct Scsi_Host *HBA_ptr; - struct get_conf gc; - int i; - - DBG((DBG_PROBE && DBG_DELAY) || DPT_DEBUG, - printk("Using lots of delays to let you read the debugging output\n")); - - tpnt->proc_dir = &proc_scsi_eata_pio; - - find_pio_PCI(&gc, tpnt); - - find_pio_EISA(&gc, tpnt); - - find_pio_ISA(&gc, tpnt); - - for (i = 0; i <= MAXIRQ; i++) - if (reg_IRQ[i]) - request_irq(i, eata_pio_int_handler, SA_INTERRUPT, "EATA-PIO"); - - HBA_ptr = first_HBA; - - if (registered_HBAs != 0) { - printk("EATA (Extended Attachment) PIO driver version: %d.%d%s\n" - "(c) 1993-95 Michael Neuffer, neuffer@goofy.zdv.uni-mainz.de\n" - " Alfred Arnold, a.arnold@kfa-juelich.de\n" - "This release only supports DASD devices (harddisks)\n", - VER_MAJOR, VER_MINOR, VER_SUB); - - printk("Registered HBAs:\n"); - printk("HBA no. Boardtype: Revis: EATA: Bus: BaseIO: IRQ: Ch: ID: Pr:" - " QS: SG: CPL:\n"); - for (i = 1; i <= registered_HBAs; i++) { - printk("scsi%-2d: %.10s v%s 2.0%c %s %#.4x %2d %d %d %c" - " %2d %2d %2d\n", - HBA_ptr->host_no, SD(HBA_ptr)->name, SD(HBA_ptr)->revision, - SD(HBA_ptr)->EATA_revision, (SD(HBA_ptr)->bustype == 'P')? - "PCI ":(SD(HBA_ptr)->bustype == 'E')?"EISA":"ISA ", - (uint) HBA_ptr->base, HBA_ptr->irq, SD(HBA_ptr)->channel, - HBA_ptr->this_id, (SD(HBA_ptr)->primary == TRUE)?'Y':'N', - HBA_ptr->can_queue, HBA_ptr->sg_tablesize, - HBA_ptr->cmd_per_lun); - HBA_ptr = SD(HBA_ptr)->next; - } - } - DBG(DPT_DEBUG,DELAY(12)); - - return (registered_HBAs); -} - -#ifdef MODULE -/* Eventually this will go into an include file, but this will be later */ -Scsi_Host_Template driver_template = EATA_PIO; - -#include "scsi_module.c" -#endif - -/* - * Overrides for Emacs so that we almost follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 4 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -4 - * c-argdecl-indent: 4 - * c-label-offset: -4 - * c-continued-statement-offset: 4 - * c-continued-brace-offset: 0 - * indent-tabs-mode: nil - * tab-width: 8 - * End: - */ diff --git a/i386/i386at/gpl/linux/scsi/eata_pio.h b/i386/i386at/gpl/linux/scsi/eata_pio.h deleted file mode 100644 index 8a626e0b..00000000 --- a/i386/i386at/gpl/linux/scsi/eata_pio.h +++ /dev/null @@ -1,116 +0,0 @@ -/******************************************************** -* Header file for eata_pio.c Linux EATA-PIO SCSI driver * -* (c) 1993,94,95 Michael Neuffer * -********************************************************* -* last change: 95/06/21 * -********************************************************/ - - -#ifndef _EATA_PIO_H -#define _EATA_PIO_H - -#include <linux/blk.h> -#include "scsi.h" -#include "hosts.h" -#include <linux/scsicam.h> - -#ifndef HOSTS_C -#include "eata_generic.h" - -#define VER_MAJOR 0 -#define VER_MINOR 0 -#define VER_SUB "1b" - -/************************************************************************ - * Here you can switch parts of the code on and of * - ************************************************************************/ - -#define VERBOSE_SETUP /* show startup screen of 2001 */ -#define ALLOW_DMA_BOARDS 1 - -/************************************************************************ - * Debug options. * - * Enable DEBUG and whichever options you require. * - ************************************************************************/ -#define DEBUG_EATA 1 /* Enable debug code. */ -#define DPT_DEBUG 0 /* Bobs special */ -#define DBG_DELAY 0 /* Build in delays so debug messages can be - * be read before they vanish of the top of - * the screen! - */ -#define DBG_PROBE 0 /* Debug probe routines. */ -#define DBG_ISA 0 /* Trace ISA routines */ -#define DBG_EISA 0 /* Trace EISA routines */ -#define DBG_PCI 0 /* Trace PCI routines */ -#define DBG_PIO 0 /* Trace get_config_PIO */ -#define DBG_COM 0 /* Trace command call */ -#define DBG_QUEUE 0 /* Trace command queueing. */ -#define DBG_INTR 0 /* Trace interrupt service routine. */ -#define DBG_INTR2 0 /* Trace interrupt service routine. */ -#define DBG_PROC 0 /* Debug proc-fs related statistics */ -#define DBG_PROC_WRITE 0 -#define DBG_REGISTER 0 /* */ -#define DBG_ABNORM 1 /* Debug abnormal actions (reset, abort) */ - -#if DEBUG_EATA -#define DBG(x, y) if ((x)) {y;} -#else -#define DBG(x, y) -#endif - -#endif /* !HOSTS_C */ - -int eata_pio_detect(Scsi_Host_Template *); -const char *eata_pio_info(struct Scsi_Host *); -int eata_pio_command(Scsi_Cmnd *); -int eata_pio_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); -int eata_pio_abort(Scsi_Cmnd *); -int eata_pio_reset(Scsi_Cmnd *); -int eata_pio_proc_info(char *, char **, off_t, int, int, int); -#ifdef MODULE -int eata_pio_release(struct Scsi_Host *); -#else -#define eata_pio_release NULL -#endif - - -#define EATA_PIO { \ - NULL, NULL, \ - NULL, /* proc_dir_entry */ \ - eata_pio_proc_info, /* procinfo */ \ - "EATA (Extended Attachment) PIO driver", \ - eata_pio_detect, \ - eata_pio_release, \ - NULL, NULL, \ - eata_pio_queue, \ - eata_pio_abort, \ - eata_pio_reset, \ - NULL, /* Slave attach */ \ - scsicam_bios_param, \ - 0, /* Canqueue */ \ - 0, /* this_id */ \ - 0, /* sg_tablesize */ \ - 0, /* cmd_per_lun */ \ - 0, /* present */ \ - 1, /* True if ISA */ \ - ENABLE_CLUSTERING } - -#endif /* _EATA_PIO_H */ - -/* - * Overrides for Emacs so that we almost follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 4 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -4 - * c-argdecl-indent: 4 - * c-label-offset: -4 - * c-continued-statement-offset: 4 - * c-continued-brace-offset: 0 - * tab-width: 8 - * End: - */ diff --git a/i386/i386at/gpl/linux/scsi/eata_pio_proc.src b/i386/i386at/gpl/linux/scsi/eata_pio_proc.src deleted file mode 100644 index b5480091..00000000 --- a/i386/i386at/gpl/linux/scsi/eata_pio_proc.src +++ /dev/null @@ -1,150 +0,0 @@ - -#define MAX_SCSI_DEVICE_CODE 10 -const char *const pio_scsi_dev_types[MAX_SCSI_DEVICE_CODE] = -{ - "Direct-Access ", - "Sequential-Access", - "Printer ", - "Processor ", - "WORM ", - "CD-ROM ", - "Scanner ", - "Optical Device ", - "Medium Changer ", - "Communications " -}; - -/* - * eata_set_info - * buffer : pointer to the data that has been written to the hostfile - * length : number of bytes written to the hostfile - * HBA_ptr: pointer to the Scsi_Host struct - */ -int eata_pio_set_info(char *buffer, int length, struct Scsi_Host *HBA_ptr) -{ - DBG(DBG_PROC_WRITE, printk("%s\n", buffer)); - return(-ENOSYS); /* Currently this is a no-op */ -} - -/* - * eata_proc_info - * inout : decides on the direction of the dataflow and the meaning of the - * variables - * buffer: If inout==FALSE data is beeing written to it else read from it - * *start: If inout==FALSE start of the valid data in the buffer - * offset: If inout==FALSE offset from the beginning of the imaginary file - * from which we start writing into the buffer - * length: If inout==FALSE max number of bytes to be written into the buffer - * else number of bytes in the buffer - */ -int eata_pio_proc_info(char *buffer, char **start, off_t offset, int length, - int hostno, int inout) -{ - - Scsi_Device *scd; - struct Scsi_Host *HBA_ptr; - static u8 buff[512]; - int i; - int size, len = 0; - off_t begin = 0; - off_t pos = 0; - - HBA_ptr = first_HBA; - for (i = 1; i <= registered_HBAs; i++) { - if (HBA_ptr->host_no == hostno) - break; - HBA_ptr = SD(HBA_ptr)->next; - } - - if(inout == TRUE) /* Has data been writen to the file ? */ - return(eata_pio_set_info(buffer, length, HBA_ptr)); - - if (offset == 0) - memset(buff, 0, sizeof(buff)); - - size = sprintf(buffer+len, "EATA (Extended Attachment) PIO driver version: " - "%d.%d%s\n",VER_MAJOR, VER_MINOR, VER_SUB); - len += size; pos = begin + len; - size = sprintf(buffer + len, "queued commands: %10ld\n" - "processed interrupts:%10ld\n", queue_counter, int_counter); - len += size; pos = begin + len; - - size = sprintf(buffer + len, "\nscsi%-2d: HBA %.10s\n", - HBA_ptr->host_no, SD(HBA_ptr)->name); - len += size; - pos = begin + len; - size = sprintf(buffer + len, "Firmware revision: v%s\n", - SD(HBA_ptr)->revision); - len += size; - pos = begin + len; - size = sprintf(buffer + len, "IO: PIO\n"); - len += size; - pos = begin + len; - size = sprintf(buffer + len, "Base IO : %#.4x\n", (u32) HBA_ptr->base); - len += size; - pos = begin + len; - size = sprintf(buffer + len, "Host Bus: %s\n", - (SD(HBA_ptr)->bustype == 'P')?"PCI ": - (SD(HBA_ptr)->bustype == 'E')?"EISA":"ISA "); - - len += size; - pos = begin + len; - - if (pos < offset) { - len = 0; - begin = pos; - } - if (pos > offset + length) - goto stop_output; - - scd = scsi_devices; - - size = sprintf(buffer+len,"Attached devices: %s\n", (scd)?"":"none"); - len += size; - pos = begin + len; - - while (scd) { - if (scd->host == HBA_ptr) { - proc_print_scsidevice(scd, buffer, &size, len); - len += size; - pos = begin + len; - - if (pos < offset) { - len = 0; - begin = pos; - } - if (pos > offset + length) - goto stop_output; - } - scd = scd->next; - } - - stop_output: - DBG(DBG_PROC, printk("2pos: %ld offset: %ld len: %d\n", pos, offset, len)); - *start=buffer+(offset-begin); /* Start of wanted data */ - len-=(offset-begin); /* Start slop */ - if(len>length) - len = length; /* Ending slop */ - DBG(DBG_PROC, printk("3pos: %ld offset: %ld len: %d\n", pos, offset, len)); - - return (len); -} - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 4 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -4 - * c-argdecl-indent: 4 - * c-label-offset: -4 - * c-continued-statement-offset: 4 - * c-continued-brace-offset: 0 - * tab-width: 8 - * End: - */ - diff --git a/i386/i386at/gpl/linux/scsi/fdomain.c b/i386/i386at/gpl/linux/scsi/fdomain.c deleted file mode 100644 index 54507046..00000000 --- a/i386/i386at/gpl/linux/scsi/fdomain.c +++ /dev/null @@ -1,2016 +0,0 @@ -/* fdomain.c -- Future Domain TMC-16x0 SCSI driver - * Created: Sun May 3 18:53:19 1992 by faith@cs.unc.edu - * Revised: Thu Oct 12 15:59:37 1995 by r.faith@ieee.org - * Author: Rickard E. Faith, faith@cs.unc.edu - * Copyright 1992, 1993, 1994, 1995 Rickard E. Faith - * - * $Id: fdomain.c,v 1.1.1.1 1997/02/25 21:27:49 thomas Exp $ - - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - - ************************************************************************** - - DESCRIPTION: - - This is the Linux low-level SCSI driver for Future Domain TMC-1660/1680 - TMC-1650/1670, and TMC-3260 SCSI host adapters. The 1650 and 1670 have a - 25-pin external connector, whereas the 1660 and 1680 have a SCSI-2 50-pin - high-density external connector. The 1670 and 1680 have floppy disk - controllers built in. The TMC-3260 is a PCI bus card. - - Future Domain's older boards are based on the TMC-1800 chip, and this - driver was originally written for a TMC-1680 board with the TMC-1800 chip. - More recently, boards are being produced with the TMC-18C50 and TMC-18C30 - chips. The latest and greatest board may not work with this driver. If - you have to patch this driver so that it will recognize your board's BIOS - signature, then the driver may fail to function after the board is - detected. - - The following BIOS versions are supported: 2.0, 3.0, 3.2, 3.4, and 3.5. - The following chips are supported: TMC-1800, TMC-18C50, TMC-18C30. - Reports suggest that the driver will also work with the 36C70 chip and - with the Quantum ISA-200S and ISA-250MG SCSI adapters. - - Please note that the drive ordering that Future Domain implemented in BIOS - versions 3.4 and 3.5 is the opposite of the order (currently) used by the - rest of the SCSI industry. If you have BIOS version 3.4 or 3.5, and have - more then one drive, then the drive ordering will be the reverse of that - which you see under DOS. For example, under DOS SCSI ID 0 will be D: and - SCSI ID 1 will be C: (the boot device). Under Linux, SCSI ID 0 will be - /dev/sda and SCSI ID 1 will be /dev/sdb. The Linux ordering is consistent - with that provided by all the other SCSI drivers for Linux. If you want - this changed, send me patches that are protected by #ifdefs. - - If you have a TMC-8xx or TMC-9xx board, then this is not the driver for - your board. Please refer to the Seagate driver for more information and - possible support. - - - - REFERENCES USED: - - "TMC-1800 SCSI Chip Specification (FDC-1800T)", Future Domain Corporation, - 1990. - - "Technical Reference Manual: 18C50 SCSI Host Adapter Chip", Future Domain - Corporation, January 1992. - - "LXT SCSI Products: Specifications and OEM Technical Manual (Revision - B/September 1991)", Maxtor Corporation, 1991. - - "7213S product Manual (Revision P3)", Maxtor Corporation, 1992. - - "Draft Proposed American National Standard: Small Computer System - Interface - 2 (SCSI-2)", Global Engineering Documents. (X3T9.2/86-109, - revision 10h, October 17, 1991) - - Private communications, Drew Eckhardt (drew@cs.colorado.edu) and Eric - Youngdale (ericy@cais.com), 1992. - - Private communication, Tuong Le (Future Domain Engineering department), - 1994. (Disk geometry computations for Future Domain BIOS version 3.4, and - TMC-18C30 detection.) - - Hogan, Thom. The Programmer's PC Sourcebook. Microsoft Press, 1988. Page - 60 (2.39: Disk Partition Table Layout). - - "18C30 Technical Reference Manual", Future Domain Corporation, 1993, page - 6-1. - - - - NOTES ON REFERENCES: - - The Maxtor manuals were free. Maxtor telephone technical support is - great! - - The Future Domain manuals were $25 and $35. They document the chip, not - the TMC-16x0 boards, so some information I had to guess at. In 1992, - Future Domain sold DOS BIOS source for $250 and the UN*X driver source was - $750, but these required a non-disclosure agreement, so even if I could - have afforded them, they would *not* have been useful for writing this - publically distributable driver. Future Domain technical support has - provided some information on the phone and have sent a few useful FAXs. - They have been much more helpful since they started to recognize that the - word "Linux" refers to an operating system :-). - - - - ALPHA TESTERS: - - There are many other alpha testers that come and go as the driver - develops. The people listed here were most helpful in times of greatest - need (mostly early on -- I've probably left out a few worthy people in - more recent times): - - Todd Carrico (todd@wutc.wustl.edu), Dan Poirier (poirier@cs.unc.edu ), Ken - Corey (kenc@sol.acs.unt.edu), C. de Bruin (bruin@bruin@sterbbs.nl), Sakari - Aaltonen (sakaria@vipunen.hit.fi), John Rice (rice@xanth.cs.odu.edu), Brad - Yearwood (brad@optilink.com), and Ray Toy (toy@soho.crd.ge.com). - - Special thanks to Tien-Wan Yang (twyang@cs.uh.edu), who graciously lent me - his 18C50-based card for debugging. He is the sole reason that this - driver works with the 18C50 chip. - - Thanks to Dave Newman (dnewman@crl.com) for providing initial patches for - the version 3.4 BIOS. - - Thanks to James T. McKinley (mckinley@msupa.pa.msu.edu) for providing - patches that support the TMC-3260, a PCI bus card with the 36C70 chip. - The 36C70 chip appears to be "completely compatible" with the 18C30 chip. - - Thanks to Eric Kasten (tigger@petroglyph.cl.msu.edu) for providing the - patch for the version 3.5 BIOS. - - Thanks for Stephen Henson (shenson@nyx10.cs.du.edu) for providing the - patch for the Quantum ISA-200S SCSI adapter. - - Thanks to Adam Bowen for the signature to the 1610M/MER/MEX scsi cards, to - Martin Andrews (andrewm@ccfadm.eeg.ccf.org) for the signature to some - random TMC-1680 repackaged by IBM; and to Mintak Ng (mintak@panix.com) for - the version 3.61 BIOS siganture. - - Thanks for Mark Singer (elf@netcom.com) and Richard Simpson - (rsimpson@ewrcsdra.demon.co.uk) for more Quantum signatures and detective - work on the Quantum RAM layout. - - Special thanks to James T. McKinley (mckinley@msupa.pa.msu.edu) for - providing patches for proper PCI BIOS32-mediated detection of the TMC-3260 - card (a PCI bus card with the 36C70 chip). Please send James PCI-related - bug reports. - - Thanks to Tom Cavin (tec@usa1.com) for preliminary command-line option - patches. - - All of the alpha testers deserve much thanks. - - - - NOTES ON USER DEFINABLE OPTIONS: - - DEBUG: This turns on the printing of various debug information. - - ENABLE_PARITY: This turns on SCSI parity checking. With the current - driver, all attached devices must support SCSI parity. If none of your - devices support parity, then you can probably get the driver to work by - turning this option off. I have no way of testing this, however. - - FIFO_COUNT: The host adapter has an 8K cache (host adapters based on the - 18C30 chip have a 2k cache). When this many 512 byte blocks are filled by - the SCSI device, an interrupt will be raised. Therefore, this could be as - low as 0, or as high as 16. Note, however, that values which are too high - or too low seem to prevent any interrupts from occurring, and thereby lock - up the machine. I have found that 2 is a good number, but throughput may - be increased by changing this value to values which are close to 2. - Please let me know if you try any different values. - - DO_DETECT: This activates some old scan code which was needed before the - high level drivers got fixed. If you are having trouble with the driver, - turning this on should not hurt, and might help. Please let me know if - this is the case, since this code will be removed from future drivers. - - RESELECTION: This is no longer an option, since I gave up trying to - implement it in version 4.x of this driver. It did not improve - performance at all and made the driver unstable (because I never found one - of the two race conditions which were introduced by the multiple - outstanding command code). The instability seems a very high price to pay - just so that you don't have to wait for the tape to rewind. If you want - this feature implemented, send me patches. I'll be happy to send a copy - of my (broken) driver to anyone who would like to see a copy. - - **************************************************************************/ - -#ifdef MODULE -#include <linux/module.h> -#endif - -#include <linux/sched.h> -#include <asm/io.h> -#include <linux/blk.h> -#include "scsi.h" -#include "hosts.h" -#include "fdomain.h" -#include <asm/system.h> -#include <linux/errno.h> -#include <linux/string.h> -#include <linux/ioport.h> -#include <linux/proc_fs.h> -#include <linux/bios32.h> -#include <linux/pci.h> -#include <linux/stat.h> - -#include <linux/config.h> /* for CONFIG_PCI */ - -struct proc_dir_entry proc_scsi_fdomain = { - PROC_SCSI_FDOMAIN, 7, "fdomain", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - -#define VERSION "$Revision: 1.1.1.1 $" - -/* START OF USER DEFINABLE OPTIONS */ - -#define DEBUG 1 /* Enable debugging output */ -#define ENABLE_PARITY 1 /* Enable SCSI Parity */ -#define FIFO_COUNT 2 /* Number of 512 byte blocks before INTR */ -#define DO_DETECT 0 /* Do device detection here (see scsi.c) */ - -/* END OF USER DEFINABLE OPTIONS */ - -#if DEBUG -#define EVERY_ACCESS 0 /* Write a line on every scsi access */ -#define ERRORS_ONLY 1 /* Only write a line if there is an error */ -#define DEBUG_DETECT 0 /* Debug fdomain_16x0_detect() */ -#define DEBUG_MESSAGES 1 /* Debug MESSAGE IN phase */ -#define DEBUG_ABORT 1 /* Debug abort() routine */ -#define DEBUG_RESET 1 /* Debug reset() routine */ -#define DEBUG_RACE 1 /* Debug interrupt-driven race condition */ -#else -#define EVERY_ACCESS 0 /* LEAVE THESE ALONE--CHANGE THE ONES ABOVE */ -#define ERRORS_ONLY 0 -#define DEBUG_DETECT 0 -#define DEBUG_MESSAGES 0 -#define DEBUG_ABORT 0 -#define DEBUG_RESET 0 -#define DEBUG_RACE 0 -#endif - -/* Errors are reported on the line, so we don't need to report them again */ -#if EVERY_ACCESS -#undef ERRORS_ONLY -#define ERRORS_ONLY 0 -#endif - -#if ENABLE_PARITY -#define PARITY_MASK 0x08 -#else -#define PARITY_MASK 0x00 -#endif - -enum chip_type { - unknown = 0x00, - tmc1800 = 0x01, - tmc18c50 = 0x02, - tmc18c30 = 0x03, -}; - -enum { - in_arbitration = 0x02, - in_selection = 0x04, - in_other = 0x08, - disconnect = 0x10, - aborted = 0x20, - sent_ident = 0x40, -}; - -enum in_port_type { - Read_SCSI_Data = 0, - SCSI_Status = 1, - TMC_Status = 2, - FIFO_Status = 3, /* tmc18c50/tmc18c30 only */ - Interrupt_Cond = 4, /* tmc18c50/tmc18c30 only */ - LSB_ID_Code = 5, - MSB_ID_Code = 6, - Read_Loopback = 7, - SCSI_Data_NoACK = 8, - Interrupt_Status = 9, - Configuration1 = 10, - Configuration2 = 11, /* tmc18c50/tmc18c30 only */ - Read_FIFO = 12, - FIFO_Data_Count = 14 -}; - -enum out_port_type { - Write_SCSI_Data = 0, - SCSI_Cntl = 1, - Interrupt_Cntl = 2, - SCSI_Mode_Cntl = 3, - TMC_Cntl = 4, - Memory_Cntl = 5, /* tmc18c50/tmc18c30 only */ - Write_Loopback = 7, - IO_Control = 11, /* tmc18c30 only */ - Write_FIFO = 12 -}; - -static int port_base = 0; -static void *bios_base = NULL; -static int bios_major = 0; -static int bios_minor = 0; -static int PCI_bus = 0; -static int Quantum = 0; /* Quantum board variant */ -static int interrupt_level = 0; -static volatile int in_command = 0; -static Scsi_Cmnd *current_SC = NULL; -static enum chip_type chip = unknown; -static int adapter_mask = 0; -static int this_id = 0; -static int setup_called = 0; - -#if DEBUG_RACE -static volatile int in_interrupt_flag = 0; -#endif - -static int SCSI_Mode_Cntl_port; -static int FIFO_Data_Count_port; -static int Interrupt_Cntl_port; -static int Interrupt_Status_port; -static int Read_FIFO_port; -static int Read_SCSI_Data_port; -static int SCSI_Cntl_port; -static int SCSI_Data_NoACK_port; -static int SCSI_Status_port; -static int TMC_Cntl_port; -static int TMC_Status_port; -static int Write_FIFO_port; -static int Write_SCSI_Data_port; - -static int FIFO_Size = 0x2000; /* 8k FIFO for - pre-tmc18c30 chips */ - -extern void fdomain_16x0_intr( int irq, struct pt_regs * regs ); - -static void *addresses[] = { - (void *)0xc8000, - (void *)0xca000, - (void *)0xce000, - (void *)0xde000, - (void *)0xd0000, /* Extra addresses for PCI boards */ - (void *)0xe0000, -}; -#define ADDRESS_COUNT (sizeof( addresses ) / sizeof( unsigned )) - -static unsigned short ports[] = { 0x140, 0x150, 0x160, 0x170 }; -#define PORT_COUNT (sizeof( ports ) / sizeof( unsigned short )) - -static unsigned short ints[] = { 3, 5, 10, 11, 12, 14, 15, 0 }; - -/* - - READ THIS BEFORE YOU ADD A SIGNATURE! - - READING THIS SHORT NOTE CAN SAVE YOU LOTS OF TIME! - - READ EVERY WORD, ESPECIALLY THE WORD *NOT* - - This driver works *ONLY* for Future Domain cards using the TMC-1800, - TMC-18C50, or TMC-18C30 chip. This includes models TMC-1650, 1660, 1670, - and 1680. - - The following BIOS signature signatures are for boards which do *NOT* - work with this driver (these TMC-8xx and TMC-9xx boards may work with the - Seagate driver): - - FUTURE DOMAIN CORP. (C) 1986-1988 V4.0I 03/16/88 - FUTURE DOMAIN CORP. (C) 1986-1989 V5.0C2/14/89 - FUTURE DOMAIN CORP. (C) 1986-1989 V6.0A7/28/89 - FUTURE DOMAIN CORP. (C) 1986-1990 V6.0105/31/90 - FUTURE DOMAIN CORP. (C) 1986-1990 V6.0209/18/90 - FUTURE DOMAIN CORP. (C) 1986-1990 V7.009/18/90 - FUTURE DOMAIN CORP. (C) 1992 V8.00.004/02/92 - -*/ - -struct signature { - const char *signature; - int sig_offset; - int sig_length; - int major_bios_version; - int minor_bios_version; - int flag; /* 1 == PCI_bus, 2 == ISA_200S, 3 == ISA_250MG, 4 == ISA_200S */ -} signatures[] = { - /* 1 2 3 4 5 6 */ - /* 123456789012345678901234567890123456789012345678901234567890 */ - { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V2.07/28/89", 5, 50, 2, 0, 0 }, - { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V1.07/28/89", 5, 50, 2, 0, 0 }, - { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V2.07/28/89", 72, 50, 2, 0, 2 }, - { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V2.0", 73, 43, 2, 0, 3 }, - { "FUTURE DOMAIN CORP. (C) 1991 1800-V2.0.", 72, 39, 2, 0, 4 }, - { "FUTURE DOMAIN CORP. (C) 1992 V3.00.004/02/92", 5, 44, 3, 0, 0 }, - { "FUTURE DOMAIN TMC-18XX (C) 1993 V3.203/12/93", 5, 44, 3, 2, 0 }, - { "IBM F1 P2 BIOS v1.0104/29/93", 5, 28, 3, -1, 0 }, - { "Future Domain Corp. V1.0008/18/93", 5, 33, 3, 4, 0 }, - { "Future Domain Corp. V1.0008/18/93", 26, 33, 3, 4, 1 }, - /* This next signature may not be a 3.5 bios */ - { "Future Domain Corp. V2.0108/18/93", 5, 33, 3, 5, 0 }, - { "FUTURE DOMAIN CORP. V3.5008/18/93", 5, 34, 3, 5, 0 }, - { "FUTURE DOMAIN 18c30/18c50/1800 (C) 1994 V3.5", 5, 44, 3, 5, 0 }, - { "FUTURE DOMAIN CORP. V3.6008/18/93", 5, 34, 3, 6, 0 }, - { "FUTURE DOMAIN CORP. V3.6108/18/93", 5, 34, 3, 6, 0 }, - { "FUTURE DOMAIN TMC-18XX", 5, 22, -1, -1, 0 }, - - /* READ NOTICE ABOVE *BEFORE* YOU WASTE YOUR TIME ADDING A SIGNATURE - Also, fix the disk geometry code for your signature and send your - changes for faith@cs.unc.edu. Above all, do *NOT* change any old - signatures! - - Note that the last line will match a "generic" 18XX bios. Because - Future Domain has changed the host SCSI ID and/or the location of the - geometry information in the on-board RAM area for each of the first - three BIOS's, it is still important to enter a fully qualified - signature in the table for any new BIOS's (after the host SCSI ID and - geometry location are verified). */ -}; - -#define SIGNATURE_COUNT (sizeof( signatures ) / sizeof( struct signature )) - -static void print_banner( struct Scsi_Host *shpnt ) -{ - if (!shpnt) return; /* This won't ever happen */ - - if (bios_major < 0 && bios_minor < 0) { - printk( "scsi%d <fdomain>: No BIOS; using scsi id %d\n", - shpnt->host_no, shpnt->this_id ); - } else { - printk( "scsi%d <fdomain>: BIOS version ", shpnt->host_no ); - - if (bios_major >= 0) printk( "%d.", bios_major ); - else printk( "?." ); - - if (bios_minor >= 0) printk( "%d", bios_minor ); - else printk( "?." ); - - printk( " at 0x%x using scsi id %d\n", - (unsigned)bios_base, shpnt->this_id ); - } - - /* If this driver works for later FD PCI - boards, we will have to modify banner - for additional PCI cards, but for now if - it's PCI it's a TMC-3260 - JTM */ - printk( "scsi%d <fdomain>: %s chip at 0x%x irq ", - shpnt->host_no, - chip == tmc1800 ? "TMC-1800" - : (chip == tmc18c50 ? "TMC-18C50" - : (chip == tmc18c30 ? - (PCI_bus ? "TMC-36C70 (PCI bus)" : "TMC-18C30") - : "Unknown")), - port_base ); - - if (interrupt_level) printk( "%d", interrupt_level ); - else printk( "<none>" ); - - printk( "\n" ); -} - -void fdomain_setup( char *str, int *ints ) -{ - if (setup_called++ || ints[0] < 2 || ints[0] > 3) { - printk( "fdomain: usage: fdomain=<PORT_BASE>,<IRQ>[,<ADAPTER_ID>]\n" ); - printk( "fdomain: bad LILO parameters?\n" ); - } - - port_base = ints[0] >= 1 ? ints[1] : 0; - interrupt_level = ints[0] >= 2 ? ints[2] : 0; - this_id = ints[0] >= 3 ? ints[3] : 0; - - bios_major = bios_minor = -1; /* Use geometry for BIOS version >= 3.4 */ -} - - -static void do_pause( unsigned amount ) /* Pause for amount*10 milliseconds */ -{ - unsigned long the_time = jiffies + amount; /* 0.01 seconds per jiffy */ - - while (jiffies < the_time); -} - -inline static void fdomain_make_bus_idle( void ) -{ - outb( 0, SCSI_Cntl_port ); - outb( 0, SCSI_Mode_Cntl_port ); - if (chip == tmc18c50 || chip == tmc18c30) - outb( 0x21 | PARITY_MASK, TMC_Cntl_port ); /* Clear forced intr. */ - else - outb( 0x01 | PARITY_MASK, TMC_Cntl_port ); -} - -static int fdomain_is_valid_port( int port ) -{ -#if DEBUG_DETECT - printk( " (%x%x),", - inb( port + MSB_ID_Code ), inb( port + LSB_ID_Code ) ); -#endif - - /* The MCA ID is a unique id for each MCA compatible board. We - are using ISA boards, but Future Domain provides the MCA ID - anyway. We can use this ID to ensure that this is a Future - Domain TMC-1660/TMC-1680. - */ - - if (inb( port + LSB_ID_Code ) != 0xe9) { /* test for 0x6127 id */ - if (inb( port + LSB_ID_Code ) != 0x27) return 0; - if (inb( port + MSB_ID_Code ) != 0x61) return 0; - chip = tmc1800; - } else { /* test for 0xe960 id */ - if (inb( port + MSB_ID_Code ) != 0x60) return 0; - chip = tmc18c50; - -#if 0 - - /* Try to toggle 32-bit mode. This only - works on an 18c30 chip. (User reports - say that this doesn't work at all, so - we'll use the other method.) */ - - outb( 0x80, port + IO_Control ); - if ((inb( port + Configuration2 ) & 0x80) == 0x80) { - outb( 0x00, port + IO_Control ); - if ((inb( port + Configuration2 ) & 0x80) == 0x00) { - chip = tmc18c30; - FIFO_Size = 0x800; /* 2k FIFO */ - } - } -#else - - /* That should have worked, but appears to - have problems. Lets assume it is an - 18c30 if the RAM is disabled. */ - - if (inb( port + Configuration2 ) & 0x02) { - chip = tmc18c30; - FIFO_Size = 0x800; /* 2k FIFO */ - } -#endif - /* If that failed, we are an 18c50. */ - } - - return 1; -} - -static int fdomain_test_loopback( void ) -{ - int i; - int result; - - for (i = 0; i < 255; i++) { - outb( i, port_base + Write_Loopback ); - result = inb( port_base + Read_Loopback ); - if (i != result) - return 1; - } - return 0; -} - -/* fdomain_get_irq assumes that we have a valid MCA ID for a - TMC-1660/TMC-1680 Future Domain board. Now, check to be sure the - bios_base matches these ports. If someone was unlucky enough to have - purchased more than one Future Domain board, then they will have to - modify this code, as we only detect one board here. [The one with the - lowest bios_base.] - - Note that this routine is only used for systems without a PCI BIOS32 - (e.g., ISA bus). For PCI bus systems, this routine will likely fail - unless one of the IRQs listed in the ints array is used by the board. - Sometimes it is possible to use the computer's BIOS setup screen to - configure a PCI system so that one of these IRQs will be used by the - Future Domain card. */ - -static int fdomain_get_irq( int base ) -{ - int options = inb( base + Configuration1 ); - -#if DEBUG_DETECT - printk( " Options = %x\n", options ); -#endif - - /* Check for board with lowest bios_base -- - this isn't valid for the 18c30 or for - boards on the PCI bus, so just assume we - have the right board. */ - - if (chip != tmc18c30 - && !PCI_bus - && addresses[ (options & 0xc0) >> 6 ] != bios_base) return 0; - - return ints[ (options & 0x0e) >> 1 ]; -} - -static int fdomain_isa_detect( int *irq, int *iobase ) -{ - int i; - int base; - int flag = 0; - - if (bios_major == 2) { - /* The TMC-1660/TMC-1680 has a RAM area just after the BIOS ROM. - Assuming the ROM is enabled (otherwise we wouldn't have been - able to read the ROM signature :-), then the ROM sets up the - RAM area with some magic numbers, such as a list of port - base addresses and a list of the disk "geometry" reported to - DOS (this geometry has nothing to do with physical geometry). - */ - - switch (Quantum) { - case 2: /* ISA_200S */ - case 3: /* ISA_250MG */ - base = *((char *)bios_base + 0x1fa2) - + (*((char *)bios_base + 0x1fa3) << 8); - break; - case 4: /* ISA_200S (another one) */ - base = *((char *)bios_base + 0x1fa3) - + (*((char *)bios_base + 0x1fa4) << 8); - break; - default: - base = *((char *)bios_base + 0x1fcc) - + (*((char *)bios_base + 0x1fcd) << 8); - break; - } - -#if DEBUG_DETECT - printk( " %x,", base ); -#endif - - for (flag = 0, i = 0; !flag && i < PORT_COUNT; i++) { - if (base == ports[i]) - ++flag; - } - - if (flag && fdomain_is_valid_port( base )) { - *irq = fdomain_get_irq( base ); - *iobase = base; - return 1; - } - - /* This is a bad sign. It usually means that someone patched the - BIOS signature list (the signatures variable) to contain a BIOS - signature for a board *OTHER THAN* the TMC-1660/TMC-1680. */ - -#if DEBUG_DETECT - printk( " RAM FAILED, " ); -#endif - } - - /* Anyway, the alternative to finding the address in the RAM is to just - search through every possible port address for one that is attached - to the Future Domain card. Don't panic, though, about reading all - these random port addresses -- there are rumors that the Future - Domain BIOS does something very similar. - - Do not, however, check ports which the kernel knows are being used by - another driver. */ - - for (i = 0; i < PORT_COUNT; i++) { - base = ports[i]; - if (check_region( base, 0x10 )) { -#if DEBUG_DETECT - printk( " (%x inuse),", base ); -#endif - continue; - } -#if DEBUG_DETECT - printk( " %x,", base ); -#endif - if ((flag = fdomain_is_valid_port( base ))) break; - } - - if (!flag) return 0; /* iobase not found */ - - *irq = fdomain_get_irq( base ); - *iobase = base; - - return 1; /* success */ -} - -static int fdomain_pci_nobios_detect( int *irq, int *iobase ) -{ - int i; - int flag = 0; - - /* The proper way of doing this is to use ask the PCI bus for the device - IRQ and interrupt level. But we can't do that if PCI BIOS32 support - isn't compiled into the kernel, or if a PCI BIOS32 isn't present. - - Instead, we scan down a bunch of addresses (Future Domain tech - support says we will probably find the address before we get to - 0xf800). This works fine on some systems -- other systems may have - to scan more addresses. If you have to modify this section for your - installation, please send mail to faith@cs.unc.edu. */ - - for (i = 0xfff8; i > 0xe000; i -= 8) { - if (check_region( i, 0x10 )) { -#if DEBUG_DETECT - printk( " (%x inuse)," , i ); -#endif - continue; - } - if ((flag = fdomain_is_valid_port( i ))) break; - } - - if (!flag) return 0; /* iobase not found */ - - *irq = fdomain_get_irq( i ); - *iobase = i; - - return 1; /* success */ -} - -/* PCI detection function: int fdomain_pci_bios_detect(int* irq, int* - iobase) This function gets the Interrupt Level and I/O base address from - the PCI configuration registers. The I/O base address is masked with - 0xfff8 since on my card the address read from the PCI config registers - is off by one from the actual I/O base address necessary for accessing - the status and control registers on the card (PCI config register gives - 0xf801, actual address is 0xf800). This is likely a bug in the FD - config code that writes to the PCI registers, however using a mask - should be safe since I think the scan done by the card to determine the - I/O base is done in increments of 8 (i.e., 0xf800, 0xf808, ...), at - least the old scan code we used to use to get the I/O base did... Also, - the device ID from the PCI config registers is 0x0 and should be 0x60e9 - as it is in the status registers (offset 5 from I/O base). If this is - changed in future hardware/BIOS changes it will need to be fixed in this - detection function. Comments, bug reports, etc... on this function - should be sent to mckinley@msupa.pa.msu.edu - James T. McKinley. */ - -#ifdef CONFIG_PCI -static int fdomain_pci_bios_detect( int *irq, int *iobase ) -{ - int error; - unsigned char pci_bus, pci_dev_fn; /* PCI bus & device function */ - unsigned char pci_irq; /* PCI interrupt line */ - unsigned int pci_base; /* PCI I/O base address */ - unsigned short pci_vendor, pci_device; /* PCI vendor & device IDs */ - - /* If the PCI BIOS doesn't exist, use the old-style detection routines. - Otherwise, get the I/O base address and interrupt from the PCI config - registers. */ - - if (!pcibios_present()) return fdomain_pci_nobios_detect( irq, iobase ); - -#if DEBUG_DETECT - /* Tell how to print a list of the known PCI devices from bios32 and - list vendor and device IDs being used if in debug mode. */ - - printk( "\nINFO: cat /proc/pci to see list of PCI devices from bios32\n" ); - printk( "\nTMC-3260 detect:" - " Using PCI Vendor ID: 0x%x, PCI Device ID: 0x%x\n", - PCI_VENDOR_ID_FD, - PCI_DEVICE_ID_FD_36C70 ); -#endif - - /* We will have to change this if more than 1 PCI bus is present and the - FD scsi host is not on the first bus (i.e., a PCI to PCI bridge, - which is not supported by bios32 right now anyway). This should - probably be done by a call to pcibios_find_device but I can't get it - to work... Also the device ID reported from the PCI config registers - does not match the device ID quoted in the tech manual or available - from offset 5 from the I/O base address. It should be 0x60E9, but it - is 0x0 if read from the PCI config registers. I guess the FD folks - neglected to write it to the PCI registers... This loop is necessary - to get the device function (at least until someone can get - pcibios_find_device to work, I cannot but 53c7,8xx.c uses it...). */ - - pci_bus = 0; - - for (pci_dev_fn = 0x0; pci_dev_fn < 0xff; pci_dev_fn++) { - pcibios_read_config_word( pci_bus, - pci_dev_fn, - PCI_VENDOR_ID, - &pci_vendor ); - - if (pci_vendor == PCI_VENDOR_ID_FD) { - pcibios_read_config_word( pci_bus, - pci_dev_fn, - PCI_DEVICE_ID, - &pci_device ); - - if (pci_device == PCI_DEVICE_ID_FD_36C70) { - /* Break out once we have the correct device. If other FD - PCI devices are added to this driver we will need to add - an or of the other PCI_DEVICE_ID_FD_XXXXX's here. */ - break; - } else { - /* If we can't find an FD scsi card we give up. */ - return 0; - } - } - } - -#if DEBUG_DETECT - printk( "Future Domain 36C70 : at PCI bus %u, device %u, function %u\n", - pci_bus, - (pci_dev_fn & 0xf8) >> 3, - pci_dev_fn & 7 ); -#endif - - /* We now have the appropriate device function for the FD board so we - just read the PCI config info from the registers. */ - - if ((error = pcibios_read_config_dword( pci_bus, - pci_dev_fn, - PCI_BASE_ADDRESS_0, - &pci_base )) - || (error = pcibios_read_config_byte( pci_bus, - pci_dev_fn, - PCI_INTERRUPT_LINE, - &pci_irq ))) { - printk ( "PCI ERROR: Future Domain 36C70 not initializing" - " due to error reading configuration space\n" ); - return 0; - } else { -#if DEBUG_DETECT - printk( "TMC-3260 PCI: IRQ = %u, I/O base = 0x%lx\n", - pci_irq, pci_base ); -#endif - - /* Now we have the I/O base address and interrupt from the PCI - configuration registers. Unfortunately it seems that the I/O base - address is off by one on my card so I mask it with 0xfff8. This - must be some kind of goof in the FD code that does the autoconfig - and writes to the PCI registers (or maybe I just don't understand - something). If they fix it in later versions of the card or BIOS - we may have to adjust the address based on the signature or - something... */ - - *irq = pci_irq; - *iobase = (pci_base & 0xfff8); - -#if DEBUG_DETECT - printk( "TMC-3260 fix: Masking I/O base address with 0xff00.\n" ); - printk( "TMC-3260: IRQ = %d, I/O base = 0x%x\n", *irq, *iobase ); -#endif - - if (!fdomain_is_valid_port( *iobase )) return 0; - return 1; - } - return 0; -} -#endif - -int fdomain_16x0_detect( Scsi_Host_Template *tpnt ) -{ - int i, j; - int retcode; - struct Scsi_Host *shpnt; -#if DO_DETECT - const int buflen = 255; - Scsi_Cmnd SCinit; - unsigned char do_inquiry[] = { INQUIRY, 0, 0, 0, buflen, 0 }; - unsigned char do_request_sense[] = { REQUEST_SENSE, 0, 0, 0, buflen, 0 }; - unsigned char do_read_capacity[] = { READ_CAPACITY, - 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - unsigned char buf[buflen]; -#endif - -#if DEBUG_DETECT - printk( "fdomain_16x0_detect()," ); -#endif - tpnt->proc_dir = &proc_scsi_fdomain; - - if (setup_called) { -#if DEBUG_DETECT - printk( "no BIOS, using port_base = 0x%x, irq = %d\n", - port_base, interrupt_level ); -#endif - if (!fdomain_is_valid_port( port_base )) { - printk( "fdomain: cannot locate chip at port base 0x%x\n", - port_base ); - printk( "fdomain: bad LILO parameters?\n" ); - return 0; - } - } else { - int flag = 0; - - for (i = 0; !bios_base && i < ADDRESS_COUNT; i++) { -#if DEBUG_DETECT - printk( " %x(%x),", (unsigned)addresses[i], (unsigned)bios_base ); -#endif - for (j = 0; !bios_base && j < SIGNATURE_COUNT; j++) { - if (!memcmp( ((char *)addresses[i] + signatures[j].sig_offset), - signatures[j].signature, signatures[j].sig_length )) { - bios_major = signatures[j].major_bios_version; - bios_minor = signatures[j].minor_bios_version; - PCI_bus = (signatures[j].flag == 1); - Quantum = (signatures[j].flag > 1) ? signatures[j].flag : 0; - bios_base = addresses[i]; - } - } - } - - if (!bios_base) { -#if DEBUG_DETECT - printk( " FAILED: NO BIOS\n" ); -#endif - return 0; - } - - if (!PCI_bus) { - flag = fdomain_isa_detect( &interrupt_level, &port_base ); - } else { -#ifdef CONFIG_PCI - flag = fdomain_pci_bios_detect( &interrupt_level, &port_base ); -#else - flag = fdomain_pci_nobios_detect( &interrupt_level, &port_base ); -#endif - } - - if (!flag) { -#if DEBUG_DETECT - printk( " FAILED: NO PORT\n" ); -#endif -#ifdef CONFIG_PCI - printk( "\nTMC-3260 36C70 PCI scsi chip detection failed.\n" ); - printk( "Send mail to mckinley@msupa.pa.msu.edu.\n" ); -#endif - return 0; /* Cannot find valid set of ports */ - } - } - - SCSI_Mode_Cntl_port = port_base + SCSI_Mode_Cntl; - FIFO_Data_Count_port = port_base + FIFO_Data_Count; - Interrupt_Cntl_port = port_base + Interrupt_Cntl; - Interrupt_Status_port = port_base + Interrupt_Status; - Read_FIFO_port = port_base + Read_FIFO; - Read_SCSI_Data_port = port_base + Read_SCSI_Data; - SCSI_Cntl_port = port_base + SCSI_Cntl; - SCSI_Data_NoACK_port = port_base + SCSI_Data_NoACK; - SCSI_Status_port = port_base + SCSI_Status; - TMC_Cntl_port = port_base + TMC_Cntl; - TMC_Status_port = port_base + TMC_Status; - Write_FIFO_port = port_base + Write_FIFO; - Write_SCSI_Data_port = port_base + Write_SCSI_Data; - - fdomain_16x0_reset( NULL ); - - if (fdomain_test_loopback()) { -#if DEBUG_DETECT - printk( "fdomain: LOOPBACK TEST FAILED, FAILING DETECT!\n" ); -#endif - if (setup_called) { - printk( "fdomain: loopback test failed at port base 0x%x\n", - port_base ); - printk( "fdomain: bad LILO parameters?\n" ); - } - return 0; - } - - if (this_id) { - tpnt->this_id = (this_id & 0x07); - adapter_mask = (1 << tpnt->this_id); - } else { - if ((bios_major == 3 && bios_minor >= 2) || bios_major < 0) { - tpnt->this_id = 7; - adapter_mask = 0x80; - } else { - tpnt->this_id = 6; - adapter_mask = 0x40; - } - } - - /* Print out a banner here in case we can't - get resources. */ - - shpnt = scsi_register( tpnt, 0 ); - print_banner( shpnt ); - - /* Log IRQ with kernel */ - if (!interrupt_level) { - panic( "fdomain: *NO* interrupt level selected!\n" ); - } else { - /* Register the IRQ with the kernel */ - - retcode = request_irq( interrupt_level, - fdomain_16x0_intr, SA_INTERRUPT, "fdomain" ); - - if (retcode < 0) { - if (retcode == -EINVAL) { - printk( "fdomain: IRQ %d is bad!\n", interrupt_level ); - printk( " This shouldn't happen!\n" ); - printk( " Send mail to faith@cs.unc.edu\n" ); - } else if (retcode == -EBUSY) { - printk( "fdomain: IRQ %d is already in use!\n", interrupt_level ); - printk( " Please use another IRQ!\n" ); - } else { - printk( "fdomain: Error getting IRQ %d\n", interrupt_level ); - printk( " This shouldn't happen!\n" ); - printk( " Send mail to faith@cs.unc.edu\n" ); - } - panic( "fdomain: Driver requires interruptions\n" ); - } - } - - /* Log I/O ports with kernel */ - request_region( port_base, 0x10, "fdomain" ); - -#if DO_DETECT - - /* These routines are here because of the way the SCSI bus behaves after - a reset. This appropriate behavior was not handled correctly by the - higher level SCSI routines when I first wrote this driver. Now, - however, correct scan routines are part of scsi.c and these routines - are no longer needed. However, this code is still good for - debugging. */ - - SCinit.request_buffer = SCinit.buffer = buf; - SCinit.request_bufflen = SCinit.bufflen = sizeof(buf)-1; - SCinit.use_sg = 0; - SCinit.lun = 0; - - printk( "fdomain: detection routine scanning for devices:\n" ); - for (i = 0; i < 8; i++) { - SCinit.target = i; - if (i == tpnt->this_id) /* Skip host adapter */ - continue; - memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense)); - retcode = fdomain_16x0_command(&SCinit); - if (!retcode) { - memcpy(SCinit.cmnd, do_inquiry, sizeof(do_inquiry)); - retcode = fdomain_16x0_command(&SCinit); - if (!retcode) { - printk( " SCSI ID %d: ", i ); - for (j = 8; j < (buf[4] < 32 ? buf[4] : 32); j++) - printk( "%c", buf[j] >= 20 ? buf[j] : ' ' ); - memcpy(SCinit.cmnd, do_read_capacity, sizeof(do_read_capacity)); - retcode = fdomain_16x0_command(&SCinit); - if (!retcode) { - unsigned long blocks, size, capacity; - - blocks = (buf[0] << 24) | (buf[1] << 16) - | (buf[2] << 8) | buf[3]; - size = (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7]; - capacity = +( +(blocks / 1024L) * +(size * 10L)) / 1024L; - - printk( "%lu MB (%lu byte blocks)", - ((capacity + 5L) / 10L), size ); - } else { - memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense)); - retcode = fdomain_16x0_command(&SCinit); - } - printk ("\n" ); - } else { - memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense)); - retcode = fdomain_16x0_command(&SCinit); - } - } - } -#endif - - return 1; /* Maximum of one adapter will be detected. */ -} - -const char *fdomain_16x0_info( struct Scsi_Host *ignore ) -{ - static char buffer[80]; - char *pt; - - strcpy( buffer, "Future Domain TMC-16x0 SCSI driver, version" ); - if (strchr( VERSION, ':')) { /* Assume VERSION is an RCS Revision string */ - strcat( buffer, strchr( VERSION, ':' ) + 1 ); - pt = strrchr( buffer, '$') - 1; - if (!pt) /* Stripped RCS Revision string? */ - pt = buffer + strlen( buffer ) - 1; - if (*pt != ' ') - ++pt; - *pt = '\0'; - } else { /* Assume VERSION is a number */ - strcat( buffer, " " VERSION ); - } - - return buffer; -} - - /* First pass at /proc information routine. */ -/* - * inout : decides on the direction of the dataflow and the meaning of the - * variables - * buffer: If inout==FALSE data is beeing written to it else read from it - * *start: If inout==FALSE start of the valid data in the buffer - * offset: If inout==FALSE offset from the beginning of the imaginary file - * from which we start writing into the buffer - * length: If inout==FALSE max number of bytes to be written into the buffer - * else number of bytes in the buffer - */ -int fdomain_16x0_proc_info( char *buffer, char **start, off_t offset, - int length, int hostno, int inout ) -{ - const char *info = fdomain_16x0_info( NULL ); - int len; - int pos; - int begin; - - if (inout) return(-ENOSYS); - - begin = 0; - strcpy( buffer, info ); - strcat( buffer, "\n" ); - - pos = len = strlen( buffer ); - - if(pos < offset) { - len = 0; - begin = pos; - } - - *start = buffer + (offset - begin); /* Start of wanted data */ - len -= (offset - begin); - if(len > length) len = length; - - return(len); -} - -#if 0 -static int fdomain_arbitrate( void ) -{ - int status = 0; - unsigned long timeout; - -#if EVERY_ACCESS - printk( "fdomain_arbitrate()\n" ); -#endif - - outb( 0x00, SCSI_Cntl_port ); /* Disable data drivers */ - outb( adapter_mask, port_base + SCSI_Data_NoACK ); /* Set our id bit */ - outb( 0x04 | PARITY_MASK, TMC_Cntl_port ); /* Start arbitration */ - - timeout = jiffies + 50; /* 500 mS */ - while (jiffies < timeout) { - status = inb( TMC_Status_port ); /* Read adapter status */ - if (status & 0x02) /* Arbitration complete */ - return 0; - } - - /* Make bus idle */ - fdomain_make_bus_idle(); - -#if EVERY_ACCESS - printk( "Arbitration failed, status = %x\n", status ); -#endif -#if ERRORS_ONLY - printk( "fdomain: Arbitration failed, status = %x\n", status ); -#endif - return 1; -} -#endif - -static int fdomain_select( int target ) -{ - int status; - unsigned long timeout; - static int flag = 0; - - - outb( 0x82, SCSI_Cntl_port ); /* Bus Enable + Select */ - outb( adapter_mask | (1 << target), SCSI_Data_NoACK_port ); - - /* Stop arbitration and enable parity */ - outb( PARITY_MASK, TMC_Cntl_port ); - - timeout = jiffies + 35; /* 350mS -- because of timeouts - (was 250mS) */ - - while (jiffies < timeout) { - status = inb( SCSI_Status_port ); /* Read adapter status */ - if (status & 1) { /* Busy asserted */ - /* Enable SCSI Bus (on error, should make bus idle with 0) */ - outb( 0x80, SCSI_Cntl_port ); - return 0; - } - } - /* Make bus idle */ - fdomain_make_bus_idle(); -#if EVERY_ACCESS - if (!target) printk( "Selection failed\n" ); -#endif -#if ERRORS_ONLY - if (!target) { - if (chip == tmc18c30 && !flag) /* Skip first failure for 18C30 chips. */ - ++flag; - else - printk( "fdomain: Selection failed\n" ); - } -#endif - return 1; -} - -void my_done( int error ) -{ - if (in_command) { - in_command = 0; - outb( 0x00, Interrupt_Cntl_port ); - fdomain_make_bus_idle(); - current_SC->result = error; - if (current_SC->scsi_done) - current_SC->scsi_done( current_SC ); - else panic( "fdomain: current_SC->scsi_done() == NULL" ); - } else { - panic( "fdomain: my_done() called outside of command\n" ); - } -#if DEBUG_RACE - in_interrupt_flag = 0; -#endif -} - -void fdomain_16x0_intr( int irq, struct pt_regs * regs ) -{ - int status; - int done = 0; - unsigned data_count; - - /* The fdomain_16x0_intr is only called via - the interrupt handler. The goal of the - sti() here is to allow other - interruptions while this routine is - running. */ - - sti(); /* Yes, we really want sti() here */ - - outb( 0x00, Interrupt_Cntl_port ); - - /* We usually have one spurious interrupt after each command. Ignore it. */ - if (!in_command || !current_SC) { /* Spurious interrupt */ -#if EVERY_ACCESS - printk( "Spurious interrupt, in_command = %d, current_SC = %x\n", - in_command, current_SC ); -#endif - return; - } - - /* Abort calls my_done, so we do nothing here. */ - if (current_SC->SCp.phase & aborted) { -#if DEBUG_ABORT - printk( "Interrupt after abort, ignoring\n" ); -#endif - /* - return; */ - } - -#if DEBUG_RACE - ++in_interrupt_flag; -#endif - - if (current_SC->SCp.phase & in_arbitration) { - status = inb( TMC_Status_port ); /* Read adapter status */ - if (!(status & 0x02)) { -#if EVERY_ACCESS - printk( " AFAIL " ); -#endif - my_done( DID_BUS_BUSY << 16 ); - return; - } - current_SC->SCp.phase = in_selection; - - outb( 0x40 | FIFO_COUNT, Interrupt_Cntl_port ); - - outb( 0x82, SCSI_Cntl_port ); /* Bus Enable + Select */ - outb( adapter_mask | (1 << current_SC->target), SCSI_Data_NoACK_port ); - - /* Stop arbitration and enable parity */ - outb( 0x10 | PARITY_MASK, TMC_Cntl_port ); -#if DEBUG_RACE - in_interrupt_flag = 0; -#endif - return; - } else if (current_SC->SCp.phase & in_selection) { - status = inb( SCSI_Status_port ); - if (!(status & 0x01)) { - /* Try again, for slow devices */ - if (fdomain_select( current_SC->target )) { -#if EVERY_ACCESS - printk( " SFAIL " ); -#endif - my_done( DID_NO_CONNECT << 16 ); - return; - } else { -#if EVERY_ACCESS - printk( " AltSel " ); -#endif - /* Stop arbitration and enable parity */ - outb( 0x10 | PARITY_MASK, TMC_Cntl_port ); - } - } - current_SC->SCp.phase = in_other; - outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port ); - outb( 0x80, SCSI_Cntl_port ); -#if DEBUG_RACE - in_interrupt_flag = 0; -#endif - return; - } - - /* current_SC->SCp.phase == in_other: this is the body of the routine */ - - status = inb( SCSI_Status_port ); - - if (status & 0x10) { /* REQ */ - - switch (status & 0x0e) { - - case 0x08: /* COMMAND OUT */ - outb( current_SC->cmnd[current_SC->SCp.sent_command++], - Write_SCSI_Data_port ); -#if EVERY_ACCESS - printk( "CMD = %x,", - current_SC->cmnd[ current_SC->SCp.sent_command - 1] ); -#endif - break; - case 0x00: /* DATA OUT -- tmc18c50/tmc18c30 only */ - if (chip != tmc1800 && !current_SC->SCp.have_data_in) { - current_SC->SCp.have_data_in = -1; - outb( 0xd0 | PARITY_MASK, TMC_Cntl_port ); - } - break; - case 0x04: /* DATA IN -- tmc18c50/tmc18c30 only */ - if (chip != tmc1800 && !current_SC->SCp.have_data_in) { - current_SC->SCp.have_data_in = 1; - outb( 0x90 | PARITY_MASK, TMC_Cntl_port ); - } - break; - case 0x0c: /* STATUS IN */ - current_SC->SCp.Status = inb( Read_SCSI_Data_port ); -#if EVERY_ACCESS - printk( "Status = %x, ", current_SC->SCp.Status ); -#endif -#if ERRORS_ONLY - if (current_SC->SCp.Status && current_SC->SCp.Status != 2) { - printk( "fdomain: target = %d, command = %x, status = %x\n", - current_SC->target, - current_SC->cmnd[0], - current_SC->SCp.Status ); - } -#endif - break; - case 0x0a: /* MESSAGE OUT */ - outb( MESSAGE_REJECT, Write_SCSI_Data_port ); /* Reject */ - break; - case 0x0e: /* MESSAGE IN */ - current_SC->SCp.Message = inb( Read_SCSI_Data_port ); -#if EVERY_ACCESS - printk( "Message = %x, ", current_SC->SCp.Message ); -#endif - if (!current_SC->SCp.Message) ++done; -#if DEBUG_MESSAGES || EVERY_ACCESS - if (current_SC->SCp.Message) { - printk( "fdomain: message = %x\n", current_SC->SCp.Message ); - } -#endif - break; - } - } - - if (chip == tmc1800 - && !current_SC->SCp.have_data_in - && (current_SC->SCp.sent_command - >= current_SC->cmd_len)) { - /* We have to get the FIFO direction - correct, so I've made a table based - on the SCSI Standard of which commands - appear to require a DATA OUT phase. - */ - /* - p. 94: Command for all device types - CHANGE DEFINITION 40 DATA OUT - COMPARE 39 DATA OUT - COPY 18 DATA OUT - COPY AND VERIFY 3a DATA OUT - INQUIRY 12 - LOG SELECT 4c DATA OUT - LOG SENSE 4d - MODE SELECT (6) 15 DATA OUT - MODE SELECT (10) 55 DATA OUT - MODE SENSE (6) 1a - MODE SENSE (10) 5a - READ BUFFER 3c - RECEIVE DIAGNOSTIC RESULTS 1c - REQUEST SENSE 03 - SEND DIAGNOSTIC 1d DATA OUT - TEST UNIT READY 00 - WRITE BUFFER 3b DATA OUT - - p.178: Commands for direct-access devices (not listed on p. 94) - FORMAT UNIT 04 DATA OUT - LOCK-UNLOCK CACHE 36 - PRE-FETCH 34 - PREVENT-ALLOW MEDIUM REMOVAL 1e - READ (6)/RECEIVE 08 - READ (10) 3c - READ CAPACITY 25 - READ DEFECT DATA (10) 37 - READ LONG 3e - REASSIGN BLOCKS 07 DATA OUT - RELEASE 17 - RESERVE 16 DATA OUT - REZERO UNIT/REWIND 01 - SEARCH DATA EQUAL (10) 31 DATA OUT - SEARCH DATA HIGH (10) 30 DATA OUT - SEARCH DATA LOW (10) 32 DATA OUT - SEEK (6) 0b - SEEK (10) 2b - SET LIMITS (10) 33 - START STOP UNIT 1b - SYNCHRONIZE CACHE 35 - VERIFY (10) 2f - WRITE (6)/PRINT/SEND 0a DATA OUT - WRITE (10)/SEND 2a DATA OUT - WRITE AND VERIFY (10) 2e DATA OUT - WRITE LONG 3f DATA OUT - WRITE SAME 41 DATA OUT ? - - p. 261: Commands for sequential-access devices (not previously listed) - ERASE 19 - LOAD UNLOAD 1b - LOCATE 2b - READ BLOCK LIMITS 05 - READ POSITION 34 - READ REVERSE 0f - RECOVER BUFFERED DATA 14 - SPACE 11 - WRITE FILEMARKS 10 ? - - p. 298: Commands for printer devices (not previously listed) - ****** NOT SUPPORTED BY THIS DRIVER, since 0b is SEEK (6) ***** - SLEW AND PRINT 0b DATA OUT -- same as seek - STOP PRINT 1b - SYNCHRONIZE BUFFER 10 - - p. 315: Commands for processor devices (not previously listed) - - p. 321: Commands for write-once devices (not previously listed) - MEDIUM SCAN 38 - READ (12) a8 - SEARCH DATA EQUAL (12) b1 DATA OUT - SEARCH DATA HIGH (12) b0 DATA OUT - SEARCH DATA LOW (12) b2 DATA OUT - SET LIMITS (12) b3 - VERIFY (12) af - WRITE (12) aa DATA OUT - WRITE AND VERIFY (12) ae DATA OUT - - p. 332: Commands for CD-ROM devices (not previously listed) - PAUSE/RESUME 4b - PLAY AUDIO (10) 45 - PLAY AUDIO (12) a5 - PLAY AUDIO MSF 47 - PLAY TRACK RELATIVE (10) 49 - PLAY TRACK RELATIVE (12) a9 - READ HEADER 44 - READ SUB-CHANNEL 42 - READ TOC 43 - - p. 370: Commands for scanner devices (not previously listed) - GET DATA BUFFER STATUS 34 - GET WINDOW 25 - OBJECT POSITION 31 - SCAN 1b - SET WINDOW 24 DATA OUT - - p. 391: Commands for optical memory devices (not listed) - ERASE (10) 2c - ERASE (12) ac - MEDIUM SCAN 38 DATA OUT - READ DEFECT DATA (12) b7 - READ GENERATION 29 - READ UPDATED BLOCK 2d - UPDATE BLOCK 3d DATA OUT - - p. 419: Commands for medium changer devices (not listed) - EXCHANGE MEDIUM 46 - INITIALIZE ELEMENT STATUS 07 - MOVE MEDIUM a5 - POSITION TO ELEMENT 2b - READ ELEMENT STATUS b8 - REQUEST VOL. ELEMENT ADDRESS b5 - SEND VOLUME TAG b6 DATA OUT - - p. 454: Commands for communications devices (not listed previously) - GET MESSAGE (6) 08 - GET MESSAGE (10) 28 - GET MESSAGE (12) a8 - */ - - switch (current_SC->cmnd[0]) { - case CHANGE_DEFINITION: case COMPARE: case COPY: - case COPY_VERIFY: case LOG_SELECT: case MODE_SELECT: - case MODE_SELECT_10: case SEND_DIAGNOSTIC: case WRITE_BUFFER: - - case FORMAT_UNIT: case REASSIGN_BLOCKS: case RESERVE: - case SEARCH_EQUAL: case SEARCH_HIGH: case SEARCH_LOW: - case WRITE_6: case WRITE_10: case WRITE_VERIFY: - case 0x3f: case 0x41: - - case 0xb1: case 0xb0: case 0xb2: - case 0xaa: case 0xae: - - case 0x24: - - case 0x38: case 0x3d: - - case 0xb6: - - case 0xea: /* alternate number for WRITE LONG */ - - current_SC->SCp.have_data_in = -1; - outb( 0xd0 | PARITY_MASK, TMC_Cntl_port ); - break; - - case 0x00: - default: - - current_SC->SCp.have_data_in = 1; - outb( 0x90 | PARITY_MASK, TMC_Cntl_port ); - break; - } - } - - if (current_SC->SCp.have_data_in == -1) { /* DATA OUT */ - while ( (data_count = FIFO_Size - inw( FIFO_Data_Count_port )) > 512 ) { -#if EVERY_ACCESS - printk( "DC=%d, ", data_count ) ; -#endif - if (data_count > current_SC->SCp.this_residual) - data_count = current_SC->SCp.this_residual; - if (data_count > 0) { -#if EVERY_ACCESS - printk( "%d OUT, ", data_count ); -#endif - if (data_count == 1) { - outb( *current_SC->SCp.ptr++, Write_FIFO_port ); - --current_SC->SCp.this_residual; - } else { - data_count >>= 1; - outsw( Write_FIFO_port, current_SC->SCp.ptr, data_count ); - current_SC->SCp.ptr += 2 * data_count; - current_SC->SCp.this_residual -= 2 * data_count; - } - } - if (!current_SC->SCp.this_residual) { - if (current_SC->SCp.buffers_residual) { - --current_SC->SCp.buffers_residual; - ++current_SC->SCp.buffer; - current_SC->SCp.ptr = current_SC->SCp.buffer->address; - current_SC->SCp.this_residual = current_SC->SCp.buffer->length; - } else - break; - } - } - } - - if (current_SC->SCp.have_data_in == 1) { /* DATA IN */ - while ((data_count = inw( FIFO_Data_Count_port )) > 0) { -#if EVERY_ACCESS - printk( "DC=%d, ", data_count ); -#endif - if (data_count > current_SC->SCp.this_residual) - data_count = current_SC->SCp.this_residual; - if (data_count) { -#if EVERY_ACCESS - printk( "%d IN, ", data_count ); -#endif - if (data_count == 1) { - *current_SC->SCp.ptr++ = inb( Read_FIFO_port ); - --current_SC->SCp.this_residual; - } else { - data_count >>= 1; /* Number of words */ - insw( Read_FIFO_port, current_SC->SCp.ptr, data_count ); - current_SC->SCp.ptr += 2 * data_count; - current_SC->SCp.this_residual -= 2 * data_count; - } - } - if (!current_SC->SCp.this_residual - && current_SC->SCp.buffers_residual) { - --current_SC->SCp.buffers_residual; - ++current_SC->SCp.buffer; - current_SC->SCp.ptr = current_SC->SCp.buffer->address; - current_SC->SCp.this_residual = current_SC->SCp.buffer->length; - } - } - } - - if (done) { -#if EVERY_ACCESS - printk( " ** IN DONE %d ** ", current_SC->SCp.have_data_in ); -#endif - -#if ERRORS_ONLY - if (current_SC->cmnd[0] == REQUEST_SENSE && !current_SC->SCp.Status) { - if ((unsigned char)(*((char *)current_SC->request_buffer+2)) & 0x0f) { - unsigned char key; - unsigned char code; - unsigned char qualifier; - - key = (unsigned char)(*((char *)current_SC->request_buffer + 2)) - & 0x0f; - code = (unsigned char)(*((char *)current_SC->request_buffer + 12)); - qualifier = (unsigned char)(*((char *)current_SC->request_buffer - + 13)); - - if (!(key == UNIT_ATTENTION && (code == 0x29 || !code)) - && !(key == NOT_READY - && code == 0x04 - && (!qualifier || qualifier == 0x02 || qualifier == 0x01)) - && !(key == ILLEGAL_REQUEST && (code == 0x25 - || code == 0x24 - || !code))) - - printk( "fdomain: REQUEST SENSE " - "Key = %x, Code = %x, Qualifier = %x\n", - key, code, qualifier ); - } - } -#endif -#if EVERY_ACCESS - printk( "BEFORE MY_DONE. . ." ); -#endif - my_done( (current_SC->SCp.Status & 0xff) - | ((current_SC->SCp.Message & 0xff) << 8) | (DID_OK << 16) ); -#if EVERY_ACCESS - printk( "RETURNING.\n" ); -#endif - - } else { - if (current_SC->SCp.phase & disconnect) { - outb( 0xd0 | FIFO_COUNT, Interrupt_Cntl_port ); - outb( 0x00, SCSI_Cntl_port ); - } else { - outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port ); - } - } -#if DEBUG_RACE - in_interrupt_flag = 0; -#endif - return; -} - -int fdomain_16x0_queue( Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) -{ - if (in_command) { - panic( "fdomain: fdomain_16x0_queue() NOT REENTRANT!\n" ); - } -#if EVERY_ACCESS - printk( "queue: target = %d cmnd = 0x%02x pieces = %d size = %u\n", - SCpnt->target, - *(unsigned char *)SCpnt->cmnd, - SCpnt->use_sg, - SCpnt->request_bufflen ); -#endif - - fdomain_make_bus_idle(); - - current_SC = SCpnt; /* Save this for the done function */ - current_SC->scsi_done = done; - - /* Initialize static data */ - - if (current_SC->use_sg) { - current_SC->SCp.buffer = - (struct scatterlist *)current_SC->request_buffer; - current_SC->SCp.ptr = current_SC->SCp.buffer->address; - current_SC->SCp.this_residual = current_SC->SCp.buffer->length; - current_SC->SCp.buffers_residual = current_SC->use_sg - 1; - } else { - current_SC->SCp.ptr = (char *)current_SC->request_buffer; - current_SC->SCp.this_residual = current_SC->request_bufflen; - current_SC->SCp.buffer = NULL; - current_SC->SCp.buffers_residual = 0; - } - - - current_SC->SCp.Status = 0; - current_SC->SCp.Message = 0; - current_SC->SCp.have_data_in = 0; - current_SC->SCp.sent_command = 0; - current_SC->SCp.phase = in_arbitration; - - /* Start arbitration */ - outb( 0x00, Interrupt_Cntl_port ); - outb( 0x00, SCSI_Cntl_port ); /* Disable data drivers */ - outb( adapter_mask, SCSI_Data_NoACK_port ); /* Set our id bit */ - ++in_command; - outb( 0x20, Interrupt_Cntl_port ); - outb( 0x14 | PARITY_MASK, TMC_Cntl_port ); /* Start arbitration */ - - return 0; -} - -/* The following code, which simulates the old-style command function, was - taken from Tommy Thorn's aha1542.c file. This code is Copyright (C) - 1992 Tommy Thorn. */ - -static volatile int internal_done_flag = 0; -static volatile int internal_done_errcode = 0; - -static void internal_done( Scsi_Cmnd *SCpnt ) -{ - internal_done_errcode = SCpnt->result; - ++internal_done_flag; -} - -int fdomain_16x0_command( Scsi_Cmnd *SCpnt ) -{ - fdomain_16x0_queue( SCpnt, internal_done ); - - while (!internal_done_flag) - ; - internal_done_flag = 0; - return internal_done_errcode; -} - -/* End of code derived from Tommy Thorn's work. */ - -void print_info( Scsi_Cmnd *SCpnt ) -{ - unsigned int imr; - unsigned int irr; - unsigned int isr; - - if (!SCpnt || !SCpnt->host) { - printk( "fdomain: cannot provide detailed information\n" ); - } - - printk( "%s\n", fdomain_16x0_info( SCpnt->host ) ); - print_banner( SCpnt->host ); - switch (SCpnt->SCp.phase) { - case in_arbitration: printk( "arbitration " ); break; - case in_selection: printk( "selection " ); break; - case in_other: printk( "other " ); break; - default: printk( "unknown " ); break; - } - - printk( "(%d), target = %d cmnd = 0x%02x pieces = %d size = %u\n", - SCpnt->SCp.phase, - SCpnt->target, - *(unsigned char *)SCpnt->cmnd, - SCpnt->use_sg, - SCpnt->request_bufflen ); - printk( "sent_command = %d, have_data_in = %d, timeout = %d\n", - SCpnt->SCp.sent_command, - SCpnt->SCp.have_data_in, - SCpnt->timeout ); -#if DEBUG_RACE - printk( "in_interrupt_flag = %d\n", in_interrupt_flag ); -#endif - - imr = (inb( 0x0a1 ) << 8) + inb( 0x21 ); - outb( 0x0a, 0xa0 ); - irr = inb( 0xa0 ) << 8; - outb( 0x0a, 0x20 ); - irr += inb( 0x20 ); - outb( 0x0b, 0xa0 ); - isr = inb( 0xa0 ) << 8; - outb( 0x0b, 0x20 ); - isr += inb( 0x20 ); - - /* Print out interesting information */ - printk( "IMR = 0x%04x", imr ); - if (imr & (1 << interrupt_level)) - printk( " (masked)" ); - printk( ", IRR = 0x%04x, ISR = 0x%04x\n", irr, isr ); - - printk( "SCSI Status = 0x%02x\n", inb( SCSI_Status_port ) ); - printk( "TMC Status = 0x%02x", inb( TMC_Status_port ) ); - if (inb( TMC_Status_port & 1)) - printk( " (interrupt)" ); - printk( "\n" ); - printk( "Interrupt Status = 0x%02x", inb( Interrupt_Status_port ) ); - if (inb( Interrupt_Status_port ) & 0x08) - printk( " (enabled)" ); - printk( "\n" ); - if (chip == tmc18c50 || chip == tmc18c30) { - printk( "FIFO Status = 0x%02x\n", inb( port_base + FIFO_Status ) ); - printk( "Int. Condition = 0x%02x\n", - inb( port_base + Interrupt_Cond ) ); - } - printk( "Configuration 1 = 0x%02x\n", inb( port_base + Configuration1 ) ); - if (chip == tmc18c50 || chip == tmc18c30) - printk( "Configuration 2 = 0x%02x\n", - inb( port_base + Configuration2 ) ); -} - -int fdomain_16x0_abort( Scsi_Cmnd *SCpnt) -{ - unsigned long flags; -#if EVERY_ACCESS || ERRORS_ONLY || DEBUG_ABORT - printk( "fdomain: abort " ); -#endif - - save_flags( flags ); - cli(); - if (!in_command) { -#if EVERY_ACCESS || ERRORS_ONLY - printk( " (not in command)\n" ); -#endif - restore_flags( flags ); - return SCSI_ABORT_NOT_RUNNING; - } else printk( "\n" ); - -#if DEBUG_ABORT - print_info( SCpnt ); -#endif - - fdomain_make_bus_idle(); - - current_SC->SCp.phase |= aborted; - - current_SC->result = DID_ABORT << 16; - - restore_flags( flags ); - - /* Aborts are not done well. . . */ - my_done( DID_ABORT << 16 ); - - return SCSI_ABORT_SUCCESS; -} - -int fdomain_16x0_reset( Scsi_Cmnd *SCpnt ) -{ -#if DEBUG_RESET - static int called_once = 0; -#endif - -#if ERRORS_ONLY - if (SCpnt) printk( "fdomain: SCSI Bus Reset\n" ); -#endif - -#if DEBUG_RESET - if (called_once) print_info( current_SC ); - called_once = 1; -#endif - - outb( 1, SCSI_Cntl_port ); - do_pause( 2 ); - outb( 0, SCSI_Cntl_port ); - do_pause( 115 ); - outb( 0, SCSI_Mode_Cntl_port ); - outb( PARITY_MASK, TMC_Cntl_port ); - - /* Unless this is the very first call (i.e., SCPnt == NULL), everything - is probably hosed at this point. We will, however, try to keep - things going by informing the high-level code that we need help. */ - - return SCSI_RESET_WAKEUP; -} - -#include "sd.h" -#include "scsi_ioctl.h" - -int fdomain_16x0_biosparam( Scsi_Disk *disk, kdev_t dev, int *info_array ) -{ - int drive; - unsigned char buf[512 + sizeof( int ) * 2]; - int size = disk->capacity; - int *sizes = (int *)buf; - unsigned char *data = (unsigned char *)(sizes + 2); - unsigned char do_read[] = { READ_6, 0, 0, 0, 1, 0 }; - int retcode; - struct drive_info { - unsigned short cylinders; - unsigned char heads; - unsigned char sectors; - } *i; - - /* NOTES: - The RAM area starts at 0x1f00 from the bios_base address. - - For BIOS Version 2.0: - - The drive parameter table seems to start at 0x1f30. - The first byte's purpose is not known. - Next is the cylinder, head, and sector information. - The last 4 bytes appear to be the drive's size in sectors. - The other bytes in the drive parameter table are unknown. - If anyone figures them out, please send me mail, and I will - update these notes. - - Tape drives do not get placed in this table. - - There is another table at 0x1fea: - If the byte is 0x01, then the SCSI ID is not in use. - If the byte is 0x18 or 0x48, then the SCSI ID is in use, - although tapes don't seem to be in this table. I haven't - seen any other numbers (in a limited sample). - - 0x1f2d is a drive count (i.e., not including tapes) - - The table at 0x1fcc are I/O ports addresses for the various - operations. I calculate these by hand in this driver code. - - - - For the ISA-200S version of BIOS Version 2.0: - - The drive parameter table starts at 0x1f33. - - WARNING: Assume that the table entry is 25 bytes long. Someone needs - to check this for the Quantum ISA-200S card. - - - - For BIOS Version 3.2: - - The drive parameter table starts at 0x1f70. Each entry is - 0x0a bytes long. Heads are one less than we need to report. - */ - - drive = MINOR(dev) / 16; - - if (bios_major == 2) { - switch (Quantum) { - case 2: /* ISA_200S */ - /* The value of 25 has never been verified. - It should probably be 15. */ - i = (struct drive_info *)( (char *)bios_base + 0x1f33 + drive * 25 ); - break; - case 3: /* ISA_250MG */ - i = (struct drive_info *)( (char *)bios_base + 0x1f36 + drive * 15 ); - break; - case 4: /* ISA_200S (another one) */ - i = (struct drive_info *)( (char *)bios_base + 0x1f34 + drive * 15 ); - break; - default: - i = (struct drive_info *)( (char *)bios_base + 0x1f31 + drive * 25 ); - break; - } - info_array[0] = i->heads; - info_array[1] = i->sectors; - info_array[2] = i->cylinders; - } else if (bios_major == 3 - && bios_minor >= 0 - && bios_minor < 4) { /* 3.0 and 3.2 BIOS */ - i = (struct drive_info *)( (char *)bios_base + 0x1f71 + drive * 10 ); - info_array[0] = i->heads + 1; - info_array[1] = i->sectors; - info_array[2] = i->cylinders; - } else { /* 3.4 BIOS (and up?) */ - /* This algorithm was provided by Future Domain (much thanks!). */ - - sizes[0] = 0; /* zero bytes out */ - sizes[1] = 512; /* one sector in */ - memcpy( data, do_read, sizeof( do_read ) ); - retcode = kernel_scsi_ioctl( disk->device, - SCSI_IOCTL_SEND_COMMAND, - (void *)buf ); - if (!retcode /* SCSI command ok */ - && data[511] == 0xaa && data[510] == 0x55 /* Partition table valid */ - && data[0x1c2]) { /* Partition type */ - - /* The partition table layout is as follows: - - Start: 0x1b3h - Offset: 0 = partition status - 1 = starting head - 2 = starting sector and cylinder (word, encoded) - 4 = partition type - 5 = ending head - 6 = ending sector and cylinder (word, encoded) - 8 = starting absolute sector (double word) - c = number of sectors (double word) - Signature: 0x1fe = 0x55aa - - So, this algorithm assumes: - 1) the first partition table is in use, - 2) the data in the first entry is correct, and - 3) partitions never divide cylinders - - Note that (1) may be FALSE for NetBSD (and other BSD flavors), - as well as for Linux. Note also, that Linux doesn't pay any - attention to the fields that are used by this algorithm -- it - only uses the absolute sector data. Recent versions of Linux's - fdisk(1) will fill this data in correctly, and forthcoming - versions will check for consistency. - - Checking for a non-zero partition type is not part of the - Future Domain algorithm, but it seemed to be a reasonable thing - to do, especially in the Linux and BSD worlds. */ - - info_array[0] = data[0x1c3] + 1; /* heads */ - info_array[1] = data[0x1c4] & 0x3f; /* sectors */ - } else { - - /* Note that this new method guarantees that there will always be - less than 1024 cylinders on a platter. This is good for drives - up to approximately 7.85GB (where 1GB = 1024 * 1024 kB). */ - - if ((unsigned int)size >= 0x7e0000U) { - info_array[0] = 0xff; /* heads = 255 */ - info_array[1] = 0x3f; /* sectors = 63 */ - } else if ((unsigned int)size >= 0x200000U) { - info_array[0] = 0x80; /* heads = 128 */ - info_array[1] = 0x3f; /* sectors = 63 */ - } else { - info_array[0] = 0x40; /* heads = 64 */ - info_array[1] = 0x20; /* sectors = 32 */ - } - } - /* For both methods, compute the cylinders */ - info_array[2] = (unsigned int)size / (info_array[0] * info_array[1] ); - } - - return 0; -} - -#ifdef MODULE -/* Eventually this will go into an include file, but this will be later */ -Scsi_Host_Template driver_template = FDOMAIN_16X0; - -#include "scsi_module.c" -#endif diff --git a/i386/i386at/gpl/linux/scsi/fdomain.h b/i386/i386at/gpl/linux/scsi/fdomain.h deleted file mode 100644 index e0c4e045..00000000 --- a/i386/i386at/gpl/linux/scsi/fdomain.h +++ /dev/null @@ -1,61 +0,0 @@ -/* fdomain.h -- Header for Future Domain TMC-16x0 driver - * Created: Sun May 3 18:47:33 1992 by faith@cs.unc.edu - * Revised: Thu Oct 12 13:21:35 1995 by r.faith@ieee.org - * Author: Rickard E. Faith, faith@cs.unc.edu - * Copyright 1992, 1993, 1994, 1995 Rickard E. Faith - * - * $Id: fdomain.h,v 1.1.1.1 1997/02/25 21:27:49 thomas Exp $ - - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - - */ - -#ifndef _FDOMAIN_H -#define _FDOMAIN_H - -int fdomain_16x0_detect( Scsi_Host_Template * ); -int fdomain_16x0_command( Scsi_Cmnd * ); -int fdomain_16x0_abort( Scsi_Cmnd * ); -const char *fdomain_16x0_info( struct Scsi_Host * ); -int fdomain_16x0_reset( Scsi_Cmnd * ); -int fdomain_16x0_queue( Scsi_Cmnd *, void (*done)(Scsi_Cmnd *) ); -int fdomain_16x0_biosparam( Disk *, kdev_t, int * ); -int fdomain_16x0_proc_info( char *buffer, char **start, off_t offset, - int length, int hostno, int inout ); - -extern struct proc_dir_entry proc_scsi_fdomain; - -#define FDOMAIN_16X0 { NULL, \ - NULL, \ - NULL, \ - fdomain_16x0_proc_info, \ - NULL, \ - fdomain_16x0_detect, \ - NULL, \ - fdomain_16x0_info, \ - fdomain_16x0_command, \ - fdomain_16x0_queue, \ - fdomain_16x0_abort, \ - fdomain_16x0_reset, \ - NULL, \ - fdomain_16x0_biosparam, \ - 1, \ - 6, \ - 64, \ - 1, \ - 0, \ - 0, \ - DISABLE_CLUSTERING } -#endif diff --git a/i386/i386at/gpl/linux/scsi/g_NCR5380.c b/i386/i386at/gpl/linux/scsi/g_NCR5380.c deleted file mode 100644 index f7f2aabc..00000000 --- a/i386/i386at/gpl/linux/scsi/g_NCR5380.c +++ /dev/null @@ -1,588 +0,0 @@ -/* - * Generic Generic NCR5380 driver - * - * Copyright 1993, Drew Eckhardt - * Visionary Computing - * (Unix and Linux consulting and custom programming) - * drew@colorado.edu - * +1 (303) 440-4894 - * - * NCR53C400 extensions (c) 1994,1995,1996, Kevin Lentin - * K.Lentin@cs.monash.edu.au - * - * ALPHA RELEASE 1. - * - * For more information, please consult - * - * NCR 5380 Family - * SCSI Protocol Controller - * Databook - * - * NCR Microelectronics - * 1635 Aeroplaza Drive - * Colorado Springs, CO 80916 - * 1+ (719) 578-3400 - * 1+ (800) 334-5454 - */ - -/* - * TODO : flesh out DMA support, find some one actually using this (I have - * a memory mapped Trantor board that works fine) - */ - -/* - * Options : - * - * PARITY - enable parity checking. Not supported. - * - * SCSI2 - enable support for SCSI-II tagged queueing. Untested. - * - * USLEEP - enable support for devices that don't disconnect. Untested. - * - * The card is detected and initialized in one of several ways : - * 1. With command line overrides - NCR5380=port,irq may be - * used on the LILO command line to override the defaults. - * - * 2. With the GENERIC_NCR5380_OVERRIDE compile time define. This is - * specified as an array of address, irq, dma, board tuples. Ie, for - * one board at 0x350, IRQ5, no dma, I could say - * -DGENERIC_NCR5380_OVERRIDE={{0xcc000, 5, DMA_NONE, BOARD_NCR5380}} - * - * -1 should be specified for no or DMA interrupt, -2 to autoprobe for an - * IRQ line if overridden on the command line. - */ - -/* - * $Log: g_NCR5380.c,v $ - * Revision 1.1.1.1 1996/10/30 01:40:05 thomas - * Imported from UK22 - * - * Revision 1.1 1996/03/25 20:25:35 goel - * Linux driver merge. - * - */ - -#define AUTOPROBE_IRQ -#define AUTOSENSE - -#include <linux/config.h> - -#ifdef MACH -#define CONFIG_SCSI_G_NCR5380_MEM -#endif - -#ifdef CONFIG_SCSI_GENERIC_NCR53C400 -#define NCR53C400_PSEUDO_DMA 1 -#define PSEUDO_DMA -#define NCR53C400 -#endif -#if defined(CONFIG_SCSI_G_NCR5380_PORT) && defined(CONFIG_SCSI_G_NCR5380_MEM) -#error You can not configure the Generic NCR 5380 SCSI Driver for memory mapped I/O and port mapped I/O at the same time (yet) -#endif -#if !defined(CONFIG_SCSI_G_NCR5380_PORT) && !defined(CONFIG_SCSI_G_NCR5380_MEM) -#error You must configure the Generic NCR 5380 SCSI Driver for one of memory mapped I/O and port mapped I/O. -#endif - -#include <asm/system.h> -#include <asm/io.h> -#include <linux/signal.h> -#include <linux/sched.h> -#include <linux/blk.h> -#include "scsi.h" -#include "hosts.h" -#include "g_NCR5380.h" -#include "NCR5380.h" -#include "constants.h" -#include "sd.h" -#include<linux/stat.h> - -struct proc_dir_entry proc_scsi_g_ncr5380 = { - PROC_SCSI_GENERIC_NCR5380, 9, "g_NCR5380", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - -static struct override { - NCR5380_implementation_fields; - int irq; - int dma; - int board; /* Use NCR53c400, Ricoh, etc. extensions ? */ -} overrides -#ifdef GENERIC_NCR5380_OVERRIDE - [] = GENERIC_NCR5380_OVERRIDE -#else - [1] = {{0,},}; -#endif - -#define NO_OVERRIDES (sizeof(overrides) / sizeof(struct override)) - -/* - * Function : static internal_setup(int board, char *str, int *ints) - * - * Purpose : LILO command line initialization of the overrides array, - * - * Inputs : board - either BOARD_NCR5380 for a normal NCR5380 board, - * or BOARD_NCR53C400 for a NCR53C400 board. str - unused, ints - - * array of integer parameters with ints[0] equal to the number of ints. - * - */ - -static void internal_setup(int board, char *str, int *ints) { - static int commandline_current = 0; - switch (board) { - case BOARD_NCR5380: - if (ints[0] != 2 && ints[0] != 3) - printk("generic_NCR5380_setup : usage ncr5380=" STRVAL(NCR5380_map_name) ",irq,dma\n"); - return; - case BOARD_NCR53C400: - if (ints[0] != 2) - printk("generic_NCR53C400_setup : usage ncr53c400= " STRVAL(NCR5380_map_name) ",irq\n"); - return; - } - - if (commandline_current < NO_OVERRIDES) { - overrides[commandline_current].NCR5380_map_name = (NCR5380_map_type)ints[1]; - overrides[commandline_current].irq = ints[2]; - if (ints[0] == 3) - overrides[commandline_current].dma = ints[3]; - else - overrides[commandline_current].dma = DMA_NONE; - overrides[commandline_current].board = board; - ++commandline_current; - } -} - -/* - * Function : generic_NCR5380_setup (char *str, int *ints) - * - * Purpose : LILO command line initialization of the overrides array, - * - * Inputs : str - unused, ints - array of integer paramters with ints[0] - * equal to the number of ints. - */ - -void generic_NCR5380_setup (char *str, int *ints) { - internal_setup (BOARD_NCR5380, str, ints); -} - -/* - * Function : generic_NCR53C400_setup (char *str, int *ints) - * - * Purpose : LILO command line initialization of the overrides array, - * - * Inputs : str - unused, ints - array of integer paramters with ints[0] - * equal to the number of ints. - */ - -void generic_NCR53C400_setup (char *str, int *ints) { - internal_setup (BOARD_NCR53C400, str, ints); -} - -/* - * Function : int generic_NCR5380_detect(Scsi_Host_Template * tpnt) - * - * Purpose : initializes generic NCR5380 driver based on the - * command line / compile time port and irq definitions. - * - * Inputs : tpnt - template for this SCSI adapter. - * - * Returns : 1 if a host adapter was found, 0 if not. - * - */ - -int generic_NCR5380_detect(Scsi_Host_Template * tpnt) { - static int current_override = 0; - int count; - int flags = 0; - struct Scsi_Host *instance; - - tpnt->proc_dir = &proc_scsi_g_ncr5380; - - for (count = 0; current_override < NO_OVERRIDES; ++current_override) { - if (!(overrides[current_override].NCR5380_map_name)) - continue; - - switch (overrides[current_override].board) { - case BOARD_NCR5380: - flags = FLAG_NO_PSEUDO_DMA; - break; - case BOARD_NCR53C400: - flags = FLAG_NCR53C400; - break; - } - - instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata)); - instance->NCR5380_instance_name = overrides[current_override].NCR5380_map_name; - - NCR5380_init(instance, flags); - - if (overrides[current_override].irq != IRQ_AUTO) - instance->irq = overrides[current_override].irq; - else - instance->irq = NCR5380_probe_irq(instance, 0xffff); - - if (instance->irq != IRQ_NONE) - if (request_irq(instance->irq, generic_NCR5380_intr, SA_INTERRUPT, "NCR5380")) { - printk("scsi%d : IRQ%d not free, interrupts disabled\n", - instance->host_no, instance->irq); - instance->irq = IRQ_NONE; - } - - if (instance->irq == IRQ_NONE) { - printk("scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no); - printk("scsi%d : please jumper the board for a free IRQ.\n", instance->host_no); - } - - printk("scsi%d : at " STRVAL(NCR5380_map_name) " 0x%x", instance->host_no, (unsigned int)instance->NCR5380_instance_name); - if (instance->irq == IRQ_NONE) - printk (" interrupts disabled"); - else - printk (" irq %d", instance->irq); - printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d", - CAN_QUEUE, CMD_PER_LUN, GENERIC_NCR5380_PUBLIC_RELEASE); - NCR5380_print_options(instance); - printk("\n"); - - ++current_override; - ++count; - } - return count; -} - -const char * generic_NCR5380_info (void) { - static const char string[]="Generic NCR5380/53C400 Info"; - return string; -} - -int generic_NCR5380_release_resources(struct Scsi_Host * instance) -{ - NCR5380_local_declare(); - - NCR5380_setup(instance); - - free_irq(instance->irq); - - return 0; -} - -#ifdef BIOSPARAM -/* - * Function : int generic_NCR5380_biosparam(Disk * disk, kdev_t dev, int *ip) - * - * Purpose : Generates a BIOS / DOS compatable H-C-S mapping for - * the specified device / size. - * - * Inputs : size = size of device in sectors (512 bytes), dev = block device - * major / minor, ip[] = {heads, sectors, cylinders} - * - * Returns : allways 0 (success), initializes ip - * - */ - -/* - * XXX Most SCSI boards use this mapping, I could be incorrect. Some one - * using hard disks on a trantor should verify that this mapping corresponds - * to that used by the BIOS / ASPI driver by running the linux fdisk program - * and matching the H_C_S coordinates to what DOS uses. - */ - -int generic_NCR5380_biosparam(Disk * disk, kdev_t dev, int *ip) -{ - int size = disk->capacity; - ip[0] = 64; - ip[1] = 32; - ip[2] = size >> 11; - return 0; -} -#endif - -int generic_NCR5380_proc_info(char* buffer, char** start, off_t offset, int length, int hostno, int inout) -{ - int len = 0; - struct Scsi_Host *scsi_ptr; - - for (scsi_ptr = first_instance; scsi_ptr; scsi_ptr=scsi_ptr->next) - if (scsi_ptr->host_no == hostno) - break; - - len += sprintf(buffer+len, "SCSI host number %d : %s\n", scsi_ptr->host_no, scsi_ptr->hostt->name); - len += sprintf(buffer+len, "Generic NCR5380 driver version %d\n", GENERIC_NCR5380_PUBLIC_RELEASE); - len += sprintf(buffer+len, "NCR5380 driver core version %d\n", NCR5380_PUBLIC_RELEASE); -#ifdef NCR53C400 - len += sprintf(buffer+len, "NCR53C400 driver extension version %d\n", NCR53C400_PUBLIC_RELEASE); - len += sprintf(buffer+len, "NCR53C400 card%s detected\n", (((struct NCR5380_hostdata *)scsi_ptr->hostdata)->flags & FLAG_NCR53C400)?"":" not"); -# if NCR53C400_PSEUDO_DMA - len += sprintf(buffer+len, "NCR53C400 pseudo DMA being used\n"); -# endif -#else - len += sprintf(buffer+len, "NO NCR53C400 driver extensions\n"); -#endif - len += sprintf(buffer+len, "Using %s mapping at %s 0x%x, ", STRVAL(NCR5380_map_config), STRVAL(NCR5380_map_name), scsi_ptr->NCR5380_instance_name); - if (scsi_ptr->irq == IRQ_NONE) - len += sprintf(buffer+len, "interrupts disabled\n"); - else - len += sprintf(buffer+len, "on interrupt %d\n", scsi_ptr->irq); - - *start = buffer + offset; - len -= offset; - if (len > length) - len = length; - return len; -} - -#if NCR53C400_PSEUDO_DMA -static inline int NCR5380_pread (struct Scsi_Host *instance, unsigned char *dst, int len) -{ - int blocks = len / 128; - int start = 0; - int i; - int bl; - NCR5380_local_declare(); - - NCR5380_setup(instance); - -#if (NDEBUG & NDEBUG_C400_PREAD) - printk("53C400r: About to read %d blocks for %d bytes\n", blocks, len); -#endif - - NCR5380_write(C400_CONTROL_STATUS_REG, CSR_BASE | CSR_TRANS_DIR); - NCR5380_write(C400_BLOCK_COUNTER_REG, blocks); - while (1) { - -#if (NDEBUG & NDEBUG_C400_PREAD) - printk("53C400r: %d blocks left\n", blocks); -#endif - - if ((bl=NCR5380_read(C400_BLOCK_COUNTER_REG)) == 0) { -#if (NDEBUG & NDEBUG_C400_PREAD) - if (blocks) - printk("53C400r: blocks still == %d\n", blocks); - else - printk("53C400r: Exiting loop\n"); -#endif - break; - } - -#if 1 - if (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_GATED_53C80_IRQ) { - printk("53C400r: Got 53C80_IRQ start=%d, blocks=%d\n", start, blocks); - return -1; - } -#endif - -#if (NDEBUG & NDEBUG_C400_PREAD) - printk("53C400r: Waiting for buffer, bl=%d\n", bl); -#endif - - while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY) - ; -#if (NDEBUG & NDEBUG_C400_PREAD) - printk("53C400r: Transferring 128 bytes\n"); -#endif - -#ifdef CONFIG_SCSI_G_NCR5380_PORT - for (i=0; i<128; i++) - dst[start+i] = NCR5380_read(C400_HOST_BUFFER); -#else - /* implies CONFIG_SCSI_G_NCR5380_MEM */ - memmove(dst+start,NCR53C400_host_buffer+NCR5380_map_name,128); -#endif - start+=128; - blocks--; - } - -#if (NDEBUG & NDEBUG_C400_PREAD) - printk("53C400r: EXTRA: Waiting for buffer\n"); -#endif - while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY) - ; - -#if (NDEBUG & NDEBUG_C400_PREAD) - printk("53C400r: Transferring EXTRA 128 bytes\n"); -#endif -#ifdef CONFIG_SCSI_G_NCR5380_PORT - for (i=0; i<128; i++) - dst[start+i] = NCR5380_read(C400_HOST_BUFFER); -#else - /* implies CONFIG_SCSI_G_NCR5380_MEM */ - memmove(dst+start,NCR53C400_host_buffer+NCR5380_map_name,128); -#endif - start+=128; - blocks--; - -#if (NDEBUG & NDEBUG_C400_PREAD) - printk("53C400r: Final values: blocks=%d start=%d\n", blocks, start); -#endif - - if (!(NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_GATED_53C80_IRQ)) - printk("53C400r: no 53C80 gated irq after transfer"); -#if (NDEBUG & NDEBUG_C400_PREAD) - else - printk("53C400r: Got 53C80 interupt and tried to clear it\n"); -#endif - -/* DON'T DO THIS - THEY NEVER ARRIVE! - printk("53C400r: Waiting for 53C80 registers\n"); - while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_53C80_REG) - ; -*/ - - if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_END_DMA_TRANSFER)) - printk("53C400r: no end dma signal\n"); -#if (NDEBUG & NDEBUG_C400_PREAD) - else - printk("53C400r: end dma as expected\n"); -#endif - - NCR5380_write(MODE_REG, MR_BASE); - NCR5380_read(RESET_PARITY_INTERRUPT_REG); - return 0; -} - -static inline int NCR5380_pwrite (struct Scsi_Host *instance, unsigned char *src, int len) -{ - int blocks = len / 128; - int start = 0; - int i; - int bl; - NCR5380_local_declare(); - - NCR5380_setup(instance); - -#if (NDEBUG & NDEBUG_C400_PWRITE) - printk("53C400w: About to write %d blocks for %d bytes\n", blocks, len); -#endif - - NCR5380_write(C400_CONTROL_STATUS_REG, CSR_BASE); - NCR5380_write(C400_BLOCK_COUNTER_REG, blocks); - while (1) { - if (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_GATED_53C80_IRQ) { - printk("53C400w: Got 53C80_IRQ start=%d, blocks=%d\n", start, blocks); - return -1; - } - - if ((bl=NCR5380_read(C400_BLOCK_COUNTER_REG)) == 0) { -#if (NDEBUG & NDEBUG_C400_PWRITE) - if (blocks) - printk("53C400w: exiting loop, blocks still == %d\n", blocks); - else - printk("53C400w: exiting loop\n"); -#endif - break; - } - -#if (NDEBUG & NDEBUG_C400_PWRITE) - printk("53C400w: %d blocks left\n", blocks); - - printk("53C400w: waiting for buffer, bl=%d\n", bl); -#endif - while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY) - ; - -#if (NDEBUG & NDEBUG_C400_PWRITE) - printk("53C400w: transferring 128 bytes\n"); -#endif -#ifdef CONFIG_SCSI_G_NCR5380_PORT - for (i=0; i<128; i++) - NCR5380_write(C400_HOST_BUFFER, src[start+i]); -#else - /* implies CONFIG_SCSI_G_NCR5380_MEM */ - memmove(NCR53C400_host_buffer+NCR5380_map_name,src+start,128); -#endif - start+=128; - blocks--; - } - if (blocks) { -#if (NDEBUG & NDEBUG_C400_PWRITE) - printk("53C400w: EXTRA waiting for buffer\n"); -#endif - while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY) - ; - -#if (NDEBUG & NDEBUG_C400_PWRITE) - printk("53C400w: transferring EXTRA 128 bytes\n"); -#endif -#ifdef CONFIG_SCSI_G_NCR5380_PORT - for (i=0; i<128; i++) - NCR5380_write(C400_HOST_BUFFER, src[start+i]); -#else - /* implies CONFIG_SCSI_G_NCR5380_MEM */ - memmove(NCR53C400_host_buffer+NCR5380_map_name,src+start,128); -#endif - start+=128; - blocks--; - } -#if (NDEBUG & NDEBUG_C400_PWRITE) - else - printk("53C400w: No EXTRA required\n"); -#endif - -#if (NDEBUG & NDEBUG_C400_PWRITE) - printk("53C400w: Final values: blocks=%d start=%d\n", blocks, start); -#endif - -#if 0 - printk("53C400w: waiting for registers to be available\n"); - THEY NEVER DO! - while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_53C80_REG) - ; - printk("53C400w: Got em\n"); -#endif - - /* Let's wait for this instead - could be ugly */ - /* All documentation says to check for this. Maybe my hardware is too - * fast. Waiting for it seems to work fine! KLL - */ - while (!(i = NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_GATED_53C80_IRQ)) - ; - - /* - * I know. i is certainly != 0 here but the loop is new. See previous - * comment. - */ - if (i) { -#if (NDEBUG & NDEBUG_C400_PWRITE) - prink("53C400w: got 53C80 gated irq (last block)\n"); -#endif - if (!((i=NCR5380_read(BUS_AND_STATUS_REG)) & BASR_END_DMA_TRANSFER)) - printk("53C400w: No END OF DMA bit - WHOOPS! BASR=%0x\n",i); -#if (NDEBUG & NDEBUG_C400_PWRITE) - else - printk("53C400w: Got END OF DMA\n"); -#endif - } - else - printk("53C400w: no 53C80 gated irq after transfer (last block)\n"); - -#if 0 - if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_END_DMA_TRANSFER)) { - printk("53C400w: no end dma signal\n"); - } -#endif - -#if (NDEBUG & NDEBUG_C400_PWRITE) - printk("53C400w: waiting for last byte...\n"); -#endif - while (!(NCR5380_read(TARGET_COMMAND_REG) & TCR_LAST_BYTE_SENT)) - ; - -#if (NDEBUG & NDEBUG_C400_PWRITE) - printk("53C400w: got last byte.\n"); - printk("53C400w: pwrite exiting with status 0, whoopee!\n"); -#endif - return 0; -} -#endif /* PSEUDO_DMA */ - -#ifdef MACH -#include "NCR5380.src" -#else -#include "NCR5380.c" -#endif - -#ifdef MODULE -/* Eventually this will go into an include file, but this will be later */ -Scsi_Host_Template driver_template = GENERIC_NCR5380; - -#include <linux/module.h> -#include "scsi_module.c" -#endif diff --git a/i386/i386at/gpl/linux/scsi/g_NCR5380.h b/i386/i386at/gpl/linux/scsi/g_NCR5380.h deleted file mode 100644 index 52e64499..00000000 --- a/i386/i386at/gpl/linux/scsi/g_NCR5380.h +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Generic Generic NCR5380 driver defines - * - * Copyright 1993, Drew Eckhardt - * Visionary Computing - * (Unix and Linux consulting and custom programming) - * drew@colorado.edu - * +1 (303) 440-4894 - * - * NCR53C400 extensions (c) 1994,1995,1996, Kevin Lentin - * K.Lentin@cs.monash.edu.au - * - * ALPHA RELEASE 1. - * - * For more information, please consult - * - * NCR 5380 Family - * SCSI Protocol Controller - * Databook - * - * NCR Microelectronics - * 1635 Aeroplaza Drive - * Colorado Springs, CO 80916 - * 1+ (719) 578-3400 - * 1+ (800) 334-5454 - */ - -/* - * $Log: g_NCR5380.h,v $ - * Revision 1.1.1.1 1996/10/30 01:40:05 thomas - * Imported from UK22 - * - * Revision 1.1 1996/03/25 20:25:35 goel - * Linux driver merge. - * - */ - -#ifndef GENERIC_NCR5380_H -#define GENERIC_NCR5380_H - -#define GENERIC_NCR5380_PUBLIC_RELEASE 1 - -#ifdef NCR53C400 -#define BIOSPARAM -#define NCR5380_BIOSPARAM generic_NCR5380_biosparam -#else -#define NCR5380_BIOSPARAM NULL -#endif - -#ifndef ASM -int generic_NCR5380_abort(Scsi_Cmnd *); -int generic_NCR5380_detect(Scsi_Host_Template *); -int generic_NCR5380_release_resources(struct Scsi_Host *); -int generic_NCR5380_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); -int generic_NCR5380_reset(Scsi_Cmnd *); -#ifdef BIOSPARAM -int generic_NCR5380_biosparam(Disk *, kdev_t, int *); -#endif - -int generic_NCR5380_proc_info(char* buffer, char** start, off_t offset, int length, int hostno, int inout); - -#ifndef NULL -#define NULL 0 -#endif - -#ifndef CMD_PER_LUN -#define CMD_PER_LUN 2 -#endif - -#ifndef CAN_QUEUE -#define CAN_QUEUE 16 -#endif - -#if defined(HOSTS_C) || defined(MODULE) - -#define GENERIC_NCR5380 {NULL, NULL, NULL, \ - generic_NCR5380_proc_info, \ - "Generic NCR5380/NCR53C400 Scsi Driver", \ - generic_NCR5380_detect, generic_NCR5380_release_resources, \ - generic_NCR5380_info, NULL, \ - generic_NCR5380_queue_command, generic_NCR5380_abort, \ - generic_NCR5380_reset, NULL, \ - NCR5380_BIOSPARAM, \ - /* can queue */ CAN_QUEUE, /* id */ 7, SG_ALL, \ - /* cmd per lun */ CMD_PER_LUN , 0, 0, DISABLE_CLUSTERING} - -#endif - -#ifndef HOSTS_C - -#define __STRVAL(x) #x -#define STRVAL(x) __STRVAL(x) - -#ifdef CONFIG_SCSI_G_NCR5380_PORT - -#define NCR5380_map_config port - -#define NCR5380_map_type int - -#define NCR5380_map_name port - -#define NCR5380_instance_name io_port - -#define NCR53C400_register_offset 0 - -#define NCR53C400_address_adjust 8 - -#ifdef NCR53C400 -#define NCR5380_region_size 16 -#else -#define NCR5380_region_size 8 -#endif - -#define NCR5380_read(reg) (inb(NCR5380_map_name + (reg))) -#define NCR5380_write(reg, value) (outb((value), (NCR5380_map_name + (reg)))) - -#else -/* therefore CONFIG_SCSI_G_NCR5380_MEM */ - -#define NCR5380_map_config memory - -#define NCR5380_map_type volatile unsigned char* - -#define NCR5380_map_name base - -#define NCR5380_instance_name base - -#define NCR53C400_register_offset 0x108 - -#define NCR53C400_address_adjust 0 - -#define NCR53C400_mem_base 0x3880 - -#define NCR53C400_host_buffer 0x3900 - -#define NCR5380_region_size 0x3a00 - - -#define NCR5380_read(reg) (*(NCR5380_map_name + NCR53C400_mem_base + (reg))) -#define NCR5380_write(reg, value) (*(NCR5380_map_name + NCR53C400_mem_base + (reg)) = value) - -#endif - -#define NCR5380_implementation_fields \ - NCR5380_map_type NCR5380_map_name - -#define NCR5380_local_declare() \ - register NCR5380_implementation_fields - -#define NCR5380_setup(instance) \ - NCR5380_map_name = (NCR5380_map_type)((instance)->NCR5380_instance_name) - -#define NCR5380_intr generic_NCR5380_intr -#define NCR5380_queue_command generic_NCR5380_queue_command -#define NCR5380_abort generic_NCR5380_abort -#define NCR5380_reset generic_NCR5380_reset -#define NCR5380_pread generic_NCR5380_pread -#define NCR5380_pwrite generic_NCR5380_pwrite - -#define BOARD_NCR5380 0 -#define BOARD_NCR53C400 1 - -#endif /* else def HOSTS_C */ -#endif /* ndef ASM */ -#endif /* GENERIC_NCR5380_H */ - diff --git a/i386/i386at/gpl/linux/scsi/hosts.c b/i386/i386at/gpl/linux/scsi/hosts.c deleted file mode 100644 index 72ae0cb6..00000000 --- a/i386/i386at/gpl/linux/scsi/hosts.c +++ /dev/null @@ -1,440 +0,0 @@ -/* - * hosts.c Copyright (C) 1992 Drew Eckhardt - * Copyright (C) 1993, 1994, 1995 Eric Youngdale - * - * mid to lowlevel SCSI driver interface - * Initial versions: Drew Eckhardt - * Subsequent revisions: Eric Youngdale - * - * <drew@colorado.edu> - */ - - -/* - * This file contains the medium level SCSI - * host interface initialization, as well as the scsi_hosts array of SCSI - * hosts currently present in the system. - */ - -/* - * Don't import our own symbols, as this would severely mess up our - * symbol tables. - */ -#define _SCSI_SYMS_VER_ -#define __NO_VERSION__ -#include <linux/module.h> - -#include <linux/config.h> -#include <linux/blk.h> -#include <linux/kernel.h> -#include <linux/string.h> -#include <linux/mm.h> -#include <linux/proc_fs.h> - -#include "scsi.h" - -#ifndef NULL -#define NULL 0L -#endif - -#define HOSTS_C - -#include "hosts.h" - -#ifdef CONFIG_SCSI_ADVANSYS -#include "advansys.h" -#endif - -#ifdef CONFIG_SCSI_AHA152X -#include "aha152x.h" -#endif - -#ifdef CONFIG_SCSI_AHA1542 -#include "aha1542.h" -#endif - -#ifdef CONFIG_SCSI_AHA1740 -#include "aha1740.h" -#endif - -#ifdef CONFIG_SCSI_AIC7XXX -#include "aic7xxx.h" -#endif - -#ifdef CONFIG_SCSI_BUSLOGIC -#include "BusLogic.h" -#endif - -#ifdef CONFIG_SCSI_EATA_DMA -#include "eata_dma.h" -#endif - -#ifdef CONFIG_SCSI_EATA_PIO -#include "eata_pio.h" -#endif - -#ifdef CONFIG_SCSI_U14_34F -#include "u14-34f.h" -#endif - -#ifdef CONFIG_SCSI_FUTURE_DOMAIN -#include "fdomain.h" -#endif - -#ifdef CONFIG_SCSI_GENERIC_NCR5380 -#include "g_NCR5380.h" -#endif - -#ifdef CONFIG_SCSI_IN2000 -#include "in2000.h" -#endif - -#ifdef CONFIG_SCSI_PAS16 -#include "pas16.h" -#endif - -#ifdef CONFIG_SCSI_QLOGIC -#include "qlogic.h" -#endif - -#ifdef CONFIG_SCSI_SEAGATE -#include "seagate.h" -#endif - -#ifdef CONFIG_SCSI_T128 -#include "t128.h" -#endif - -#ifdef CONFIG_SCSI_NCR53C7xx -#include "53c7,8xx.h" -#endif - -#ifdef CONFIG_SCSI_ULTRASTOR -#include "ultrastor.h" -#endif - -#ifdef CONFIG_SCSI_7000FASST -#include "wd7000.h" -#endif - -#ifdef CONFIG_SCSI_EATA -#include "eata.h" -#endif - -#ifdef CONFIG_SCSI_NCR53C406A -#include "NCR53c406a.h" -#endif - -#ifdef CONFIG_SCSI_AM53C974 -#include "AM53C974.h" -#endif - -#ifdef CONFIG_SCSI_DEBUG -#include "scsi_debug.h" -#endif - -/* -static const char RCSid[] = "$Header: cvs/gnumach/i386/i386at/gpl/linux/scsi/Attic/hosts.c,v 1.2 1997/03/24 21:51:24 thomas Exp $"; -*/ - -/* - * The scsi host entries should be in the order you wish the - * cards to be detected. A driver may appear more than once IFF - * it can deal with being detected (and therefore initialized) - * with more than one simultaneous host number, can handle being - * reentrant, etc. - * - * They may appear in any order, as each SCSI host is told which host - * number it is during detection. - */ - -/* This is a placeholder for controllers that are not configured into - * the system - we do this to ensure that the controller numbering is - * always consistent, no matter how the kernel is configured. */ - -#define NO_CONTROLLER {NULL, NULL, NULL, NULL, NULL, NULL, NULL, \ - NULL, NULL, 0, 0, 0, 0, 0, 0} - -/* - * When figure is run, we don't want to link to any object code. Since - * the macro for each host will contain function pointers, we cannot - * use it and instead must use a "blank" that does no such - * idiocy. - */ - -Scsi_Host_Template * scsi_hosts = NULL; - -static Scsi_Host_Template builtin_scsi_hosts[] = -{ -#ifdef CONFIG_SCSI_ADVANSYS - ADVANSYS, -#endif -/* BusLogic must come before aha1542.c */ -#ifdef CONFIG_SCSI_BUSLOGIC - BUSLOGIC, -#endif -#ifdef CONFIG_SCSI_U14_34F - ULTRASTOR_14_34F, -#endif -#ifdef CONFIG_SCSI_ULTRASTOR - ULTRASTOR_14F, -#endif -#ifdef CONFIG_SCSI_AHA152X - AHA152X, -#endif -#ifdef CONFIG_SCSI_AHA1542 - AHA1542, -#endif -#ifdef CONFIG_SCSI_AHA1740 - AHA1740, -#endif -#ifdef CONFIG_SCSI_AIC7XXX - AIC7XXX, -#endif -#ifdef CONFIG_SCSI_FUTURE_DOMAIN - FDOMAIN_16X0, -#endif -#ifdef CONFIG_SCSI_IN2000 - IN2000, -#endif -#ifdef CONFIG_SCSI_GENERIC_NCR5380 - GENERIC_NCR5380, -#endif -#ifdef CONFIG_SCSI_NCR53C406A /* 53C406A should come before QLOGIC */ - NCR53c406a, -#endif -#ifdef CONFIG_SCSI_QLOGIC - QLOGIC, -#endif -#ifdef CONFIG_SCSI_PAS16 - MV_PAS16, -#endif -#ifdef CONFIG_SCSI_SEAGATE - SEAGATE_ST0X, -#endif -#ifdef CONFIG_SCSI_T128 - TRANTOR_T128, -#endif -#ifdef CONFIG_SCSI_NCR53C7xx - NCR53c7xx, -#endif -#ifdef CONFIG_SCSI_EATA_DMA - EATA_DMA, -#endif -#ifdef CONFIG_SCSI_EATA_PIO - EATA_PIO, -#endif -#ifdef CONFIG_SCSI_7000FASST - WD7000, -#endif -#ifdef CONFIG_SCSI_EATA - EATA, -#endif -#ifdef CONFIG_SCSI_AM53C974 - AM53C974, -#endif -#ifdef CONFIG_SCSI_DEBUG - SCSI_DEBUG, -#endif -}; - -#define MAX_SCSI_HOSTS (sizeof(builtin_scsi_hosts) / sizeof(Scsi_Host_Template)) - - -/* - * Our semaphores and timeout counters, where size depends on - * MAX_SCSI_HOSTS here. - */ - -struct Scsi_Host * scsi_hostlist = NULL; -struct Scsi_Device_Template * scsi_devicelist = NULL; - -int max_scsi_hosts = 0; -int next_scsi_host = 0; - -void -scsi_unregister(struct Scsi_Host * sh){ - struct Scsi_Host * shpnt; - - if(scsi_hostlist == sh) - scsi_hostlist = sh->next; - else { - shpnt = scsi_hostlist; - while(shpnt->next != sh) shpnt = shpnt->next; - shpnt->next = shpnt->next->next; - } - - /* If we are removing the last host registered, it is safe to reuse - * its host number (this avoids "holes" at boot time) (DB) - */ - if (max_scsi_hosts == next_scsi_host && !scsi_loadable_module_flag) - max_scsi_hosts--; - - next_scsi_host--; - scsi_init_free((char *) sh, sizeof(struct Scsi_Host) + sh->extra_bytes); -} - -/* We call this when we come across a new host adapter. We only do this - * once we are 100% sure that we want to use this host adapter - it is a - * pain to reverse this, so we try and avoid it - */ - -struct Scsi_Host * scsi_register(Scsi_Host_Template * tpnt, int j){ - struct Scsi_Host * retval, *shpnt; - retval = (struct Scsi_Host *)scsi_init_malloc(sizeof(struct Scsi_Host) + j, - (tpnt->unchecked_isa_dma && j ? GFP_DMA : 0) | GFP_ATOMIC); - retval->host_busy = 0; - retval->block = NULL; - retval->wish_block = 0; - if(j > 0xffff) panic("Too many extra bytes requested\n"); - retval->extra_bytes = j; - retval->loaded_as_module = scsi_loadable_module_flag; - retval->host_no = max_scsi_hosts++; /* never reuse host_no (DB) */ - next_scsi_host++; - retval->host_queue = NULL; - retval->host_wait = NULL; - retval->last_reset = 0; - retval->irq = 0; - retval->dma_channel = 0xff; - - /* These three are default values which can be overridden */ - retval->max_channel = 0; - retval->max_id = 8; - retval->max_lun = 8; - - retval->unique_id = 0; - retval->io_port = 0; - retval->hostt = tpnt; - retval->next = NULL; -#ifdef DEBUG - printk("Register %x %x: %d\n", (int)retval, (int)retval->hostt, j); -#endif - - /* The next six are the default values which can be overridden - * if need be */ - retval->this_id = tpnt->this_id; - retval->can_queue = tpnt->can_queue; - retval->sg_tablesize = tpnt->sg_tablesize; - retval->cmd_per_lun = tpnt->cmd_per_lun; - retval->unchecked_isa_dma = tpnt->unchecked_isa_dma; - retval->use_clustering = tpnt->use_clustering; - if(!scsi_hostlist) - scsi_hostlist = retval; - else - { - shpnt = scsi_hostlist; - while(shpnt->next) shpnt = shpnt->next; - shpnt->next = retval; - } - - return retval; -} - -int -scsi_register_device(struct Scsi_Device_Template * sdpnt) -{ - if(sdpnt->next) panic("Device already registered"); - sdpnt->next = scsi_devicelist; - scsi_devicelist = sdpnt; - return 0; -} - -unsigned int scsi_init() -{ - static int called = 0; - int i, pcount; - Scsi_Host_Template * tpnt; - struct Scsi_Host * shpnt; - const char * name; - - if(called) return 0; - - called = 1; - for (tpnt = &builtin_scsi_hosts[0], i = 0; i < MAX_SCSI_HOSTS; ++i, tpnt++) - { - /* - * Initialize our semaphores. -1 is interpreted to mean - * "inactive" - where as 0 will indicate a time out condition. - */ - - pcount = next_scsi_host; - if ((tpnt->detect) && - (tpnt->present = - tpnt->detect(tpnt))) - { - /* The only time this should come up is when people use - * some kind of patched driver of some kind or another. */ - if(pcount == next_scsi_host) { - if(tpnt->present > 1) - panic("Failure to register low-level scsi driver"); - /* The low-level driver failed to register a driver. We - * can do this now. */ - scsi_register(tpnt,0); - } - tpnt->next = scsi_hosts; - scsi_hosts = tpnt; - - /* Add the driver to /proc/scsi */ -#if CONFIG_PROC_FS - build_proc_dir_entries(tpnt); -#endif - } - } - - for(shpnt=scsi_hostlist; shpnt; shpnt = shpnt->next) - { - if(shpnt->hostt->info) - name = shpnt->hostt->info(shpnt); - else - name = shpnt->hostt->name; -#if 0 - printk ("scsi%d : %s\n", /* And print a little message */ - shpnt->host_no, name); -#endif - } - -#if 0 - printk ("scsi : %d host%s.\n", next_scsi_host, - (next_scsi_host == 1) ? "" : "s"); -#endif - - scsi_make_blocked_list(); - - /* Now attach the high level drivers */ -#ifdef CONFIG_BLK_DEV_SD - scsi_register_device(&sd_template); -#endif -#ifdef CONFIG_BLK_DEV_SR - scsi_register_device(&sr_template); -#endif -#ifdef CONFIG_CHR_DEV_ST - scsi_register_device(&st_template); -#endif -#ifdef CONFIG_CHR_DEV_SG - scsi_register_device(&sg_template); -#endif - -#if 0 - max_scsi_hosts = next_scsi_host; -#endif - return 0; -} - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 4 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -4 - * c-argdecl-indent: 4 - * c-label-offset: -4 - * c-continued-statement-offset: 4 - * c-continued-brace-offset: 0 - * indent-tabs-mode: nil - * tab-width: 8 - * End: - */ diff --git a/i386/i386at/gpl/linux/scsi/hosts.h b/i386/i386at/gpl/linux/scsi/hosts.h deleted file mode 100644 index 1da480de..00000000 --- a/i386/i386at/gpl/linux/scsi/hosts.h +++ /dev/null @@ -1,409 +0,0 @@ -/* - * hosts.h Copyright (C) 1992 Drew Eckhardt - * Copyright (C) 1993, 1994, 1995 Eric Youngdale - * - * mid to low-level SCSI driver interface header - * Initial versions: Drew Eckhardt - * Subsequent revisions: Eric Youngdale - * - * <drew@colorado.edu> - * - * Modified by Eric Youngdale eric@aib.com to - * add scatter-gather, multiple outstanding request, and other - * enhancements. - * - * Further modified by Eric Youngdale to support multiple host adapters - * of the same type. - */ - -#ifndef _HOSTS_H -#define _HOSTS_H - -/* - $Header: cvs/gnumach/i386/i386at/gpl/linux/scsi/Attic/hosts.h,v 1.1.1.1 1997/02/25 21:27:49 thomas Exp $ -*/ - -#include <linux/proc_fs.h> - -/* It is senseless to set SG_ALL any higher than this - the performance - * does not get any better, and it wastes memory - */ -#define SG_NONE 0 -#define SG_ALL 0xff - -#define DISABLE_CLUSTERING 0 -#define ENABLE_CLUSTERING 1 - -/* The various choices mean: - * NONE: Self evident. Host adapter is not capable of scatter-gather. - * ALL: Means that the host adapter module can do scatter-gather, - * and that there is no limit to the size of the table to which - * we scatter/gather data. - * Anything else: Indicates the maximum number of chains that can be - * used in one scatter-gather request. - */ - -/* - * The Scsi_Host_Template type has all that is needed to interface with a SCSI - * host in a device independent matter. There is one entry for each different - * type of host adapter that is supported on the system. - */ - -typedef struct scsi_disk Disk; - -typedef struct SHT -{ - - /* Used with loadable modules so we can construct a linked list. */ - struct SHT * next; - - /* Used with loadable modules so that we know when it is safe to unload */ - long * usage_count; - - /* The pointer to the /proc/scsi directory entry */ - struct proc_dir_entry *proc_dir; - - /* proc-fs info function. - * Can be used to export driver statistics and other infos to the world - * outside the kernel ie. userspace and it also provides an interface - * to feed the driver with information. Check eata_dma_proc.c for reference - */ - int (*proc_info)(char *, char **, off_t, int, int, int); - - /* - * The name pointer is a pointer to the name of the SCSI - * device detected. - */ - const char *name; - - /* - * The detect function shall return non zero on detection, - * indicating the number of host adapters of this particular - * type were found. It should also - * initialize all data necessary for this particular - * SCSI driver. It is passed the host number, so this host - * knows where the first entry is in the scsi_hosts[] array. - * - * Note that the detect routine MUST not call any of the mid level - * functions to queue commands because things are not guaranteed - * to be set up yet. The detect routine can send commands to - * the host adapter as long as the program control will not be - * passed to scsi.c in the processing of the command. Note - * especially that scsi_malloc/scsi_free must not be called. - */ - int (* detect)(struct SHT *); - - /* Used with loadable modules to unload the host structures. Note: - * there is a default action built into the modules code which may - * be sufficient for most host adapters. Thus you may not have to supply - * this at all. - */ - int (*release)(struct Scsi_Host *); - - /* - * The info function will return whatever useful - * information the developer sees fit. If not provided, then - * the name field will be used instead. - */ - const char *(* info)(struct Scsi_Host *); - - /* - * The command function takes a target, a command (this is a SCSI - * command formatted as per the SCSI spec, nothing strange), a - * data buffer pointer, and data buffer length pointer. The return - * is a status int, bit fielded as follows : - * Byte What - * 0 SCSI status code - * 1 SCSI 1 byte message - * 2 host error return. - * 3 mid level error return - */ - int (* command)(Scsi_Cmnd *); - - /* - * The QueueCommand function works in a similar manner - * to the command function. It takes an additional parameter, - * void (* done)(int host, int code) which is passed the host - * # and exit result when the command is complete. - * Host number is the POSITION IN THE hosts array of THIS - * host adapter. - */ - int (* queuecommand)(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); - - /* - * Since the mid level driver handles time outs, etc, we want to - * be able to abort the current command. Abort returns 0 if the - * abortion was successful. The field SCpnt->abort reason - * can be filled in with the appropriate reason why we wanted - * the abort in the first place, and this will be used - * in the mid-level code instead of the host_byte(). - * If non-zero, the code passed to it - * will be used as the return code, otherwise - * DID_ABORT should be returned. - * - * Note that the scsi driver should "clean up" after itself, - * resetting the bus, etc. if necessary. - */ - int (* abort)(Scsi_Cmnd *); - - /* - * The reset function will reset the SCSI bus. Any executing - * commands should fail with a DID_RESET in the host byte. - * The Scsi_Cmnd is passed so that the reset routine can figure - * out which host adapter should be reset, and also which command - * within the command block was responsible for the reset in - * the first place. Some hosts do not implement a reset function, - * and these hosts must call scsi_request_sense(SCpnt) to keep - * the command alive. - */ - int (* reset)(Scsi_Cmnd *); - - /* - * This function is used to select synchronous communications, - * which will result in a higher data throughput. Not implemented - * yet. - */ - int (* slave_attach)(int, int); - - /* - * This function determines the bios parameters for a given - * harddisk. These tend to be numbers that are made up by - * the host adapter. Parameters: - * size, device number, list (heads, sectors, cylinders) - */ - int (* bios_param)(Disk *, kdev_t, int []); - - /* - * This determines if we will use a non-interrupt driven - * or an interrupt driven scheme, It is set to the maximum number - * of simultaneous commands a given host adapter will accept. - */ - int can_queue; - - /* - * In many instances, especially where disconnect / reconnect are - * supported, our host also has an ID on the SCSI bus. If this is - * the case, then it must be reserved. Please set this_id to -1 if - * your setup is in single initiator mode, and the host lacks an - * ID. - */ - int this_id; - - /* - * This determines the degree to which the host adapter is capable - * of scatter-gather. - */ - short unsigned int sg_tablesize; - - /* - * True if this host adapter can make good use of linked commands. - * This will allow more than one command to be queued to a given - * unit on a given host. Set this to the maximum number of command - * blocks to be provided for each device. Set this to 1 for one - * command block per lun, 2 for two, etc. Do not set this to 0. - * You should make sure that the host adapter will do the right thing - * before you try setting this above 1. - */ - short cmd_per_lun; - - /* - * present contains counter indicating how many boards of this - * type were found when we did the scan. - */ - unsigned char present; - - /* - * true if this host adapter uses unchecked DMA onto an ISA bus. - */ - unsigned unchecked_isa_dma:1; - - /* - * true if this host adapter can make good use of clustering. - * I originally thought that if the tablesize was large that it - * was a waste of CPU cycles to prepare a cluster list, but - * it works out that the Buslogic is faster if you use a smaller - * number of segments (i.e. use clustering). I guess it is - * inefficient. - */ - unsigned use_clustering:1; - -} Scsi_Host_Template; - -/* - * The scsi_hosts array is the array containing the data for all - * possible <supported> scsi hosts. This is similar to the - * Scsi_Host_Template, except that we have one entry for each - * actual physical host adapter on the system, stored as a linked - * list. Note that if there are 2 aha1542 boards, then there will - * be two Scsi_Host entries, but only 1 Scsi_Host_Template entries. - */ - -struct Scsi_Host -{ - struct Scsi_Host * next; - unsigned short extra_bytes; - volatile unsigned char host_busy; - char host_no; /* Used for IOCTL_GET_IDLUN, /proc/scsi et al. */ - int last_reset; - struct wait_queue *host_wait; - Scsi_Cmnd *host_queue; - Scsi_Host_Template * hostt; - - /* - * These three parameters can be used to allow for wide scsi, - * and for host adapters that support multiple busses - * The first two should be set to 1 more than the actual max id - * or lun (i.e. 8 for normal systems). - */ - unsigned int max_id; - unsigned int max_lun; - unsigned int max_channel; - - /* - * Pointer to a circularly linked list - this indicates the hosts - * that should be locked out of performing I/O while we have an active - * command on this host. - */ - struct Scsi_Host * block; - unsigned wish_block:1; - - /* These parameters should be set by the detect routine */ - unsigned char *base; - unsigned int io_port; - unsigned char n_io_port; - unsigned char irq; - unsigned char dma_channel; - - /* - * This is a unique identifier that must be assigned so that we - * have some way of identifying each detected host adapter properly - * and uniquely. For hosts that do not support more than one card - * in the system at one time, this does not need to be set. It is - * initialized to 0 in scsi_register. - */ - unsigned int unique_id; - - /* - * The rest can be copied from the template, or specifically - * initialized, as required. - */ - - int this_id; - int can_queue; - short cmd_per_lun; - short unsigned int sg_tablesize; - unsigned unchecked_isa_dma:1; - unsigned use_clustering:1; - /* - * True if this host was loaded as a loadable module - */ - unsigned loaded_as_module:1; - - /* - * True when we call the low-level reset function, and - * the midlevel code suggests a full bus reset. - */ - unsigned suggest_bus_reset:1; - - unsigned long hostdata[0]; /* Used for storage of host specific stuff */ -}; - -extern struct Scsi_Host * scsi_hostlist; -extern struct Scsi_Device_Template * scsi_devicelist; - -extern Scsi_Host_Template * scsi_hosts; - -extern void build_proc_dir_entries(Scsi_Host_Template *); - - -/* - * scsi_init initializes the scsi hosts. - */ - -/* - * We use these goofy things because the MM is not set up when we init - * the scsi subsystem. By using these functions we can write code that - * looks normal. Also, it makes it possible to use the same code for a - * loadable module. - */ - -extern void * scsi_init_malloc(unsigned int size, int priority); -extern void scsi_init_free(char * ptr, unsigned int size); - -extern int next_scsi_host; - -extern int scsi_loadable_module_flag; -unsigned int scsi_init(void); -extern struct Scsi_Host * scsi_register(Scsi_Host_Template *, int j); -extern void scsi_unregister(struct Scsi_Host * i); - -#define BLANK_HOST {"", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} - -struct Scsi_Device_Template -{ - struct Scsi_Device_Template * next; - const char * name; - const char * tag; - long * usage_count; /* Used for loadable modules */ - unsigned char scsi_type; - unsigned char major; - unsigned char nr_dev; /* Number currently attached */ - unsigned char dev_noticed; /* Number of devices detected. */ - unsigned char dev_max; /* Current size of arrays */ - unsigned blk:1; /* 0 if character device */ - int (*detect)(Scsi_Device *); /* Returns 1 if we can attach this device */ - int (*init)(void); /* Sizes arrays based upon number of devices - * detected */ - void (*finish)(void); /* Perform initialization after attachment */ - int (*attach)(Scsi_Device *); /* Attach devices to arrays */ - void (*detach)(Scsi_Device *); -}; - -extern struct Scsi_Device_Template sd_template; -extern struct Scsi_Device_Template st_template; -extern struct Scsi_Device_Template sr_template; -extern struct Scsi_Device_Template sg_template; - -int scsi_register_device(struct Scsi_Device_Template * sdpnt); - -/* These are used by loadable modules */ -extern int scsi_register_module(int, void *); -extern void scsi_unregister_module(int, void *); - -/* The different types of modules that we can load and unload */ -#define MODULE_SCSI_HA 1 -#define MODULE_SCSI_CONST 2 -#define MODULE_SCSI_IOCTL 3 -#define MODULE_SCSI_DEV 4 - - -/* - * This is an ugly hack. If we expect to be able to load devices at run time, - * we need to leave extra room in some of the data structures. Doing a - * realloc to enlarge the structures would be riddled with race conditions, - * so until a better solution is discovered, we use this crude approach - */ -#define SD_EXTRA_DEVS 2 -#define ST_EXTRA_DEVS 2 -#define SR_EXTRA_DEVS 2 -#define SG_EXTRA_DEVS (SD_EXTRA_DEVS + SR_EXTRA_DEVS + ST_EXTRA_DEVS) - -#endif -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 4 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -4 - * c-argdecl-indent: 4 - * c-label-offset: -4 - * c-continued-statement-offset: 4 - * c-continued-brace-offset: 0 - * indent-tabs-mode: nil - * tab-width: 8 - * End: - */ diff --git a/i386/i386at/gpl/linux/scsi/in2000.c b/i386/i386at/gpl/linux/scsi/in2000.c deleted file mode 100644 index ac2cc656..00000000 --- a/i386/i386at/gpl/linux/scsi/in2000.c +++ /dev/null @@ -1,731 +0,0 @@ -/* - * This file is in2000.c, written and - * Copyright (C) 1993 Brad McLean - * Last edit 1/19/95 TZ - * Disclaimer: - * Note: This is ugly. I know it, I wrote it, but my whole - * focus was on getting the damn thing up and out quickly. - * Future stuff that would be nice: Command chaining, and - * a local queue of commands would speed stuff up considerably. - * Disconnection needs some supporting code. All of this - * is beyond the scope of what I wanted to address, but if you - * have time and patience, more power to you. - * Also, there are some constants scattered throughout that - * should have defines, and I should have built functions to - * address the registers on the WD chip. - * Oh well, I'm out of time for this project. - * The one good thing to be said is that you can use the card. - */ - -/* - * This module was updated by Shaun Savage first on 5-13-93 - * At that time the write was fixed, irq detection, and some - * timing stuff. since that time other problems were fixed. - * On 7-20-93 this file was updated for patch level 11 - * There are still problems with it but it work on 95% of - * the machines. There are still problems with it working with - * IDE drives, as swap drive and HD that support reselection. - * But for most people it will work. - */ -/* More changes by Bill Earnest, wde@aluxpo.att.com - * through 4/07/94. Includes rewrites of FIFO routines, - * length-limited commands to make swap partitions work. - * Merged the changes released by Larry Doolittle, based on input - * from Jon Luckey, Roger Sunshine, John Shifflett. The FAST_FIFO - * doesn't work for me. Scatter-gather code from Eric. The change to - * an IF stmt. in the interrupt routine finally made it stable. - * Limiting swap request size patch to ll_rw_blk.c not needed now. - * Please ignore the clutter of debug stmts., pretty can come later. - */ -/* Merged code from Matt Postiff improving the auto-sense validation - * for all I/O addresses. Some reports of problems still come in, but - * have been unable to reproduce or localize the cause. Some are from - * LUN > 0 problems, but that is not host specific. Now 6/6/94. - */ -/* Changes for 1.1.28 kernel made 7/19/94, code not affected. (WDE) - */ -/* Changes for 1.1.43+ kernels made 8/25/94, code added to check for - * new BIOS version, derived by jshiffle@netcom.com. (WDE) - * - * 1/7/95 Fix from Peter Lu (swift@world.std.com) for datalen vs. dataptr - * logic, much more stable under load. - * - * 1/19/95 (zerucha@shell.portal.com) Added module and biosparam support for - * larger SCSI hard drives (untested). - */ - -#ifdef MODULE -#include <linux/module.h> -#endif - -#include <linux/kernel.h> -#include <linux/head.h> -#include <linux/types.h> -#include <linux/string.h> -#include <linux/sched.h> -#include <linux/proc_fs.h> -#include <asm/dma.h> -#include <asm/system.h> -#include <asm/io.h> -#include <linux/blk.h> -#include "scsi.h" -#include "hosts.h" -#include "sd.h" - -#include "in2000.h" -#include<linux/stat.h> - -struct proc_dir_entry proc_scsi_in2000 = { - PROC_SCSI_IN2000, 6, "in2000", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - -/*#define FAST_FIFO_IO*/ - -/*#define DEBUG*/ -#ifdef DEBUG -#define DEB(x) x -#else -#define DEB(x) -#endif - -/* These functions are based on include/asm/io.h */ -#ifndef inw -inline static unsigned short inw( unsigned short port ) -{ - unsigned short _v; - - __asm__ volatile ("inw %1,%0" - :"=a" (_v):"d" ((unsigned short) port)); - return _v; -} -#endif - -#ifndef outw -inline static void outw( unsigned short value, unsigned short port ) -{ - __asm__ volatile ("outw %0,%1" - : /* no outputs */ - :"a" ((unsigned short) value), - "d" ((unsigned short) port)); -} -#endif - -/* These functions are lifted from drivers/block/hd.c */ - -#define port_read(port,buf,nr) \ -__asm__("cld;rep;insw": :"d" (port),"D" (buf),"c" (nr):"cx","di") - -#define port_write(port,buf,nr) \ -__asm__("cld;rep;outsw": :"d" (port),"S" (buf),"c" (nr):"cx","si") - -static unsigned int base; -static unsigned int ficmsk; -static unsigned char irq_level; -static int in2000_datalen; -static unsigned int in2000_nsegment; -static unsigned int in2000_current_segment; -static unsigned short *in2000_dataptr; -static char in2000_datawrite; -static struct scatterlist * in2000_scatter; -static Scsi_Cmnd *in2000_SCptr = 0; - -static void (*in2000_done)(Scsi_Cmnd *); - -static int in2000_test_port(int index) -{ - static const int *bios_tab[] = { - (int *) 0xc8000, (int *) 0xd0000, (int *) 0xd8000 }; - int i; - char tmp; - - tmp = inb(INFLED); - /* First, see if the DIP switch values are valid */ - /* The test of B7 may fail on some early boards, mine works. */ - if ( ((~tmp & 0x3) != index ) || (tmp & 0x80) || !(tmp & 0x4) ) - return 0; - printk("IN-2000 probe got dip setting of %02X\n", tmp); - tmp = inb(INVERS); -/* Add some extra sanity checks here */ - for(i=0; i < 3; i++) - if(*(bios_tab[i]+0x04) == 0x41564f4e || - *(bios_tab[i]+0xc) == 0x61776c41) { - printk("IN-2000 probe found hdw. vers. %02x, BIOS at %06x\n", - tmp, (unsigned int)bios_tab[i]); - return 1; - } - printk("in2000 BIOS not found.\n"); - return 0; -} - - -/* - * retrieve the current transaction counter from the WD - */ - -static unsigned in2000_txcnt(void) -{ - unsigned total=0; - - if(inb(INSTAT) & 0x20) return 0xffffff; /* not readable now */ - outb(TXCNTH,INSTAT); /* then autoincrement */ - total = (inb(INDATA) & 0xff) << 16; - outb(TXCNTM,INSTAT); - total += (inb(INDATA) & 0xff) << 8; - outb(TXCNTL,INSTAT); - total += (inb(INDATA) & 0xff); - return total; -} - -/* - * Note: the FIFO is screwy, and has a counter granularity of 16 bytes, so - * we have to reconcile the FIFO counter, the transaction byte count from the - * WD chip, and of course, our desired transaction size. It may look strange, - * and could probably use improvement, but it works, for now. - */ - -static void in2000_fifo_out(void) /* uses FIFOCNTR */ -{ - unsigned count, infcnt, txcnt; - - infcnt = inb(INFCNT)& 0xfe; /* FIFO counter */ - do { - txcnt = in2000_txcnt(); -/*DEB(printk("FIw:%d %02x %d\n", in2000_datalen, infcnt, txcnt));*/ - count = (infcnt << 3) - 32; /* don't fill completely */ - if ( count > in2000_datalen ) - count = in2000_datalen; /* limit to actual data on hand */ - count >>= 1; /* Words, not bytes */ -#ifdef FAST_FIFO_IO - if ( count ) { - port_write(INFIFO, in2000_dataptr, count); - in2000_datalen -= (count<<1); - } -#else - while ( count-- ) - { - outw(*in2000_dataptr++, INFIFO); - in2000_datalen -= 2; - } -#endif - } while((in2000_datalen > 0) && ((infcnt = (inb(INFCNT)) & 0xfe) >= 0x20) ); - /* If scatter-gather, go on to next segment */ - if( !in2000_datalen && ++in2000_current_segment < in2000_nsegment) - { - in2000_scatter++; - in2000_datalen = in2000_scatter->length; - in2000_dataptr = (unsigned short*)in2000_scatter->address; - } - if ( in2000_datalen <= 0 ) - { - ficmsk = 0; - count = 32; /* Always says to use this much flush */ - while ( count-- ) - outw(0, INFIFO); - outb(2, ININTR); /* Mask FIFO Interrupts when done */ - } -} - -static void in2000_fifo_in(void) /* uses FIFOCNTR */ -{ - unsigned fic, count, count2; - - count = inb(INFCNT) & 0xe1; - do{ - count2 = count; - count = (fic = inb(INFCNT)) & 0xe1; - } while ( count != count2 ); -DEB(printk("FIir:%d %02x %08x\n", in2000_datalen,fic,(unsigned int )in2000_dataptr)); - do { - count2 = in2000_txcnt(); /* bytes yet to come over SCSI bus */ -DEB(printk("FIr:%d %02x %08x %08x\n", in2000_datalen,fic,count2,(unsigned int)in2000_dataptr)); - if(count2 > 65536) count2 = 0; - if(fic > 128) count = 1024; - else if(fic > 64) count = 512; - else if (fic > 32) count = 256; - else if ( count2 < in2000_datalen ) /* if drive has < what we want */ - count = in2000_datalen - count2; /* FIFO has the rest */ - if ( count > in2000_datalen ) /* count2 is lesser of FIFO & rqst */ - count2 = in2000_datalen >> 1; /* converted to word count */ - else - count2 = count >> 1; - count >>= 1; /* also to words */ - count -= count2; /* extra left over in FIFO */ -#ifdef FAST_FIFO_IO - if ( count2 ) { - port_read(INFIFO, in2000_dataptr, count2); - in2000_datalen -= (count2<<1); - } -#else - while ( count2-- ) - { - *in2000_dataptr++ = inw(INFIFO); - in2000_datalen -=2; - } -#endif - } while((in2000_datalen > 0) && (fic = inb(INFCNT)) ); -DEB(printk("FIer:%d %02x %08x\n", in2000_datalen,fic,(unsigned int )in2000_dataptr)); -/* while ( count-- ) - inw(INFIFO);*/ /* Throw away some extra stuff */ - if( !in2000_datalen && ++in2000_current_segment < in2000_nsegment) - { - in2000_scatter++; - in2000_datalen = in2000_scatter->length; - in2000_dataptr = (unsigned short*)in2000_scatter->address; - } - if ( ! in2000_datalen ){ - outb(2, ININTR); /* Mask FIFO Interrupts when done */ - ficmsk = 0;} -} - -static void in2000_intr_handle(int irq, struct pt_regs *regs) -{ - int result=0; - unsigned int count,auxstatus,scsistatus,cmdphase,scsibyte; - int action=0; - Scsi_Cmnd *SCptr; - - DEB(printk("INT:%d %02x %08x\n", in2000_datalen, inb(INFCNT),(unsigned int)in2000_dataptr)); - - if (( (ficmsk & (count = inb(INFCNT))) == 0xfe ) || - ( (inb(INSTAT) & 0x8c) == 0x80)) - { /* FIFO interrupt or WD interrupt */ - auxstatus = inb(INSTAT); /* need to save now */ - outb(SCSIST,INSTAT); - scsistatus = inb(INDATA); /* This clears the WD intrpt bit */ - outb(TARGETU,INSTAT); /* then autoincrement */ - scsibyte = inb(INDATA); /* Get the scsi status byte */ - outb(CMDPHAS,INSTAT); - cmdphase = inb(INDATA); - DEB(printk("(int2000:%02x %02x %02x %02x %02x)\n",count,auxstatus, - scsistatus,cmdphase,scsibyte)); - - /* Why do we assume that we need to send more data here??? ERY */ - if ( in2000_datalen ) /* data xfer pending */ - { - if ( in2000_dataptr == NULL ) - printk("int2000: dataptr=NULL datalen=%d\n", - in2000_datalen); - else if ( in2000_datawrite ) - in2000_fifo_out(); - else - in2000_fifo_in(); - } - if ( (auxstatus & 0x8c) == 0x80 ) - { /* There is a WD Chip interrupt & register read good */ - outb(2,ININTR); /* Disable fifo interrupts */ - ficmsk = 0; - result = DID_OK << 16; - /* 16=Select & transfer complete, 85=got disconnect */ - if ((scsistatus != 0x16) && (scsistatus != 0x85) - && (scsistatus != 0x42)){ -/* printk("(WDi2000:%02x %02x %02x %02x %02x)\n",count,auxstatus, - scsistatus,cmdphase,scsibyte);*/ -/* printk("QDAT:%d %08x %02x\n", - in2000_datalen,(unsigned int)in2000_dataptr,ficmsk);*/ - ; - } - switch ( scsistatus & 0xf0 ) - { - case 0x00: /* Card Reset Completed */ - action = 3; - break; - case 0x10: /* Successful Command Completion */ - if ( scsistatus & 0x8 ) - action = 1; - break; - case 0x20: /* Command Paused or Aborted */ - if ( (scsistatus & 0x8) ) - action = 1; - else if ( (scsistatus & 7) < 2 ) - action = 2; - else - result = DID_ABORT << 16; - break; - case 0x40: /* Terminated early */ - if ( scsistatus & 0x8 ) - action = 1; - else if ( (scsistatus & 7) > 2 ) - action = 2; - else - result = DID_TIME_OUT << 16; - break; - case 0x80: /* Service Required from SCSI bus */ - if ( scsistatus & 0x8 ) - action = 1; - else - action = 2; - break; - } /* end switch(scsistatus) */ - outb(0,INFLED); - switch ( action ) - { - case 0x02: /* Issue an abort */ - outb(COMMAND,INSTAT); - outb(1,INDATA); /* ABORT COMMAND */ - result = DID_ABORT << 16; - case 0x00: /* Basically all done */ - if ( ! in2000_SCptr ) - return; - in2000_SCptr->result = result | scsibyte; - SCptr = in2000_SCptr; - in2000_SCptr = 0; - if ( in2000_done ) - (*in2000_done)(SCptr); - break; - case 0x01: /* We need to reissue a command */ - outb(CMDPHAS,INSTAT); - switch ( scsistatus & 7 ) - { - case 0: /* Data out phase */ - case 1: /* Data in phase */ - case 4: /* Unspec info out phase */ - case 5: /* Unspec info in phase */ - case 6: /* Message in phase */ - case 7: /* Message in phase */ - outb(0x41,INDATA); /* rdy to disconn */ - break; - case 2: /* command phase */ - outb(0x30,INDATA); /* rdy to send cmd bytes */ - break; - case 3: /* status phase */ - outb(0x45,INDATA); /* To go to status phase,*/ - outb(TXCNTH,INSTAT); /* elim. data, autoinc */ - outb(0,INDATA); - outb(0,INDATA); - outb(0,INDATA); - in2000_datalen = 0; - in2000_dataptr = 0; - break; - } /* end switch(scsistatus) */ - outb(COMMAND,INSTAT); - outb(8,INDATA); /* RESTART THE COMMAND */ - break; - case 0x03: /* Finish up a Card Reset */ - outb(TIMEOUT,INSTAT); /* I got these values */ - /* by reverse Engineering */ - outb(IN2000_TMOUT,INDATA); /* the Always' bios. */ - outb(CONTROL,INSTAT); - outb(0,INDATA); - outb(SYNCTXR,INSTAT); - outb(0x40,INDATA); /* async, 4 cyc xfer per. */ - break; - } /* end switch(action) */ - } /* end if auxstatus for WD int */ - } /* end while intrpt active */ -} - -int in2000_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) -{ - unchar direction; - unchar *cmd = (unchar *) SCpnt->cmnd; - unchar target = SCpnt->target; - void *buff = SCpnt->request_buffer; - unsigned long flags; - int bufflen = SCpnt->request_bufflen; - int timeout, size, loop; - int i; - - /* - * This SCSI command has no data phase, but unfortunately the mid-level - * SCSI drivers ask for 256 bytes of data xfer. Our card hangs if you - * do this, so we protect against it here. It would be nice if the mid- - * level could be changed, but who knows if that would break other host - * adapter drivers. - */ - if ( *cmd == TEST_UNIT_READY ) - bufflen = 0; - - /* - * What it looks like. Boy did I get tired of reading its output. - */ - if (*cmd == READ_10 || *cmd == WRITE_10) { - i = xscsi2int((cmd+1)); - } else if (*cmd == READ_6 || *cmd == WRITE_6) { - i = scsi2int((cmd+1)); - } else { - i = -1; - } -#ifdef DEBUG - printk("in2000qcmd: pos %d len %d ", i, bufflen); - printk("scsi cmd:"); - for (i = 0; i < SCpnt->cmd_len; i++) printk("%02x ", cmd[i]); - printk("\n"); -#endif - direction = 1; /* assume for most commands */ - if (*cmd == WRITE_10 || *cmd == WRITE_6) - direction = 0; - size = SCpnt->cmd_len; /* CDB length */ - /* - * Setup our current pointers - * This is where you would allocate a control structure in a queue, - * If you were going to upgrade this to do multiple issue. - * Note that datalen and dataptr exist because we can change the - * values during the course of the operation, while managing the - * FIFO. - * Note the nasty little first clause. In theory, the mid-level - * drivers should never hand us more than one command at a time, - * but just in case someone gets cute in configuring the driver, - * we'll protect them, although not very politely. - */ - if ( in2000_SCptr ) - { - printk("in2000_queue_command waiting for free command block!\n"); - while ( in2000_SCptr ) - barrier(); - } - for ( timeout = jiffies + 5; timeout > jiffies; ) - { - if ( ! ( inb(INSTAT) & 0xb0 ) ) - { - timeout = 0; - break; - } - else - { - inb(INSTAT); - outb(SCSIST,INSTAT); - inb(INDATA); - outb(TARGETU,INSTAT); /* then autoinc */ - inb(INDATA); - inb(INDATA); - } - } - if ( timeout ) - { - printk("in2000_queue_command timeout!\n"); - SCpnt->result = DID_TIME_OUT << 16; - (*done)(SCpnt); - return 1; - } - /* Added for scatter-gather support */ - in2000_nsegment = SCpnt->use_sg; - in2000_current_segment = 0; - if(SCpnt->use_sg){ - in2000_scatter = (struct scatterlist *) buff; - in2000_datalen = in2000_scatter->length; - in2000_dataptr = (unsigned short*)in2000_scatter->address; - } else { - in2000_scatter = NULL; - in2000_datalen = bufflen; - in2000_dataptr = (unsigned short*) buff; - }; - in2000_done = done; - in2000_SCptr = SCpnt; - /* - * Write the CDB to the card, then the LUN, the length, and the target. - */ - outb(TOTSECT, INSTAT); /* start here then autoincrement */ - for ( loop=0; loop < size; loop++ ) - outb(cmd[loop],INDATA); - outb(TARGETU,INSTAT); - outb(SCpnt->lun & 7,INDATA); - SCpnt->host_scribble = NULL; - outb(TXCNTH,INSTAT); /* then autoincrement */ - outb(bufflen>>16,INDATA); - outb(bufflen>>8,INDATA); - outb(bufflen,INDATA); - outb(target&7,INDATA); - /* - * Set up the FIFO - */ - save_flags(flags); - cli(); /* so FIFO init waits till WD set */ - outb(0,INFRST); - if ( direction == 1 ) - { - in2000_datawrite = 0; - outb(0,INFWRT); - } - else - { - in2000_datawrite = 1; - for ( loop=16; --loop; ) /* preload the outgoing fifo */ - { - outw(*in2000_dataptr++,INFIFO); - if(in2000_datalen > 0) in2000_datalen-=2; - } - } - ficmsk = 0xff; - /* - * Start it up - */ - outb(CONTROL,INSTAT); /* WD BUS Mode */ - outb(0x4C,INDATA); - if ( in2000_datalen ) /* if data xfer cmd */ - outb(0,ININTR); /* Enable FIFO intrpt some boards? */ - outb(COMMAND,INSTAT); - outb(0,INNLED); - outb(8,INDATA); /* Select w/ATN & Transfer */ - restore_flags(flags); /* let the intrpt rip */ - return 0; -} - -static volatile int internal_done_flag = 0; -static volatile int internal_done_errcode = 0; - -static void internal_done(Scsi_Cmnd * SCpnt) -{ - internal_done_errcode = SCpnt->result; - ++internal_done_flag; -} - -int in2000_command(Scsi_Cmnd * SCpnt) -{ - in2000_queuecommand(SCpnt, internal_done); - - while (!internal_done_flag); - internal_done_flag = 0; - return internal_done_errcode; -} - -int in2000_detect(Scsi_Host_Template * tpnt) -{ -/* Order chosen to reduce conflicts with some multi-port serial boards */ - int base_tab[] = { 0x220,0x200,0x110,0x100 }; - int int_tab[] = { 15,14,11,10 }; - struct Scsi_Host * shpnt; - int loop, tmp; - - DEB(printk("in2000_detect: \n")); - - tpnt->proc_dir = &proc_scsi_in2000; - - for ( loop=0; loop < 4; loop++ ) - { - base = base_tab[loop]; - if ( in2000_test_port(loop)) break; - } - if ( loop == 4 ) - return 0; - - /* Read the dip switch values again for miscellaneous checking and - informative messages */ - tmp = inb(INFLED); - - /* Bit 2 tells us if interrupts are disabled */ - if ( (tmp & 0x4) == 0 ) { - printk("The IN-2000 is not configured for interrupt operation\n"); - printk("Change the DIP switch settings to enable interrupt operation\n"); - } - - /* Bit 6 tells us about floppy controller */ - printk("IN-2000 probe found floppy controller on IN-2000 "); - if ( (tmp & 0x40) == 0) - printk("enabled\n"); - else - printk("disabled\n"); - - /* Bit 5 tells us about synch/asynch mode */ - printk("IN-2000 probe found IN-2000 in "); - if ( (tmp & 0x20) == 0) - printk("synchronous mode\n"); - else - printk("asynchronous mode\n"); - - irq_level = int_tab [ ((~inb(INFLED)>>3)&0x3) ]; - - printk("Configuring IN2000 at IO:%x, IRQ %d" -#ifdef FAST_FIFO_IO - " (using fast FIFO I/O code)" -#endif - "\n",base, irq_level); - - outb(2,ININTR); /* Shut off the FIFO first, so it won't ask for data.*/ - if (request_irq(irq_level,in2000_intr_handle, 0, "in2000")) - { - printk("in2000_detect: Unable to allocate IRQ.\n"); - return 0; - } - outb(0,INFWRT); /* read mode so WD can intrpt */ - outb(SCSIST,INSTAT); - inb(INDATA); /* free status reg, clear WD intrpt */ - outb(OWNID,INSTAT); - outb(0x7,INDATA); /* we use addr 7 */ - outb(COMMAND,INSTAT); - outb(0,INDATA); /* do chip reset */ - shpnt = scsi_register(tpnt, 0); - /* Set these up so that we can unload the driver properly. */ - shpnt->io_port = base; - shpnt->n_io_port = 12; - shpnt->irq = irq_level; - request_region(base, 12,"in2000"); /* Prevent other drivers from using this space */ - return 1; -} - -int in2000_abort(Scsi_Cmnd * SCpnt) -{ - DEB(printk("in2000_abort\n")); - /* - * Ask no stupid questions, just order the abort. - */ - outb(COMMAND,INSTAT); - outb(1,INDATA); /* Abort Command */ - return 0; -} - -static inline void delay( unsigned how_long ) -{ - unsigned long time = jiffies + how_long; - while (jiffies < time) ; -} - -int in2000_reset(Scsi_Cmnd * SCpnt) -{ - DEB(printk("in2000_reset called\n")); - /* - * Note: this is finished off by an incoming interrupt - */ - outb(0,INFWRT); /* read mode so WD can intrpt */ - outb(SCSIST,INSTAT); - inb(INDATA); - outb(OWNID,INSTAT); - outb(0x7,INDATA); /* ID=7,noadv, no parity, clk div=2 (8-10Mhz clk) */ - outb(COMMAND,INSTAT); - outb(0,INDATA); /* reset WD chip */ - delay(2); -#ifdef SCSI_RESET_PENDING - return SCSI_RESET_PENDING; -#else - if(SCpnt) SCpnt->flags |= NEEDS_JUMPSTART; - return 0; -#endif -} - -int in2000_biosparam(Disk * disk, kdev_t dev, int* iinfo) - { - int size = disk->capacity; - DEB(printk("in2000_biosparam\n")); - iinfo[0] = 64; - iinfo[1] = 32; - iinfo[2] = size >> 11; -/* This should approximate the large drive handling that the DOS ASPI manager - uses. Drives very near the boundaries may not be handled correctly (i.e. - near 2.0 Gb and 4.0 Gb) */ - if (iinfo[2] > 1024) { - iinfo[0] = 64; - iinfo[1] = 63; - iinfo[2] = disk->capacity / (iinfo[0] * iinfo[1]); - } - if (iinfo[2] > 1024) { - iinfo[0] = 128; - iinfo[1] = 63; - iinfo[2] = disk->capacity / (iinfo[0] * iinfo[1]); - } - if (iinfo[2] > 1024) { - iinfo[0] = 255; - iinfo[1] = 63; - iinfo[2] = disk->capacity / (iinfo[0] * iinfo[1]); - if (iinfo[2] > 1023) - iinfo[2] = 1023; - } - return 0; - } - -#ifdef MODULE -/* Eventually this will go into an include file, but this will be later */ -Scsi_Host_Template driver_template = IN2000; - -#include "scsi_module.c" -#endif - diff --git a/i386/i386at/gpl/linux/scsi/in2000.h b/i386/i386at/gpl/linux/scsi/in2000.h deleted file mode 100644 index cf68db7f..00000000 --- a/i386/i386at/gpl/linux/scsi/in2000.h +++ /dev/null @@ -1,122 +0,0 @@ -#ifndef _IN2000_H - -/* $Id: in2000.h,v 1.1.1.1 1997/02/25 21:27:50 thomas Exp $ - * - * Header file for the Always IN 2000 driver for Linux - * - */ - -#include <linux/types.h> -#include <linux/ioport.h> - -/* The IN-2000 is based on a WD33C93 */ - -#define INSTAT (base + 0x0) /* R: Auxiliary Status; W: register select */ -#define INDATA (base + 0x1) /* R/W: Data port */ -#define INFIFO (base + 0x2) /* R/W FIFO, Word access only */ -#define INREST (base + 0x3) /* W: Reset everything */ -#define INFCNT (base + 0x4) /* R: FIFO byte count */ -#define INFRST (base + 0x5) /* W: Reset Fifo count and to write */ -#define INFWRT (base + 0x7) /* W: Set FIFO to read */ -#define INFLED (base + 0x8) /* W: Set LED; R: Dip Switch settings */ -#define INNLED (base + 0x9) /* W: reset LED */ -#define INVERS (base + 0xa) /* R: Read hw version, end-reset */ -#define ININTR (base + 0xc) /* W: Interrupt Mask Port */ -#define G2CNTRL_HRDY 0x20 /* Sets HOST ready */ - -/* WD33C93 defines */ -#define OWNID 0 -#undef CONTROL -#define CONTROL 1 -#define TIMEOUT 2 -#define TOTSECT 3 -#define TOTHEAD 4 -#define TOTCYLH 5 -#define TOTCYLL 6 -#define LADRSHH 7 -#define LADRSHL 8 -#define LADRSLH 9 -#define LADRSLL 10 -#define SECTNUM 11 -#define HEADNUM 12 -#define CYLNUMH 13 -#define CYLNUML 14 -#define TARGETU 15 -#define CMDPHAS 16 -#define SYNCTXR 17 -#define TXCNTH 18 -#define TXCNTM 19 -#define TXCNTL 20 -#define DESTID 21 -#define SRCID 22 -#define SCSIST 23 -#define COMMAND 24 -#define WDDATA 25 -#define AUXSTAT 31 - -/* OWNID Register Bits */ -#define OWN_EAF 0x08 -#define OWN_EHP 0x10 -#define OWN_FS0 0x40 -#define OWN_FS1 0x80 -/* AUX Register Bits */ -#define AUX_DBR 0 -#define AUX_PE 1 -#define AUX_CIP 0x10 -#define AUX_BSY 0x20 -#define AUX_LCI 0x40 -#define AUX_INT 0x80 - -/* Select timeout const, 1 count = 8ms */ -#define IN2000_TMOUT 0x1f - -/* These belong in scsi.h also */ -#undef any2scsi -#define any2scsi(up, p) \ -(up)[0] = (((unsigned long)(p)) >> 16); \ -(up)[1] = (((unsigned long)(p)) >> 8); \ -(up)[2] = ((unsigned long)(p)); - -#undef scsi2int -#define scsi2int(up) ( ((((long)*(up))&0x1f) << 16) + (((long)(up)[1]) << 8) + ((long)(up)[2]) ) - -#undef xany2scsi -#define xany2scsi(up, p) \ -(up)[0] = ((long)(p)) >> 24; \ -(up)[1] = ((long)(p)) >> 16; \ -(up)[2] = ((long)(p)) >> 8; \ -(up)[3] = ((long)(p)); - -#define xscsi2int(up) ( (((long)(up)[0]) << 24) + (((long)(up)[1]) << 16) \ - + (((long)(up)[2]) << 8) + ((long)(up)[3]) ) - -#define MAX_CDB 12 -#define MAX_SENSE 14 -#define MAX_STATUS 32 - -int in2000_detect(Scsi_Host_Template *); -int in2000_command(Scsi_Cmnd *); -int in2000_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); -int in2000_abort(Scsi_Cmnd *); -int in2000_reset(Scsi_Cmnd *); -int in2000_biosparam(Disk *, kdev_t, int*); - -#ifndef NULL - #define NULL 0 -#endif - - -/* next may be "SG_NONE" or "SG_ALL" or nr. of (1k) blocks per R/W Cmd. */ -#define IN2000_SG SG_ALL -#define IN2000 {NULL, NULL, \ - NULL, NULL, \ - "Always IN2000", in2000_detect, NULL, \ - NULL, in2000_command, \ - in2000_queuecommand, \ - in2000_abort, \ - in2000_reset, \ - NULL, \ - in2000_biosparam, \ - 1, 7, IN2000_SG, 1, 0, 0} - -#endif diff --git a/i386/i386at/gpl/linux/scsi/pas16.c b/i386/i386at/gpl/linux/scsi/pas16.c deleted file mode 100644 index 9f5d8826..00000000 --- a/i386/i386at/gpl/linux/scsi/pas16.c +++ /dev/null @@ -1,553 +0,0 @@ -#define AUTOSENSE -#define PSEUDO_DMA -#define FOO -#define UNSAFE /* Not unsafe for PAS16 -- use it */ - -/* - * This driver adapted from Drew Eckhardt's Trantor T128 driver - * - * Copyright 1993, Drew Eckhardt - * Visionary Computing - * (Unix and Linux consulting and custom programming) - * drew@colorado.edu - * +1 (303) 666-5836 - * - * ( Based on T128 - DISTRIBUTION RELEASE 3. ) - * - * Modified to work with the Pro Audio Spectrum/Studio 16 - * by John Weidman. - * - * - * For more information, please consult - * - * Media Vision - * (510) 770-8600 - * (800) 348-7116 - * - * and - * - * NCR 5380 Family - * SCSI Protocol Controller - * Databook - * - * NCR Microelectronics - * 1635 Aeroplaza Drive - * Colorado Springs, CO 80916 - * 1+ (719) 578-3400 - * 1+ (800) 334-5454 - */ - -/* - * Options : - * AUTOSENSE - if defined, REQUEST SENSE will be performed automatically - * for commands that return with a CHECK CONDITION status. - * - * LIMIT_TRANSFERSIZE - if defined, limit the pseudo-dma transfers to 512 - * bytes at a time. Since interrupts are disabled by default during - * these transfers, we might need this to give reasonable interrupt - * service time if the transfer size gets too large. - * - * PSEUDO_DMA - enables PSEUDO-DMA hardware, should give a 3-4X performance - * increase compared to polled I/O. - * - * PARITY - enable parity checking. Not supported. - * - * SCSI2 - enable support for SCSI-II tagged queueing. Untested. - * - * UNSAFE - leave interrupts enabled during pseudo-DMA transfers. This - * parameter comes from the NCR5380 code. It is NOT unsafe with - * the PAS16 and you should use it. If you don't you will have - * a problem with dropped characters during high speed - * communications during SCSI transfers. If you really don't - * want to use UNSAFE you can try defining LIMIT_TRANSFERSIZE or - * twiddle with the transfer size in the high level code. - * - * USLEEP - enable support for devices that don't disconnect. Untested. - * - * The card is detected and initialized in one of several ways : - * 1. Autoprobe (default) - There are many different models of - * the Pro Audio Spectrum/Studio 16, and I only have one of - * them, so this may require a little tweaking. An interrupt - * is triggered to autoprobe for the interrupt line. Note: - * with the newer model boards, the interrupt is set via - * software after reset using the default_irq for the - * current board number. - * - * - * 2. With command line overrides - pas16=port,irq may be - * used on the LILO command line to override the defaults. - * - * 3. With the PAS16_OVERRIDE compile time define. This is - * specified as an array of address, irq tuples. Ie, for - * one board at the default 0x388 address, IRQ10, I could say - * -DPAS16_OVERRIDE={{0x388, 10}} - * NOTE: Untested. - * - * Note that if the override methods are used, place holders must - * be specified for other boards in the system. - * - * - * Configuration notes : - * The current driver does not support interrupt sharing with the - * sound portion of the card. If you use the same irq for the - * scsi port and sound you will have problems. Either use - * a different irq for the scsi port or don't use interrupts - * for the scsi port. - * - * If you have problems with your card not being recognized, use - * the LILO command line override. Try to get it recognized without - * interrupts. Ie, for a board at the default 0x388 base port, - * boot: linux pas16=0x388,255 - * - * (255 is the IRQ_NONE constant in NCR5380.h) - */ - -#ifdef MODULE -#include <linux/module.h> -#endif - -#include <asm/system.h> -#include <linux/signal.h> -#include <linux/proc_fs.h> -#include <linux/sched.h> -#include <asm/io.h> -#include <linux/blk.h> -#include "scsi.h" -#include "hosts.h" -#include "pas16.h" -#define AUTOPROBE_IRQ -#include "NCR5380.h" -#include "constants.h" -#include "sd.h" - -#include<linux/stat.h> - -struct proc_dir_entry proc_scsi_pas16 = { - PROC_SCSI_PAS16, 5, "pas16", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - -int scsi_irq_translate[] = - { 0, 0, 1, 2, 3, 4, 5, 6, 0, 0, 7, 8, 9, 0, 10, 11 }; - -/* The default_irqs array contains values used to set the irq into the - * board via software (as must be done on newer model boards without - * irq jumpers on the board). The first value in the array will be - * assigned to logical board 0, the next to board 1, etc. - */ -int default_irqs[] = { PAS16_DEFAULT_BOARD_1_IRQ, - PAS16_DEFAULT_BOARD_2_IRQ, - PAS16_DEFAULT_BOARD_3_IRQ, - PAS16_DEFAULT_BOARD_4_IRQ - }; - -static struct override { - unsigned short io_port; - int irq; -} overrides -#ifdef PAS16_OVERRIDE - [] = PAS16_OVERRIDE; -#else - [4] = {{0,IRQ_AUTO}, {0,IRQ_AUTO}, {0,IRQ_AUTO}, - {0,IRQ_AUTO}}; -#endif - -#define NO_OVERRIDES (sizeof(overrides) / sizeof(struct override)) - -static struct base { - unsigned short io_port; - int noauto; -} bases[] = { {PAS16_DEFAULT_BASE_1, 0}, - {PAS16_DEFAULT_BASE_2, 0}, - {PAS16_DEFAULT_BASE_3, 0}, - {PAS16_DEFAULT_BASE_4, 0} - }; - -#define NO_BASES (sizeof (bases) / sizeof (struct base)) - -unsigned short pas16_offset[ 8 ] = - { - 0x1c00, /* OUTPUT_DATA_REG */ - 0x1c01, /* INITIATOR_COMMAND_REG */ - 0x1c02, /* MODE_REG */ - 0x1c03, /* TARGET_COMMAND_REG */ - 0x3c00, /* STATUS_REG ro, SELECT_ENABLE_REG wo */ - 0x3c01, /* BUS_AND_STATUS_REG ro, START_DMA_SEND_REG wo */ - 0x3c02, /* INPUT_DATA_REGISTER ro, (N/A on PAS16 ?) - * START_DMA_TARGET_RECEIVE_REG wo - */ - 0x3c03, /* RESET_PARITY_INTERRUPT_REG ro, - * START_DMA_INITIATOR_RECEIVE_REG wo - */ - }; - - - -/* - * Function : enable_board( int board_num, unsigned short port ) - * - * Purpose : set address in new model board - * - * Inputs : board_num - logical board number 0-3, port - base address - * - */ - -void enable_board( int board_num, unsigned short port ) -{ - outb( 0xbc + board_num, MASTER_ADDRESS_PTR ); - outb( port >> 2, MASTER_ADDRESS_PTR ); -} - - - -/* - * Function : init_board( unsigned short port, int irq ) - * - * Purpose : Set the board up to handle the SCSI interface - * - * Inputs : port - base address of the board, - * irq - irq to assign to the SCSI port - * force_irq - set it even if it conflicts with sound driver - * - */ - -void init_board( unsigned short io_port, int irq, int force_irq ) -{ - unsigned int tmp; - unsigned int pas_irq_code; - - /* Initialize the SCSI part of the board */ - - outb( 0x30, io_port + P_TIMEOUT_COUNTER_REG ); /* Timeout counter */ - outb( 0x01, io_port + P_TIMEOUT_STATUS_REG_OFFSET ); /* Reset TC */ - outb( 0x01, io_port + WAIT_STATE ); /* 1 Wait state */ - - NCR5380_read( RESET_PARITY_INTERRUPT_REG ); - - /* Set the SCSI interrupt pointer without mucking up the sound - * interrupt pointer in the same byte. - */ - pas_irq_code = ( irq < 16 ) ? scsi_irq_translate[irq] : 0; - tmp = inb( io_port + IO_CONFIG_3 ); - - if( (( tmp & 0x0f ) == pas_irq_code) && pas_irq_code > 0 - && !force_irq ) - { - printk( "pas16: WARNING: Can't use same irq as sound " - "driver -- interrupts disabled\n" ); - /* Set up the drive parameters, disable 5380 interrupts */ - outb( 0x4d, io_port + SYS_CONFIG_4 ); - } - else - { - tmp = ( tmp & 0x0f ) | ( pas_irq_code << 4 ); - outb( tmp, io_port + IO_CONFIG_3 ); - - /* Set up the drive parameters and enable 5380 interrupts */ - outb( 0x6d, io_port + SYS_CONFIG_4 ); - } -} - - -/* - * Function : pas16_hw_detect( unsigned short board_num ) - * - * Purpose : determine if a pas16 board is present - * - * Inputs : board_num - logical board number ( 0 - 3 ) - * - * Returns : 0 if board not found, 1 if found. - */ - -int pas16_hw_detect( unsigned short board_num ) -{ - unsigned char board_rev, tmp; - unsigned short io_port = bases[ board_num ].io_port; - - /* See if we can find a PAS16 board at the address associated - * with this logical board number. - */ - - /* First, attempt to take a newer model board out of reset and - * give it a base address. This shouldn't affect older boards. - */ - enable_board( board_num, io_port ); - - /* Now see if it looks like a PAS16 board */ - board_rev = inb( io_port + PCB_CONFIG ); - - if( board_rev == 0xff ) - return 0; - - tmp = board_rev ^ 0xe0; - - outb( tmp, io_port + PCB_CONFIG ); - tmp = inb( io_port + PCB_CONFIG ); - outb( board_rev, io_port + PCB_CONFIG ); - - if( board_rev != tmp ) /* Not a PAS-16 */ - return 0; - - if( ( inb( io_port + OPERATION_MODE_1 ) & 0x03 ) != 0x03 ) - return 0; /* return if no SCSI interface found */ - - /* Mediavision has some new model boards that return ID bits - * that indicate a SCSI interface, but they're not (LMS). We'll - * put in an additional test to try and weed them out. - */ - - outb( 0x01, io_port + WAIT_STATE ); /* 1 Wait state */ - NCR5380_write( MODE_REG, 0x20 ); /* Is it really SCSI? */ - if( NCR5380_read( MODE_REG ) != 0x20 ) /* Write to a reg. */ - return 0; /* and try to read */ - NCR5380_write( MODE_REG, 0x00 ); /* it back. */ - if( NCR5380_read( MODE_REG ) != 0x00 ) - return 0; - - return 1; -} - - -/* - * Function : pas16_setup(char *str, int *ints) - * - * Purpose : LILO command line initialization of the overrides array, - * - * Inputs : str - unused, ints - array of integer parameters with ints[0] - * equal to the number of ints. - * - */ - -void pas16_setup(char *str, int *ints) { - static int commandline_current = 0; - int i; - if (ints[0] != 2) - printk("pas16_setup : usage pas16=io_port,irq\n"); - else - if (commandline_current < NO_OVERRIDES) { - overrides[commandline_current].io_port = (unsigned short) ints[1]; - overrides[commandline_current].irq = ints[2]; - for (i = 0; i < NO_BASES; ++i) - if (bases[i].io_port == (unsigned short) ints[1]) { - bases[i].noauto = 1; - break; - } - ++commandline_current; - } -} - -/* - * Function : int pas16_detect(Scsi_Host_Template * tpnt) - * - * Purpose : detects and initializes PAS16 controllers - * that were autoprobed, overridden on the LILO command line, - * or specified at compile time. - * - * Inputs : tpnt - template for this SCSI adapter. - * - * Returns : 1 if a host adapter was found, 0 if not. - * - */ - -int pas16_detect(Scsi_Host_Template * tpnt) { - static int current_override = 0; - static unsigned short current_base = 0; - struct Scsi_Host *instance; - unsigned short io_port; - int count; - - tpnt->proc_dir = &proc_scsi_pas16; - - for (count = 0; current_override < NO_OVERRIDES; ++current_override) { - io_port = 0; - - if (overrides[current_override].io_port) - { - io_port = overrides[current_override].io_port; - enable_board( current_override, io_port ); - init_board( io_port, overrides[current_override].irq, 1 ); - } - else - for (; !io_port && (current_base < NO_BASES); ++current_base) { -#if (PDEBUG & PDEBUG_INIT) - printk("scsi-pas16 : probing io_port %04x\n", (unsigned int) bases[current_base].io_port); -#endif - if ( !bases[current_base].noauto && - pas16_hw_detect( current_base ) ){ - io_port = bases[current_base].io_port; - init_board( io_port, default_irqs[ current_base ], 0 ); -#if (PDEBUG & PDEBUG_INIT) - printk("scsi-pas16 : detected board.\n"); -#endif - } - } - - -#if defined(PDEBUG) && (PDEBUG & PDEBUG_INIT) - printk("scsi-pas16 : io_port = %04x\n", (unsigned int) io_port); -#endif - - if (!io_port) - break; - - instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata)); - instance->io_port = io_port; - - NCR5380_init(instance, 0); - - if (overrides[current_override].irq != IRQ_AUTO) - instance->irq = overrides[current_override].irq; - else - instance->irq = NCR5380_probe_irq(instance, PAS16_IRQS); - - if (instance->irq != IRQ_NONE) - if (request_irq(instance->irq, pas16_intr, SA_INTERRUPT, "pas16")) { - printk("scsi%d : IRQ%d not free, interrupts disabled\n", - instance->host_no, instance->irq); - instance->irq = IRQ_NONE; - } - - if (instance->irq == IRQ_NONE) { - printk("scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no); - printk("scsi%d : please jumper the board for a free IRQ.\n", instance->host_no); - /* Disable 5380 interrupts, leave drive params the same */ - outb( 0x4d, io_port + SYS_CONFIG_4 ); - outb( (inb(io_port + IO_CONFIG_3) & 0x0f), io_port + IO_CONFIG_3 ); - } - -#if defined(PDEBUG) && (PDEBUG & PDEBUG_INIT) - printk("scsi%d : irq = %d\n", instance->host_no, instance->irq); -#endif - - printk("scsi%d : at 0x%04x", instance->host_no, (int) - instance->io_port); - if (instance->irq == IRQ_NONE) - printk (" interrupts disabled"); - else - printk (" irq %d", instance->irq); - printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d", - CAN_QUEUE, CMD_PER_LUN, PAS16_PUBLIC_RELEASE); - NCR5380_print_options(instance); - printk("\n"); - - ++current_override; - ++count; - } - return count; -} - -/* - * Function : int pas16_biosparam(Disk *disk, kdev_t dev, int *ip) - * - * Purpose : Generates a BIOS / DOS compatible H-C-S mapping for - * the specified device / size. - * - * Inputs : size = size of device in sectors (512 bytes), dev = block device - * major / minor, ip[] = {heads, sectors, cylinders} - * - * Returns : always 0 (success), initializes ip - * - */ - -/* - * XXX Most SCSI boards use this mapping, I could be incorrect. Some one - * using hard disks on a trantor should verify that this mapping corresponds - * to that used by the BIOS / ASPI driver by running the linux fdisk program - * and matching the H_C_S coordinates to what DOS uses. - */ - -int pas16_biosparam(Disk * disk, kdev_t dev, int * ip) -{ - int size = disk->capacity; - ip[0] = 64; - ip[1] = 32; - ip[2] = size >> 11; /* I think I have it as /(32*64) */ - if( ip[2] > 1024 ) { /* yes, >, not >= */ - ip[0]=255; - ip[1]=63; - ip[2]=size/(63*255); - if( ip[2] > 1023 ) /* yes >1023... */ - ip[2] = 1023; - } - - return 0; -} - -/* - * Function : int NCR5380_pread (struct Scsi_Host *instance, - * unsigned char *dst, int len) - * - * Purpose : Fast 5380 pseudo-dma read function, transfers len bytes to - * dst - * - * Inputs : dst = destination, len = length in bytes - * - * Returns : 0 on success, non zero on a failure such as a watchdog - * timeout. - */ - -static inline int NCR5380_pread (struct Scsi_Host *instance, unsigned char *dst, - int len) { - register unsigned char *d = dst; - register unsigned short reg = (unsigned short) (instance->io_port + - P_DATA_REG_OFFSET); - register i = len; - - while ( !(inb(instance->io_port + P_STATUS_REG_OFFSET) & P_ST_RDY) ); - - insb( reg, d, i ); - - if ( inb(instance->io_port + P_TIMEOUT_STATUS_REG_OFFSET) & P_TS_TIM) { - outb( P_TS_CT, instance->io_port + P_TIMEOUT_STATUS_REG_OFFSET); - printk("scsi%d : watchdog timer fired in NCR5380_pread()\n", - instance->host_no); - return -1; - } else - return 0; -} - -/* - * Function : int NCR5380_pwrite (struct Scsi_Host *instance, - * unsigned char *src, int len) - * - * Purpose : Fast 5380 pseudo-dma write function, transfers len bytes from - * src - * - * Inputs : src = source, len = length in bytes - * - * Returns : 0 on success, non zero on a failure such as a watchdog - * timeout. - */ - -static inline int NCR5380_pwrite (struct Scsi_Host *instance, unsigned char *src, - int len) { - register unsigned char *s = src; - register unsigned short reg = (instance->io_port + P_DATA_REG_OFFSET); - register i = len; - - while ( !((inb(instance->io_port + P_STATUS_REG_OFFSET)) & P_ST_RDY) ); - - outsb( reg, s, i ); - - if (inb(instance->io_port + P_TIMEOUT_STATUS_REG_OFFSET) & P_TS_TIM) { - outb( P_TS_CT, instance->io_port + P_TIMEOUT_STATUS_REG_OFFSET); - printk("scsi%d : watchdog timer fired in NCR5380_pwrite()\n", - instance->host_no); - return -1; - } else - return 0; -} - -#ifdef MACH -#include "NCR5380.src" -#else -#include "NCR5380.c" -#endif - -#ifdef MODULE -/* Eventually this will go into an include file, but this will be later */ -Scsi_Host_Template driver_template = MV_PAS16; - -#include <linux/module.h> -#include "scsi_module.c" -#endif diff --git a/i386/i386at/gpl/linux/scsi/pas16.h b/i386/i386at/gpl/linux/scsi/pas16.h deleted file mode 100644 index 9733792b..00000000 --- a/i386/i386at/gpl/linux/scsi/pas16.h +++ /dev/null @@ -1,193 +0,0 @@ -/* - * This driver adapted from Drew Eckhardt's Trantor T128 driver - * - * Copyright 1993, Drew Eckhardt - * Visionary Computing - * (Unix and Linux consulting and custom programming) - * drew@colorado.edu - * +1 (303) 666-5836 - * - * ( Based on T128 - DISTRIBUTION RELEASE 3. ) - * - * Modified to work with the Pro Audio Spectrum/Studio 16 - * by John Weidman. - * - * - * For more information, please consult - * - * Media Vision - * (510) 770-8600 - * (800) 348-7116 - * - * and - * - * NCR 5380 Family - * SCSI Protocol Controller - * Databook - * - * NCR Microelectronics - * 1635 Aeroplaza Drive - * Colorado Springs, CO 80916 - * 1+ (719) 578-3400 - * 1+ (800) 334-5454 - */ - - -#ifndef PAS16_H -#define PAS16_H - -#define PAS16_PUBLIC_RELEASE 3 - -#define PDEBUG_INIT 0x1 -#define PDEBUG_TRANSFER 0x2 - -#define PAS16_DEFAULT_BASE_1 0x388 -#define PAS16_DEFAULT_BASE_2 0x384 -#define PAS16_DEFAULT_BASE_3 0x38c -#define PAS16_DEFAULT_BASE_4 0x288 - -#define PAS16_DEFAULT_BOARD_1_IRQ 10 -#define PAS16_DEFAULT_BOARD_2_IRQ 12 -#define PAS16_DEFAULT_BOARD_3_IRQ 14 -#define PAS16_DEFAULT_BOARD_4_IRQ 15 - - -/* - * The Pro Audio Spectrum boards are I/O mapped. They use a Zilog 5380 - * SCSI controller, which is the equivalent of NCR's 5380. "Pseudo-DMA" - * architecture is used, where a PAL drives the DMA signals on the 5380 - * allowing fast, blind transfers with proper handshaking. - */ - - -/* The Time-out Counter register is used to safe-guard against a stuck - * bus (in the case of RDY driven handshake) or a stuck byte (if 16-Bit - * DMA conversion is used). The counter uses a 28.224MHz clock - * divided by 14 as its clock source. In the case of a stuck byte in - * the holding register, an interrupt is generated (and mixed with the - * one with the drive) using the CD-ROM interrupt pointer. - */ - -#define P_TIMEOUT_COUNTER_REG 0x4000 -#define P_TC_DISABLE 0x80 /* Set to 0 to enable timeout int. */ - /* Bits D6-D0 contain timeout count */ - - -#define P_TIMEOUT_STATUS_REG_OFFSET 0x4001 -#define P_TS_TIM 0x80 /* check timeout status */ - /* Bits D6-D4 N/U */ -#define P_TS_ARM_DRQ_INT 0x08 /* Arm DRQ Int. When set high, - * the next rising edge will - * cause a CD-ROM interrupt. - * When set low, the interrupt - * will be cleared. There is - * no status available for - * this interrupt. - */ -#define P_TS_ENABLE_TO_ERR_INTERRUPT /* Enable timeout error int. */ -#define P_TS_ENABLE_WAIT /* Enable Wait */ - -#define P_TS_CT 0x01 /* clear timeout. Note: writing - * to this register clears the - * timeout error int. or status - */ - - -/* - * The data register reads/writes to/from the 5380 in pseudo-DMA mode - */ - -#define P_DATA_REG_OFFSET 0x5c00 /* rw */ - -#define P_STATUS_REG_OFFSET 0x5c01 /* ro */ -#define P_ST_RDY 0x80 /* 5380 DDRQ Status */ - -#define P_IRQ_STATUS 0x5c03 -#define P_IS_IRQ 0x80 /* DIRQ status */ - -#define PCB_CONFIG 0x803 -#define MASTER_ADDRESS_PTR 0x9a01 /* Fixed position - no relo */ -#define SYS_CONFIG_4 0x8003 -#define WAIT_STATE 0xbc00 -#define OPERATION_MODE_1 0xec03 -#define IO_CONFIG_3 0xf002 - - -#ifndef ASM -int pas16_abort(Scsi_Cmnd *); -int pas16_biosparam(Disk *, kdev_t, int*); -int pas16_detect(Scsi_Host_Template *); -int pas16_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); -int pas16_reset(Scsi_Cmnd *); - -#ifndef NULL -#define NULL 0 -#endif - -#ifndef CMD_PER_LUN -#define CMD_PER_LUN 2 -#endif - -#ifndef CAN_QUEUE -#define CAN_QUEUE 32 -#endif - -/* - * I hadn't thought of this with the earlier drivers - but to prevent - * macro definition conflicts, we shouldn't define all of the internal - * macros when this is being used solely for the host stub. - */ - -#if defined(HOSTS_C) || defined(MODULE) - -#define MV_PAS16 {NULL, NULL, NULL, NULL, \ - "Pro Audio Spectrum-16 SCSI", \ - pas16_detect, NULL, NULL, \ - NULL, pas16_queue_command, pas16_abort, pas16_reset, NULL, \ - pas16_biosparam, \ - /* can queue */ CAN_QUEUE, /* id */ 7, SG_ALL, \ - /* cmd per lun */ CMD_PER_LUN , 0, 0, DISABLE_CLUSTERING} - -#endif -#ifndef HOSTS_C - -#define NCR5380_implementation_fields \ - volatile unsigned short io_port - -#define NCR5380_local_declare() \ - volatile unsigned short io_port - -#define NCR5380_setup(instance) \ - io_port = (instance)->io_port - -#define PAS16_io_port(reg) ( io_port + pas16_offset[(reg)] ) - -#if !(PDEBUG & PDEBUG_TRANSFER) -#define NCR5380_read(reg) ( inb(PAS16_io_port(reg)) ) -#define NCR5380_write(reg, value) ( outb((value),PAS16_io_port(reg)) ) -#else -#define NCR5380_read(reg) \ - (((unsigned char) printk("scsi%d : read register %d at io_port %04x\n"\ - , instance->hostno, (reg), PAS16_io_port(reg))), inb( PAS16_io_port(reg)) ) - -#define NCR5380_write(reg, value) \ - (printk("scsi%d : write %02x to register %d at io_port %04x\n", \ - instance->hostno, (value), (reg), PAS16_io_port(reg)), \ - outb( (value),PAS16_io_port(reg) ) ) - -#endif - - -#define NCR5380_intr pas16_intr -#define NCR5380_queue_command pas16_queue_command -#define NCR5380_abort pas16_abort -#define NCR5380_reset pas16_reset - -/* 15 14 12 10 7 5 3 - 1101 0100 1010 1000 */ - -#define PAS16_IRQS 0xd4a8 - -#endif /* else def HOSTS_C */ -#endif /* ndef ASM */ -#endif /* PAS16_H */ diff --git a/i386/i386at/gpl/linux/scsi/qlogic.c b/i386/i386at/gpl/linux/scsi/qlogic.c deleted file mode 100644 index 8333275b..00000000 --- a/i386/i386at/gpl/linux/scsi/qlogic.c +++ /dev/null @@ -1,678 +0,0 @@ -/*----------------------------------------------------------------*/ -/* - Qlogic linux driver - work in progress. No Warranty express or implied. - Use at your own risk. Support Tort Reform so you won't have to read all - these silly disclaimers. - - Copyright 1994, Tom Zerucha. - zerucha@shell.portal.com - - Additional Code, and much appreciated help by - Michael A. Griffith - grif@cs.ucr.edu - - Thanks to Eric Youngdale and Dave Hinds for loadable module and PCMCIA - help respectively, and for suffering through my foolishness during the - debugging process. - - Reference Qlogic FAS408 Technical Manual, 53408-510-00A, May 10, 1994 - (you can reference it, but it is incomplete and inaccurate in places) - - Version 0.43 4/6/95 - kernel 1.2.0+, pcmcia 2.5.4+ - - Functions as standalone, loadable, and PCMCIA driver, the latter from - Dave Hind's PCMCIA package. - - Redistributable under terms of the GNU Public License - -*/ -/*----------------------------------------------------------------*/ -/* Configuration */ - -/* Set the following to 2 to use normal interrupt (active high/totempole- - tristate), otherwise use 0 (REQUIRED FOR PCMCIA) for active low, open - drain */ -#define QL_INT_ACTIVE_HIGH 2 - -/* Set the following to 1 to enable the use of interrupts. Note that 0 tends - to be more stable, but slower (or ties up the system more) */ -#define QL_USE_IRQ 1 - -/* Set the following to max out the speed of the PIO PseudoDMA transfers, - again, 0 tends to be slower, but more stable. */ -#define QL_TURBO_PDMA 1 - -/* This should be 1 to enable parity detection */ -#define QL_ENABLE_PARITY 1 - -/* This will reset all devices when the driver is initialized (during bootup). - The other linux drivers don't do this, but the DOS drivers do, and after - using DOS or some kind of crash or lockup this will bring things back - without requiring a cold boot. It does take some time to recover from a - reset, so it is slower, and I have seen timeouts so that devices weren't - recognized when this was set. */ -#define QL_RESET_AT_START 0 - -/* crystal frequency in megahertz (for offset 5 and 9) - Please set this for your card. Most Qlogic cards are 40 Mhz. The - Control Concepts ISA (not VLB) is 24 Mhz */ -#define XTALFREQ 40 - -/**********/ -/* DANGER! modify these at your own risk */ -/* SLOWCABLE can usually be reset to zero if you have a clean setup and - proper termination. The rest are for synchronous transfers and other - advanced features if your device can transfer faster than 5Mb/sec. - If you are really curious, email me for a quick howto until I have - something official */ -/**********/ - -/*****/ -/* config register 1 (offset 8) options */ -/* This needs to be set to 1 if your cabling is long or noisy */ -#define SLOWCABLE 1 - -/*****/ -/* offset 0xc */ -/* This will set fast (10Mhz) synchronous timing when set to 1 - For this to have an effect, FASTCLK must also be 1 */ -#define FASTSCSI 0 - -/* This when set to 1 will set a faster sync transfer rate */ -#define FASTCLK 0 -/*(XTALFREQ>25?1:0)*/ - -/*****/ -/* offset 6 */ -/* This is the sync transfer divisor, XTALFREQ/X will be the maximum - achievable data rate (assuming the rest of the system is capable - and set properly) */ -#define SYNCXFRPD 5 -/*(XTALFREQ/5)*/ - -/*****/ -/* offset 7 */ -/* This is the count of how many synchronous transfers can take place - i.e. how many reqs can occur before an ack is given. - The maximum value for this is 15, the upper bits can modify - REQ/ACK assertion and deassertion during synchronous transfers - If this is 0, the bus will only transfer asynchronously */ -#define SYNCOFFST 0 -/* for the curious, bits 7&6 control the deassertion delay in 1/2 cycles - of the 40Mhz clock. If FASTCLK is 1, specifying 01 (1/2) will - cause the deassertion to be early by 1/2 clock. Bits 5&4 control - the assertion delay, also in 1/2 clocks (FASTCLK is ignored here). */ - -/*----------------------------------------------------------------*/ -#ifdef PCMCIA -#undef QL_INT_ACTIVE_HIGH -#define QL_INT_ACTIVE_HIGH 0 -#define MODULE -#endif - -#include <linux/module.h> - -#ifdef PCMCIA -#undef MODULE -#endif - -#include <linux/blk.h> /* to get disk capacity */ -#include <linux/kernel.h> -#include <linux/string.h> -#include <linux/ioport.h> -#include <linux/sched.h> -#include <linux/proc_fs.h> -#include <linux/unistd.h> -#include <asm/io.h> -#include <asm/irq.h> -#include "sd.h" -#include "hosts.h" -#include "qlogic.h" -#include<linux/stat.h> - -struct proc_dir_entry proc_scsi_qlogic = { - PROC_SCSI_QLOGIC, 6, "qlogic", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - -/*----------------------------------------------------------------*/ -/* driver state info, local to driver */ -static int qbase = 0; /* Port */ -static int qinitid; /* initiator ID */ -static int qabort; /* Flag to cause an abort */ -static int qlirq = -1; /* IRQ being used */ -static char qinfo[80]; /* description */ -static Scsi_Cmnd *qlcmd; /* current command being processed */ - -static int qlcfg5 = ( XTALFREQ << 5 ); /* 15625/512 */ -static int qlcfg6 = SYNCXFRPD; -static int qlcfg7 = SYNCOFFST; -static int qlcfg8 = ( SLOWCABLE << 7 ) | ( QL_ENABLE_PARITY << 4 ); -static int qlcfg9 = ( ( XTALFREQ + 4 ) / 5 ); -static int qlcfgc = ( FASTCLK << 3 ) | ( FASTSCSI << 4 ); - -/*----------------------------------------------------------------*/ -/* The qlogic card uses two register maps - These macros select which one */ -#define REG0 ( outb( inb( qbase + 0xd ) & 0x7f , qbase + 0xd ), outb( 4 , qbase + 0xd )) -#define REG1 ( outb( inb( qbase + 0xd ) | 0x80 , qbase + 0xd ), outb( 0xb4 | QL_INT_ACTIVE_HIGH , qbase + 0xd )) - -/* following is watchdog timeout in microseconds */ -#define WATCHDOG 5000000 - -/*----------------------------------------------------------------*/ -/* the following will set the monitor border color (useful to find - where something crashed or gets stuck at and as a simple profiler) */ - -#if 0 -#define rtrc(i) {inb(0x3da);outb(0x31,0x3c0);outb((i),0x3c0);} -#else -#define rtrc(i) {} -#endif - -/*----------------------------------------------------------------*/ -/* local functions */ -/*----------------------------------------------------------------*/ -static void ql_zap(void); -/* error recovery - reset everything */ -void ql_zap() -{ -int x; -unsigned long flags; - save_flags( flags ); - cli(); - x = inb(qbase + 0xd); - REG0; - outb(3, qbase + 3); /* reset SCSI */ - outb(2, qbase + 3); /* reset chip */ - if (x & 0x80) - REG1; - restore_flags( flags ); -} - -/*----------------------------------------------------------------*/ -/* do pseudo-dma */ -static int ql_pdma(int phase, char *request, int reqlen) -{ -int j; - j = 0; - if (phase & 1) { /* in */ -#if QL_TURBO_PDMA -rtrc(4) - /* empty fifo in large chunks */ - if( reqlen >= 128 && (inb( qbase + 8 ) & 2) ) { /* full */ - insl( qbase + 4, request, 32 ); - reqlen -= 128; - request += 128; - } - while( reqlen >= 84 && !( j & 0xc0 ) ) /* 2/3 */ - if( (j=inb( qbase + 8 )) & 4 ) { - insl( qbase + 4, request, 21 ); - reqlen -= 84; - request += 84; - } - if( reqlen >= 44 && (inb( qbase + 8 ) & 8) ) { /* 1/3 */ - insl( qbase + 4, request, 11 ); - reqlen -= 44; - request += 44; - } -#endif - /* until both empty and int (or until reclen is 0) */ -rtrc(7) - j = 0; - while( reqlen && !( (j & 0x10) && (j & 0xc0) ) ) { - /* while bytes to receive and not empty */ - j &= 0xc0; - while ( reqlen && !( (j=inb(qbase + 8)) & 0x10 ) ) { - *request++ = inb(qbase + 4); - reqlen--; - } - if( j & 0x10 ) - j = inb(qbase+8); - - } - } - else { /* out */ -#if QL_TURBO_PDMA -rtrc(4) - if( reqlen >= 128 && inb( qbase + 8 ) & 0x10 ) { /* empty */ - outsl(qbase + 4, request, 32 ); - reqlen -= 128; - request += 128; - } - while( reqlen >= 84 && !( j & 0xc0 ) ) /* 1/3 */ - if( !((j=inb( qbase + 8 )) & 8) ) { - outsl( qbase + 4, request, 21 ); - reqlen -= 84; - request += 84; - } - if( reqlen >= 40 && !(inb( qbase + 8 ) & 4 ) ) { /* 2/3 */ - outsl( qbase + 4, request, 10 ); - reqlen -= 40; - request += 40; - } -#endif - /* until full and int (or until reclen is 0) */ -rtrc(7) - j = 0; - while( reqlen && !( (j & 2) && (j & 0xc0) ) ) { - /* while bytes to send and not full */ - while ( reqlen && !( (j=inb(qbase + 8)) & 2 ) ) { - outb(*request++, qbase + 4); - reqlen--; - } - if( j & 2 ) - j = inb(qbase+8); - } - } -/* maybe return reqlen */ - return inb( qbase + 8 ) & 0xc0; -} - -/*----------------------------------------------------------------*/ -/* wait for interrupt flag (polled - not real hardware interrupt) */ -static int ql_wai(void) -{ -int i,k; - k = 0; - i = jiffies + WATCHDOG; - while ( i > jiffies && !qabort && !((k = inb(qbase + 4)) & 0xe0)) - barrier(); - if (i <= jiffies) - return (DID_TIME_OUT); - if (qabort) - return (qabort == 1 ? DID_ABORT : DID_RESET); - if (k & 0x60) - ql_zap(); - if (k & 0x20) - return (DID_PARITY); - if (k & 0x40) - return (DID_ERROR); - return 0; -} - -/*----------------------------------------------------------------*/ -/* initiate scsi command - queueing handler */ -static void ql_icmd(Scsi_Cmnd * cmd) -{ -unsigned int i; -unsigned long flags; - - qabort = 0; - - save_flags( flags ); - cli(); - REG0; -/* clearing of interrupts and the fifo is needed */ - inb(qbase + 5); /* clear interrupts */ - if (inb(qbase + 5)) /* if still interrupting */ - outb(2, qbase + 3); /* reset chip */ - else if (inb(qbase + 7) & 0x1f) - outb(1, qbase + 3); /* clear fifo */ - while (inb(qbase + 5)); /* clear ints */ - REG1; - outb(1, qbase + 8); /* set for PIO pseudo DMA */ - outb(0, qbase + 0xb); /* disable ints */ - inb(qbase + 8); /* clear int bits */ - REG0; - outb(0x40, qbase + 0xb); /* enable features */ - -/* configurables */ - outb( qlcfgc , qbase + 0xc); -/* config: no reset interrupt, (initiator) bus id */ - outb( 0x40 | qlcfg8 | qinitid, qbase + 8); - outb( qlcfg7 , qbase + 7 ); - outb( qlcfg6 , qbase + 6 ); -/**/ - outb(qlcfg5, qbase + 5); /* select timer */ - outb(qlcfg9 & 7, qbase + 9); /* prescaler */ -/* outb(0x99, qbase + 5); */ - outb(cmd->target, qbase + 4); - - for (i = 0; i < cmd->cmd_len; i++) - outb(cmd->cmnd[i], qbase + 2); - qlcmd = cmd; - outb(0x41, qbase + 3); /* select and send command */ - restore_flags( flags ); -} -/*----------------------------------------------------------------*/ -/* process scsi command - usually after interrupt */ -static unsigned int ql_pcmd(Scsi_Cmnd * cmd) -{ -unsigned int i, j, k; -unsigned int result; /* ultimate return result */ -unsigned int status; /* scsi returned status */ -unsigned int message; /* scsi returned message */ -unsigned int phase; /* recorded scsi phase */ -unsigned int reqlen; /* total length of transfer */ -struct scatterlist *sglist; /* scatter-gather list pointer */ -unsigned int sgcount; /* sg counter */ - -rtrc(1) - j = inb(qbase + 6); - i = inb(qbase + 5); - if (i == 0x20) { - return (DID_NO_CONNECT << 16); - } - i |= inb(qbase + 5); /* the 0x10 bit can be set after the 0x08 */ - if (i != 0x18) { - printk("Ql:Bad Interrupt status:%02x\n", i); - ql_zap(); - return (DID_BAD_INTR << 16); - } - j &= 7; /* j = inb( qbase + 7 ) >> 5; */ -/* correct status is supposed to be step 4 */ -/* it sometimes returns step 3 but with 0 bytes left to send */ -/* We can try stuffing the FIFO with the max each time, but we will get a - sequence of 3 if any bytes are left (but we do flush the FIFO anyway */ - if(j != 3 && j != 4) { - printk("Ql:Bad sequence for command %d, int %02X, cmdleft = %d\n", j, i, inb( qbase+7 ) & 0x1f ); - ql_zap(); - return (DID_ERROR << 16); - } - result = DID_OK; - if (inb(qbase + 7) & 0x1f) /* if some bytes in fifo */ - outb(1, qbase + 3); /* clear fifo */ -/* note that request_bufflen is the total xfer size when sg is used */ - reqlen = cmd->request_bufflen; -/* note that it won't work if transfers > 16M are requested */ - if (reqlen && !((phase = inb(qbase + 4)) & 6)) { /* data phase */ -rtrc(2) - outb(reqlen, qbase); /* low-mid xfer cnt */ - outb(reqlen >> 8, qbase+1); /* low-mid xfer cnt */ - outb(reqlen >> 16, qbase + 0xe); /* high xfer cnt */ - outb(0x90, qbase + 3); /* command do xfer */ -/* PIO pseudo DMA to buffer or sglist */ - REG1; - if (!cmd->use_sg) - ql_pdma(phase, cmd->request_buffer, cmd->request_bufflen); - else { - sgcount = cmd->use_sg; - sglist = cmd->request_buffer; - while (sgcount--) { - if (qabort) { - REG0; - return ((qabort == 1 ? DID_ABORT : DID_RESET) << 16); - } - if (ql_pdma(phase, sglist->address, sglist->length)) - break; - sglist++; - } - } - REG0; -rtrc(2) -/* wait for irq (split into second state of irq handler if this can take time) */ - if ((k = ql_wai())) - return (k << 16); - k = inb(qbase + 5); /* should be 0x10, bus service */ - } -/*** Enter Status (and Message In) Phase ***/ - k = jiffies + WATCHDOG; - while ( k > jiffies && !qabort && !(inb(qbase + 4) & 6)); /* wait for status phase */ - if ( k <= jiffies ) { - ql_zap(); - return (DID_TIME_OUT << 16); - } - while (inb(qbase + 5)); /* clear pending ints */ - if (qabort) - return ((qabort == 1 ? DID_ABORT : DID_RESET) << 16); - outb(0x11, qbase + 3); /* get status and message */ - if ((k = ql_wai())) - return (k << 16); - i = inb(qbase + 5); /* get chip irq stat */ - j = inb(qbase + 7) & 0x1f; /* and bytes rec'd */ - status = inb(qbase + 2); - message = inb(qbase + 2); -/* should get function complete int if Status and message, else bus serv if only status */ - if (!((i == 8 && j == 2) || (i == 0x10 && j == 1))) { - printk("Ql:Error during status phase, int=%02X, %d bytes recd\n", i, j); - result = DID_ERROR; - } - outb(0x12, qbase + 3); /* done, disconnect */ -rtrc(1) - if ((k = ql_wai())) - return (k << 16); -/* should get bus service interrupt and disconnect interrupt */ - i = inb(qbase + 5); /* should be bus service */ - while (!qabort && ((i & 0x20) != 0x20)) { - barrier(); - i |= inb(qbase + 5); - } -rtrc(0) - if (qabort) - return ((qabort == 1 ? DID_ABORT : DID_RESET) << 16); - return (result << 16) | (message << 8) | (status & STATUS_MASK); -} - -#if QL_USE_IRQ -/*----------------------------------------------------------------*/ -/* interrupt handler */ -static void ql_ihandl(int irq, struct pt_regs * regs) -{ -Scsi_Cmnd *icmd; - REG0; - if (!(inb(qbase + 4) & 0x80)) /* false alarm? */ - return; - if (qlcmd == NULL) { /* no command to process? */ - int i; - i = 16; - while (i-- && inb(qbase + 5)); /* maybe also ql_zap() */ - return; - } - icmd = qlcmd; - icmd->result = ql_pcmd(icmd); - qlcmd = NULL; -/* if result is CHECK CONDITION done calls qcommand to request sense */ - (icmd->scsi_done) (icmd); -} -#endif - -/*----------------------------------------------------------------*/ -/* global functions */ -/*----------------------------------------------------------------*/ -/* non queued command */ -#if QL_USE_IRQ -static void qlidone(Scsi_Cmnd * cmd) {}; /* null function */ -#endif - -/* command process */ -int qlogic_command(Scsi_Cmnd * cmd) -{ -int k; -#if QL_USE_IRQ - if (qlirq >= 0) { - qlogic_queuecommand(cmd, qlidone); - while (qlcmd != NULL); - return cmd->result; - } -#endif -/* non-irq version */ - if (cmd->target == qinitid) - return (DID_BAD_TARGET << 16); - ql_icmd(cmd); - if ((k = ql_wai())) - return (k << 16); - return ql_pcmd(cmd); - -} - -#if QL_USE_IRQ -/*----------------------------------------------------------------*/ -/* queued command */ -int qlogic_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) -{ - if(cmd->target == qinitid) { - cmd->result = DID_BAD_TARGET << 16; - done(cmd); - return 0; - } - - cmd->scsi_done = done; -/* wait for the last command's interrupt to finish */ - while (qlcmd != NULL) - barrier(); - ql_icmd(cmd); - return 0; -} -#else -int qlogic_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) -{ - return 1; -} -#endif - -#ifdef PCMCIA -/*----------------------------------------------------------------*/ -/* allow PCMCIA code to preset the port */ -/* port should be 0 and irq to -1 respectively for autoprobing */ -void qlogic_preset(int port, int irq) -{ - qbase=port; - qlirq=irq; -} -#endif - -/*----------------------------------------------------------------*/ -/* look for qlogic card and init if found */ -int qlogic_detect(Scsi_Host_Template * host) -{ -int i, j; /* these are only used by IRQ detect */ -int qltyp; /* type of chip */ -struct Scsi_Host *hreg; /* registered host structure */ -unsigned long flags; - -host->proc_dir = &proc_scsi_qlogic; - -/* Qlogic Cards only exist at 0x230 or 0x330 (the chip itself decodes the - address - I check 230 first since MIDI cards are typically at 330 - - Theoretically, two Qlogic cards can coexist in the same system. This - should work by simply using this as a loadable module for the second - card, but I haven't tested this. -*/ - - if( !qbase ) { - for (qbase = 0x230; qbase < 0x430; qbase += 0x100) { - if( check_region( qbase , 0x10 ) ) - continue; - REG1; - if ( ( (inb(qbase + 0xe) ^ inb(qbase + 0xe)) == 7 ) - && ( (inb(qbase + 0xe) ^ inb(qbase + 0xe)) == 7 ) ) - break; - } - if (qbase == 0x430) - return 0; - } - else - printk( "Ql: Using preset base address of %03x\n", qbase ); - - qltyp = inb(qbase + 0xe) & 0xf8; - qinitid = host->this_id; - if (qinitid < 0) - qinitid = 7; /* if no ID, use 7 */ - outb(1, qbase + 8); /* set for PIO pseudo DMA */ - REG0; - outb(0x40 | qlcfg8 | qinitid, qbase + 8); /* (ini) bus id, disable scsi rst */ - outb(qlcfg5, qbase + 5); /* select timer */ - outb(qlcfg9, qbase + 9); /* prescaler */ -#if QL_RESET_AT_START - outb( 3 , qbase + 3 ); - REG1; - while( inb( qbase + 0xf ) & 4 ); - REG0; -#endif -#if QL_USE_IRQ -/* IRQ probe - toggle pin and check request pending */ - - if( qlirq == -1 ) { - save_flags( flags ); - cli(); - i = 0xffff; - j = 3; - outb(0x90, qbase + 3); /* illegal command - cause interrupt */ - REG1; - outb(10, 0x20); /* access pending interrupt map */ - outb(10, 0xa0); - while (j--) { - outb(0xb0 | QL_INT_ACTIVE_HIGH , qbase + 0xd); /* int pin off */ - i &= ~(inb(0x20) | (inb(0xa0) << 8)); /* find IRQ off */ - outb(0xb4 | QL_INT_ACTIVE_HIGH , qbase + 0xd); /* int pin on */ - i &= inb(0x20) | (inb(0xa0) << 8); /* find IRQ on */ - } - REG0; - while (inb(qbase + 5)); /* purge int */ - j = -1; - while (i) /* find on bit */ - i >>= 1, j++; /* should check for exactly 1 on */ - qlirq = j; - restore_flags( flags ); - } - else - printk( "Ql: Using preset IRQ %d\n", qlirq ); - - if (qlirq >= 0 && !request_irq(qlirq, ql_ihandl, 0, "qlogic")) - host->can_queue = 1; -#endif - request_region( qbase , 0x10 ,"qlogic"); - hreg = scsi_register( host , 0 ); /* no host data */ - hreg->io_port = qbase; - hreg->n_io_port = 16; - hreg->dma_channel = -1; - if( qlirq != -1 ) - hreg->irq = qlirq; - - sprintf(qinfo, "Qlogic Driver version 0.43, chip %02X at %03X, IRQ %d, TPdma:%d", - qltyp, qbase, qlirq, QL_TURBO_PDMA ); - host->name = qinfo; - - return 1; -} - -/*----------------------------------------------------------------*/ -/* return bios parameters */ -int qlogic_biosparam(Disk * disk, kdev_t dev, int ip[]) -{ -/* This should mimic the DOS Qlogic driver's behavior exactly */ - ip[0] = 0x40; - ip[1] = 0x20; - ip[2] = disk->capacity / (ip[0] * ip[1]); - if (ip[2] > 1024) { - ip[0] = 0xff; - ip[1] = 0x3f; - ip[2] = disk->capacity / (ip[0] * ip[1]); - if (ip[2] > 1023) - ip[2] = 1023; - } - return 0; -} - -/*----------------------------------------------------------------*/ -/* abort command in progress */ -int qlogic_abort(Scsi_Cmnd * cmd) -{ - qabort = 1; - ql_zap(); - return 0; -} - -/*----------------------------------------------------------------*/ -/* reset SCSI bus */ -int qlogic_reset(Scsi_Cmnd * cmd) -{ - qabort = 2; - ql_zap(); - return 1; -} - -/*----------------------------------------------------------------*/ -/* return info string */ -const char *qlogic_info(struct Scsi_Host * host) -{ - return qinfo; -} - -#ifdef MODULE -/* Eventually this will go into an include file, but this will be later */ -Scsi_Host_Template driver_template = QLOGIC; - -#include "scsi_module.c" -#endif diff --git a/i386/i386at/gpl/linux/scsi/qlogic.h b/i386/i386at/gpl/linux/scsi/qlogic.h deleted file mode 100644 index 0ff119ae..00000000 --- a/i386/i386at/gpl/linux/scsi/qlogic.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef _QLOGIC_H -#define _QLOGIC_H - -int qlogic_detect(Scsi_Host_Template * ); -const char * qlogic_info(struct Scsi_Host *); -int qlogic_command(Scsi_Cmnd *); -int qlogic_queuecommand(Scsi_Cmnd *, void (* done)(Scsi_Cmnd *)); -int qlogic_abort(Scsi_Cmnd *); -int qlogic_reset(Scsi_Cmnd *); -int qlogic_biosparam(Disk *, kdev_t, int[]); - -#ifndef NULL -#define NULL (0) -#endif - -#define QLOGIC { \ - NULL, \ - NULL, \ - NULL, \ - NULL, \ - NULL, \ - qlogic_detect, \ - NULL, \ - qlogic_info, \ - qlogic_command, \ - qlogic_queuecommand, \ - qlogic_abort, \ - qlogic_reset, \ - NULL, \ - qlogic_biosparam, \ - 0, \ - -1, \ - SG_ALL, \ - 1, \ - 0, \ - 0, \ - DISABLE_CLUSTERING \ -} - -#endif /* _QLOGIC_H */ diff --git a/i386/i386at/gpl/linux/scsi/scsi.c b/i386/i386at/gpl/linux/scsi/scsi.c deleted file mode 100644 index 7b29168f..00000000 --- a/i386/i386at/gpl/linux/scsi/scsi.c +++ /dev/null @@ -1,3206 +0,0 @@ -/* - * scsi.c Copyright (C) 1992 Drew Eckhardt - * Copyright (C) 1993, 1994, 1995 Eric Youngdale - * - * generic mid-level SCSI driver - * Initial versions: Drew Eckhardt - * Subsequent revisions: Eric Youngdale - * - * <drew@colorado.edu> - * - * Bug correction thanks go to : - * Rik Faith <faith@cs.unc.edu> - * Tommy Thorn <tthorn> - * Thomas Wuensche <tw@fgb1.fgb.mw.tu-muenchen.de> - * - * Modified by Eric Youngdale eric@aib.com to - * add scatter-gather, multiple outstanding request, and other - * enhancements. - * - * Native multichannel and wide scsi support added - * by Michael Neuffer neuffer@goofy.zdv.uni-mainz.de - */ - -/* - * Don't import our own symbols, as this would severely mess up our - * symbol tables. - */ -#define _SCSI_SYMS_VER_ -#include <linux/module.h> - -#include <asm/system.h> -#include <linux/sched.h> -#include <linux/timer.h> -#include <linux/string.h> -#include <linux/malloc.h> -#include <asm/irq.h> -#include <asm/dma.h> -#include <linux/ioport.h> -#include <linux/kernel.h> -#include<linux/stat.h> - -#include <linux/blk.h> -#include "scsi.h" -#include "hosts.h" -#include "constants.h" - -#include <linux/config.h> - -#undef USE_STATIC_SCSI_MEMORY - -/* -static const char RCSid[] = "$Header: cvs/gnumach/i386/i386at/gpl/linux/scsi/Attic/scsi.c,v 1.2 1997/03/24 21:51:33 thomas Exp $"; -*/ - - -/* Command groups 3 and 4 are reserved and should never be used. */ -const unsigned char scsi_command_size[8] = { 6, 10, 10, 12, 12, 12, 10, 10 }; - -#define INTERNAL_ERROR (panic ("Internal error in file %s, line %d.\n", __FILE__, __LINE__)) - -/* - * PAGE_SIZE must be a multiple of the sector size (512). True - * for all reasonably recent architectures (even the VAX...). - */ -#define SECTOR_SIZE 512 -#define SECTORS_PER_PAGE (PAGE_SIZE/SECTOR_SIZE) - -#if SECTORS_PER_PAGE <= 8 - typedef unsigned char FreeSectorBitmap; -#elif SECTORS_PER_PAGE <= 32 - typedef unsigned int FreeSectorBitmap; -#else -# error You lose. -#endif - -static void scsi_done (Scsi_Cmnd *SCpnt); -static int update_timeout (Scsi_Cmnd *, int); -static void print_inquiry(unsigned char *data); -static void scsi_times_out (Scsi_Cmnd * SCpnt, int pid); -static int scan_scsis_single (int channel,int dev,int lun,int * max_scsi_dev , - Scsi_Device ** SDpnt, Scsi_Cmnd * SCpnt, - struct Scsi_Host *shpnt, char * scsi_result); -void scsi_build_commandblocks(Scsi_Device * SDpnt); - -#ifdef CONFIG_MODULES -extern struct symbol_table scsi_symbol_table; -#endif - -static FreeSectorBitmap * dma_malloc_freelist = NULL; -static int scsi_need_isa_bounce_buffers; -static unsigned int dma_sectors = 0; -unsigned int dma_free_sectors = 0; -unsigned int need_isa_buffer = 0; -static unsigned char ** dma_malloc_pages = NULL; - -static int time_start; -static int time_elapsed; -static volatile struct Scsi_Host * host_active = NULL; -#define SCSI_BLOCK(HOST) ((HOST->block && host_active && HOST != host_active) \ - || (HOST->can_queue && HOST->host_busy >= HOST->can_queue)) - -#define MAX_SCSI_DEVICE_CODE 10 -const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE] = -{ - "Direct-Access ", - "Sequential-Access", - "Printer ", - "Processor ", - "WORM ", - "CD-ROM ", - "Scanner ", - "Optical Device ", - "Medium Changer ", - "Communications " -}; - - -/* - * global variables : - * scsi_devices an array of these specifying the address for each - * (host, id, LUN) - */ - -Scsi_Device * scsi_devices = NULL; - -/* Process ID of SCSI commands */ -unsigned long scsi_pid = 0; - -static unsigned char generic_sense[6] = {REQUEST_SENSE, 0,0,0, 255, 0}; -static void resize_dma_pool(void); - -/* This variable is merely a hook so that we can debug the kernel with gdb. */ -Scsi_Cmnd * last_cmnd = NULL; - -/* This is the pointer to the /proc/scsi code. - * It is only initialized to !=0 if the scsi code is present - */ -extern int (* dispatch_scsi_info_ptr)(int ino, char *buffer, char **start, - off_t offset, int length, int inout); -extern int dispatch_scsi_info(int ino, char *buffer, char **start, - off_t offset, int length, int inout); - -struct proc_dir_entry proc_scsi_scsi = { - PROC_SCSI_SCSI, 4, "scsi", - S_IFREG | S_IRUGO | S_IWUSR, 2, 0, 0, 0, - NULL, - NULL, NULL, - NULL, NULL, NULL -}; - - -/* - * As the scsi do command functions are intelligent, and may need to - * redo a command, we need to keep track of the last command - * executed on each one. - */ - -#define WAS_RESET 0x01 -#define WAS_TIMEDOUT 0x02 -#define WAS_SENSE 0x04 -#define IS_RESETTING 0x08 -#define IS_ABORTING 0x10 -#define ASKED_FOR_SENSE 0x20 - -/* - * This is the number of clock ticks we should wait before we time out - * and abort the command. This is for where the scsi.c module generates - * the command, not where it originates from a higher level, in which - * case the timeout is specified there. - * - * ABORT_TIMEOUT and RESET_TIMEOUT are the timeouts for RESET and ABORT - * respectively. - */ - -#ifdef DEBUG_TIMEOUT -static void scsi_dump_status(void); -#endif - - -#ifdef DEBUG - #define SCSI_TIMEOUT (5*HZ) -#else - #define SCSI_TIMEOUT (1*HZ) -#endif - -#ifdef DEBUG - #define SENSE_TIMEOUT SCSI_TIMEOUT - #define ABORT_TIMEOUT SCSI_TIMEOUT - #define RESET_TIMEOUT SCSI_TIMEOUT -#else - #define SENSE_TIMEOUT (5*HZ/10) - #define RESET_TIMEOUT (5*HZ/10) - #define ABORT_TIMEOUT (5*HZ/10) -#endif - -#define MIN_RESET_DELAY (1*HZ) - -/* Do not call reset on error if we just did a reset within 10 sec. */ -#define MIN_RESET_PERIOD (10*HZ) - -/* The following devices are known not to tolerate a lun != 0 scan for - * one reason or another. Some will respond to all luns, others will - * lock up. - */ - -#define BLIST_NOLUN 0x01 -#define BLIST_FORCELUN 0x02 -#define BLIST_BORKEN 0x04 -#define BLIST_KEY 0x08 -#define BLIST_SINGLELUN 0x10 - -struct dev_info{ - const char * vendor; - const char * model; - const char * revision; /* Latest revision known to be bad. Not used yet */ - unsigned flags; -}; - -/* - * This is what was previously known as the blacklist. The concept - * has been expanded so that we can specify other types of things we - * need to be aware of. - */ -static struct dev_info device_list[] = -{ -{"CHINON","CD-ROM CDS-431","H42", BLIST_NOLUN}, /* Locks up if polled for lun != 0 */ -{"CHINON","CD-ROM CDS-535","Q14", BLIST_NOLUN}, /* Locks up if polled for lun != 0 */ -{"DENON","DRD-25X","V", BLIST_NOLUN}, /* Locks up if probed for lun != 0 */ -{"HITACHI","DK312C","CM81", BLIST_NOLUN}, /* Responds to all lun - dtg */ -{"HITACHI","DK314C","CR21" , BLIST_NOLUN}, /* responds to all lun */ -{"IMS", "CDD521/10","2.06", BLIST_NOLUN}, /* Locks-up when LUN>0 polled. */ -{"MAXTOR","XT-3280","PR02", BLIST_NOLUN}, /* Locks-up when LUN>0 polled. */ -{"MAXTOR","XT-4380S","B3C", BLIST_NOLUN}, /* Locks-up when LUN>0 polled. */ -{"MAXTOR","MXT-1240S","I1.2", BLIST_NOLUN}, /* Locks up when LUN>0 polled */ -{"MAXTOR","XT-4170S","B5A", BLIST_NOLUN}, /* Locks-up sometimes when LUN>0 polled. */ -{"MAXTOR","XT-8760S","B7B", BLIST_NOLUN}, /* guess what? */ -{"MEDIAVIS","RENO CD-ROMX2A","2.03",BLIST_NOLUN},/*Responds to all lun */ -{"NEC","CD-ROM DRIVE:841","1.0", BLIST_NOLUN}, /* Locks-up when LUN>0 polled. */ -{"RODIME","RO3000S","2.33", BLIST_NOLUN}, /* Locks up if polled for lun != 0 */ -{"SEAGATE", "ST157N", "\004|j", BLIST_NOLUN}, /* causes failed REQUEST SENSE on lun 1 - * for aha152x controller, which causes - * SCSI code to reset bus.*/ -{"SEAGATE", "ST296","921", BLIST_NOLUN}, /* Responds to all lun */ -{"SEAGATE","ST1581","6538",BLIST_NOLUN}, /* Responds to all lun */ -{"SONY","CD-ROM CDU-541","4.3d", BLIST_NOLUN}, -{"SONY","CD-ROM CDU-55S","1.0i", BLIST_NOLUN}, -{"SONY","CD-ROM CDU-561","1.7x", BLIST_NOLUN}, -{"TANDBERG","TDC 3600","U07", BLIST_NOLUN}, /* Locks up if polled for lun != 0 */ -{"TEAC","CD-ROM","1.06", BLIST_NOLUN}, /* causes failed REQUEST SENSE on lun 1 - * for seagate controller, which causes - * SCSI code to reset bus.*/ -{"TEXEL","CD-ROM","1.06", BLIST_NOLUN}, /* causes failed REQUEST SENSE on lun 1 - * for seagate controller, which causes - * SCSI code to reset bus.*/ -{"QUANTUM","LPS525S","3110", BLIST_NOLUN}, /* Locks sometimes if polled for lun != 0 */ -{"QUANTUM","PD1225S","3110", BLIST_NOLUN}, /* Locks sometimes if polled for lun != 0 */ -{"MEDIAVIS","CDR-H93MV","1.31", BLIST_NOLUN}, /* Locks up if polled for lun != 0 */ -{"SANKYO", "CP525","6.64", BLIST_NOLUN}, /* causes failed REQ SENSE, extra reset */ -{"HP", "C1750A", "3226", BLIST_NOLUN}, /* scanjet iic */ -{"HP", "C1790A", "", BLIST_NOLUN}, /* scanjet iip */ -{"HP", "C2500A", "", BLIST_NOLUN}, /* scanjet iicx */ - -/* - * Other types of devices that have special flags. - */ -{"SONY","CD-ROM CDU-8001","*", BLIST_BORKEN}, -{"TEXEL","CD-ROM","1.06", BLIST_BORKEN}, -{"INSITE","Floptical F*8I","*", BLIST_KEY}, -{"INSITE","I325VM","*", BLIST_KEY}, -{"PIONEER","CD-ROMDRM-602X","*", BLIST_FORCELUN | BLIST_SINGLELUN}, -{"PIONEER","CD-ROMDRM-604X","*", BLIST_FORCELUN | BLIST_SINGLELUN}, -/* - * Must be at end of list... - */ -{NULL, NULL, NULL} -}; - -static int get_device_flags(unsigned char * response_data){ - int i = 0; - unsigned char * pnt; - for(i=0; 1; i++){ - if(device_list[i].vendor == NULL) return 0; - pnt = &response_data[8]; - while(*pnt && *pnt == ' ') pnt++; - if(memcmp(device_list[i].vendor, pnt, - strlen(device_list[i].vendor))) continue; - pnt = &response_data[16]; - while(*pnt && *pnt == ' ') pnt++; - if(memcmp(device_list[i].model, pnt, - strlen(device_list[i].model))) continue; - return device_list[i].flags; - } - return 0; -} - -void scsi_make_blocked_list(void) { - int block_count = 0, index; - unsigned int flags; - struct Scsi_Host * sh[128], * shpnt; - - /* - * Create a circular linked list from the scsi hosts which have - * the "wish_block" field in the Scsi_Host structure set. - * The blocked list should include all the scsi hosts using ISA DMA. - * In some systems, using two dma channels simultaneously causes - * unpredictable results. - * Among the scsi hosts in the blocked list, only one host at a time - * is allowed to have active commands queued. The transition from - * one active host to the next one is allowed only when host_busy == 0 - * for the active host (which implies host_busy == 0 for all the hosts - * in the list). Moreover for block devices the transition to a new - * active host is allowed only when a request is completed, since a - * block device request can be divided into multiple scsi commands - * (when there are few sg lists or clustering is disabled). - * - * (DB, 4 Feb 1995) - */ - - save_flags(flags); - cli(); - host_active = NULL; - - for(shpnt=scsi_hostlist; shpnt; shpnt = shpnt->next) { - -#if 0 - /* - * Is this is a candidate for the blocked list? - * Useful to put into the blocked list all the hosts whose driver - * does not know about the host->block feature. - */ - if (shpnt->unchecked_isa_dma) shpnt->wish_block = 1; -#endif - - if (shpnt->wish_block) sh[block_count++] = shpnt; - } - - if (block_count == 1) sh[0]->block = NULL; - - else if (block_count > 1) { - - for(index = 0; index < block_count - 1; index++) { - sh[index]->block = sh[index + 1]; - printk("scsi%d : added to blocked host list.\n", - sh[index]->host_no); - } - - sh[block_count - 1]->block = sh[0]; - printk("scsi%d : added to blocked host list.\n", - sh[index]->host_no); - } - - restore_flags(flags); -} - -static void scan_scsis_done (Scsi_Cmnd * SCpnt) -{ - -#ifdef DEBUG - printk ("scan_scsis_done(%p, %06x)\n", SCpnt->host, SCpnt->result); -#endif - SCpnt->request.rq_status = RQ_SCSI_DONE; - - if (SCpnt->request.sem != NULL) - up(SCpnt->request.sem); -} - -#ifdef CONFIG_SCSI_MULTI_LUN -static int max_scsi_luns = 8; -#else -static int max_scsi_luns = 1; -#endif - -void scsi_luns_setup(char *str, int *ints) { - if (ints[0] != 1) - printk("scsi_luns_setup : usage max_scsi_luns=n (n should be between 1 and 8)\n"); - else - max_scsi_luns = ints[1]; -} - -/* - * Detecting SCSI devices : - * We scan all present host adapter's busses, from ID 0 to ID (max_id). - * We use the INQUIRY command, determine device type, and pass the ID / - * lun address of all sequential devices to the tape driver, all random - * devices to the disk driver. - */ -static void scan_scsis (struct Scsi_Host *shpnt, unchar hardcoded, - unchar hchannel, unchar hid, unchar hlun) -{ - int dev, lun, channel; - unsigned char scsi_result0[256]; - unsigned char *scsi_result; - Scsi_Device *SDpnt; - int max_dev_lun; - Scsi_Cmnd *SCpnt; - - SCpnt = (Scsi_Cmnd *) scsi_init_malloc (sizeof (Scsi_Cmnd), GFP_ATOMIC | GFP_DMA); - SDpnt = (Scsi_Device *) scsi_init_malloc (sizeof (Scsi_Device), GFP_ATOMIC); - memset (SCpnt, 0, sizeof (Scsi_Cmnd)); - - - /* Make sure we have something that is valid for DMA purposes */ - scsi_result = ( ( !shpnt->unchecked_isa_dma ) - ? &scsi_result0[0] : scsi_init_malloc (512, GFP_DMA)); - - if (scsi_result == NULL) { - printk ("Unable to obtain scsi_result buffer\n"); - goto leave; - } - - /* We must chain ourself in the host_queue, so commands can time out */ - if(shpnt->host_queue) - shpnt->host_queue->prev = SCpnt; - SCpnt->next = shpnt->host_queue; - SCpnt->prev = NULL; - shpnt->host_queue = SCpnt; - - - if (hardcoded == 1) { - Scsi_Device *oldSDpnt=SDpnt; - struct Scsi_Device_Template * sdtpnt; - channel = hchannel; - if(channel > shpnt->max_channel) goto leave; - dev = hid; - if(dev >= shpnt->max_id) goto leave; - lun = hlun; - if(lun >= shpnt->max_lun) goto leave; - scan_scsis_single (channel, dev, lun, &max_dev_lun, - &SDpnt, SCpnt, shpnt, scsi_result); - if(SDpnt!=oldSDpnt) { - - /* it could happen the blockdevice hasn't yet been inited */ - for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) - if(sdtpnt->init && sdtpnt->dev_noticed) (*sdtpnt->init)(); - - oldSDpnt->scsi_request_fn = NULL; - for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) - if(sdtpnt->attach) { - (*sdtpnt->attach)(oldSDpnt); - if(oldSDpnt->attached) scsi_build_commandblocks(oldSDpnt);} - resize_dma_pool(); - - for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) { - if(sdtpnt->finish && sdtpnt->nr_dev) - {(*sdtpnt->finish)();} - } - } - - } - else { - for (channel = 0; channel <= shpnt->max_channel; channel++) { - for (dev = 0; dev < shpnt->max_id; ++dev) { - if (shpnt->this_id != dev) { - - /* - * We need the for so our continue, etc. work fine. We put this in - * a variable so that we can override it during the scan if we - * detect a device *KNOWN* to have multiple logical units. - */ - max_dev_lun = (max_scsi_luns < shpnt->max_lun ? - max_scsi_luns : shpnt->max_lun); - for (lun = 0; lun < max_dev_lun; ++lun) { - if (!scan_scsis_single (channel, dev, lun, &max_dev_lun, - &SDpnt, SCpnt, shpnt, scsi_result)) - break; /* break means don't probe further for luns!=0 */ - } /* for lun ends */ - } /* if this_id != id ends */ - } /* for dev ends */ - } /* for channel ends */ - } /* if/else hardcoded */ - - leave: - - {/* Unchain SCpnt from host_queue */ - Scsi_Cmnd *prev,*next,*hqptr; - for(hqptr=shpnt->host_queue; hqptr!=SCpnt; hqptr=hqptr->next) ; - if(hqptr) { - prev=hqptr->prev; - next=hqptr->next; - if(prev) - prev->next=next; - else - shpnt->host_queue=next; - if(next) next->prev=prev; - } - } - - /* Last device block does not exist. Free memory. */ - if (SDpnt != NULL) - scsi_init_free ((char *) SDpnt, sizeof (Scsi_Device)); - - if (SCpnt != NULL) - scsi_init_free ((char *) SCpnt, sizeof (Scsi_Cmnd)); - - /* If we allocated a buffer so we could do DMA, free it now */ - if (scsi_result != &scsi_result0[0] && scsi_result != NULL) - scsi_init_free (scsi_result, 512); - -} - -/* - * The worker for scan_scsis. - * Returning 0 means Please don't ask further for lun!=0, 1 means OK go on. - * Global variables used : scsi_devices(linked list) - */ -int scan_scsis_single (int channel, int dev, int lun, int *max_dev_lun, - Scsi_Device **SDpnt2, Scsi_Cmnd * SCpnt, struct Scsi_Host * shpnt, - char *scsi_result) -{ - unsigned char scsi_cmd[12]; - struct Scsi_Device_Template *sdtpnt; - Scsi_Device * SDtail, *SDpnt=*SDpnt2; - int bflags, type=-1; - - SDtail = scsi_devices; - if (scsi_devices) - while (SDtail->next) - SDtail = SDtail->next; - - memset (SDpnt, 0, sizeof (Scsi_Device)); - SDpnt->host = shpnt; - SDpnt->id = dev; - SDpnt->lun = lun; - SDpnt->channel = channel; - - /* Some low level driver could use device->type (DB) */ - SDpnt->type = -1; - - /* - * Assume that the device will have handshaking problems, and then fix this - * field later if it turns out it doesn't - */ - SDpnt->borken = 1; - SDpnt->was_reset = 0; - SDpnt->expecting_cc_ua = 0; - - scsi_cmd[0] = TEST_UNIT_READY; - scsi_cmd[1] = lun << 5; - scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[4] = scsi_cmd[5] = 0; - - SCpnt->host = SDpnt->host; - SCpnt->device = SDpnt; - SCpnt->target = SDpnt->id; - SCpnt->lun = SDpnt->lun; - SCpnt->channel = SDpnt->channel; - { - struct semaphore sem = MUTEX_LOCKED; - SCpnt->request.sem = &sem; - SCpnt->request.rq_status = RQ_SCSI_BUSY; - scsi_do_cmd (SCpnt, (void *) scsi_cmd, - (void *) scsi_result, - 256, scan_scsis_done, SCSI_TIMEOUT + 4 * HZ, 5); - down (&sem); - } - -#if defined(DEBUG) || defined(DEBUG_INIT) - printk ("scsi: scan_scsis_single id %d lun %d. Return code 0x%08x\n", - dev, lun, SCpnt->result); - print_driverbyte(SCpnt->result); print_hostbyte(SCpnt->result); - printk("\n"); -#endif - - if (SCpnt->result) { - if (((driver_byte (SCpnt->result) & DRIVER_SENSE) || - (status_byte (SCpnt->result) & CHECK_CONDITION)) && - ((SCpnt->sense_buffer[0] & 0x70) >> 4) == 7) { - if (((SCpnt->sense_buffer[2] & 0xf) != NOT_READY) && - ((SCpnt->sense_buffer[2] & 0xf) != UNIT_ATTENTION) && - ((SCpnt->sense_buffer[2] & 0xf) != ILLEGAL_REQUEST || lun > 0)) - return 1; - } - else - return 0; - } - -#if defined (DEBUG) || defined(DEBUG_INIT) - printk ("scsi: performing INQUIRY\n"); -#endif - /* - * Build an INQUIRY command block. - */ - scsi_cmd[0] = INQUIRY; - scsi_cmd[1] = (lun << 5) & 0xe0; - scsi_cmd[2] = 0; - scsi_cmd[3] = 0; - scsi_cmd[4] = 255; - scsi_cmd[5] = 0; - SCpnt->cmd_len = 0; - { - struct semaphore sem = MUTEX_LOCKED; - SCpnt->request.sem = &sem; - SCpnt->request.rq_status = RQ_SCSI_BUSY; - scsi_do_cmd (SCpnt, (void *) scsi_cmd, - (void *) scsi_result, - 256, scan_scsis_done, SCSI_TIMEOUT, 3); - down (&sem); - } - -#if defined(DEBUG) || defined(DEBUG_INIT) - printk ("scsi: INQUIRY %s with code 0x%x\n", - SCpnt->result ? "failed" : "successful", SCpnt->result); -#endif - - if (SCpnt->result) - return 0; /* assume no peripheral if any sort of error */ - - /* - * It would seem some TOSHIBA CDROM gets things wrong - */ - if (!strncmp (scsi_result + 8, "TOSHIBA", 7) && - !strncmp (scsi_result + 16, "CD-ROM", 6) && - scsi_result[0] == TYPE_DISK) { - scsi_result[0] = TYPE_ROM; - scsi_result[1] |= 0x80; /* removable */ - } - - if (!strncmp (scsi_result + 8, "NEC", 3)) { - if (!strncmp (scsi_result + 16, "CD-ROM DRIVE:84 ", 16) || - !strncmp (scsi_result + 16, "CD-ROM DRIVE:25", 15)) - SDpnt->manufacturer = SCSI_MAN_NEC_OLDCDR; - else - SDpnt->manufacturer = SCSI_MAN_NEC; - } - else if (!strncmp (scsi_result + 8, "TOSHIBA", 7)) - SDpnt->manufacturer = SCSI_MAN_TOSHIBA; - else if (!strncmp (scsi_result + 8, "SONY", 4)) - SDpnt->manufacturer = SCSI_MAN_SONY; - else if (!strncmp (scsi_result + 8, "PIONEER", 7)) - SDpnt->manufacturer = SCSI_MAN_PIONEER; - else - SDpnt->manufacturer = SCSI_MAN_UNKNOWN; - - memcpy (SDpnt->vendor, scsi_result + 8, 8); - memcpy (SDpnt->model, scsi_result + 16, 16); - memcpy (SDpnt->rev, scsi_result + 32, 4); - - SDpnt->removable = (0x80 & scsi_result[1]) >> 7; - SDpnt->lockable = SDpnt->removable; - SDpnt->changed = 0; - SDpnt->access_count = 0; - SDpnt->busy = 0; - SDpnt->has_cmdblocks = 0; - /* - * Currently, all sequential devices are assumed to be tapes, all random - * devices disk, with the appropriate read only flags set for ROM / WORM - * treated as RO. - */ - switch (type = (scsi_result[0] & 0x1f)) { - case TYPE_TAPE: - case TYPE_DISK: - case TYPE_MOD: - case TYPE_PROCESSOR: - case TYPE_SCANNER: - SDpnt->writeable = 1; - break; - case TYPE_WORM: - case TYPE_ROM: - SDpnt->writeable = 0; - break; - default: - printk ("scsi: unknown type %d\n", type); - } - - SDpnt->single_lun = 0; - SDpnt->soft_reset = - (scsi_result[7] & 1) && ((scsi_result[3] & 7) == 2); - SDpnt->random = (type == TYPE_TAPE) ? 0 : 1; - SDpnt->type = (type & 0x1f); - - print_inquiry (scsi_result); - - for (sdtpnt = scsi_devicelist; sdtpnt; - sdtpnt = sdtpnt->next) - if (sdtpnt->detect) - SDpnt->attached += - (*sdtpnt->detect) (SDpnt); - - SDpnt->scsi_level = scsi_result[2] & 0x07; - if (SDpnt->scsi_level >= 2 || - (SDpnt->scsi_level == 1 && - (scsi_result[3] & 0x0f) == 1)) - SDpnt->scsi_level++; - - /* - * Set the tagged_queue flag for SCSI-II devices that purport to support - * tagged queuing in the INQUIRY data. - */ - SDpnt->tagged_queue = 0; - if ((SDpnt->scsi_level >= SCSI_2) && - (scsi_result[7] & 2)) { - SDpnt->tagged_supported = 1; - SDpnt->current_tag = 0; - } - - /* - * Accommodate drivers that want to sleep when they should be in a polling - * loop. - */ - SDpnt->disconnect = 0; - - /* - * Get any flags for this device. - */ - bflags = get_device_flags (scsi_result); - - /* - * Some revisions of the Texel CD ROM drives have handshaking problems when - * used with the Seagate controllers. Before we know what type of device - * we're talking to, we assume it's borken and then change it here if it - * turns out that it isn't a TEXEL drive. - */ - if ((bflags & BLIST_BORKEN) == 0) - SDpnt->borken = 0; - - /* - * These devices need this "key" to unlock the devices so we can use it - */ - if ((bflags & BLIST_KEY) != 0) { - printk ("Unlocked floptical drive.\n"); - SDpnt->lockable = 0; - scsi_cmd[0] = MODE_SENSE; - scsi_cmd[1] = (lun << 5) & 0xe0; - scsi_cmd[2] = 0x2e; - scsi_cmd[3] = 0; - scsi_cmd[4] = 0x2a; - scsi_cmd[5] = 0; - SCpnt->cmd_len = 0; - { - struct semaphore sem = MUTEX_LOCKED; - SCpnt->request.rq_status = RQ_SCSI_BUSY; - SCpnt->request.sem = &sem; - scsi_do_cmd (SCpnt, (void *) scsi_cmd, - (void *) scsi_result, 0x2a, - scan_scsis_done, SCSI_TIMEOUT, 3); - down (&sem); - } - } - /* Add this device to the linked list at the end */ - if (SDtail) - SDtail->next = SDpnt; - else - scsi_devices = SDpnt; - SDtail = SDpnt; - - SDpnt = (Scsi_Device *) scsi_init_malloc (sizeof (Scsi_Device), GFP_ATOMIC); - *SDpnt2=SDpnt; - if (!SDpnt) - printk ("scsi: scan_scsis_single: Cannot malloc\n"); - - - /* - * Some scsi devices cannot be polled for lun != 0 due to firmware bugs - */ - if (bflags & BLIST_NOLUN) - return 0; /* break; */ - - /* - * If we want to only allow I/O to one of the luns attached to this device - * at a time, then we set this flag. - */ - if (bflags & BLIST_SINGLELUN) - SDpnt->single_lun = 1; - - /* - * If this device is known to support multiple units, override the other - * settings, and scan all of them. - */ - if (bflags & BLIST_FORCELUN) - *max_dev_lun = 8; - /* - * We assume the device can't handle lun!=0 if: - it reports scsi-0 (ANSI - * SCSI Revision 0) (old drives like MAXTOR XT-3280) or - it reports scsi-1 - * (ANSI SCSI Revision 1) and Response Data Format 0 - */ - if (((scsi_result[2] & 0x07) == 0) - || - ((scsi_result[2] & 0x07) == 1 && - (scsi_result[3] & 0x0f) == 0)) - return 0; - return 1; -} - -/* - * Flag bits for the internal_timeout array - */ -#define NORMAL_TIMEOUT 0 -#define IN_ABORT 1 -#define IN_RESET 2 - -/* - * This is our time out function, called when the timer expires for a - * given host adapter. It will attempt to abort the currently executing - * command, that failing perform a kernel panic. - */ - -static void scsi_times_out (Scsi_Cmnd * SCpnt, int pid) -{ - - switch (SCpnt->internal_timeout & (IN_ABORT | IN_RESET)) - { - case NORMAL_TIMEOUT: - { -#ifdef DEBUG_TIMEOUT - scsi_dump_status(); -#endif - } - - if (!scsi_abort (SCpnt, DID_TIME_OUT, pid)) - return; - case IN_ABORT: - printk("SCSI host %d abort (pid %ld) timed out - resetting\n", - SCpnt->host->host_no, SCpnt->pid); - if (!scsi_reset (SCpnt, FALSE)) - return; - case IN_RESET: - case (IN_ABORT | IN_RESET): - /* This might be controversial, but if there is a bus hang, - * you might conceivably want the machine up and running - * esp if you have an ide disk. - */ - printk("Unable to reset scsi host %d - ", SCpnt->host->host_no); - printk("probably a SCSI bus hang.\n"); - SCpnt->internal_timeout &= ~IN_RESET; - scsi_reset (SCpnt, TRUE); - return; - - default: - INTERNAL_ERROR; - } - -} - - -/* This function takes a quick look at a request, and decides if it - * can be queued now, or if there would be a stall while waiting for - * something else to finish. This routine assumes that interrupts are - * turned off when entering the routine. It is the responsibility - * of the calling code to ensure that this is the case. - */ - -Scsi_Cmnd * request_queueable (struct request * req, Scsi_Device * device) -{ - Scsi_Cmnd * SCpnt = NULL; - int tablesize; - Scsi_Cmnd * found = NULL; - struct buffer_head * bh, *bhp; - - if (!device) - panic ("No device passed to request_queueable().\n"); - - if (req && req->rq_status == RQ_INACTIVE) - panic("Inactive in request_queueable"); - - SCpnt = device->host->host_queue; - - /* - * Look for a free command block. If we have been instructed not to queue - * multiple commands to multi-lun devices, then check to see what else is - * going for this device first. - */ - - SCpnt = device->host->host_queue; - if (!device->single_lun) { - while(SCpnt){ - if(SCpnt->target == device->id && - SCpnt->lun == device->lun) { - if(SCpnt->request.rq_status == RQ_INACTIVE) break; - } - SCpnt = SCpnt->next; - } - } else { - while(SCpnt){ - if(SCpnt->target == device->id) { - if (SCpnt->lun == device->lun) { - if(found == NULL - && SCpnt->request.rq_status == RQ_INACTIVE) - { - found=SCpnt; - } - } - if(SCpnt->request.rq_status != RQ_INACTIVE) { - /* - * I think that we should really limit things to one - * outstanding command per device - this is what tends - * to trip up buggy firmware. - */ - return NULL; - } - } - SCpnt = SCpnt->next; - } - SCpnt = found; - } - - if (!SCpnt) return NULL; - - if (SCSI_BLOCK(device->host)) return NULL; - - if (req) { - memcpy(&SCpnt->request, req, sizeof(struct request)); - tablesize = device->host->sg_tablesize; - bhp = bh = req->bh; - if(!tablesize) bh = NULL; - /* Take a quick look through the table to see how big it is. - * We already have our copy of req, so we can mess with that - * if we want to. - */ - while(req->nr_sectors && bh){ - bhp = bhp->b_reqnext; - if(!bhp || !CONTIGUOUS_BUFFERS(bh,bhp)) tablesize--; - req->nr_sectors -= bh->b_size >> 9; - req->sector += bh->b_size >> 9; - if(!tablesize) break; - bh = bhp; - } - if(req->nr_sectors && bh && bh->b_reqnext){ /* Any leftovers? */ - SCpnt->request.bhtail = bh; - req->bh = bh->b_reqnext; /* Divide request */ - bh->b_reqnext = NULL; - bh = req->bh; - - /* Now reset things so that req looks OK */ - SCpnt->request.nr_sectors -= req->nr_sectors; - req->current_nr_sectors = bh->b_size >> 9; - req->buffer = bh->b_data; - SCpnt->request.sem = NULL; /* Wait until whole thing done */ - } else { - req->rq_status = RQ_INACTIVE; - wake_up(&wait_for_request); - } - } else { - SCpnt->request.rq_status = RQ_SCSI_BUSY; /* Busy, but no request */ - SCpnt->request.sem = NULL; /* And no one is waiting for the device - * either */ - } - - SCpnt->use_sg = 0; /* Reset the scatter-gather flag */ - SCpnt->old_use_sg = 0; - SCpnt->transfersize = 0; - SCpnt->underflow = 0; - SCpnt->cmd_len = 0; - -/* Since not everyone seems to set the device info correctly - * before Scsi_Cmnd gets send out to scsi_do_command, we do it here. - */ - SCpnt->channel = device->channel; - SCpnt->lun = device->lun; - SCpnt->target = device->id; - - return SCpnt; -} - -/* This function returns a structure pointer that will be valid for - * the device. The wait parameter tells us whether we should wait for - * the unit to become free or not. We are also able to tell this routine - * not to return a descriptor if the host is unable to accept any more - * commands for the time being. We need to keep in mind that there is no - * guarantee that the host remain not busy. Keep in mind the - * request_queueable function also knows the internal allocation scheme - * of the packets for each device - */ - -Scsi_Cmnd * allocate_device (struct request ** reqp, Scsi_Device * device, - int wait) -{ - kdev_t dev; - struct request * req = NULL; - int tablesize; - unsigned int flags; - struct buffer_head * bh, *bhp; - struct Scsi_Host * host; - Scsi_Cmnd * SCpnt = NULL; - Scsi_Cmnd * SCwait = NULL; - Scsi_Cmnd * found = NULL; - - if (!device) - panic ("No device passed to allocate_device().\n"); - - if (reqp) req = *reqp; - - /* See if this request has already been queued by an interrupt routine */ - if (req) { - if(req->rq_status == RQ_INACTIVE) return NULL; - dev = req->rq_dev; - } else - dev = 0; /* unused */ - - host = device->host; - - if (intr_count && SCSI_BLOCK(host)) return NULL; - - while (1==1){ - SCpnt = device->host->host_queue; - if (!device->single_lun) { - while(SCpnt){ - if(SCpnt->target == device->id && - SCpnt->lun == device->lun) { - SCwait = SCpnt; - if(SCpnt->request.rq_status == RQ_INACTIVE) break; - } - SCpnt = SCpnt->next; - } - } else { - while(SCpnt){ - if(SCpnt->target == device->id) { - if (SCpnt->lun == device->lun) { - SCwait = SCpnt; - if(found == NULL - && SCpnt->request.rq_status == RQ_INACTIVE) - { - found=SCpnt; - } - } - if(SCpnt->request.rq_status != RQ_INACTIVE) { - /* - * I think that we should really limit things to one - * outstanding command per device - this is what tends - * to trip up buggy firmware. - */ - found = NULL; - break; - } - } - SCpnt = SCpnt->next; - } - SCpnt = found; - } - - save_flags(flags); - cli(); - /* See if this request has already been queued by an interrupt routine - */ - if (req && (req->rq_status == RQ_INACTIVE || req->rq_dev != dev)) { - restore_flags(flags); - return NULL; - } - if (!SCpnt || SCpnt->request.rq_status != RQ_INACTIVE) /* Might have changed */ - { - restore_flags(flags); - if(!wait) return NULL; - if (!SCwait) { - printk("Attempt to allocate device channel %d, target %d, " - "lun %d\n", device->channel, device->id, device->lun); - panic("No device found in allocate_device\n"); - } - SCSI_SLEEP(&device->device_wait, - (SCwait->request.rq_status != RQ_INACTIVE)); - } else { - if (req) { - memcpy(&SCpnt->request, req, sizeof(struct request)); - tablesize = device->host->sg_tablesize; - bhp = bh = req->bh; - if(!tablesize) bh = NULL; - /* Take a quick look through the table to see how big it is. - * We already have our copy of req, so we can mess with that - * if we want to. - */ - while(req->nr_sectors && bh){ - bhp = bhp->b_reqnext; - if(!bhp || !CONTIGUOUS_BUFFERS(bh,bhp)) tablesize--; - req->nr_sectors -= bh->b_size >> 9; - req->sector += bh->b_size >> 9; - if(!tablesize) break; - bh = bhp; - } - if(req->nr_sectors && bh && bh->b_reqnext){/* Any leftovers? */ - SCpnt->request.bhtail = bh; - req->bh = bh->b_reqnext; /* Divide request */ - bh->b_reqnext = NULL; - bh = req->bh; - /* Now reset things so that req looks OK */ - SCpnt->request.nr_sectors -= req->nr_sectors; - req->current_nr_sectors = bh->b_size >> 9; - req->buffer = bh->b_data; - SCpnt->request.sem = NULL; /* Wait until whole thing done*/ - } - else - { - req->rq_status = RQ_INACTIVE; - *reqp = req->next; - wake_up(&wait_for_request); - } - } else { - SCpnt->request.rq_status = RQ_SCSI_BUSY; - SCpnt->request.sem = NULL; /* And no one is waiting for this - * to complete */ - } - restore_flags(flags); - break; - } - } - - SCpnt->use_sg = 0; /* Reset the scatter-gather flag */ - SCpnt->old_use_sg = 0; - SCpnt->transfersize = 0; /* No default transfer size */ - SCpnt->cmd_len = 0; - - SCpnt->underflow = 0; /* Do not flag underflow conditions */ - - /* Since not everyone seems to set the device info correctly - * before Scsi_Cmnd gets send out to scsi_do_command, we do it here. - */ - SCpnt->channel = device->channel; - SCpnt->lun = device->lun; - SCpnt->target = device->id; - - return SCpnt; -} - -/* - * This is inline because we have stack problemes if we recurse to deeply. - */ - -inline void internal_cmnd (Scsi_Cmnd * SCpnt) -{ - int temp; - struct Scsi_Host * host; - unsigned int flags; -#ifdef DEBUG_DELAY - int clock; -#endif - - host = SCpnt->host; - - /* - * We will wait MIN_RESET_DELAY clock ticks after the last reset so - * we can avoid the drive not being ready. - */ - save_flags(flags); - sti(); - temp = host->last_reset + MIN_RESET_DELAY; - while (jiffies < temp); - restore_flags(flags); - - update_timeout(SCpnt, SCpnt->timeout_per_command); - - /* - * We will use a queued command if possible, otherwise we will emulate the - * queuing and calling of completion function ourselves. - */ -#ifdef DEBUG - printk("internal_cmnd (host = %d, channel = %d, target = %d, " - "command = %p, buffer = %p, \nbufflen = %d, done = %p)\n", - SCpnt->host->host_no, SCpnt->channel, SCpnt->target, SCpnt->cmnd, - SCpnt->buffer, SCpnt->bufflen, SCpnt->done); -#endif - - if (host->can_queue) - { -#ifdef DEBUG - printk("queuecommand : routine at %p\n", - host->hostt->queuecommand); -#endif - /* This locking tries to prevent all sorts of races between - * queuecommand and the interrupt code. In effect, - * we are only allowed to be in queuecommand once at - * any given time, and we can only be in the interrupt - * handler and the queuecommand function at the same time - * when queuecommand is called while servicing the - * interrupt. - */ - - if(!intr_count && SCpnt->host->irq) - disable_irq(SCpnt->host->irq); - - host->hostt->queuecommand (SCpnt, scsi_done); - - if(!intr_count && SCpnt->host->irq) - enable_irq(SCpnt->host->irq); - } - else - { - -#ifdef DEBUG - printk("command() : routine at %p\n", host->hostt->command); -#endif - temp=host->hostt->command (SCpnt); - SCpnt->result = temp; -#ifdef DEBUG_DELAY - clock = jiffies + 4 * HZ; - while (jiffies < clock); - printk("done(host = %d, result = %04x) : routine at %p\n", - host->host_no, temp, host->hostt->command); -#endif - scsi_done(SCpnt); - } -#ifdef DEBUG - printk("leaving internal_cmnd()\n"); -#endif -} - -static void scsi_request_sense (Scsi_Cmnd * SCpnt) -{ - unsigned int flags; - - save_flags(flags); - cli(); - SCpnt->flags |= WAS_SENSE | ASKED_FOR_SENSE; - update_timeout(SCpnt, SENSE_TIMEOUT); - restore_flags(flags); - - - memcpy ((void *) SCpnt->cmnd , (void *) generic_sense, - sizeof(generic_sense)); - - SCpnt->cmnd[1] = SCpnt->lun << 5; - SCpnt->cmnd[4] = sizeof(SCpnt->sense_buffer); - - SCpnt->request_buffer = &SCpnt->sense_buffer; - SCpnt->request_bufflen = sizeof(SCpnt->sense_buffer); - SCpnt->use_sg = 0; - SCpnt->cmd_len = COMMAND_SIZE(SCpnt->cmnd[0]); - internal_cmnd (SCpnt); -} - - - -/* - * scsi_do_cmd sends all the commands out to the low-level driver. It - * handles the specifics required for each low level driver - ie queued - * or non queued. It also prevents conflicts when different high level - * drivers go for the same host at the same time. - */ - -void scsi_do_cmd (Scsi_Cmnd * SCpnt, const void *cmnd , - void *buffer, unsigned bufflen, void (*done)(Scsi_Cmnd *), - int timeout, int retries) -{ - unsigned long flags; - struct Scsi_Host * host = SCpnt->host; - -#ifdef DEBUG - { - int i; - int target = SCpnt->target; - printk ("scsi_do_cmd (host = %d, channel = %d target = %d, " - "buffer =%p, bufflen = %d, done = %p, timeout = %d, " - "retries = %d)\n" - "command : " , host->host_no, SCpnt->channel, target, buffer, - bufflen, done, timeout, retries); - for (i = 0; i < 10; ++i) - printk ("%02x ", ((unsigned char *) cmnd)[i]); - printk("\n"); - } -#endif - - if (!host) - { - panic ("Invalid or not present host.\n"); - } - - - /* - * We must prevent reentrancy to the lowlevel host driver. This prevents - * it - we enter a loop until the host we want to talk to is not busy. - * Race conditions are prevented, as interrupts are disabled in between the - * time we check for the host being not busy, and the time we mark it busy - * ourselves. - */ - - save_flags(flags); - cli(); - SCpnt->pid = scsi_pid++; - - while (SCSI_BLOCK(host)) { - restore_flags(flags); - SCSI_SLEEP(&host->host_wait, SCSI_BLOCK(host)); - cli(); - } - - if (host->block) host_active = host; - - host->host_busy++; - restore_flags(flags); - - /* - * Our own function scsi_done (which marks the host as not busy, disables - * the timeout counter, etc) will be called by us or by the - * scsi_hosts[host].queuecommand() function needs to also call - * the completion function for the high level driver. - */ - - memcpy ((void *) SCpnt->data_cmnd , (const void *) cmnd, 12); -#if 0 - SCpnt->host = host; - SCpnt->channel = channel; - SCpnt->target = target; - SCpnt->lun = (SCpnt->data_cmnd[1] >> 5); -#endif - SCpnt->bufflen = bufflen; - SCpnt->buffer = buffer; - SCpnt->flags=0; - SCpnt->retries=0; - SCpnt->allowed=retries; - SCpnt->done = done; - SCpnt->timeout_per_command = timeout; - - memcpy ((void *) SCpnt->cmnd , (const void *) cmnd, 12); - /* Zero the sense buffer. Some host adapters automatically request - * sense on error. 0 is not a valid sense code. - */ - memset ((void *) SCpnt->sense_buffer, 0, sizeof SCpnt->sense_buffer); - SCpnt->request_buffer = buffer; - SCpnt->request_bufflen = bufflen; - SCpnt->old_use_sg = SCpnt->use_sg; - if (SCpnt->cmd_len == 0) - SCpnt->cmd_len = COMMAND_SIZE(SCpnt->cmnd[0]); - SCpnt->old_cmd_len = SCpnt->cmd_len; - - /* Start the timer ticking. */ - - SCpnt->internal_timeout = 0; - SCpnt->abort_reason = 0; - internal_cmnd (SCpnt); - -#ifdef DEBUG - printk ("Leaving scsi_do_cmd()\n"); -#endif -} - -static int check_sense (Scsi_Cmnd * SCpnt) -{ - /* If there is no sense information, request it. If we have already - * requested it, there is no point in asking again - the firmware must - * be confused. - */ - if (((SCpnt->sense_buffer[0] & 0x70) >> 4) != 7) { - if(!(SCpnt->flags & ASKED_FOR_SENSE)) - return SUGGEST_SENSE; - else - return SUGGEST_RETRY; - } - - SCpnt->flags &= ~ASKED_FOR_SENSE; - -#ifdef DEBUG_INIT - printk("scsi%d, channel%d : ", SCpnt->host->host_no, SCpnt->channel); - print_sense("", SCpnt); - printk("\n"); -#endif - if (SCpnt->sense_buffer[2] & 0xe0) - return SUGGEST_ABORT; - - switch (SCpnt->sense_buffer[2] & 0xf) - { - case NO_SENSE: - return 0; - case RECOVERED_ERROR: - return SUGGEST_IS_OK; - - case ABORTED_COMMAND: - return SUGGEST_RETRY; - case NOT_READY: - case UNIT_ATTENTION: - /* - * If we are expecting a CC/UA because of a bus reset that we - * performed, treat this just as a retry. Otherwise this is - * information that we should pass up to the upper-level driver - * so that we can deal with it there. - */ - if( SCpnt->device->expecting_cc_ua ) - { - SCpnt->device->expecting_cc_ua = 0; - return SUGGEST_RETRY; - } - return SUGGEST_ABORT; - - /* these three are not supported */ - case COPY_ABORTED: - case VOLUME_OVERFLOW: - case MISCOMPARE: - - case MEDIUM_ERROR: - return SUGGEST_REMAP; - case BLANK_CHECK: - case DATA_PROTECT: - case HARDWARE_ERROR: - case ILLEGAL_REQUEST: - default: - return SUGGEST_ABORT; - } -} - -/* This function is the mid-level interrupt routine, which decides how - * to handle error conditions. Each invocation of this function must - * do one and *only* one of the following: - * - * (1) Call last_cmnd[host].done. This is done for fatal errors and - * normal completion, and indicates that the handling for this - * request is complete. - * (2) Call internal_cmnd to requeue the command. This will result in - * scsi_done being called again when the retry is complete. - * (3) Call scsi_request_sense. This asks the host adapter/drive for - * more information about the error condition. When the information - * is available, scsi_done will be called again. - * (4) Call reset(). This is sort of a last resort, and the idea is that - * this may kick things loose and get the drive working again. reset() - * automatically calls scsi_request_sense, and thus scsi_done will be - * called again once the reset is complete. - * - * If none of the above actions are taken, the drive in question - * will hang. If more than one of the above actions are taken by - * scsi_done, then unpredictable behavior will result. - */ -static void scsi_done (Scsi_Cmnd * SCpnt) -{ - int status=0; - int exit=0; - int checked; - int oldto; - struct Scsi_Host * host = SCpnt->host; - int result = SCpnt->result; - oldto = update_timeout(SCpnt, 0); - -#ifdef DEBUG_TIMEOUT - if(result) printk("Non-zero result in scsi_done %x %d:%d\n", - result, SCpnt->target, SCpnt->lun); -#endif - - /* If we requested an abort, (and we got it) then fix up the return - * status to say why - */ - if(host_byte(result) == DID_ABORT && SCpnt->abort_reason) - SCpnt->result = result = (result & 0xff00ffff) | - (SCpnt->abort_reason << 16); - - -#define FINISHED 0 -#define MAYREDO 1 -#define REDO 3 -#define PENDING 4 - -#ifdef DEBUG - printk("In scsi_done(host = %d, result = %06x)\n", host->host_no, result); -#endif - - if(SCpnt->flags & WAS_SENSE) - { - SCpnt->use_sg = SCpnt->old_use_sg; - SCpnt->cmd_len = SCpnt->old_cmd_len; - } - - switch (host_byte(result)) - { - case DID_OK: - if (status_byte(result) && (SCpnt->flags & WAS_SENSE)) - /* Failed to obtain sense information */ - { - SCpnt->flags &= ~WAS_SENSE; - SCpnt->internal_timeout &= ~SENSE_TIMEOUT; - - if (!(SCpnt->flags & WAS_RESET)) - { - printk("scsi%d : channel %d target %d lun %d request sense" - " failed, performing reset.\n", - SCpnt->host->host_no, SCpnt->channel, SCpnt->target, - SCpnt->lun); - scsi_reset(SCpnt, FALSE); - return; - } - else - { - exit = (DRIVER_HARD | SUGGEST_ABORT); - status = FINISHED; - } - } - else switch(msg_byte(result)) - { - case COMMAND_COMPLETE: - switch (status_byte(result)) - { - case GOOD: - if (SCpnt->flags & WAS_SENSE) - { -#ifdef DEBUG - printk ("In scsi_done, GOOD status, COMMAND COMPLETE, parsing sense information.\n"); -#endif - SCpnt->flags &= ~WAS_SENSE; - SCpnt->internal_timeout &= ~SENSE_TIMEOUT; - - switch (checked = check_sense(SCpnt)) - { - case SUGGEST_SENSE: - case 0: -#ifdef DEBUG - printk("NO SENSE. status = REDO\n"); -#endif - update_timeout(SCpnt, oldto); - status = REDO; - break; - case SUGGEST_IS_OK: - break; - case SUGGEST_REMAP: - case SUGGEST_RETRY: -#ifdef DEBUG - printk("SENSE SUGGEST REMAP or SUGGEST RETRY - status = MAYREDO\n"); -#endif - status = MAYREDO; - exit = DRIVER_SENSE | SUGGEST_RETRY; - break; - case SUGGEST_ABORT: -#ifdef DEBUG - printk("SENSE SUGGEST ABORT - status = FINISHED"); -#endif - status = FINISHED; - exit = DRIVER_SENSE | SUGGEST_ABORT; - break; - default: - printk ("Internal error %s %d \n", __FILE__, - __LINE__); - } - } /* end WAS_SENSE */ - else - { -#ifdef DEBUG - printk("COMMAND COMPLETE message returned, status = FINISHED. \n"); -#endif - exit = DRIVER_OK; - status = FINISHED; - } - break; - - case CHECK_CONDITION: - switch (check_sense(SCpnt)) - { - case 0: - update_timeout(SCpnt, oldto); - status = REDO; - break; - case SUGGEST_REMAP: - case SUGGEST_RETRY: - status = MAYREDO; - exit = DRIVER_SENSE | SUGGEST_RETRY; - break; - case SUGGEST_ABORT: - status = FINISHED; - exit = DRIVER_SENSE | SUGGEST_ABORT; - break; - case SUGGEST_SENSE: - scsi_request_sense (SCpnt); - status = PENDING; - break; - } - break; - - case CONDITION_GOOD: - case INTERMEDIATE_GOOD: - case INTERMEDIATE_C_GOOD: - break; - - case BUSY: - update_timeout(SCpnt, oldto); - status = REDO; - break; - - case RESERVATION_CONFLICT: - printk("scsi%d, channel %d : RESERVATION CONFLICT performing" - " reset.\n", SCpnt->host->host_no, SCpnt->channel); - scsi_reset(SCpnt, FALSE); - return; -#if 0 - exit = DRIVER_SOFT | SUGGEST_ABORT; - status = MAYREDO; - break; -#endif - default: - printk ("Internal error %s %d \n" - "status byte = %d \n", __FILE__, - __LINE__, status_byte(result)); - - } - break; - default: - panic("scsi: unsupported message byte %d received\n", - msg_byte(result)); - } - break; - case DID_TIME_OUT: -#ifdef DEBUG - printk("Host returned DID_TIME_OUT - "); -#endif - - if (SCpnt->flags & WAS_TIMEDOUT) - { -#ifdef DEBUG - printk("Aborting\n"); -#endif - /* - Allow TEST_UNIT_READY and INQUIRY commands to timeout early - without causing resets. All other commands should be retried. - */ - if (SCpnt->cmnd[0] != TEST_UNIT_READY && - SCpnt->cmnd[0] != INQUIRY) - status = MAYREDO; - exit = (DRIVER_TIMEOUT | SUGGEST_ABORT); - } - else - { -#ifdef DEBUG - printk ("Retrying.\n"); -#endif - SCpnt->flags |= WAS_TIMEDOUT; - SCpnt->internal_timeout &= ~IN_ABORT; - status = REDO; - } - break; - case DID_BUS_BUSY: - case DID_PARITY: - status = REDO; - break; - case DID_NO_CONNECT: -#ifdef DEBUG - printk("Couldn't connect.\n"); -#endif - exit = (DRIVER_HARD | SUGGEST_ABORT); - break; - case DID_ERROR: - status = MAYREDO; - exit = (DRIVER_HARD | SUGGEST_ABORT); - break; - case DID_BAD_TARGET: - case DID_ABORT: - exit = (DRIVER_INVALID | SUGGEST_ABORT); - break; - case DID_RESET: - if (SCpnt->flags & IS_RESETTING) - { - SCpnt->flags &= ~IS_RESETTING; - status = REDO; - break; - } - - if(msg_byte(result) == GOOD && - status_byte(result) == CHECK_CONDITION) { - switch (check_sense(SCpnt)) { - case 0: - update_timeout(SCpnt, oldto); - status = REDO; - break; - case SUGGEST_REMAP: - case SUGGEST_RETRY: - status = MAYREDO; - exit = DRIVER_SENSE | SUGGEST_RETRY; - break; - case SUGGEST_ABORT: - status = FINISHED; - exit = DRIVER_SENSE | SUGGEST_ABORT; - break; - case SUGGEST_SENSE: - scsi_request_sense (SCpnt); - status = PENDING; - break; - } - } else { - status=REDO; - exit = SUGGEST_RETRY; - } - break; - default : - exit = (DRIVER_ERROR | SUGGEST_DIE); - } - - switch (status) - { - case FINISHED: - case PENDING: - break; - case MAYREDO: -#ifdef DEBUG - printk("In MAYREDO, allowing %d retries, have %d\n", - SCpnt->allowed, SCpnt->retries); -#endif - if ((++SCpnt->retries) < SCpnt->allowed) - { - if ((SCpnt->retries >= (SCpnt->allowed >> 1)) - && !(jiffies < SCpnt->host->last_reset + MIN_RESET_PERIOD) - && !(SCpnt->flags & WAS_RESET)) - { - printk("scsi%d channel %d : resetting for second half of retries.\n", - SCpnt->host->host_no, SCpnt->channel); - scsi_reset(SCpnt, FALSE); - break; - } - - } - else - { - status = FINISHED; - break; - } - /* fall through to REDO */ - - case REDO: - - if (SCpnt->flags & WAS_SENSE) - scsi_request_sense(SCpnt); - else - { - memcpy ((void *) SCpnt->cmnd, - (void*) SCpnt->data_cmnd, - sizeof(SCpnt->data_cmnd)); - SCpnt->request_buffer = SCpnt->buffer; - SCpnt->request_bufflen = SCpnt->bufflen; - SCpnt->use_sg = SCpnt->old_use_sg; - SCpnt->cmd_len = SCpnt->old_cmd_len; - internal_cmnd (SCpnt); - } - break; - default: - INTERNAL_ERROR; - } - - if (status == FINISHED) { -#ifdef DEBUG - printk("Calling done function - at address %p\n", SCpnt->done); -#endif - host->host_busy--; /* Indicate that we are free */ - - if (host->block && host->host_busy == 0) { - host_active = NULL; - - /* For block devices "wake_up" is done in end_scsi_request */ - if (MAJOR(SCpnt->request.rq_dev) != SCSI_DISK_MAJOR && - MAJOR(SCpnt->request.rq_dev) != SCSI_CDROM_MAJOR) { - struct Scsi_Host * next; - - for (next = host->block; next != host; next = next->block) - wake_up(&next->host_wait); - } - - } - - wake_up(&host->host_wait); - SCpnt->result = result | ((exit & 0xff) << 24); - SCpnt->use_sg = SCpnt->old_use_sg; - SCpnt->cmd_len = SCpnt->old_cmd_len; - SCpnt->done (SCpnt); - } - -#undef FINISHED -#undef REDO -#undef MAYREDO -#undef PENDING -} - -/* - * The scsi_abort function interfaces with the abort() function of the host - * we are aborting, and causes the current command to not complete. The - * caller should deal with any error messages or status returned on the - * next call. - * - * This will not be called reentrantly for a given host. - */ - -/* - * Since we're nice guys and specified that abort() and reset() - * can be non-reentrant. The internal_timeout flags are used for - * this. - */ - - -int scsi_abort (Scsi_Cmnd * SCpnt, int why, int pid) -{ - int oldto; - unsigned long flags; - struct Scsi_Host * host = SCpnt->host; - - while(1) - { - save_flags(flags); - cli(); - - /* - * Protect against races here. If the command is done, or we are - * on a different command forget it. - */ - if (SCpnt->request.rq_status == RQ_INACTIVE || pid != SCpnt->pid) { - restore_flags(flags); - return 0; - } - - if (SCpnt->internal_timeout & IN_ABORT) - { - restore_flags(flags); - while (SCpnt->internal_timeout & IN_ABORT) - barrier(); - } - else - { - SCpnt->internal_timeout |= IN_ABORT; - oldto = update_timeout(SCpnt, ABORT_TIMEOUT); - - if ((SCpnt->flags & IS_RESETTING) && SCpnt->device->soft_reset) { - /* OK, this command must have died when we did the - * reset. The device itself must have lied. - */ - printk("Stale command on %d %d:%d appears to have died when" - " the bus was reset\n", - SCpnt->channel, SCpnt->target, SCpnt->lun); - } - - restore_flags(flags); - if (!host->host_busy) { - SCpnt->internal_timeout &= ~IN_ABORT; - update_timeout(SCpnt, oldto); - return 0; - } - printk("scsi : aborting command due to timeout : pid %lu, scsi%d," - " channel %d, id %d, lun %d ", - SCpnt->pid, SCpnt->host->host_no, (int) SCpnt->channel, - (int) SCpnt->target, (int) SCpnt->lun); - print_command (SCpnt->cmnd); - if (SCpnt->request.rq_status == RQ_INACTIVE || pid != SCpnt->pid) - return 0; - SCpnt->abort_reason = why; - switch(host->hostt->abort(SCpnt)) { - /* We do not know how to abort. Try waiting another - * time increment and see if this helps. Set the - * WAS_TIMEDOUT flag set so we do not try this twice - */ - case SCSI_ABORT_BUSY: /* Tough call - returning 1 from - * this is too severe - */ - case SCSI_ABORT_SNOOZE: - if(why == DID_TIME_OUT) { - save_flags(flags); - cli(); - SCpnt->internal_timeout &= ~IN_ABORT; - if(SCpnt->flags & WAS_TIMEDOUT) { - restore_flags(flags); - return 1; /* Indicate we cannot handle this. - * We drop down into the reset handler - * and try again - */ - } else { - SCpnt->flags |= WAS_TIMEDOUT; - oldto = SCpnt->timeout_per_command; - update_timeout(SCpnt, oldto); - } - restore_flags(flags); - } - return 0; - case SCSI_ABORT_PENDING: - if(why != DID_TIME_OUT) { - save_flags(flags); - cli(); - update_timeout(SCpnt, oldto); - restore_flags(flags); - } - return 0; - case SCSI_ABORT_SUCCESS: - /* We should have already aborted this one. No - * need to adjust timeout - */ - SCpnt->internal_timeout &= ~IN_ABORT; - return 0; - case SCSI_ABORT_NOT_RUNNING: - SCpnt->internal_timeout &= ~IN_ABORT; - update_timeout(SCpnt, 0); - return 0; - case SCSI_ABORT_ERROR: - default: - SCpnt->internal_timeout &= ~IN_ABORT; - return 1; - } - } - } -} - - -/* Mark a single SCSI Device as having been reset. */ - -static inline void scsi_mark_device_reset(Scsi_Device *Device) -{ - Device->was_reset = 1; - Device->expecting_cc_ua = 1; -} - - -/* Mark all SCSI Devices on a specific Host as having been reset. */ - -void scsi_mark_host_bus_reset(struct Scsi_Host *Host) -{ - Scsi_Cmnd *SCpnt; - for(SCpnt = Host->host_queue; SCpnt; SCpnt = SCpnt->next) - scsi_mark_device_reset(SCpnt->device); -} - - -int scsi_reset (Scsi_Cmnd * SCpnt, int bus_reset_flag) -{ - int temp, oldto; - unsigned long flags; - Scsi_Cmnd * SCpnt1; - struct Scsi_Host * host = SCpnt->host; - - printk("SCSI bus is being reset for host %d.\n", - host->host_no); - - /* - * First of all, we need to make a recommendation to the low-level - * driver as to whether a BUS_DEVICE_RESET should be performed, - * or whether we should do a full BUS_RESET. There is no simple - * algorithm here - we basically use a series of heuristics - * to determine what we should do. - */ - SCpnt->host->suggest_bus_reset = FALSE; - - /* - * First see if all of the active devices on the bus have - * been jammed up so that we are attempting resets. If so, - * then suggest a bus reset. Forcing a bus reset could - * result in some race conditions, but no more than - * you would usually get with timeouts. We will cross - * that bridge when we come to it. - */ - SCpnt1 = host->host_queue; - while(SCpnt1) { - if( SCpnt1->request.rq_status != RQ_INACTIVE - && (SCpnt1->flags & (WAS_RESET | IS_RESETTING)) == 0 ) - break; - SCpnt1 = SCpnt1->next; - } - if( SCpnt1 == NULL ) { - SCpnt->host->suggest_bus_reset = TRUE; - } - - - /* - * If the code that called us is suggesting a hard reset, then - * definitely request it. This usually occurs because a - * BUS_DEVICE_RESET times out. - */ - if( bus_reset_flag ) { - SCpnt->host->suggest_bus_reset = TRUE; - } - - while (1) { - save_flags(flags); - cli(); - if (SCpnt->internal_timeout & IN_RESET) - { - restore_flags(flags); - while (SCpnt->internal_timeout & IN_RESET) - barrier(); - } - else - { - SCpnt->internal_timeout |= IN_RESET; - oldto = update_timeout(SCpnt, RESET_TIMEOUT); - - if (host->host_busy) - { - restore_flags(flags); - SCpnt1 = host->host_queue; - while(SCpnt1) { - if (SCpnt1->request.rq_status != RQ_INACTIVE) { -#if 0 - if (!(SCpnt1->flags & IS_RESETTING) && - !(SCpnt1->internal_timeout & IN_ABORT)) - scsi_abort(SCpnt1, DID_RESET, SCpnt->pid); -#endif - SCpnt1->flags |= (WAS_RESET | IS_RESETTING); - } - SCpnt1 = SCpnt1->next; - } - - host->last_reset = jiffies; - temp = host->hostt->reset(SCpnt); - host->last_reset = jiffies; - } - else - { - if (!host->block) host->host_busy++; - restore_flags(flags); - host->last_reset = jiffies; - SCpnt->flags |= (WAS_RESET | IS_RESETTING); - temp = host->hostt->reset(SCpnt); - host->last_reset = jiffies; - if (!host->block) host->host_busy--; - } - -#ifdef DEBUG - printk("scsi reset function returned %d\n", temp); -#endif - - /* - * Now figure out what we need to do, based upon - * what the low level driver said that it did. - * If the result is SCSI_RESET_SUCCESS, SCSI_RESET_PENDING, - * or SCSI_RESET_WAKEUP, then the low level driver did a - * bus device reset or bus reset, so we should go through - * and mark one or all of the devices on that bus - * as having been reset. - */ - switch(temp & SCSI_RESET_ACTION) { - case SCSI_RESET_SUCCESS: - if (temp & SCSI_RESET_BUS_RESET) - scsi_mark_host_bus_reset(host); - else scsi_mark_device_reset(SCpnt->device); - save_flags(flags); - cli(); - SCpnt->internal_timeout &= ~IN_RESET; - update_timeout(SCpnt, oldto); - restore_flags(flags); - return 0; - case SCSI_RESET_PENDING: - if (temp & SCSI_RESET_BUS_RESET) - scsi_mark_host_bus_reset(host); - else scsi_mark_device_reset(SCpnt->device); - return 0; - case SCSI_RESET_PUNT: - SCpnt->internal_timeout &= ~IN_RESET; - scsi_request_sense (SCpnt); - return 0; - case SCSI_RESET_WAKEUP: - if (temp & SCSI_RESET_BUS_RESET) - scsi_mark_host_bus_reset(host); - else scsi_mark_device_reset(SCpnt->device); - SCpnt->internal_timeout &= ~IN_RESET; - scsi_request_sense (SCpnt); - /* - * Since a bus reset was performed, we - * need to wake up each and every command - * that was active on the bus. - */ - if( temp & SCSI_RESET_BUS_RESET ) - { - SCpnt1 = host->host_queue; - while(SCpnt1) { - if( SCpnt->request.rq_status != RQ_INACTIVE - && SCpnt1 != SCpnt) - scsi_request_sense (SCpnt); - SCpnt1 = SCpnt1->next; - } - } - return 0; - case SCSI_RESET_SNOOZE: - /* In this case, we set the timeout field to 0 - * so that this command does not time out any more, - * and we return 1 so that we get a message on the - * screen. - */ - save_flags(flags); - cli(); - SCpnt->internal_timeout &= ~IN_RESET; - update_timeout(SCpnt, 0); - restore_flags(flags); - /* If you snooze, you lose... */ - case SCSI_RESET_ERROR: - default: - return 1; - } - - return temp; - } - } -} - - -static void scsi_main_timeout(void) -{ - /* - * We must not enter update_timeout with a timeout condition still pending. - */ - - int timed_out, pid; - unsigned long flags; - struct Scsi_Host * host; - Scsi_Cmnd * SCpnt = NULL; - - do { - save_flags(flags); - cli(); - - update_timeout(NULL, 0); - /* - * Find all timers such that they have 0 or negative (shouldn't happen) - * time remaining on them. - */ - - timed_out = 0; - for(host = scsi_hostlist; host; host = host->next) { - for(SCpnt = host->host_queue; SCpnt; SCpnt = SCpnt->next) - if (SCpnt->timeout == -1) - { - SCpnt->timeout = 0; - pid = SCpnt->pid; - restore_flags(flags); - scsi_times_out(SCpnt, pid); - ++timed_out; - save_flags(flags); - cli(); - } - } - } while (timed_out); - restore_flags(flags); -} - -/* - * The strategy is to cause the timer code to call scsi_times_out() - * when the soonest timeout is pending. - * The arguments are used when we are queueing a new command, because - * we do not want to subtract the time used from this time, but when we - * set the timer, we want to take this value into account. - */ - -static int update_timeout(Scsi_Cmnd * SCset, int timeout) -{ - unsigned int least, used; - unsigned int oldto; - unsigned long flags; - struct Scsi_Host * host; - Scsi_Cmnd * SCpnt = NULL; - - save_flags(flags); - cli(); - - /* - * Figure out how much time has passed since the last time the timeouts - * were updated - */ - used = (time_start) ? (jiffies - time_start) : 0; - - /* - * Find out what is due to timeout soonest, and adjust all timeouts for - * the amount of time that has passed since the last time we called - * update_timeout. - */ - - oldto = 0; - - if(SCset){ - oldto = SCset->timeout - used; - SCset->timeout = timeout + used; - } - - least = 0xffffffff; - - for(host = scsi_hostlist; host; host = host->next) - for(SCpnt = host->host_queue; SCpnt; SCpnt = SCpnt->next) - if (SCpnt->timeout > 0) { - SCpnt->timeout -= used; - if(SCpnt->timeout <= 0) SCpnt->timeout = -1; - if(SCpnt->timeout > 0 && SCpnt->timeout < least) - least = SCpnt->timeout; - } - - /* - * If something is due to timeout again, then we will set the next timeout - * interrupt to occur. Otherwise, timeouts are disabled. - */ - - if (least != 0xffffffff) - { - time_start = jiffies; - timer_table[SCSI_TIMER].expires = (time_elapsed = least) + jiffies; - timer_active |= 1 << SCSI_TIMER; - } - else - { - timer_table[SCSI_TIMER].expires = time_start = time_elapsed = 0; - timer_active &= ~(1 << SCSI_TIMER); - } - restore_flags(flags); - return oldto; -} - -#ifdef CONFIG_MODULES -static int scsi_register_host(Scsi_Host_Template *); -static void scsi_unregister_host(Scsi_Host_Template *); -#endif - -void *scsi_malloc(unsigned int len) -{ - unsigned int nbits, mask; - unsigned long flags; - int i, j; - if(len % SECTOR_SIZE != 0 || len > PAGE_SIZE) - return NULL; - - save_flags(flags); - cli(); - nbits = len >> 9; - mask = (1 << nbits) - 1; - - for(i=0;i < dma_sectors / SECTORS_PER_PAGE; i++) - for(j=0; j<=SECTORS_PER_PAGE - nbits; j++){ - if ((dma_malloc_freelist[i] & (mask << j)) == 0){ - dma_malloc_freelist[i] |= (mask << j); - restore_flags(flags); - dma_free_sectors -= nbits; -#ifdef DEBUG - printk("SMalloc: %d %p\n",len, dma_malloc_pages[i] + (j << 9)); -#endif - return (void *) ((unsigned long) dma_malloc_pages[i] + (j << 9)); - } - } - restore_flags(flags); - return NULL; /* Nope. No more */ -} - -int scsi_free(void *obj, unsigned int len) -{ - unsigned int page, sector, nbits, mask; - unsigned long flags; - -#ifdef DEBUG - printk("scsi_free %p %d\n",obj, len); -#endif - - for (page = 0; page < dma_sectors / SECTORS_PER_PAGE; page++) { - unsigned long page_addr = (unsigned long) dma_malloc_pages[page]; - if ((unsigned long) obj >= page_addr && - (unsigned long) obj < page_addr + PAGE_SIZE) - { - sector = (((unsigned long) obj) - page_addr) >> 9; - - nbits = len >> 9; - mask = (1 << nbits) - 1; - - if ((mask << sector) >= (1 << SECTORS_PER_PAGE)) - panic ("scsi_free:Bad memory alignment"); - - save_flags(flags); - cli(); - if((dma_malloc_freelist[page] & (mask << sector)) != (mask<<sector)) - panic("scsi_free:Trying to free unused memory"); - - dma_free_sectors += nbits; - dma_malloc_freelist[page] &= ~(mask << sector); - restore_flags(flags); - return 0; - } - } - panic("scsi_free:Bad offset"); -} - - -int scsi_loadable_module_flag; /* Set after we scan builtin drivers */ - -void * scsi_init_malloc(unsigned int size, int priority) -{ - void * retval; - - /* - * For buffers used by the DMA pool, we assume page aligned - * structures. - */ - if ((size % PAGE_SIZE) == 0) { - int order, a_size; - for (order = 0, a_size = PAGE_SIZE; - a_size < size; order++, a_size <<= 1) - ; - retval = (void *) __get_dma_pages(priority & GFP_LEVEL_MASK, - order); - } else - retval = kmalloc(size, priority); - - if (retval) - memset(retval, 0, size); - return retval; -} - - -void scsi_init_free(char * ptr, unsigned int size) -{ - /* - * We need this special code here because the DMA pool assumes - * page aligned data. Besides, it is wasteful to allocate - * page sized chunks with kmalloc. - */ - if ((size % PAGE_SIZE) == 0) { - int order, a_size; - - for (order = 0, a_size = PAGE_SIZE; - a_size < size; order++, a_size <<= 1) - ; - free_pages((unsigned long)ptr, order); - } else - kfree(ptr); -} - -void scsi_build_commandblocks(Scsi_Device * SDpnt) -{ - int j; - Scsi_Cmnd * SCpnt; - struct Scsi_Host * host = NULL; - - for(j=0;j<SDpnt->host->cmd_per_lun;j++){ - SCpnt = (Scsi_Cmnd *) scsi_init_malloc(sizeof(Scsi_Cmnd), GFP_ATOMIC); - SCpnt->host = SDpnt->host; - SCpnt->device = SDpnt; - SCpnt->target = SDpnt->id; - SCpnt->lun = SDpnt->lun; - SCpnt->channel = SDpnt->channel; - SCpnt->request.rq_status = RQ_INACTIVE; - SCpnt->use_sg = 0; - SCpnt->old_use_sg = 0; - SCpnt->old_cmd_len = 0; - SCpnt->timeout = 0; - SCpnt->underflow = 0; - SCpnt->transfersize = 0; - SCpnt->host_scribble = NULL; - host = SDpnt->host; - if(host->host_queue) - host->host_queue->prev = SCpnt; - SCpnt->next = host->host_queue; - SCpnt->prev = NULL; - host->host_queue = SCpnt; - } - SDpnt->has_cmdblocks = 1; -} - -/* - * scsi_dev_init() is our initialization routine, which in turn calls host - * initialization, bus scanning, and sd/st initialization routines. - */ - -int scsi_dev_init(void) -{ - Scsi_Device * SDpnt; - struct Scsi_Host * shpnt; - struct Scsi_Device_Template * sdtpnt; -#ifdef FOO_ON_YOU - return; -#endif - - /* Yes we're here... */ - dispatch_scsi_info_ptr = dispatch_scsi_info; - - /* Init a few things so we can "malloc" memory. */ - scsi_loadable_module_flag = 0; - - timer_table[SCSI_TIMER].fn = scsi_main_timeout; - timer_table[SCSI_TIMER].expires = 0; - -#ifdef CONFIG_MODULES - register_symtab(&scsi_symbol_table); -#endif - - /* Register the /proc/scsi/scsi entry */ -#if CONFIG_PROC_FS - proc_scsi_register(0, &proc_scsi_scsi); -#endif - - /* initialize all hosts */ - scsi_init(); - - scsi_devices = (Scsi_Device *) NULL; - - for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) - scan_scsis(shpnt,0,0,0,0); /* scan for scsi devices */ - -#if 0 - printk("scsi : detected "); - for (sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) - if (sdtpnt->dev_noticed && sdtpnt->name) - printk("%d SCSI %s%s ", sdtpnt->dev_noticed, sdtpnt->name, - (sdtpnt->dev_noticed != 1) ? "s" : ""); - printk("total.\n"); -#endif - - for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) - if(sdtpnt->init && sdtpnt->dev_noticed) (*sdtpnt->init)(); - - for (SDpnt=scsi_devices; SDpnt; SDpnt = SDpnt->next) { - SDpnt->scsi_request_fn = NULL; - for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) - if(sdtpnt->attach) (*sdtpnt->attach)(SDpnt); - if(SDpnt->attached) scsi_build_commandblocks(SDpnt); - } - - - /* - * This should build the DMA pool. - */ - resize_dma_pool(); - - /* - * OK, now we finish the initialization by doing spin-up, read - * capacity, etc, etc - */ - for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) - if(sdtpnt->finish && sdtpnt->nr_dev) - (*sdtpnt->finish)(); - - scsi_loadable_module_flag = 1; - - return 0; -} - -static void print_inquiry(unsigned char *data) -{ - int i; - - printk(" Vendor: "); - for (i = 8; i < 16; i++) - { - if (data[i] >= 0x20 && i < data[4] + 5) - printk("%c", data[i]); - else - printk(" "); - } - - printk(" Model: "); - for (i = 16; i < 32; i++) - { - if (data[i] >= 0x20 && i < data[4] + 5) - printk("%c", data[i]); - else - printk(" "); - } - - printk(" Rev: "); - for (i = 32; i < 36; i++) - { - if (data[i] >= 0x20 && i < data[4] + 5) - printk("%c", data[i]); - else - printk(" "); - } - - printk("\n"); - - i = data[0] & 0x1f; - - printk(" Type: %s ", - i < MAX_SCSI_DEVICE_CODE ? scsi_device_types[i] : "Unknown " ); - printk(" ANSI SCSI revision: %02x", data[2] & 0x07); - if ((data[2] & 0x07) == 1 && (data[3] & 0x0f) == 1) - printk(" CCS\n"); - else - printk("\n"); -} - - -#ifdef CONFIG_PROC_FS -int scsi_proc_info(char *buffer, char **start, off_t offset, int length, - int hostno, int inout) -{ - Scsi_Device *scd; - struct Scsi_Host *HBA_ptr; - int parameter[4]; - char *p; - int i,size, len = 0; - off_t begin = 0; - off_t pos = 0; - - scd = scsi_devices; - HBA_ptr = scsi_hostlist; - - if(inout == 0) { - size = sprintf(buffer+len,"Attached devices: %s\n", (scd)?"":"none"); - len += size; - pos = begin + len; - while (HBA_ptr) { -#if 0 - size += sprintf(buffer+len,"scsi%2d: %s\n", (int) HBA_ptr->host_no, - HBA_ptr->hostt->procname); - len += size; - pos = begin + len; -#endif - scd = scsi_devices; - while (scd) { - if (scd->host == HBA_ptr) { - proc_print_scsidevice(scd, buffer, &size, len); - len += size; - pos = begin + len; - - if (pos < offset) { - len = 0; - begin = pos; - } - if (pos > offset + length) - goto stop_output; - } - scd = scd->next; - } - HBA_ptr = HBA_ptr->next; - } - - stop_output: - *start=buffer+(offset-begin); /* Start of wanted data */ - len-=(offset-begin); /* Start slop */ - if(len>length) - len = length; /* Ending slop */ - return (len); - } - - /* - * Usage: echo "scsi singledevice 0 1 2 3" >/proc/scsi/scsi - * with "0 1 2 3" replaced by your "Host Channel Id Lun". - * Consider this feature BETA. - * CAUTION: This is not for hotplugging your peripherals. As - * SCSI was not designed for this you could damage your - * hardware ! - * However perhaps it is legal to switch on an - * already connected device. It is perhaps not - * guaranteed this device doesn't corrupt an ongoing data transfer. - */ - if(!buffer || length < 25 || strncmp("scsi", buffer, 4)) - return(-EINVAL); - - if(!strncmp("singledevice", buffer + 5, 12)) { - p = buffer + 17; - - for(i=0; i<4; i++) { - p++; - parameter[i] = simple_strtoul(p, &p, 0); - } - printk("scsi singledevice %d %d %d %d\n", parameter[0], parameter[1], - parameter[2], parameter[3]); - - while(scd && (scd->host->host_no != parameter[0] - || scd->channel != parameter[1] - || scd->id != parameter[2] - || scd->lun != parameter[3])) { - scd = scd->next; - } - if(scd) - return(-ENOSYS); /* We do not yet support unplugging */ - while(HBA_ptr && HBA_ptr->host_no != parameter[0]) - HBA_ptr = HBA_ptr->next; - - if(!HBA_ptr) - return(-ENXIO); - - scan_scsis (HBA_ptr, 1, parameter[1], parameter[2], parameter[3]); - return(length); - } - return(-EINVAL); -} -#endif - -/* - * Go through the device list and recompute the most appropriate size - * for the dma pool. Then grab more memory (as required). - */ -static void resize_dma_pool(void) -{ - int i; - unsigned long size; - struct Scsi_Host * shpnt; - struct Scsi_Host * host = NULL; - Scsi_Device * SDpnt; - unsigned long flags; - FreeSectorBitmap * new_dma_malloc_freelist = NULL; - unsigned int new_dma_sectors = 0; - unsigned int new_need_isa_buffer = 0; - unsigned char ** new_dma_malloc_pages = NULL; - - if( !scsi_devices ) - { - /* - * Free up the DMA pool. - */ - if( dma_free_sectors != dma_sectors ) - panic("SCSI DMA pool memory leak %d %d\n",dma_free_sectors,dma_sectors); - - for(i=0; i < dma_sectors / SECTORS_PER_PAGE; i++) - scsi_init_free(dma_malloc_pages[i], PAGE_SIZE); - if (dma_malloc_pages) - scsi_init_free((char *) dma_malloc_pages, - (dma_sectors / SECTORS_PER_PAGE)*sizeof(*dma_malloc_pages)); - dma_malloc_pages = NULL; - if (dma_malloc_freelist) - scsi_init_free((char *) dma_malloc_freelist, - (dma_sectors / SECTORS_PER_PAGE)*sizeof(*dma_malloc_freelist)); - dma_malloc_freelist = NULL; - dma_sectors = 0; - dma_free_sectors = 0; - return; - } - /* Next, check to see if we need to extend the DMA buffer pool */ - - new_dma_sectors = 2*SECTORS_PER_PAGE; /* Base value we use */ - - if (high_memory-1 > ISA_DMA_THRESHOLD) - scsi_need_isa_bounce_buffers = 1; - else - scsi_need_isa_bounce_buffers = 0; - - if (scsi_devicelist) - for(shpnt=scsi_hostlist; shpnt; shpnt = shpnt->next) - new_dma_sectors += SECTORS_PER_PAGE; /* Increment for each host */ - - for (SDpnt=scsi_devices; SDpnt; SDpnt = SDpnt->next) { - host = SDpnt->host; - - if(SDpnt->type != TYPE_TAPE) - new_dma_sectors += ((host->sg_tablesize * - sizeof(struct scatterlist) + 511) >> 9) * - host->cmd_per_lun; - - if(host->unchecked_isa_dma && - scsi_need_isa_bounce_buffers && - SDpnt->type != TYPE_TAPE) { - new_dma_sectors += (PAGE_SIZE >> 9) * host->sg_tablesize * - host->cmd_per_lun; - new_need_isa_buffer++; - } - } - - /* limit DMA memory to 32MB: */ - new_dma_sectors = (new_dma_sectors + 15) & 0xfff0; - - /* - * We never shrink the buffers - this leads to - * race conditions that I would rather not even think - * about right now. - */ - if( new_dma_sectors < dma_sectors ) - new_dma_sectors = dma_sectors; - - if (new_dma_sectors) - { - size = (new_dma_sectors / SECTORS_PER_PAGE)*sizeof(FreeSectorBitmap); - new_dma_malloc_freelist = (FreeSectorBitmap *) scsi_init_malloc(size, GFP_ATOMIC); - memset(new_dma_malloc_freelist, 0, size); - - size = (new_dma_sectors / SECTORS_PER_PAGE)*sizeof(*new_dma_malloc_pages); - new_dma_malloc_pages = (unsigned char **) scsi_init_malloc(size, GFP_ATOMIC); - memset(new_dma_malloc_pages, 0, size); - } - - /* - * If we need more buffers, expand the list. - */ - if( new_dma_sectors > dma_sectors ) { - for(i=dma_sectors / SECTORS_PER_PAGE; i< new_dma_sectors / SECTORS_PER_PAGE; i++) - new_dma_malloc_pages[i] = (unsigned char *) - scsi_init_malloc(PAGE_SIZE, GFP_ATOMIC | GFP_DMA); - } - - /* When we dick with the actual DMA list, we need to - * protect things - */ - save_flags(flags); - cli(); - if (dma_malloc_freelist) - { - size = (dma_sectors / SECTORS_PER_PAGE)*sizeof(FreeSectorBitmap); - memcpy(new_dma_malloc_freelist, dma_malloc_freelist, size); - scsi_init_free((char *) dma_malloc_freelist, size); - } - dma_malloc_freelist = new_dma_malloc_freelist; - - if (dma_malloc_pages) - { - size = (dma_sectors / SECTORS_PER_PAGE)*sizeof(*dma_malloc_pages); - memcpy(new_dma_malloc_pages, dma_malloc_pages, size); - scsi_init_free((char *) dma_malloc_pages, size); - } - - dma_free_sectors += new_dma_sectors - dma_sectors; - dma_malloc_pages = new_dma_malloc_pages; - dma_sectors = new_dma_sectors; - need_isa_buffer = new_need_isa_buffer; - restore_flags(flags); -} - -#ifdef CONFIG_MODULES /* a big #ifdef block... */ - -/* - * This entry point should be called by a loadable module if it is trying - * add a low level scsi driver to the system. - */ -static int scsi_register_host(Scsi_Host_Template * tpnt) -{ - int pcount; - struct Scsi_Host * shpnt; - Scsi_Device * SDpnt; - struct Scsi_Device_Template * sdtpnt; - const char * name; - - if (tpnt->next || !tpnt->detect) return 1;/* Must be already loaded, or - * no detect routine available - */ - pcount = next_scsi_host; - if ((tpnt->present = tpnt->detect(tpnt))) - { - if(pcount == next_scsi_host) { - if(tpnt->present > 1) { - printk("Failure to register low-level scsi driver"); - scsi_unregister_host(tpnt); - return 1; - } - /* The low-level driver failed to register a driver. We - * can do this now. - */ - scsi_register(tpnt,0); - } - tpnt->next = scsi_hosts; /* Add to the linked list */ - scsi_hosts = tpnt; - - /* Add the new driver to /proc/scsi */ -#if CONFIG_PROC_FS - build_proc_dir_entries(tpnt); -#endif - - for(shpnt=scsi_hostlist; shpnt; shpnt = shpnt->next) - if(shpnt->hostt == tpnt) - { - if(tpnt->info) - name = tpnt->info(shpnt); - else - name = tpnt->name; - printk ("scsi%d : %s\n", /* And print a little message */ - shpnt->host_no, name); - } - - printk ("scsi : %d host%s.\n", next_scsi_host, - (next_scsi_host == 1) ? "" : "s"); - - scsi_make_blocked_list(); - - /* The next step is to call scan_scsis here. This generates the - * Scsi_Devices entries - */ - - for(shpnt=scsi_hostlist; shpnt; shpnt = shpnt->next) - if(shpnt->hostt == tpnt) scan_scsis(shpnt,0,0,0,0); - - for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) - if(sdtpnt->init && sdtpnt->dev_noticed) (*sdtpnt->init)(); - - /* Next we create the Scsi_Cmnd structures for this host */ - - for(SDpnt = scsi_devices; SDpnt; SDpnt = SDpnt->next) - if(SDpnt->host->hostt == tpnt) - { - for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) - if(sdtpnt->attach) (*sdtpnt->attach)(SDpnt); - if(SDpnt->attached) scsi_build_commandblocks(SDpnt); - } - - /* - * Now that we have all of the devices, resize the DMA pool, - * as required. */ - resize_dma_pool(); - - - /* This does any final handling that is required. */ - for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) - if(sdtpnt->finish && sdtpnt->nr_dev) - (*sdtpnt->finish)(); - } - -#if defined(USE_STATIC_SCSI_MEMORY) - printk ("SCSI memory: total %ldKb, used %ldKb, free %ldKb.\n", - (scsi_memory_upper_value - scsi_memory_lower_value) / 1024, - (scsi_init_memory_start - scsi_memory_lower_value) / 1024, - (scsi_memory_upper_value - scsi_init_memory_start) / 1024); -#endif - - MOD_INC_USE_COUNT; - return 0; -} - -/* - * Similarly, this entry point should be called by a loadable module if it - * is trying to remove a low level scsi driver from the system. - */ -static void scsi_unregister_host(Scsi_Host_Template * tpnt) -{ - Scsi_Host_Template * SHT, *SHTp; - Scsi_Device *sdpnt, * sdppnt, * sdpnt1; - Scsi_Cmnd * SCpnt; - unsigned long flags; - struct Scsi_Device_Template * sdtpnt; - struct Scsi_Host * shpnt, *sh1; - int pcount; - - /* First verify that this host adapter is completely free with no pending - * commands */ - - for(sdpnt = scsi_devices; sdpnt; sdpnt = sdpnt->next) - if(sdpnt->host->hostt == tpnt && sdpnt->host->hostt->usage_count - && *sdpnt->host->hostt->usage_count) return; - - for(shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) - { - if (shpnt->hostt != tpnt) continue; - for(SCpnt = shpnt->host_queue; SCpnt; SCpnt = SCpnt->next) - { - save_flags(flags); - cli(); - if(SCpnt->request.rq_status != RQ_INACTIVE) { - restore_flags(flags); - for(SCpnt = shpnt->host_queue; SCpnt; SCpnt = SCpnt->next) - if(SCpnt->request.rq_status == RQ_SCSI_DISCONNECTING) - SCpnt->request.rq_status = RQ_INACTIVE; - printk("Device busy???\n"); - return; - } - SCpnt->request.rq_status = RQ_SCSI_DISCONNECTING; /* Mark as busy */ - restore_flags(flags); - } - } - /* Next we detach the high level drivers from the Scsi_Device structures */ - - for(sdpnt = scsi_devices; sdpnt; sdpnt = sdpnt->next) - if(sdpnt->host->hostt == tpnt) - { - for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) - if(sdtpnt->detach) (*sdtpnt->detach)(sdpnt); - /* If something still attached, punt */ - if (sdpnt->attached) { - printk("Attached usage count = %d\n", sdpnt->attached); - return; - } - } - - /* Next we free up the Scsi_Cmnd structures for this host */ - - for(sdpnt = scsi_devices; sdpnt; sdpnt = sdpnt->next) - if(sdpnt->host->hostt == tpnt) - while (sdpnt->host->host_queue) { - SCpnt = sdpnt->host->host_queue->next; - scsi_init_free((char *) sdpnt->host->host_queue, sizeof(Scsi_Cmnd)); - sdpnt->host->host_queue = SCpnt; - if (SCpnt) SCpnt->prev = NULL; - sdpnt->has_cmdblocks = 0; - } - - /* Next free up the Scsi_Device structures for this host */ - - sdppnt = NULL; - for(sdpnt = scsi_devices; sdpnt; sdpnt = sdpnt1) - { - sdpnt1 = sdpnt->next; - if (sdpnt->host->hostt == tpnt) { - if (sdppnt) - sdppnt->next = sdpnt->next; - else - scsi_devices = sdpnt->next; - scsi_init_free((char *) sdpnt, sizeof (Scsi_Device)); - } else - sdppnt = sdpnt; - } - - /* Next we go through and remove the instances of the individual hosts - * that were detected */ - - shpnt = scsi_hostlist; - while(shpnt) { - sh1 = shpnt->next; - if(shpnt->hostt == tpnt) { - if(shpnt->loaded_as_module) { - pcount = next_scsi_host; - /* Remove the /proc/scsi directory entry */ -#if CONFIG_PROC_FS - proc_scsi_unregister(tpnt->proc_dir, - shpnt->host_no + PROC_SCSI_FILE); -#endif - if(tpnt->release) - (*tpnt->release)(shpnt); - else { - /* This is the default case for the release function. - * It should do the right thing for most correctly - * written host adapters. - */ - if (shpnt->irq) free_irq(shpnt->irq); - if (shpnt->dma_channel != 0xff) free_dma(shpnt->dma_channel); - if (shpnt->io_port && shpnt->n_io_port) - release_region(shpnt->io_port, shpnt->n_io_port); - } - if(pcount == next_scsi_host) scsi_unregister(shpnt); - tpnt->present--; - } - } - shpnt = sh1; - } - - /* - * If there are absolutely no more hosts left, it is safe - * to completely nuke the DMA pool. The resize operation will - * do the right thing and free everything. - */ - if( !scsi_devices ) - resize_dma_pool(); - - printk ("scsi : %d host%s.\n", next_scsi_host, - (next_scsi_host == 1) ? "" : "s"); - -#if defined(USE_STATIC_SCSI_MEMORY) - printk ("SCSI memory: total %ldKb, used %ldKb, free %ldKb.\n", - (scsi_memory_upper_value - scsi_memory_lower_value) / 1024, - (scsi_init_memory_start - scsi_memory_lower_value) / 1024, - (scsi_memory_upper_value - scsi_init_memory_start) / 1024); -#endif - - scsi_make_blocked_list(); - - /* There were some hosts that were loaded at boot time, so we cannot - do any more than this */ - if (tpnt->present) return; - - /* OK, this is the very last step. Remove this host adapter from the - linked list. */ - for(SHTp=NULL, SHT=scsi_hosts; SHT; SHTp=SHT, SHT=SHT->next) - if(SHT == tpnt) { - if(SHTp) - SHTp->next = SHT->next; - else - scsi_hosts = SHT->next; - SHT->next = NULL; - break; - } - - /* Rebuild the /proc/scsi directory entries */ -#if CONFIG_PROC_FS - proc_scsi_unregister(tpnt->proc_dir, tpnt->proc_dir->low_ino); -#endif - MOD_DEC_USE_COUNT; -} - -/* - * This entry point should be called by a loadable module if it is trying - * add a high level scsi driver to the system. - */ -static int scsi_register_device_module(struct Scsi_Device_Template * tpnt) -{ - Scsi_Device * SDpnt; - - if (tpnt->next) return 1; - - scsi_register_device(tpnt); - /* - * First scan the devices that we know about, and see if we notice them. - */ - - for(SDpnt = scsi_devices; SDpnt; SDpnt = SDpnt->next) - if(tpnt->detect) SDpnt->attached += (*tpnt->detect)(SDpnt); - - /* - * If any of the devices would match this driver, then perform the - * init function. - */ - if(tpnt->init && tpnt->dev_noticed) - if ((*tpnt->init)()) return 1; - - /* - * Now actually connect the devices to the new driver. - */ - for(SDpnt = scsi_devices; SDpnt; SDpnt = SDpnt->next) - { - if(tpnt->attach) (*tpnt->attach)(SDpnt); - /* - * If this driver attached to the device, and we no longer - * have anything attached, release the scso command blocks. - */ - if(SDpnt->attached && SDpnt->has_cmdblocks == 0) - scsi_build_commandblocks(SDpnt); - } - - /* - * This does any final handling that is required. - */ - if(tpnt->finish && tpnt->nr_dev) (*tpnt->finish)(); - MOD_INC_USE_COUNT; - return 0; -} - -static int scsi_unregister_device(struct Scsi_Device_Template * tpnt) -{ - Scsi_Device * SDpnt; - Scsi_Cmnd * SCpnt; - struct Scsi_Device_Template * spnt; - struct Scsi_Device_Template * prev_spnt; - - /* - * If we are busy, this is not going to fly. - */ - if( *tpnt->usage_count != 0) return 0; - /* - * Next, detach the devices from the driver. - */ - - for(SDpnt = scsi_devices; SDpnt; SDpnt = SDpnt->next) - { - if(tpnt->detach) (*tpnt->detach)(SDpnt); - if(SDpnt->attached == 0) - { - /* - * Nobody is using this device any more. Free all of the - * command structures. - */ - for(SCpnt = SDpnt->host->host_queue; SCpnt; SCpnt = SCpnt->next) - { - if(SCpnt->device == SDpnt) - { - if(SCpnt->prev != NULL) - SCpnt->prev->next = SCpnt->next; - if(SCpnt->next != NULL) - SCpnt->next->prev = SCpnt->prev; - if(SCpnt == SDpnt->host->host_queue) - SDpnt->host->host_queue = SCpnt->next; - scsi_init_free((char *) SCpnt, sizeof(*SCpnt)); - } - } - SDpnt->has_cmdblocks = 0; - } - } - /* - * Extract the template from the linked list. - */ - spnt = scsi_devicelist; - prev_spnt = NULL; - while(spnt != tpnt) - { - prev_spnt = spnt; - spnt = spnt->next; - } - if(prev_spnt == NULL) - scsi_devicelist = tpnt->next; - else - prev_spnt->next = spnt->next; - - MOD_DEC_USE_COUNT; - /* - * Final cleanup for the driver is done in the driver sources in the - * cleanup function. - */ - return 0; -} - - -int scsi_register_module(int module_type, void * ptr) -{ - switch(module_type){ - case MODULE_SCSI_HA: - return scsi_register_host((Scsi_Host_Template *) ptr); - - /* Load upper level device handler of some kind */ - case MODULE_SCSI_DEV: - return scsi_register_device_module((struct Scsi_Device_Template *) ptr); - /* The rest of these are not yet implemented */ - - /* Load constants.o */ - case MODULE_SCSI_CONST: - - /* Load specialized ioctl handler for some device. Intended for - * cdroms that have non-SCSI2 audio command sets. */ - case MODULE_SCSI_IOCTL: - - default: - return 1; - } -} - -void scsi_unregister_module(int module_type, void * ptr) -{ - switch(module_type) { - case MODULE_SCSI_HA: - scsi_unregister_host((Scsi_Host_Template *) ptr); - break; - case MODULE_SCSI_DEV: - scsi_unregister_device((struct Scsi_Device_Template *) ptr); - break; - /* The rest of these are not yet implemented. */ - case MODULE_SCSI_CONST: - case MODULE_SCSI_IOCTL: - break; - default: - } - return; -} - -#endif /* CONFIG_MODULES */ - -#ifdef DEBUG_TIMEOUT -static void -scsi_dump_status(void) -{ - int i; - struct Scsi_Host * shpnt; - Scsi_Cmnd * SCpnt; - printk("Dump of scsi parameters:\n"); - i = 0; - for(shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) - for(SCpnt=shpnt->host_queue; SCpnt; SCpnt = SCpnt->next) - { - /* (0) 0:0:0:0 (802 123434 8 8 0) (3 3 2) (%d %d %d) %d %x */ - printk("(%d) %d:%d:%d:%d (%s %ld %ld %ld %d) (%d %d %x) (%d %d %d) %x %x %x\n", - i++, SCpnt->host->host_no, - SCpnt->channel, - SCpnt->target, - SCpnt->lun, - kdevname(SCpnt->request.rq_dev), - SCpnt->request.sector, - SCpnt->request.nr_sectors, - SCpnt->request.current_nr_sectors, - SCpnt->use_sg, - SCpnt->retries, - SCpnt->allowed, - SCpnt->flags, - SCpnt->timeout_per_command, - SCpnt->timeout, - SCpnt->internal_timeout, - SCpnt->cmnd[0], - SCpnt->sense_buffer[2], - SCpnt->result); - } - printk("wait_for_request = %p\n", wait_for_request); - /* Now dump the request lists for each block device */ - printk("Dump of pending block device requests\n"); - for(i=0; i<MAX_BLKDEV; i++) - if(blk_dev[i].current_request) - { - struct request * req; - printk("%d: ", i); - req = blk_dev[i].current_request; - while(req) { - printk("(%s %d %ld %ld %ld) ", - kdevname(req->rq_dev), - req->cmd, - req->sector, - req->nr_sectors, - req->current_nr_sectors); - req = req->next; - } - printk("\n"); - } -} -#endif - -#ifdef MODULE - -int init_module(void) { - unsigned long size; - - /* - * This makes /proc/scsi visible. - */ - dispatch_scsi_info_ptr = dispatch_scsi_info; - - timer_table[SCSI_TIMER].fn = scsi_main_timeout; - timer_table[SCSI_TIMER].expires = 0; - register_symtab(&scsi_symbol_table); - scsi_loadable_module_flag = 1; - - /* Register the /proc/scsi/scsi entry */ -#if CONFIG_PROC_FS - proc_scsi_register(0, &proc_scsi_scsi); -#endif - - - dma_sectors = PAGE_SIZE / SECTOR_SIZE; - dma_free_sectors= dma_sectors; - /* - * Set up a minimal DMA buffer list - this will be used during scan_scsis - * in some cases. - */ - - /* One bit per sector to indicate free/busy */ - size = (dma_sectors / SECTORS_PER_PAGE)*sizeof(FreeSectorBitmap); - dma_malloc_freelist = (unsigned char *) scsi_init_malloc(size, GFP_ATOMIC); - memset(dma_malloc_freelist, 0, size); - - /* One pointer per page for the page list */ - dma_malloc_pages = (unsigned char **) - scsi_init_malloc((dma_sectors / SECTORS_PER_PAGE)*sizeof(*dma_malloc_pages), GFP_ATOMIC); - dma_malloc_pages[0] = (unsigned char *) - scsi_init_malloc(PAGE_SIZE, GFP_ATOMIC | GFP_DMA); - return 0; -} - -void cleanup_module( void) -{ -#if CONFIG_PROC_FS - proc_scsi_unregister(0, PROC_SCSI_SCSI); -#endif - - /* No, we're not here anymore. Don't show the /proc/scsi files. */ - dispatch_scsi_info_ptr = 0L; - - /* - * Free up the DMA pool. - */ - resize_dma_pool(); - - timer_table[SCSI_TIMER].fn = NULL; - timer_table[SCSI_TIMER].expires = 0; -} -#endif /* MODULE */ - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 4 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -4 - * c-argdecl-indent: 4 - * c-label-offset: -4 - * c-continued-statement-offset: 4 - * c-continued-brace-offset: 0 - * indent-tabs-mode: nil - * tab-width: 8 - * End: - */ diff --git a/i386/i386at/gpl/linux/scsi/scsi.h b/i386/i386at/gpl/linux/scsi/scsi.h deleted file mode 100644 index fefe1c73..00000000 --- a/i386/i386at/gpl/linux/scsi/scsi.h +++ /dev/null @@ -1,618 +0,0 @@ -/* - * scsi.h Copyright (C) 1992 Drew Eckhardt - * Copyright (C) 1993, 1994, 1995 Eric Youngdale - * generic SCSI package header file by - * Initial versions: Drew Eckhardt - * Subsequent revisions: Eric Youngdale - * - * <drew@colorado.edu> - * - * Modified by Eric Youngdale eric@aib.com to - * add scatter-gather, multiple outstanding request, and other - * enhancements. - */ - -#ifndef _SCSI_H -#define _SCSI_H - -/* - * Some of the public constants are being moved to this file. - * We include it here so that what came from where is transparent. - */ -#include <linux/scsi.h> - - -/* - * Some defs, in case these are not defined elsewhere. - */ -#ifndef TRUE -# define TRUE 1 -#endif -#ifndef FALSE -# define FALSE 0 -#endif - -#ifdef MACH -#ifndef LINUX_SCSI_DEBUG -#undef DEBUG -#endif -#endif - -extern void scsi_make_blocked_list(void); -extern volatile int in_scan_scsis; -extern const unsigned char scsi_command_size[8]; -#define COMMAND_SIZE(opcode) scsi_command_size[((opcode) >> 5) & 7] - -#define IDENTIFY_BASE 0x80 -#define IDENTIFY(can_disconnect, lun) (IDENTIFY_BASE |\ - ((can_disconnect) ? 0x40 : 0) |\ - ((lun) & 0x07)) - - - -/* - * the return of the status word will be in the following format : - * The low byte is the status returned by the SCSI command, - * with vendor specific bits masked. - * - * The next byte is the message which followed the SCSI status. - * This allows a stos to be used, since the Intel is a little - * endian machine. - * - * The final byte is a host return code, which is one of the following. - * - * IE - * lsb msb - * status msg host code - * - * Our errors returned by OUR driver, NOT SCSI message. Or'd with - * SCSI message passed back to driver <IF any>. - */ - - -#define DID_OK 0x00 /* NO error */ -#define DID_NO_CONNECT 0x01 /* Couldn't connect before timeout period */ -#define DID_BUS_BUSY 0x02 /* BUS stayed busy through time out period */ -#define DID_TIME_OUT 0x03 /* TIMED OUT for other reason */ -#define DID_BAD_TARGET 0x04 /* BAD target. */ -#define DID_ABORT 0x05 /* Told to abort for some other reason */ -#define DID_PARITY 0x06 /* Parity error */ -#define DID_ERROR 0x07 /* Internal error */ -#define DID_RESET 0x08 /* Reset by somebody. */ -#define DID_BAD_INTR 0x09 /* Got an interrupt we weren't expecting. */ -#define DRIVER_OK 0x00 /* Driver status */ - -/* - * These indicate the error that occurred, and what is available. - */ - -#define DRIVER_BUSY 0x01 -#define DRIVER_SOFT 0x02 -#define DRIVER_MEDIA 0x03 -#define DRIVER_ERROR 0x04 - -#define DRIVER_INVALID 0x05 -#define DRIVER_TIMEOUT 0x06 -#define DRIVER_HARD 0x07 -#define DRIVER_SENSE 0x08 - -#define SUGGEST_RETRY 0x10 -#define SUGGEST_ABORT 0x20 -#define SUGGEST_REMAP 0x30 -#define SUGGEST_DIE 0x40 -#define SUGGEST_SENSE 0x80 -#define SUGGEST_IS_OK 0xff - -#define DRIVER_MASK 0x0f -#define SUGGEST_MASK 0xf0 - -#define MAX_COMMAND_SIZE 12 - -/* - * SCSI command sets - */ - -#define SCSI_UNKNOWN 0 -#define SCSI_1 1 -#define SCSI_1_CCS 2 -#define SCSI_2 3 - -/* - * Every SCSI command starts with a one byte OP-code. - * The next byte's high three bits are the LUN of the - * device. Any multi-byte quantities are stored high byte - * first, and may have a 5 bit MSB in the same byte - * as the LUN. - */ - -/* - * Manufacturers list - */ - -#define SCSI_MAN_UNKNOWN 0 -#define SCSI_MAN_NEC 1 -#define SCSI_MAN_TOSHIBA 2 -#define SCSI_MAN_NEC_OLDCDR 3 -#define SCSI_MAN_SONY 4 -#define SCSI_MAN_PIONEER 5 - -/* - * As the scsi do command functions are intelligent, and may need to - * redo a command, we need to keep track of the last command - * executed on each one. - */ - -#define WAS_RESET 0x01 -#define WAS_TIMEDOUT 0x02 -#define WAS_SENSE 0x04 -#define IS_RESETTING 0x08 -#define IS_ABORTING 0x10 -#define ASKED_FOR_SENSE 0x20 - -/* - * The scsi_device struct contains what we know about each given scsi - * device. - */ - -typedef struct scsi_device { - struct scsi_device * next; /* Used for linked list */ - - unsigned char id, lun, channel; - - unsigned int manufacturer; /* Manufacturer of device, for using - * vendor-specific cmd's */ - int attached; /* # of high level drivers attached to - * this */ - int access_count; /* Count of open channels/mounts */ - struct wait_queue * device_wait;/* Used to wait if device is busy */ - struct Scsi_Host * host; - void (*scsi_request_fn)(void); /* Used to jumpstart things after an - * ioctl */ - void *hostdata; /* available to low-level driver */ - char type; - char scsi_level; - char vendor[8], model[16], rev[4]; - unsigned char current_tag; /* current tag */ - unsigned char sync_min_period; /* Not less than this period */ - unsigned char sync_max_offset; /* Not greater than this offset */ - - unsigned writeable:1; - unsigned removable:1; - unsigned random:1; - unsigned has_cmdblocks:1; - unsigned changed:1; /* Data invalid due to media change */ - unsigned busy:1; /* Used to prevent races */ - unsigned lockable:1; /* Able to prevent media removal */ - unsigned borken:1; /* Tell the Seagate driver to be - * painfully slow on this device */ - unsigned tagged_supported:1; /* Supports SCSI-II tagged queuing */ - unsigned tagged_queue:1; /* SCSI-II tagged queuing enabled */ - unsigned disconnect:1; /* can disconnect */ - unsigned soft_reset:1; /* Uses soft reset option */ - unsigned sync:1; /* Negotiate for sync transfers */ - unsigned single_lun:1; /* Indicates we should only allow I/O to - one of the luns for the device at a time. */ - unsigned was_reset:1; /* There was a bus reset on the bus for this - device */ - unsigned expecting_cc_ua:1; /* Expecting a CHECK_CONDITION/UNIT_ATTN - because we did a bus reset. */ -} Scsi_Device; - -/* - * Use these to separate status msg and our bytes - */ - -#define status_byte(result) (((result) >> 1) & 0xf) -#define msg_byte(result) (((result) >> 8) & 0xff) -#define host_byte(result) (((result) >> 16) & 0xff) -#define driver_byte(result) (((result) >> 24) & 0xff) -#define suggestion(result) (driver_byte(result) & SUGGEST_MASK) - -#define sense_class(sense) (((sense) >> 4) & 0x7) -#define sense_error(sense) ((sense) & 0xf) -#define sense_valid(sense) ((sense) & 0x80); - -/* - * These are the SCSI devices available on the system. - */ - -extern Scsi_Device * scsi_devices; - -/* - * Initializes all SCSI devices. This scans all scsi busses. - */ - -extern int scsi_dev_init (void); - -struct scatterlist { - char * address; /* Location data is to be transferred to */ - char * alt_address; /* Location of actual if address is a - * dma indirect buffer. NULL otherwise */ - unsigned int length; -}; - -#ifdef __alpha__ -# define ISA_DMA_THRESHOLD (~0UL) -#else -# define ISA_DMA_THRESHOLD (0x00ffffff) -#endif -#define CONTIGUOUS_BUFFERS(X,Y) ((X->b_data+X->b_size) == Y->b_data) - - -/* - * These are the return codes for the abort and reset functions. The mid-level - * code uses these to decide what to do next. Each of the low level abort - * and reset functions must correctly indicate what it has done. - * The descriptions are written from the point of view of the mid-level code, - * so that the return code is telling the mid-level drivers exactly what - * the low level driver has already done, and what remains to be done. - */ - -/* We did not do anything. - * Wait some more for this command to complete, and if this does not work, - * try something more serious. */ -#define SCSI_ABORT_SNOOZE 0 - -/* This means that we were able to abort the command. We have already - * called the mid-level done function, and do not expect an interrupt that - * will lead to another call to the mid-level done function for this command */ -#define SCSI_ABORT_SUCCESS 1 - -/* We called for an abort of this command, and we should get an interrupt - * when this succeeds. Thus we should not restore the timer for this - * command in the mid-level abort function. */ -#define SCSI_ABORT_PENDING 2 - -/* Unable to abort - command is currently on the bus. Grin and bear it. */ -#define SCSI_ABORT_BUSY 3 - -/* The command is not active in the low level code. Command probably - * finished. */ -#define SCSI_ABORT_NOT_RUNNING 4 - -/* Something went wrong. The low level driver will indicate the correct - * error condition when it calls scsi_done, so the mid-level abort function - * can simply wait until this comes through */ -#define SCSI_ABORT_ERROR 5 - -/* We do not know how to reset the bus, or we do not want to. Bummer. - * Anyway, just wait a little more for the command in question, and hope that - * it eventually finishes. If it never finishes, the SCSI device could - * hang, so use this with caution. */ -#define SCSI_RESET_SNOOZE 0 - -/* We do not know how to reset the bus, or we do not want to. Bummer. - * We have given up on this ever completing. The mid-level code will - * request sense information to decide how to proceed from here. */ -#define SCSI_RESET_PUNT 1 - -/* This means that we were able to reset the bus. We have restarted all of - * the commands that should be restarted, and we should be able to continue - * on normally from here. We do not expect any interrupts that will return - * DID_RESET to any of the other commands in the host_queue, and the mid-level - * code does not need to do anything special to keep the commands alive. - * If a hard reset was performed then all outstanding commands on the - * bus have been restarted. */ -#define SCSI_RESET_SUCCESS 2 - -/* We called for a reset of this bus, and we should get an interrupt - * when this succeeds. Each command should get its own status - * passed up to scsi_done, but this has not happened yet. - * If a hard reset was performed, then we expect an interrupt - * for *each* of the outstanding commands that will have the - * effect of restarting the commands. - */ -#define SCSI_RESET_PENDING 3 - -/* We did a reset, but do not expect an interrupt to signal DID_RESET. - * This tells the upper level code to request the sense info, and this - * should keep the command alive. */ -#define SCSI_RESET_WAKEUP 4 - -/* Something went wrong, and we do not know how to fix it. */ -#define SCSI_RESET_ERROR 5 - -/* - * This is a bitmask that is ored with one of the above codes. - * It tells the mid-level code that we did a hard reset. - */ -#define SCSI_RESET_BUS_RESET 0x100 -/* - * Used to mask off bits and to obtain the basic action that was - * performed. - */ -#define SCSI_RESET_ACTION 0xff - -void * scsi_malloc(unsigned int); -int scsi_free(void *, unsigned int); -extern unsigned int dma_free_sectors; /* How much room do we have left */ -extern unsigned int need_isa_buffer; /* True if some devices need indirection - * buffers */ - -/* - * The Scsi_Cmnd structure is used by scsi.c internally, and for communication - * with low level drivers that support multiple outstanding commands. - */ -typedef struct scsi_pointer { - char * ptr; /* data pointer */ - int this_residual; /* left in this buffer */ - struct scatterlist *buffer; /* which buffer */ - int buffers_residual; /* how many buffers left */ - - volatile int Status; - volatile int Message; - volatile int have_data_in; - volatile int sent_command; - volatile int phase; -} Scsi_Pointer; - -typedef struct scsi_cmnd { - struct Scsi_Host * host; - Scsi_Device * device; - unsigned char target, lun, channel; - unsigned char cmd_len; - unsigned char old_cmd_len; - struct scsi_cmnd *next, *prev; - - /* These elements define the operation we are about to perform */ - unsigned char cmnd[12]; - unsigned request_bufflen; /* Actual request size */ - - void * request_buffer; /* Actual requested buffer */ - - /* These elements define the operation we ultimately want to perform */ - unsigned char data_cmnd[12]; - unsigned short old_use_sg; /* We save use_sg here when requesting - * sense info */ - unsigned short use_sg; /* Number of pieces of scatter-gather */ - unsigned short sglist_len; /* size of malloc'd scatter-gather list */ - unsigned short abort_reason;/* If the mid-level code requests an - * abort, this is the reason. */ - unsigned bufflen; /* Size of data buffer */ - void *buffer; /* Data buffer */ - - unsigned underflow; /* Return error if less than this amount is - * transfered */ - - unsigned transfersize; /* How much we are guaranteed to transfer with - * each SCSI transfer (ie, between disconnect / - * reconnects. Probably == sector size */ - - - struct request request; /* A copy of the command we are working on */ - - unsigned char sense_buffer[16]; /* Sense for this command, if needed */ - - - int retries; - int allowed; - int timeout_per_command, timeout_total, timeout; - - /* - * We handle the timeout differently if it happens when a reset, - * abort, etc are in process. - */ - unsigned volatile char internal_timeout; - - unsigned flags; - - /* These variables are for the cdrom only. Once we have variable size - * buffers in the buffer cache, they will go away. */ - int this_count; - /* End of special cdrom variables */ - - /* Low-level done function - can be used by low-level driver to point - * to completion function. Not used by mid/upper level code. */ - void (*scsi_done)(struct scsi_cmnd *); - void (*done)(struct scsi_cmnd *); /* Mid-level done function */ - - /* - * The following fields can be written to by the host specific code. - * Everything else should be left alone. - */ - - Scsi_Pointer SCp; /* Scratchpad used by some host adapters */ - - unsigned char * host_scribble; /* The host adapter is allowed to - * call scsi_malloc and get some memory - * and hang it here. The host adapter - * is also expected to call scsi_free - * to release this memory. (The memory - * obtained by scsi_malloc is guaranteed - * to be at an address < 16Mb). */ - - int result; /* Status code from lower level driver */ - - unsigned char tag; /* SCSI-II queued command tag */ - unsigned long pid; /* Process ID, starts at 0 */ -} Scsi_Cmnd; - -/* - * scsi_abort aborts the current command that is executing on host host. - * The error code, if non zero is returned in the host byte, otherwise - * DID_ABORT is returned in the hostbyte. - */ - -extern int scsi_abort (Scsi_Cmnd *, int code, int pid); - -extern void scsi_do_cmd (Scsi_Cmnd *, const void *cmnd , - void *buffer, unsigned bufflen, - void (*done)(struct scsi_cmnd *), - int timeout, int retries); - - -extern Scsi_Cmnd * allocate_device(struct request **, Scsi_Device *, int); - -extern Scsi_Cmnd * request_queueable(struct request *, Scsi_Device *); -extern int scsi_reset (Scsi_Cmnd *, int); - -extern int max_scsi_hosts; - -extern void proc_print_scsidevice(Scsi_Device *, char *, int *, int); - -extern void print_command(unsigned char *); -extern void print_sense(const char *, Scsi_Cmnd *); -extern void print_driverbyte(int scsiresult); -extern void print_hostbyte(int scsiresult); - -extern void scsi_mark_host_bus_reset(struct Scsi_Host *Host); - -#if defined(MAJOR_NR) && (MAJOR_NR != SCSI_TAPE_MAJOR) -#include "hosts.h" - -static Scsi_Cmnd * end_scsi_request(Scsi_Cmnd * SCpnt, int uptodate, int sectors) -{ - struct request * req; - struct buffer_head * bh; - - req = &SCpnt->request; - if (!uptodate) { - printk(DEVICE_NAME " I/O error: dev %s, sector %lu\n", - kdevname(req->rq_dev), req->sector); -#ifdef MACH - req->errors = 1; - while (req->bh) { - bh = req->bh; - req->bh = bh->b_reqnext; - mark_buffer_uptodate(bh, 0); - unlock_buffer(bh); - } - goto done; -#endif - } - - do { - if ((bh = req->bh) != NULL) { - req->bh = bh->b_reqnext; - req->nr_sectors -= bh->b_size >> 9; - req->sector += bh->b_size >> 9; - bh->b_reqnext = NULL; - mark_buffer_uptodate(bh, uptodate); - unlock_buffer(bh); - sectors -= bh->b_size >> 9; - if ((bh = req->bh) != NULL) { - req->current_nr_sectors = bh->b_size >> 9; - if (req->nr_sectors < req->current_nr_sectors) { - req->nr_sectors = req->current_nr_sectors; - printk("end_scsi_request: buffer-list destroyed\n"); - } - } - } - } while(sectors && bh); - if (req->bh){ - req->buffer = bh->b_data; - return SCpnt; - }; -#ifdef MACH - req->errors = 0; - -done: -#endif - DEVICE_OFF(req->rq_dev); - if (req->sem != NULL) { - up(req->sem); - } - - if (SCpnt->host->block) { - struct Scsi_Host * next; - - for (next = SCpnt->host->block; next != SCpnt->host; - next = next->block) - wake_up(&next->host_wait); - } - - req->rq_status = RQ_INACTIVE; -#ifndef MACH - wake_up(&wait_for_request); -#endif - wake_up(&SCpnt->device->device_wait); -#ifdef MACH - { - unsigned long flags; - - save_flags(flags); - cli(); - (*blk_dev[MAJOR(req->rq_dev)].request_fn)(); - restore_flags(flags); - } -#endif - return NULL; -} - - -/* This is just like INIT_REQUEST, but we need to be aware of the fact - * that an interrupt may start another request, so we run this with interrupts - * turned off - */ -#define INIT_SCSI_REQUEST \ - if (!CURRENT) { \ - CLEAR_INTR; \ - restore_flags(flags); \ - return; \ - } \ - if (MAJOR(CURRENT->rq_dev) != MAJOR_NR) \ - panic(DEVICE_NAME ": request list destroyed");\ - if (CURRENT->bh) { \ - if (!buffer_locked(CURRENT->bh)) \ - panic(DEVICE_NAME ": block not locked"); \ - } -#endif - -#ifdef MACH -#define SCSI_SLEEP(QUEUE, CONDITION) { \ - if (CONDITION) { \ - struct wait_queue wait = { NULL, NULL}; \ - add_wait_queue(QUEUE, &wait); \ - for(;;) { \ - if (CONDITION) { \ - if (intr_count) \ - panic("scsi: trying to call schedule() in interrupt" \ - ", file %s, line %d.\n", __FILE__, __LINE__); \ - schedule(); \ - } \ - else \ - break; \ - } \ - remove_wait_queue(QUEUE, &wait);\ - }; } -#else /* ! MACH */ -#define SCSI_SLEEP(QUEUE, CONDITION) { \ - if (CONDITION) { \ - struct wait_queue wait = { current, NULL}; \ - add_wait_queue(QUEUE, &wait); \ - for(;;) { \ - current->state = TASK_UNINTERRUPTIBLE; \ - if (CONDITION) { \ - if (intr_count) \ - panic("scsi: trying to call schedule() in interrupt" \ - ", file %s, line %d.\n", __FILE__, __LINE__); \ - schedule(); \ - } \ - else \ - break; \ - } \ - remove_wait_queue(QUEUE, &wait);\ - current->state = TASK_RUNNING; \ - }; } -#endif /* ! MACH */ - -#endif - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 4 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -4 - * c-argdecl-indent: 4 - * c-label-offset: -4 - * c-continued-statement-offset: 4 - * c-continued-brace-offset: 0 - * indent-tabs-mode: nil - * tab-width: 8 - * End: - */ diff --git a/i386/i386at/gpl/linux/scsi/scsi_debug.c b/i386/i386at/gpl/linux/scsi/scsi_debug.c deleted file mode 100644 index e98f53e2..00000000 --- a/i386/i386at/gpl/linux/scsi/scsi_debug.c +++ /dev/null @@ -1,710 +0,0 @@ -/* $Id: scsi_debug.c,v 1.1.1.1 1997/02/25 21:27:51 thomas Exp $ - * linux/kernel/scsi_debug.c - * - * Copyright (C) 1992 Eric Youngdale - * Simulate a host adapter with 2 disks attached. Do a lot of checking - * to make sure that we are not getting blocks mixed up, and panic if - * anything out of the ordinary is seen. - */ - -#include <linux/module.h> - -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/errno.h> -#include <linux/timer.h> -#include <linux/head.h> -#include <linux/types.h> -#include <linux/string.h> -#include <linux/genhd.h> -#include <linux/fs.h> -#include <linux/proc_fs.h> - -#include <asm/system.h> -#include <asm/io.h> - -#ifdef MODULE -#include <linux/module.h> -#endif - -#include <linux/blk.h> -#include "scsi.h" -#include "hosts.h" - -#include "sd.h" - -#include<linux/stat.h> - -struct proc_dir_entry proc_scsi_scsi_debug = { - PROC_SCSI_SCSI_DEBUG, 10, "scsi_debug", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - - -/* A few options that we want selected */ - -/* Do not attempt to use a timer to simulate a real disk with latency */ -/* Only use this in the actual kernel, not in the simulator. */ -#define IMMEDIATE - -/* Skip some consistency checking. Good for benchmarking */ -#define SPEEDY - -/* Number of real scsi disks that will be detected ahead of time */ -static int NR_REAL=-1; - -#define NR_BLK_DEV 12 -#ifndef MAJOR_NR -#define MAJOR_NR 8 -#endif -#define START_PARTITION 4 -#define SCSI_DEBUG_TIMER 20 -/* Number of jiffies to wait before completing a command */ -#define DISK_SPEED 10 -#define CAPACITY (0x80000) - -static int starts[] = {4, 1000, 50000, CAPACITY, 0}; -static int npart = 0; - -#include "scsi_debug.h" -#ifdef DEBUG -#define DEB(x) x -#else -#define DEB(x) -#endif - -#ifdef SPEEDY -#define VERIFY1_DEBUG(RW) 1 -#define VERIFY_DEBUG(RW) 1 -#else - -#define VERIFY1_DEBUG(RW) \ - if (bufflen != 1024) {printk("%d", bufflen); panic("(1)Bad bufflen");}; \ - start = 0; \ - if ((MINOR(SCpnt->request.rq_dev) & 0xf) != 0) start = starts[(MINOR(SCpnt->request.rq_dev) & 0xf) - 1]; \ - if (bh){ \ - if (bh->b_size != 1024) panic ("Wrong bh size"); \ - if ((bh->b_blocknr << 1) + start != block) \ - { printk("Wrong bh block# %d %d ",bh->b_blocknr, block); \ - panic ("Wrong bh block#"); \ - }; \ - if (bh->b_dev != SCpnt->request.rq_dev) \ - panic ("Bad bh target"); \ - }; - -#define VERIFY_DEBUG(RW) \ - if (bufflen != 1024 && (!SCpnt->use_sg)) {printk("%x %d\n ",bufflen, SCpnt->use_sg); panic("Bad bufflen");}; \ - start = 0; \ - if ((MINOR(SCpnt->request.rq_dev) & 0xf) > npart) panic ("Bad partition"); \ - if ((MINOR(SCpnt->request.rq_dev) & 0xf) != 0) start = starts[(MINOR(SCpnt->request.rq_dev) & 0xf) - 1]; \ - if (SCpnt->request.cmd != RW) panic ("Wrong operation"); \ - if (SCpnt->request.sector + start != block) panic("Wrong block."); \ - if (SCpnt->request.current_nr_sectors != 2 && (!SCpnt->use_sg)) panic ("Wrong # blocks"); \ - if (SCpnt->request.bh){ \ - if (SCpnt->request.bh->b_size != 1024) panic ("Wrong bh size"); \ - if ((SCpnt->request.bh->b_blocknr << 1) + start != block) \ - { printk("Wrong bh block# %d %d ",SCpnt->request.bh->b_blocknr, block); \ - panic ("Wrong bh block#"); \ - }; \ - if (SCpnt->request.bh->b_dev != SCpnt->request.rq_dev) \ - panic ("Bad bh target");\ - }; -#endif - -static volatile void (*do_done[SCSI_DEBUG_MAILBOXES])(Scsi_Cmnd *) = {NULL, }; -extern void scsi_debug_interrupt(); - -volatile Scsi_Cmnd * SCint[SCSI_DEBUG_MAILBOXES] = {NULL,}; -static char SCrst[SCSI_DEBUG_MAILBOXES] = {0,}; -static volatile unsigned int timeout[8] ={0,}; - -/* - * Semaphore used to simulate bus lockups. - */ -static int scsi_debug_lockup = 0; - -static char sense_buffer[128] = {0,}; - -static void scsi_dump(Scsi_Cmnd * SCpnt, int flag){ - int i; -#if 0 - unsigned char * pnt; -#endif - unsigned int * lpnt; - struct scatterlist * sgpnt = NULL; - printk("use_sg: %d",SCpnt->use_sg); - if (SCpnt->use_sg){ - sgpnt = (struct scatterlist *) SCpnt->buffer; - for(i=0; i<SCpnt->use_sg; i++) { - lpnt = (int *) sgpnt[i].alt_address; - printk(":%x %x %d\n",sgpnt[i].alt_address, sgpnt[i].address, sgpnt[i].length); - if (lpnt) printk(" (Alt %x) ",lpnt[15]); - }; - } else { - printk("nosg: %x %x %d\n",SCpnt->request.buffer, SCpnt->buffer, - SCpnt->bufflen); - lpnt = (int *) SCpnt->request.buffer; - if (lpnt) printk(" (Alt %x) ",lpnt[15]); - }; - lpnt = (unsigned int *) SCpnt; - for (i=0;i<sizeof(Scsi_Cmnd)/4+1; i++) { - if ((i & 7) == 0) printk("\n"); - printk("%x ",*lpnt++); - }; - printk("\n"); - if (flag == 0) return; - lpnt = (unsigned int *) sgpnt[0].alt_address; - for (i=0;i<sizeof(Scsi_Cmnd)/4+1; i++) { - if ((i & 7) == 0) printk("\n"); - printk("%x ",*lpnt++); - }; -#if 0 - printk("\n"); - lpnt = (unsigned int *) sgpnt[0].address; - for (i=0;i<sizeof(Scsi_Cmnd)/4+1; i++) { - if ((i & 7) == 0) printk("\n"); - printk("%x ",*lpnt++); - }; - printk("\n"); -#endif - printk("DMA free %d sectors.\n", dma_free_sectors); -} - -int scsi_debug_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) -{ - unchar *cmd = (unchar *) SCpnt->cmnd; - struct partition * p; - int block, start; - struct buffer_head * bh = NULL; - unsigned char * buff; - int nbytes, sgcount; - int scsi_debug_errsts; - struct scatterlist * sgpnt; - int target = SCpnt->target; - int bufflen = SCpnt->request_bufflen; - unsigned long flags; - int i; - sgcount = 0; - sgpnt = NULL; - - DEB(if (target > 1) { SCpnt->result = DID_TIME_OUT << 16;done(SCpnt);return 0;}); - - buff = (unsigned char *) SCpnt->request_buffer; - - if(target>=1 || SCpnt->lun != 0) { - SCpnt->result = DID_NO_CONNECT << 16; - done(SCpnt); - return 0; - }; - - if( SCrst[target] != 0 && !scsi_debug_lockup ) - { - SCrst[target] = 0; - memset(SCpnt->sense_buffer, 0, sizeof(SCpnt->sense_buffer)); - SCpnt->sense_buffer[0] = 0x70; - SCpnt->sense_buffer[2] = UNIT_ATTENTION; - SCpnt->result = (CHECK_CONDITION << 1); - done(SCpnt); - } - switch(*cmd){ - case REQUEST_SENSE: - printk("Request sense...\n"); -#ifndef DEBUG - { - int i; - printk("scsi_debug: Requesting sense buffer (%x %x %x %d):", SCpnt, buff, done, bufflen); - for(i=0;i<12;i++) printk("%d ",sense_buffer[i]); - printk("\n"); - }; -#endif - memset(buff, 0, bufflen); - memcpy(buff, sense_buffer, bufflen); - memset(sense_buffer, 0, sizeof(sense_buffer)); - SCpnt->result = 0; - done(SCpnt); - return 0; - case ALLOW_MEDIUM_REMOVAL: - if(cmd[4]) printk("Medium removal inhibited..."); - else printk("Medium removal enabled..."); - scsi_debug_errsts = 0; - break; - case INQUIRY: - printk("Inquiry...(%x %d)\n", buff, bufflen); - memset(buff, 0, bufflen); - buff[0] = TYPE_DISK; - buff[1] = 0x80; /* Removable disk */ - buff[2] = 1; - buff[4] = 33 - 5; - memcpy(&buff[8],"Foo Inc",7); - memcpy(&buff[16],"XYZZY",5); - memcpy(&buff[32],"1",1); - scsi_debug_errsts = 0; - break; - case TEST_UNIT_READY: - printk("Test unit ready(%x %d)\n", buff, bufflen); - if (buff) - memset(buff, 0, bufflen); - scsi_debug_errsts = 0; - break; - case READ_CAPACITY: - printk("Read Capacity\n"); - if(NR_REAL < 0) NR_REAL = (MINOR(SCpnt->request.rq_dev) >> 4) & 0x0f; - memset(buff, 0, bufflen); - buff[0] = (CAPACITY >> 24); - buff[1] = (CAPACITY >> 16) & 0xff; - buff[2] = (CAPACITY >> 8) & 0xff; - buff[3] = CAPACITY & 0xff; - buff[6] = 2; /* 512 byte sectors */ - scsi_debug_errsts = 0; - break; - case READ_10: - case READ_6: -#ifdef DEBUG - printk("Read..."); -#endif - if ((*cmd) == READ_10) - block = cmd[5] + (cmd[4] << 8) + (cmd[3] << 16) + (cmd[2] << 24); - else - block = cmd[3] + (cmd[2] << 8) + ((cmd[1] & 0x1f) << 16); - VERIFY_DEBUG(READ); -#if defined(SCSI_SETUP_LATENCY) || defined(SCSI_DATARATE) - { - int delay = SCSI_SETUP_LATENCY; - double usec; - - usec = 0.0; - usec = (SCpnt->request.nr_sectors << 9) * 1.0e6 / SCSI_DATARATE; - delay += usec; - if(delay) usleep(delay); - }; -#endif - -#ifdef DEBUG - printk("(r%d)",SCpnt->request.nr_sectors); -#endif - nbytes = bufflen; - if(SCpnt->use_sg){ - sgcount = 0; - sgpnt = (struct scatterlist *) buff; - buff = sgpnt[sgcount].address; - bufflen = sgpnt[sgcount].length; - bh = SCpnt->request.bh; - }; - scsi_debug_errsts = 0; - do{ - VERIFY1_DEBUG(READ); - /* For the speedy test, we do not even want to fill the buffer with anything */ -#ifndef SPEEDY - memset(buff, 0, bufflen); -#endif - /* If this is block 0, then we want to read the partition table for this - * device. Let's make one up */ - if(block == 0 && target == 0) { - memset(buff, 0, bufflen); - *((unsigned short *) (buff+510)) = 0xAA55; - p = (struct partition* ) (buff + 0x1be); - npart = 0; - while(starts[npart+1]){ - p->start_sect = starts[npart]; - p->nr_sects = starts[npart+1] - starts [npart]; - p->sys_ind = 0x81; /* Linux partition */ - p++; - npart++; - }; - scsi_debug_errsts = 0; - break; - }; -#ifdef DEBUG - if (SCpnt->use_sg) printk("Block %x (%d %d)\n",block, SCpnt->request.nr_sectors, - SCpnt->request.current_nr_sectors); -#endif - -#if 0 - /* Simulate a disk change */ - if(block == 0xfff0) { - sense_buffer[0] = 0x70; - sense_buffer[2] = UNIT_ATTENTION; - starts[0] += 10; - starts[1] += 10; - starts[2] += 10; - -#ifdef DEBUG - { - int i; - printk("scsi_debug: Filling sense buffer:"); - for(i=0;i<12;i++) printk("%d ",sense_buffer[i]); - printk("\n"); - }; -#endif - scsi_debug_errsts = (COMMAND_COMPLETE << 8) | (CHECK_CONDITION << 1); - break; - } /* End phony disk change code */ -#endif - -#ifndef SPEEDY - memcpy(buff, &target, sizeof(target)); - memcpy(buff+sizeof(target), cmd, 24); - memcpy(buff+60, &block, sizeof(block)); - memcpy(buff+64, SCpnt, sizeof(Scsi_Cmnd)); -#endif - nbytes -= bufflen; - if(SCpnt->use_sg){ -#ifndef SPEEDY - memcpy(buff+128, bh, sizeof(struct buffer_head)); -#endif - block += bufflen >> 9; - bh = bh->b_reqnext; - sgcount++; - if (nbytes) { - if(!bh) panic("Too few blocks for linked request."); - buff = sgpnt[sgcount].address; - bufflen = sgpnt[sgcount].length; - }; - } - } while(nbytes); - - SCpnt->result = 0; - (done)(SCpnt); - return; - - if (SCpnt->use_sg && !scsi_debug_errsts) - if(bh) scsi_dump(SCpnt, 0); - break; - case WRITE_10: - case WRITE_6: -#ifdef DEBUG - printk("Write\n"); -#endif - if ((*cmd) == WRITE_10) - block = cmd[5] + (cmd[4] << 8) + (cmd[3] << 16) + (cmd[2] << 24); - else - block = cmd[3] + (cmd[2] << 8) + ((cmd[1] & 0x1f) << 16); - VERIFY_DEBUG(WRITE); - /* printk("(w%d)",SCpnt->request.nr_sectors); */ - if (SCpnt->use_sg){ - if ((bufflen >> 9) != SCpnt->request.nr_sectors) - panic ("Trying to write wrong number of blocks\n"); - sgpnt = (struct scatterlist *) buff; - buff = sgpnt[sgcount].address; - }; -#if 0 - if (block != *((unsigned long *) (buff+60))) { - printk("%x %x :",block, *((unsigned long *) (buff+60))); - scsi_dump(SCpnt,1); - panic("Bad block written.\n"); - }; -#endif - scsi_debug_errsts = 0; - break; - default: - printk("Unknown command %d\n",*cmd); - SCpnt->result = DID_NO_CONNECT << 16; - done(SCpnt); - return 0; - }; - - save_flags(flags); - cli(); - for(i=0;i<SCSI_DEBUG_MAILBOXES; i++){ - if (SCint[i] == 0) break; - }; - - if (i >= SCSI_DEBUG_MAILBOXES || SCint[i] != 0) - panic("Unable to find empty SCSI_DEBUG command slot.\n"); - - SCint[i] = SCpnt; - - if (done) { - DEB(printk("scsi_debug_queuecommand: now waiting for interrupt ");); - if (do_done[i]) - printk("scsi_debug_queuecommand: Two concurrent queuecommand?\n"); - else - do_done[i] = done; - } - else - printk("scsi_debug_queuecommand: done cant be NULL\n"); - -#ifdef IMMEDIATE - if( !scsi_debug_lockup ) - { - SCpnt->result = scsi_debug_errsts; - scsi_debug_intr_handle(); /* No timer - do this one right away */ - } - restore_flags(flags); -#else - timeout[i] = jiffies+DISK_SPEED; - - /* If no timers active, then set this one */ - if ((timer_active & (1 << SCSI_DEBUG_TIMER)) == 0) { - timer_table[SCSI_DEBUG_TIMER].expires = timeout[i]; - timer_active |= 1 << SCSI_DEBUG_TIMER; - }; - - SCpnt->result = scsi_debug_errsts; - restore_flags(flags); - -#if 0 - printk("Sending command (%d %x %d %d)...", i, done, timeout[i],jiffies); -#endif -#endif - - return 0; -} - -volatile static int internal_done_flag = 0; -volatile static int internal_done_errcode = 0; -static void internal_done(Scsi_Cmnd * SCpnt) -{ - internal_done_errcode = SCpnt->result; - ++internal_done_flag; -} - -int scsi_debug_command(Scsi_Cmnd * SCpnt) -{ - DEB(printk("scsi_debug_command: ..calling scsi_debug_queuecommand\n")); - scsi_debug_queuecommand(SCpnt, internal_done); - - while (!internal_done_flag); - internal_done_flag = 0; - return internal_done_errcode; -} - -/* A "high" level interrupt handler. This should be called once per jiffy - * to simulate a regular scsi disk. We use a timer to do this. */ - -static void scsi_debug_intr_handle(void) -{ - Scsi_Cmnd * SCtmp; - int i, pending; - void (*my_done)(Scsi_Cmnd *); - unsigned long flags; - int to; - -#ifndef IMMEDIATE - timer_table[SCSI_DEBUG_TIMER].expires = 0; - timer_active &= ~(1 << SCSI_DEBUG_TIMER); -#endif - - repeat: - save_flags(flags); - cli(); - for(i=0;i<SCSI_DEBUG_MAILBOXES; i++) { - if (SCint[i] == 0) continue; -#ifndef IMMEDIATE - if (timeout[i] == 0) continue; - if (timeout[i] <= jiffies) break; -#else - break; -#endif - }; - - if(i == SCSI_DEBUG_MAILBOXES){ -#ifndef IMMEDIATE - pending = INT_MAX; - for(i=0;i<SCSI_DEBUG_MAILBOXES; i++) { - if (SCint[i] == 0) continue; - if (timeout[i] == 0) continue; - if (timeout[i] <= jiffies) {restore_flags(flags); goto repeat;}; - if (timeout[i] > jiffies) { - if (pending > timeout[i]) pending = timeout[i]; - continue; - }; - }; - if (pending && pending != INT_MAX) { - timer_table[SCSI_DEBUG_TIMER].expires = - (pending <= jiffies ? jiffies+1 : pending); - timer_active |= 1 << SCSI_DEBUG_TIMER; - }; - restore_flags(flags); -#endif - return; - }; - - if(i < SCSI_DEBUG_MAILBOXES){ - timeout[i] = 0; - my_done = do_done[i]; - do_done[i] = NULL; - to = timeout[i]; - timeout[i] = 0; - SCtmp = (Scsi_Cmnd *) SCint[i]; - SCint[i] = NULL; - restore_flags(flags); - - if (!my_done) { - printk("scsi_debug_intr_handle: Unexpected interrupt\n"); - return; - } - -#ifdef DEBUG - printk("In intr_handle..."); - printk("...done %d %x %d %d\n",i , my_done, to, jiffies); - printk("In intr_handle: %d %x %x\n",i, SCtmp, my_done); -#endif - - my_done(SCtmp); -#ifdef DEBUG - printk("Called done.\n"); -#endif - }; - goto repeat; -} - - -int scsi_debug_detect(Scsi_Host_Template * tpnt) -{ - tpnt->proc_dir = &proc_scsi_scsi_debug; -#ifndef IMMEDIATE - timer_table[SCSI_DEBUG_TIMER].fn = scsi_debug_intr_handle; - timer_table[SCSI_DEBUG_TIMER].expires = 0; -#endif - return 1; -} - -int scsi_debug_abort(Scsi_Cmnd * SCpnt) -{ - int j; - void (*my_done)(Scsi_Cmnd *); - unsigned long flags; - - DEB(printk("scsi_debug_abort\n")); -#if 0 - SCpnt->result = SCpnt->abort_reason << 16; - for(j=0;j<SCSI_DEBUG_MAILBOXES; j++) { - if(SCpnt == SCint[j]) { - my_done = do_done[j]; - my_done(SCpnt); - save_flags(flags); - cli(); - timeout[j] = 0; - SCint[j] = NULL; - do_done[j] = NULL; - restore_flags(flags); - }; - }; -#endif - return SCSI_ABORT_SNOOZE; -} - -int scsi_debug_biosparam(Disk * disk, kdev_t dev, int* info){ - int size = disk->capacity; - info[0] = 32; - info[1] = 64; - info[2] = (size + 2047) >> 11; - if (info[2] >= 1024) info[2] = 1024; - return 0; -} - -int scsi_debug_reset(Scsi_Cmnd * SCpnt) -{ - int i; - unsigned long flags; - - void (*my_done)(Scsi_Cmnd *); - printk("Bus unlocked by reset(%d)\n", SCpnt->host->suggest_bus_reset); - scsi_debug_lockup = 0; - DEB(printk("scsi_debug_reset called\n")); - for(i=0;i<SCSI_DEBUG_MAILBOXES; i++) { - if (SCint[i] == NULL) continue; - SCint[i]->result = DID_RESET << 16; - my_done = do_done[i]; - my_done(SCint[i]); - save_flags(flags); - cli(); - SCint[i] = NULL; - do_done[i] = NULL; - timeout[i] = 0; - restore_flags(flags); - } - return SCSI_RESET_SUCCESS; -} - -const char *scsi_debug_info(void) -{ - static char buffer[] = " "; /* looks nicer without anything here */ - return buffer; -} - -/* scsi_debug_proc_info - * Used if the driver currently has no own support for /proc/scsi - */ -int scsi_debug_proc_info(char *buffer, char **start, off_t offset, - int length, int inode, int inout) -{ - int len, pos, begin; - int orig_length; - - if(inout == 1) - { - /* First check for the Signature */ - if (length >= 10 && strncmp(buffer, "scsi_debug", 10) == 0) { - buffer += 11; - length -= 11; - /* - * OK, we are getting some kind of command. Figure out - * what we are supposed to do here. Simulate bus lockups - * to test our reset capability. - */ - if( length == 6 && strncmp(buffer, "lockup", length) == 0 ) - { - scsi_debug_lockup = 1; - return length; - } - - if( length == 6 && strncmp(buffer, "unlock", length) == 0 ) - { - scsi_debug_lockup = 0; - return length; - } - - printk("Unknown command:%s\n", buffer); - } else - printk("Wrong Signature:%10s\n", (char *) ((ulong)buffer-11)); - - return -EINVAL; - - } - - begin = 0; - pos = len = sprintf(buffer, - "This driver is not a real scsi driver, but it plays one on TV.\n" - "It is very handy for debugging specific problems because you\n" - "can simulate a variety of error conditions\n"); - if(pos < offset) - { - len = 0; - begin = pos; - } - - *start = buffer + (offset - begin); /* Start of wanted data */ - len -= (offset - begin); - if(len > length) - len = length; - - return(len); -} - -#ifdef MODULE -/* Eventually this will go into an include file, but this will be later */ -Scsi_Host_Template driver_template = SCSI_DEBUG; - -#include "scsi_module.c" -#endif - -/* - * Overrides for Emacs so that we almost follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 4 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -4 - * c-argdecl-indent: 4 - * c-label-offset: -4 - * c-continued-statement-offset: 4 - * c-continued-brace-offset: 0 - * indent-tabs-mode: nil - * tab-width: 8 - * End: - */ diff --git a/i386/i386at/gpl/linux/scsi/scsi_debug.h b/i386/i386at/gpl/linux/scsi/scsi_debug.h deleted file mode 100644 index 87ae155f..00000000 --- a/i386/i386at/gpl/linux/scsi/scsi_debug.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef _SCSI_DEBUG_H - -#include <linux/types.h> -#include <linux/kdev_t.h> - -int scsi_debug_detect(Scsi_Host_Template *); -int scsi_debug_command(Scsi_Cmnd *); -int scsi_debug_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); -int scsi_debug_abort(Scsi_Cmnd *); -int scsi_debug_biosparam(Disk *, kdev_t, int[]); -int scsi_debug_reset(Scsi_Cmnd *); -int scsi_debug_proc_info(char *, char **, off_t, int, int, int); - -#ifndef NULL - #define NULL 0 -#endif - - -#define SCSI_DEBUG_MAILBOXES 8 - -#define SCSI_DEBUG {NULL, NULL, NULL, scsi_debug_proc_info, \ - "SCSI DEBUG", scsi_debug_detect, NULL, \ - NULL, scsi_debug_command, \ - scsi_debug_queuecommand, \ - scsi_debug_abort, \ - scsi_debug_reset, \ - NULL, \ - scsi_debug_biosparam, \ - SCSI_DEBUG_MAILBOXES, 7, SG_ALL, 1, 0, 1, ENABLE_CLUSTERING} -#endif diff --git a/i386/i386at/gpl/linux/scsi/scsi_ioctl.c b/i386/i386at/gpl/linux/scsi/scsi_ioctl.c deleted file mode 100644 index 11d57bae..00000000 --- a/i386/i386at/gpl/linux/scsi/scsi_ioctl.c +++ /dev/null @@ -1,397 +0,0 @@ -/* - * Don't import our own symbols, as this would severely mess up our - * symbol tables. - */ -#define _SCSI_SYMS_VER_ -#define __NO_VERSION__ -#include <linux/module.h> - -#include <asm/io.h> -#include <asm/segment.h> -#include <asm/system.h> - -#include <linux/errno.h> -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/mm.h> -#include <linux/string.h> - -#include <linux/blk.h> -#include "scsi.h" -#include "hosts.h" -#include "scsi_ioctl.h" - -#define MAX_RETRIES 5 -#define MAX_TIMEOUT 900 -#define MAX_BUF 4096 - -#define max(a,b) (((a) > (b)) ? (a) : (b)) - -/* - * If we are told to probe a host, we will return 0 if the host is not - * present, 1 if the host is present, and will return an identifying - * string at *arg, if arg is non null, filling to the length stored at - * (int *) arg - */ - -static int ioctl_probe(struct Scsi_Host * host, void *buffer) -{ - int temp, result; - unsigned int len,slen; - const char * string; - - if ((temp = host->hostt->present) && buffer) { - result = verify_area(VERIFY_READ, buffer, sizeof(long)); - if (result) return result; - - len = get_user ((unsigned int *) buffer); - if(host->hostt->info) - string = host->hostt->info(host); - else - string = host->hostt->name; - if(string) { - slen = strlen(string); - if (len > slen) - len = slen + 1; - result = verify_area(VERIFY_WRITE, buffer, len); - if (result) return result; - - memcpy_tofs (buffer, string, len); - } - } - return temp; -} - -/* - * - * The SCSI_IOCTL_SEND_COMMAND ioctl sends a command out to the SCSI host. - * The MAX_TIMEOUT and MAX_RETRIES variables are used. - * - * dev is the SCSI device struct ptr, *(int *) arg is the length of the - * input data, if any, not including the command string & counts, - * *((int *)arg + 1) is the output buffer size in bytes. - * - * *(char *) ((int *) arg)[2] the actual command byte. - * - * Note that no more than MAX_BUF data bytes will be transfered. Since - * SCSI block device size is 512 bytes, I figured 1K was good. - * but (WDE) changed it to 8192 to handle large bad track buffers. - * ERY: I changed this to a dynamic allocation using scsi_malloc - we were - * getting a kernel stack overflow which was crashing the system when we - * were using 8192 bytes. - * - * This size *does not* include the initial lengths that were passed. - * - * The SCSI command is read from the memory location immediately after the - * length words, and the input data is right after the command. The SCSI - * routines know the command size based on the opcode decode. - * - * The output area is then filled in starting from the command byte. - */ - -static void scsi_ioctl_done (Scsi_Cmnd * SCpnt) -{ - struct request * req; - - req = &SCpnt->request; - req->rq_status = RQ_SCSI_DONE; /* Busy, but indicate request done */ - - if (req->sem != NULL) { - up(req->sem); - } -} - -static int ioctl_internal_command(Scsi_Device *dev, char * cmd) -{ - int result; - Scsi_Cmnd * SCpnt; - - SCpnt = allocate_device(NULL, dev, 1); - { - struct semaphore sem = MUTEX_LOCKED; - SCpnt->request.sem = &sem; - scsi_do_cmd(SCpnt, cmd, NULL, 0, - scsi_ioctl_done, MAX_TIMEOUT, - MAX_RETRIES); - down(&sem); - } - - if(driver_byte(SCpnt->result) != 0) - switch(SCpnt->sense_buffer[2] & 0xf) { - case ILLEGAL_REQUEST: - if(cmd[0] == ALLOW_MEDIUM_REMOVAL) dev->lockable = 0; - else printk("SCSI device (ioctl) reports ILLEGAL REQUEST.\n"); - break; - case NOT_READY: /* This happens if there is no disc in drive */ - if(dev->removable){ - printk(KERN_INFO "Device not ready. Make sure there is a disc in the drive.\n"); - break; - }; - case UNIT_ATTENTION: - if (dev->removable){ - dev->changed = 1; - SCpnt->result = 0; /* This is no longer considered an error */ - printk(KERN_INFO "Disc change detected.\n"); - break; - }; - default: /* Fall through for non-removable media */ - printk("SCSI error: host %d id %d lun %d return code = %x\n", - dev->host->host_no, - dev->id, - dev->lun, - SCpnt->result); - printk("\tSense class %x, sense error %x, extended sense %x\n", - sense_class(SCpnt->sense_buffer[0]), - sense_error(SCpnt->sense_buffer[0]), - SCpnt->sense_buffer[2] & 0xf); - - }; - - result = SCpnt->result; - SCpnt->request.rq_status = RQ_INACTIVE; - wake_up(&SCpnt->device->device_wait); - return result; -} - -/* - * This interface is depreciated - users should use the scsi generics - * interface instead, as this is a more flexible approach to performing - * generic SCSI commands on a device. - */ -static int ioctl_command(Scsi_Device *dev, void *buffer) -{ - char * buf; - char cmd[12]; - char * cmd_in; - Scsi_Cmnd * SCpnt; - unsigned char opcode; - int inlen, outlen, cmdlen; - int needed, buf_needed; - int result; - - if (!buffer) - return -EINVAL; - - - /* - * Verify that we can read at least this much. - */ - result = verify_area(VERIFY_READ, buffer, 2*sizeof(long) + 1); - if (result) return result; - - /* - * The structure that we are passed should look like: - * - * struct sdata{ - * int inlen; - * int outlen; - * char cmd[]; # However many bytes are used for cmd. - * char data[]; - */ - inlen = get_user((unsigned int *) buffer); - outlen = get_user( ((unsigned int *) buffer) + 1); - - /* - * We do not transfer more than MAX_BUF with this interface. - * If the user needs to transfer more data than this, they - * should use scsi_generics instead. - */ - if( inlen > MAX_BUF ) inlen = MAX_BUF; - if( outlen > MAX_BUF ) outlen = MAX_BUF; - - cmd_in = (char *) ( ((int *)buffer) + 2); - opcode = get_user(cmd_in); - - needed = buf_needed = (inlen > outlen ? inlen : outlen); - if(buf_needed){ - buf_needed = (buf_needed + 511) & ~511; - if (buf_needed > MAX_BUF) buf_needed = MAX_BUF; - buf = (char *) scsi_malloc(buf_needed); - if (!buf) return -ENOMEM; - memset(buf, 0, buf_needed); - } else - buf = NULL; - - /* - * Obtain the command from the user's address space. - */ - cmdlen = COMMAND_SIZE(opcode); - - result = verify_area(VERIFY_READ, cmd_in, - cmdlen + inlen > MAX_BUF ? MAX_BUF : inlen); - if (result) return result; - - memcpy_fromfs ((void *) cmd, cmd_in, cmdlen); - - /* - * Obtain the data to be sent to the device (if any). - */ - memcpy_fromfs ((void *) buf, - (void *) (cmd_in + cmdlen), - inlen); - - /* - * Set the lun field to the correct value. - */ - cmd[1] = ( cmd[1] & 0x1f ) | (dev->lun << 5); - -#ifndef DEBUG_NO_CMD - - SCpnt = allocate_device(NULL, dev, 1); - - { - struct semaphore sem = MUTEX_LOCKED; - SCpnt->request.sem = &sem; - scsi_do_cmd(SCpnt, cmd, buf, needed, scsi_ioctl_done, MAX_TIMEOUT, - MAX_RETRIES); - down(&sem); - } - - /* - * If there was an error condition, pass the info back to the user. - */ - if(SCpnt->result) { - result = verify_area(VERIFY_WRITE, - cmd_in, - sizeof(SCpnt->sense_buffer)); - if (result) return result; - memcpy_tofs((void *) cmd_in, - SCpnt->sense_buffer, - sizeof(SCpnt->sense_buffer)); - } else { - result = verify_area(VERIFY_WRITE, cmd_in, outlen); - if (result) return result; - memcpy_tofs ((void *) cmd_in, buf, outlen); - } - result = SCpnt->result; - - SCpnt->request.rq_status = RQ_INACTIVE; - - if (buf) scsi_free(buf, buf_needed); - - if(SCpnt->device->scsi_request_fn) - (*SCpnt->device->scsi_request_fn)(); - - wake_up(&SCpnt->device->device_wait); - return result; -#else - { - int i; - printk("scsi_ioctl : device %d. command = ", dev->id); - for (i = 0; i < 12; ++i) - printk("%02x ", cmd[i]); - printk("\nbuffer ="); - for (i = 0; i < 20; ++i) - printk("%02x ", buf[i]); - printk("\n"); - printk("inlen = %d, outlen = %d, cmdlen = %d\n", - inlen, outlen, cmdlen); - printk("buffer = %d, cmd_in = %d\n", buffer, cmd_in); - } - return 0; -#endif -} - -/* - * the scsi_ioctl() function differs from most ioctls in that it does - * not take a major/minor number as the dev filed. Rather, it takes - * a pointer to a scsi_devices[] element, a structure. - */ -int scsi_ioctl (Scsi_Device *dev, int cmd, void *arg) -{ - int result; - char scsi_cmd[12]; - - /* No idea how this happens.... */ - if (!dev) return -ENXIO; - - switch (cmd) { - case SCSI_IOCTL_GET_IDLUN: - result = verify_area(VERIFY_WRITE, (void *) arg, 2*sizeof(long)); - if (result) return result; - - put_user(dev->id - + (dev->lun << 8) - + (dev->channel << 16) - + ((dev->host->hostt->proc_dir->low_ino & 0xff) << 24), - (unsigned long *) arg); - put_user( dev->host->unique_id, (unsigned long *) arg+1); - return 0; - case SCSI_IOCTL_TAGGED_ENABLE: - if(!suser()) return -EACCES; - if(!dev->tagged_supported) return -EINVAL; - dev->tagged_queue = 1; - dev->current_tag = 1; - break; - case SCSI_IOCTL_TAGGED_DISABLE: - if(!suser()) return -EACCES; - if(!dev->tagged_supported) return -EINVAL; - dev->tagged_queue = 0; - dev->current_tag = 0; - break; - case SCSI_IOCTL_PROBE_HOST: - return ioctl_probe(dev->host, arg); - case SCSI_IOCTL_SEND_COMMAND: - if(!suser()) return -EACCES; - return ioctl_command((Scsi_Device *) dev, arg); - case SCSI_IOCTL_DOORLOCK: - if (!dev->removable || !dev->lockable) return 0; - scsi_cmd[0] = ALLOW_MEDIUM_REMOVAL; - scsi_cmd[1] = dev->lun << 5; - scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0; - scsi_cmd[4] = SCSI_REMOVAL_PREVENT; - return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd); - break; - case SCSI_IOCTL_DOORUNLOCK: - if (!dev->removable || !dev->lockable) return 0; - scsi_cmd[0] = ALLOW_MEDIUM_REMOVAL; - scsi_cmd[1] = dev->lun << 5; - scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0; - scsi_cmd[4] = SCSI_REMOVAL_ALLOW; - return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd); - case SCSI_IOCTL_TEST_UNIT_READY: - scsi_cmd[0] = TEST_UNIT_READY; - scsi_cmd[1] = dev->lun << 5; - scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0; - scsi_cmd[4] = 0; - return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd); - break; - default : - return -EINVAL; - } - return -EINVAL; -} - -/* - * Just like scsi_ioctl, only callable from kernel space with no - * fs segment fiddling. - */ - -int kernel_scsi_ioctl (Scsi_Device *dev, int cmd, void *arg) { - unsigned long oldfs; - int tmp; - oldfs = get_fs(); - set_fs(get_ds()); - tmp = scsi_ioctl (dev, cmd, arg); - set_fs(oldfs); - return tmp; -} - -/* - * Overrides for Emacs so that we almost follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 4 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -4 - * c-argdecl-indent: 4 - * c-label-offset: -4 - * c-continued-statement-offset: 4 - * c-continued-brace-offset: 0 - * indent-tabs-mode: nil - * tab-width: 8 - * End: - */ diff --git a/i386/i386at/gpl/linux/scsi/scsi_ioctl.h b/i386/i386at/gpl/linux/scsi/scsi_ioctl.h deleted file mode 100644 index a42fed00..00000000 --- a/i386/i386at/gpl/linux/scsi/scsi_ioctl.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef _SCSI_IOCTL_H -#define _SCSI_IOCTL_H - -#define SCSI_IOCTL_SEND_COMMAND 1 -#define SCSI_IOCTL_TEST_UNIT_READY 2 -#define SCSI_IOCTL_BENCHMARK_COMMAND 3 -#define SCSI_IOCTL_SYNC 4 /* Request synchronous parameters */ -/* The door lock/unlock constants are compatible with Sun constants for - the cdrom */ -#define SCSI_IOCTL_DOORLOCK 0x5380 /* lock the eject mechanism */ -#define SCSI_IOCTL_DOORUNLOCK 0x5381 /* unlock the mechanism */ - -#define SCSI_REMOVAL_PREVENT 1 -#define SCSI_REMOVAL_ALLOW 0 - -extern int scsi_ioctl (Scsi_Device *dev, int cmd, void *arg); -extern int kernel_scsi_ioctl (Scsi_Device *dev, int cmd, void *arg); - -#endif - - diff --git a/i386/i386at/gpl/linux/scsi/scsi_proc.c b/i386/i386at/gpl/linux/scsi/scsi_proc.c deleted file mode 100644 index 6650cec9..00000000 --- a/i386/i386at/gpl/linux/scsi/scsi_proc.c +++ /dev/null @@ -1,317 +0,0 @@ -/* - * linux/drivers/scsi/scsi_proc.c - * - * The functions in this file provide an interface between - * the PROC file system and the SCSI device drivers - * It is mainly used for debugging, statistics and to pass - * information directly to the lowlevel driver. - * - * (c) 1995 Michael Neuffer neuffer@goofy.zdv.uni-mainz.de - * Version: 0.99.8 last change: 95/09/13 - * - * generic command parser provided by: - * Andreas Heilwagen <crashcar@informatik.uni-koblenz.de> - */ - -/* - * Don't import our own symbols, as this would severely mess up our - * symbol tables. - */ -#define _SCSI_SYMS_VER_ -#define __NO_VERSION__ -#include <linux/module.h> - -#include <linux/string.h> -#include <linux/mm.h> -#include <linux/malloc.h> -#include <linux/proc_fs.h> -#include <linux/errno.h> -#include <linux/stat.h> -#include <linux/blk.h> -#include "scsi.h" -#include "hosts.h" - -#ifndef TRUE -#define TRUE 1 -#define FALSE 0 -#endif - -extern int scsi_proc_info(char *, char **, off_t, int, int, int); - -struct scsi_dir { - struct proc_dir_entry entry; - char name[4]; -}; - - -/* generic_proc_info - * Used if the driver currently has no own support for /proc/scsi - */ -int generic_proc_info(char *buffer, char **start, off_t offset, - int length, int inode, int inout) -{ - int len, pos, begin; - - if(inout == TRUE) - return(-ENOSYS); /* This is a no-op */ - - begin = 0; - pos = len = sprintf(buffer, - "The driver does not yet support the proc-fs\n"); - if(pos < offset) { - len = 0; - begin = pos; - } - - *start = buffer + (offset - begin); /* Start of wanted data */ - len -= (offset - begin); - if(len > length) - len = length; - - return(len); -} - -/* dispatch_scsi_info is the central dispatcher - * It is the interface between the proc-fs and the SCSI subsystem code - */ -extern int dispatch_scsi_info(int ino, char *buffer, char **start, - off_t offset, int length, int func) -{ - struct Scsi_Host *hpnt = scsi_hostlist; - - if(ino == PROC_SCSI_SCSI) { - /* - * This is for the scsi core, rather than any specific - * lowlevel driver. - */ - return(scsi_proc_info(buffer, start, offset, length, 0, func)); - } - - while(hpnt) { - if (ino == (hpnt->host_no + PROC_SCSI_FILE)) { - if(hpnt->hostt->proc_info == NULL) - return generic_proc_info(buffer, start, offset, length, - hpnt->host_no, func); - else - return(hpnt->hostt->proc_info(buffer, start, offset, - length, hpnt->host_no, func)); - } - hpnt = hpnt->next; - } - return(-EBADF); -} - -void build_proc_dir_entries(Scsi_Host_Template *tpnt) -{ - struct Scsi_Host *hpnt; - - struct scsi_dir *scsi_hba_dir; - - proc_scsi_register(0, tpnt->proc_dir); - - hpnt = scsi_hostlist; - while (hpnt) { - if (tpnt == hpnt->hostt) { - scsi_hba_dir = scsi_init_malloc(sizeof(struct scsi_dir), GFP_KERNEL); - if(scsi_hba_dir == NULL) - panic("Not enough memory to register SCSI HBA in /proc/scsi !\n"); - memset(scsi_hba_dir, 0, sizeof(struct scsi_dir)); - scsi_hba_dir->entry.low_ino = PROC_SCSI_FILE + hpnt->host_no; - scsi_hba_dir->entry.namelen = sprintf(scsi_hba_dir->name,"%d", - hpnt->host_no); - scsi_hba_dir->entry.name = scsi_hba_dir->name; - scsi_hba_dir->entry.mode = S_IFREG | S_IRUGO | S_IWUSR; - proc_scsi_register(tpnt->proc_dir, &scsi_hba_dir->entry); - } - hpnt = hpnt->next; - } -} - -/* - * parseHandle *parseInit(char *buf, char *cmdList, int cmdNum); - * gets a pointer to a null terminated data buffer - * and a list of commands with blanks as delimiter - * in between. - * The commands have to be alphanumerically sorted. - * cmdNum has to contain the number of commands. - * On success, a pointer to a handle structure - * is returned, NULL on failure - * - * int parseOpt(parseHandle *handle, char **param); - * processes the next parameter. On success, the - * index of the appropriate command in the cmdList - * is returned, starting with zero. - * param points to the null terminated parameter string. - * On failure, -1 is returned. - * - * The databuffer buf may only contain pairs of commands - * options, separated by blanks: - * <Command> <Parameter> [<Command> <Parameter>]* - */ - -typedef struct -{ - char *buf, /* command buffer */ - *cmdList, /* command list */ - *bufPos, /* actual position */ - **cmdPos, /* cmdList index */ - cmdNum; /* cmd number */ -} parseHandle; - - -inline int parseFree (parseHandle *handle) /* free memory */ -{ - kfree (handle->cmdPos); - kfree (handle); - - return(-1); -} - - -parseHandle *parseInit(char *buf, char *cmdList, int cmdNum) -{ - char *ptr; /* temp pointer */ - parseHandle *handle; /* new handle */ - - if (!buf || !cmdList) /* bad input ? */ - return(NULL); - if ((handle = (parseHandle*) kmalloc(sizeof(parseHandle), 1)) == 0) - return(NULL); /* out of memory */ - if ((handle->cmdPos = (char**) kmalloc(sizeof(int), cmdNum)) == 0) { - kfree(handle); - return(NULL); /* out of memory */ - } - - handle->buf = handle->bufPos = buf; /* init handle */ - handle->cmdList = cmdList; - handle->cmdNum = cmdNum; - - handle->cmdPos[cmdNum = 0] = cmdList; - for (ptr = cmdList; *ptr; ptr++) { /* scan command string */ - if(*ptr == ' ') { /* and insert zeroes */ - *ptr++ = 0; - handle->cmdPos[++cmdNum] = ptr++; - } - } - return(handle); -} - - -int parseOpt(parseHandle *handle, char **param) -{ - int cmdIndex = 0, - cmdLen = 0; - char *startPos; - - if (!handle) /* invalid handle */ - return(parseFree(handle)); - /* skip spaces */ - for (; *(handle->bufPos) && *(handle->bufPos) == ' '; handle->bufPos++); - if (!*(handle->bufPos)) - return(parseFree(handle)); /* end of data */ - - startPos = handle->bufPos; /* store cmd start */ - for (; handle->cmdPos[cmdIndex][cmdLen] && *(handle->bufPos); handle->bufPos++) - { /* no string end? */ - for (;;) - { - if (*(handle->bufPos) == handle->cmdPos[cmdIndex][cmdLen]) - break; /* char matches ? */ - else - if (memcmp(startPos, (char*)(handle->cmdPos[++cmdIndex]), cmdLen)) - return(parseFree(handle)); /* unknown command */ - - if (cmdIndex >= handle->cmdNum) - return(parseFree(handle)); /* unknown command */ - } - - cmdLen++; /* next char */ - } - - /* Get param. First skip all blanks, then insert zero after param */ - - for (; *(handle->bufPos) && *(handle->bufPos) == ' '; handle->bufPos++); - *param = handle->bufPos; - - for (; *(handle->bufPos) && *(handle->bufPos) != ' '; handle->bufPos++); - *(handle->bufPos++) = 0; - - return(cmdIndex); -} - -#define MAX_SCSI_DEVICE_CODE 10 -const char *const scsi_dev_types[MAX_SCSI_DEVICE_CODE] = -{ - "Direct-Access ", - "Sequential-Access", - "Printer ", - "Processor ", - "WORM ", - "CD-ROM ", - "Scanner ", - "Optical Device ", - "Medium Changer ", - "Communications " -}; - -void proc_print_scsidevice(Scsi_Device *scd, char *buffer, int *size, int len) -{ - int x, y = *size; - - y = sprintf(buffer + len, - "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n Vendor: ", - scd->host->host_no, scd->channel, scd->id, scd->lun); - for (x = 0; x < 8; x++) { - if (scd->vendor[x] >= 0x20) - y += sprintf(buffer + len + y, "%c", scd->vendor[x]); - else - y += sprintf(buffer + len + y," "); - } - y += sprintf(buffer + len + y, " Model: "); - for (x = 0; x < 16; x++) { - if (scd->model[x] >= 0x20) - y += sprintf(buffer + len + y, "%c", scd->model[x]); - else - y += sprintf(buffer + len + y, " "); - } - y += sprintf(buffer + len + y, " Rev: "); - for (x = 0; x < 4; x++) { - if (scd->rev[x] >= 0x20) - y += sprintf(buffer + len + y, "%c", scd->rev[x]); - else - y += sprintf(buffer + len + y, " "); - } - y += sprintf(buffer + len + y, "\n"); - - y += sprintf(buffer + len + y, " Type: %s ", - scd->type < MAX_SCSI_DEVICE_CODE ? - scsi_dev_types[(int)scd->type] : "Unknown " ); - y += sprintf(buffer + len + y, " ANSI" - " SCSI revision: %02x", (scd->scsi_level < 3)?1:2); - if (scd->scsi_level == 2) - y += sprintf(buffer + len + y, " CCS\n"); - else - y += sprintf(buffer + len + y, "\n"); - - *size = y; - return; -} - -/* - * Overrides for Emacs so that we get a uniform tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 4 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -4 - * c-argdecl-indent: 4 - * c-label-offset: -4 - * c-continued-statement-offset: 4 - * c-continued-brace-offset: 0 - * indent-tabs-mode: nil - * tab-width: 8 - * End: - */ diff --git a/i386/i386at/gpl/linux/scsi/scsicam.c b/i386/i386at/gpl/linux/scsi/scsicam.c deleted file mode 100644 index e4e4e764..00000000 --- a/i386/i386at/gpl/linux/scsi/scsicam.c +++ /dev/null @@ -1,214 +0,0 @@ -/* - * scsicam.c - SCSI CAM support functions, use for HDIO_GETGEO, etc. - * - * Copyright 1993, 1994 Drew Eckhardt - * Visionary Computing - * (Unix and Linux consulting and custom programming) - * drew@Colorado.EDU - * +1 (303) 786-7975 - * - * For more information, please consult the SCSI-CAM draft. - */ - -/* - * Don't import our own symbols, as this would severely mess up our - * symbol tables. - */ -#define _SCSI_SYMS_VER_ -#define __NO_VERSION__ -#include <linux/module.h> - -#include <linux/fs.h> -#include <linux/genhd.h> -#include <linux/kernel.h> -#include <linux/blk.h> -#include "scsi.h" -#include "hosts.h" -#include "sd.h" - -static int partsize(struct buffer_head *bh, unsigned long capacity, - unsigned int *cyls, unsigned int *hds, unsigned int *secs); -static int setsize(unsigned long capacity,unsigned int *cyls,unsigned int *hds, - unsigned int *secs); - -/* - * Function : int scsicam_bios_param (Disk *disk, int dev, int *ip) - * - * Purpose : to determine the BIOS mapping used for a drive in a - * SCSI-CAM system, storing the results in ip as required - * by the HDIO_GETGEO ioctl(). - * - * Returns : -1 on failure, 0 on success. - * - */ - -int scsicam_bios_param (Disk *disk, /* SCSI disk */ - kdev_t dev, /* Device major, minor */ - int *ip /* Heads, sectors, cylinders in that order */) { - - struct buffer_head *bh; - int ret_code; - int size = disk->capacity; - - if (!(bh = bread(MKDEV(MAJOR(dev), MINOR(dev)&~0xf), 0, 1024))) - return -1; - -#ifdef DEBUG - printk ("scsicam_bios_param : trying existing mapping\n"); -#endif - ret_code = partsize (bh, (unsigned long) size, (unsigned int *) ip + 2, - (unsigned int *) ip + 0, (unsigned int *) ip + 1); - brelse (bh); - - if (ret_code == -1) { -#ifdef DEBUG - printk ("scsicam_bios_param : trying optimal mapping\n"); -#endif - ret_code = setsize ((unsigned long) size, (unsigned int *) ip + 2, - (unsigned int *) ip + 0, (unsigned int *) ip + 1); - } - - return ret_code; -} - -/* - * Function : static int partsize(struct buffer_head *bh, unsigned long - * capacity,unsigned int *cyls, unsigned int *hds, unsigned int *secs); - * - * Purpose : to determine the BIOS mapping used to create the partition - * table, storing the results in *cyls, *hds, and *secs - * - * Returns : -1 on failure, 0 on success. - * - */ - -static int partsize(struct buffer_head *bh, unsigned long capacity, - unsigned int *cyls, unsigned int *hds, unsigned int *secs) { - struct partition *p, *largest = NULL; - int i, largest_cyl; - int cyl, ext_cyl, end_head, end_cyl, end_sector; - unsigned int logical_end, physical_end, ext_physical_end; - - - if (*(unsigned short *) (bh->b_data+510) == 0xAA55) { - for (largest_cyl = -1, p = (struct partition *) - (0x1BE + bh->b_data), i = 0; i < 4; ++i, ++p) { - if (!p->sys_ind) - continue; -#ifdef DEBUG - printk ("scsicam_bios_param : partition %d has system \n", - i); -#endif - cyl = p->cyl + ((p->sector & 0xc0) << 2); - if (cyl > largest_cyl) { - largest_cyl = cyl; - largest = p; - } - } - } - - if (largest) { - end_cyl = largest->end_cyl + ((largest->end_sector & 0xc0) << 2); - end_head = largest->end_head; - end_sector = largest->end_sector & 0x3f; - -#ifdef DEBUG - printk ("scsicam_bios_param : end at h = %d, c = %d, s = %d\n", - end_head, end_cyl, end_sector); -#endif - - physical_end = end_cyl * (end_head + 1) * end_sector + - end_head * end_sector + end_sector; - - /* This is the actual _sector_ number at the end */ - logical_end = largest->start_sect + largest->nr_sects; - - /* This is for >1023 cylinders */ - ext_cyl= (logical_end-(end_head * end_sector + end_sector)) - /(end_head + 1) / end_sector; - ext_physical_end = ext_cyl * (end_head + 1) * end_sector + - end_head * end_sector + end_sector; - -#ifdef DEBUG - printk("scsicam_bios_param : logical_end=%d physical_end=%d ext_physical_end=%d ext_cyl=%d\n" - ,logical_end,physical_end,ext_physical_end,ext_cyl); -#endif - - if ((logical_end == physical_end) || - (end_cyl==1023 && ext_physical_end==logical_end)) { - *secs = end_sector; - *hds = end_head + 1; - *cyls = capacity / ((end_head + 1) * end_sector); - return 0; - } - -#ifdef DEBUG - printk ("scsicam_bios_param : logical (%u) != physical (%u)\n", - logical_end, physical_end); -#endif - } - return -1; -} - -/* - * Function : static int setsize(unsigned long capacity,unsigned int *cyls, - * unsigned int *hds, unsigned int *secs); - * - * Purpose : to determine a near-optimal int 0x13 mapping for a - * SCSI disk in terms of lost space of size capacity, storing - * the results in *cyls, *hds, and *secs. - * - * Returns : -1 on failure, 0 on success. - * - * Extracted from - * - * WORKING X3T9.2 - * DRAFT 792D - * - * - * Revision 6 - * 10-MAR-94 - * Information technology - - * SCSI-2 Common access method - * transport and SCSI interface module - * - * ANNEX A : - * - * setsize() converts a read capacity value to int 13h - * head-cylinder-sector requirements. It minimizes the value for - * number of heads and maximizes the number of cylinders. This - * will support rather large disks before the number of heads - * will not fit in 4 bits (or 6 bits). This algorithm also - * minimizes the number of sectors that will be unused at the end - * of the disk while allowing for very large disks to be - * accommodated. This algorithm does not use physical geometry. - */ - -static int setsize(unsigned long capacity,unsigned int *cyls,unsigned int *hds, - unsigned int *secs) { - unsigned int rv = 0; - unsigned long heads, sectors, cylinders, temp; - - cylinders = 1024L; /* Set number of cylinders to max */ - sectors = 62L; /* Maximize sectors per track */ - - temp = cylinders * sectors; /* Compute divisor for heads */ - heads = capacity / temp; /* Compute value for number of heads */ - if (capacity % temp) { /* If no remainder, done! */ - heads++; /* Else, increment number of heads */ - temp = cylinders * heads; /* Compute divisor for sectors */ - sectors = capacity / temp; /* Compute value for sectors per - track */ - if (capacity % temp) { /* If no remainder, done! */ - sectors++; /* Else, increment number of sectors */ - temp = heads * sectors; /* Compute divisor for cylinders */ - cylinders = capacity / temp;/* Compute number of cylinders */ - } - } - if (cylinders == 0) rv=(unsigned)-1;/* Give error if 0 cylinders */ - - *cyls = (unsigned int) cylinders; /* Stuff return values */ - *secs = (unsigned int) sectors; - *hds = (unsigned int) heads; - return(rv); -} diff --git a/i386/i386at/gpl/linux/scsi/sd.c b/i386/i386at/gpl/linux/scsi/sd.c deleted file mode 100644 index 47bf2263..00000000 --- a/i386/i386at/gpl/linux/scsi/sd.c +++ /dev/null @@ -1,1543 +0,0 @@ -/* - * sd.c Copyright (C) 1992 Drew Eckhardt - * Copyright (C) 1993, 1994, 1995 Eric Youngdale - * - * Linux scsi disk driver - * Initial versions: Drew Eckhardt - * Subsequent revisions: Eric Youngdale - * - * <drew@colorado.edu> - * - * Modified by Eric Youngdale ericy@cais.com to - * add scatter-gather, multiple outstanding request, and other - * enhancements. - * - * Modified by Eric Youngdale eric@aib.com to support loadable - * low-level scsi drivers. - */ - -#include <linux/module.h> -#ifdef MODULE -/* - * This is a variable in scsi.c that is set when we are processing something - * after boot time. By definition, this is true when we are a loadable module - * ourselves. - */ -#define MODULE_FLAG 1 -#else -#define MODULE_FLAG scsi_loadable_module_flag -#endif /* MODULE */ - -#include <linux/fs.h> -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/mm.h> -#include <linux/string.h> -#include <linux/errno.h> -#include <asm/system.h> - -#define MAJOR_NR SCSI_DISK_MAJOR -#include <linux/blk.h> -#include "scsi.h" -#include "hosts.h" -#include "sd.h" -#include "scsi_ioctl.h" -#include "constants.h" - -#include <linux/genhd.h> - -/* - * static const char RCSid[] = "$Header:"; - */ - -#define MAX_RETRIES 5 - -/* - * Time out in seconds for disks and Magneto-opticals (which are slower). - */ - -#define SD_TIMEOUT (7 * HZ) -#define SD_MOD_TIMEOUT (8 * HZ) - -#define CLUSTERABLE_DEVICE(SC) (SC->host->use_clustering && \ - SC->device->type != TYPE_MOD) - -struct hd_struct * sd; - -Scsi_Disk * rscsi_disks = NULL; -static int * sd_sizes; -static int * sd_blocksizes; -static int * sd_hardsizes; /* Hardware sector size */ - -extern int sd_ioctl(struct inode *, struct file *, unsigned int, unsigned long); - -static int check_scsidisk_media_change(kdev_t); -static int fop_revalidate_scsidisk(kdev_t); - -static sd_init_onedisk(int); - -static void requeue_sd_request (Scsi_Cmnd * SCpnt); - -static int sd_init(void); -static void sd_finish(void); -static int sd_attach(Scsi_Device *); -static int sd_detect(Scsi_Device *); -static void sd_detach(Scsi_Device *); - -struct Scsi_Device_Template sd_template = -{ NULL, "disk", "sd", NULL, TYPE_DISK, - SCSI_DISK_MAJOR, 0, 0, 0, 1, - sd_detect, sd_init, - sd_finish, sd_attach, sd_detach -}; - -static int sd_open(struct inode * inode, struct file * filp) -{ - int target; - target = DEVICE_NR(inode->i_rdev); - - if(target >= sd_template.dev_max || !rscsi_disks[target].device) - return -ENXIO; /* No such device */ - - /* - * Make sure that only one process can do a check_change_disk at one time. - * This is also used to lock out further access when the partition table - * is being re-read. - */ - - while (rscsi_disks[target].device->busy) - barrier(); - if(rscsi_disks[target].device->removable) { - check_disk_change(inode->i_rdev); - - /* - * If the drive is empty, just let the open fail. - */ - if ( !rscsi_disks[target].ready ) { - return -ENXIO; - } - - /* - * Similarily, if the device has the write protect tab set, - * have the open fail if the user expects to be able to write - * to the thing. - */ - if ( (rscsi_disks[target].write_prot) && (filp->f_mode & 2) ) { - return -EROFS; - } - - if(!rscsi_disks[target].device->access_count) - sd_ioctl(inode, NULL, SCSI_IOCTL_DOORLOCK, 0); - }; - - /* - * See if we are requesting a non-existent partition. Do this - * after checking for disk change. - */ - if(sd_sizes[MINOR(inode->i_rdev)] == 0) - return -ENXIO; - - rscsi_disks[target].device->access_count++; - if (rscsi_disks[target].device->host->hostt->usage_count) - (*rscsi_disks[target].device->host->hostt->usage_count)++; - if(sd_template.usage_count) (*sd_template.usage_count)++; - return 0; -} - -static void sd_release(struct inode * inode, struct file * file) -{ - int target; - sync_dev(inode->i_rdev); - - target = DEVICE_NR(inode->i_rdev); - - rscsi_disks[target].device->access_count--; - if (rscsi_disks[target].device->host->hostt->usage_count) - (*rscsi_disks[target].device->host->hostt->usage_count)--; - if(sd_template.usage_count) (*sd_template.usage_count)--; - - if(rscsi_disks[target].device->removable) { - if(!rscsi_disks[target].device->access_count) - sd_ioctl(inode, NULL, SCSI_IOCTL_DOORUNLOCK, 0); - } -} - -static void sd_geninit(struct gendisk *); - -static struct file_operations sd_fops = { - NULL, /* lseek - default */ - block_read, /* read - general block-dev read */ - block_write, /* write - general block-dev write */ - NULL, /* readdir - bad */ - NULL, /* select */ - sd_ioctl, /* ioctl */ - NULL, /* mmap */ - sd_open, /* open code */ - sd_release, /* release */ - block_fsync, /* fsync */ - NULL, /* fasync */ - check_scsidisk_media_change, /* Disk change */ - fop_revalidate_scsidisk /* revalidate */ -}; - -static struct gendisk sd_gendisk = { - MAJOR_NR, /* Major number */ - "sd", /* Major name */ - 4, /* Bits to shift to get real from partition */ - 1 << 4, /* Number of partitions per real */ - 0, /* maximum number of real */ - sd_geninit, /* init function */ - NULL, /* hd struct */ - NULL, /* block sizes */ - 0, /* number */ - NULL, /* internal */ - NULL /* next */ -}; - -static void sd_geninit (struct gendisk *ignored) -{ - int i; - - for (i = 0; i < sd_template.dev_max; ++i) - if(rscsi_disks[i].device) - sd[i << 4].nr_sects = rscsi_disks[i].capacity; -#if 0 - /* No longer needed - we keep track of this as we attach/detach */ - sd_gendisk.nr_real = sd_template.dev_max; -#endif -} - -/* - * rw_intr is the interrupt routine for the device driver. It will - * be notified on the end of a SCSI read / write, and - * will take on of several actions based on success or failure. - */ - -static void rw_intr (Scsi_Cmnd *SCpnt) -{ - int result = SCpnt->result; - int this_count = SCpnt->bufflen >> 9; - -#ifdef DEBUG - printk("sd%c : rw_intr(%d, %d)\n", 'a' + MINOR(SCpnt->request.rq_dev), - SCpnt->host->host_no, result); -#endif - - /* - * First case : we assume that the command succeeded. One of two things - * will happen here. Either we will be finished, or there will be more - * sectors that we were unable to read last time. - */ - - if (!result) { - -#ifdef DEBUG - printk("sd%c : %d sectors remain.\n", 'a' + MINOR(SCpnt->request.rq_dev), - SCpnt->request.nr_sectors); - printk("use_sg is %d\n ",SCpnt->use_sg); -#endif - if (SCpnt->use_sg) { - struct scatterlist * sgpnt; - int i; - sgpnt = (struct scatterlist *) SCpnt->buffer; - for(i=0; i<SCpnt->use_sg; i++) { -#ifdef DEBUG - printk(":%x %x %d\n",sgpnt[i].alt_address, sgpnt[i].address, - sgpnt[i].length); -#endif - if (sgpnt[i].alt_address) { - if (SCpnt->request.cmd == READ) - memcpy(sgpnt[i].alt_address, sgpnt[i].address, - sgpnt[i].length); - scsi_free(sgpnt[i].address, sgpnt[i].length); - }; - }; - - /* Free list of scatter-gather pointers */ - scsi_free(SCpnt->buffer, SCpnt->sglist_len); - } else { - if (SCpnt->buffer != SCpnt->request.buffer) { -#ifdef DEBUG - printk("nosg: %x %x %d\n",SCpnt->request.buffer, SCpnt->buffer, - SCpnt->bufflen); -#endif - if (SCpnt->request.cmd == READ) - memcpy(SCpnt->request.buffer, SCpnt->buffer, - SCpnt->bufflen); - scsi_free(SCpnt->buffer, SCpnt->bufflen); - }; - }; - /* - * If multiple sectors are requested in one buffer, then - * they will have been finished off by the first command. - * If not, then we have a multi-buffer command. - */ - if (SCpnt->request.nr_sectors > this_count) - { - SCpnt->request.errors = 0; - - if (!SCpnt->request.bh) - { -#ifdef DEBUG - printk("sd%c : handling page request, no buffer\n", - 'a' + MINOR(SCpnt->request.rq_dev)); -#endif - /* - * The SCpnt->request.nr_sectors field is always done in - * 512 byte sectors, even if this really isn't the case. - */ - panic("sd.c: linked page request (%lx %x)", - SCpnt->request.sector, this_count); - } - } - SCpnt = end_scsi_request(SCpnt, 1, this_count); - requeue_sd_request(SCpnt); - return; - } - - /* Free up any indirection buffers we allocated for DMA purposes. */ - if (SCpnt->use_sg) { - struct scatterlist * sgpnt; - int i; - sgpnt = (struct scatterlist *) SCpnt->buffer; - for(i=0; i<SCpnt->use_sg; i++) { -#ifdef DEBUG - printk("err: %x %x %d\n",SCpnt->request.buffer, SCpnt->buffer, - SCpnt->bufflen); -#endif - if (sgpnt[i].alt_address) { - scsi_free(sgpnt[i].address, sgpnt[i].length); - }; - }; - scsi_free(SCpnt->buffer, SCpnt->sglist_len); /* Free list of scatter-gather pointers */ - } else { -#ifdef DEBUG - printk("nosgerr: %x %x %d\n",SCpnt->request.buffer, SCpnt->buffer, - SCpnt->bufflen); -#endif - if (SCpnt->buffer != SCpnt->request.buffer) - scsi_free(SCpnt->buffer, SCpnt->bufflen); - }; - - /* - * Now, if we were good little boys and girls, Santa left us a request - * sense buffer. We can extract information from this, so we - * can choose a block to remap, etc. - */ - - if (driver_byte(result) != 0) { - if (suggestion(result) == SUGGEST_REMAP) { -#ifdef REMAP - /* - * Not yet implemented. A read will fail after being remapped, - * a write will call the strategy routine again. - */ - if rscsi_disks[DEVICE_NR(SCpnt->request.rq_dev)].remap - { - result = 0; - } - else -#endif - } - - if ((SCpnt->sense_buffer[0] & 0x7f) == 0x70) { - if ((SCpnt->sense_buffer[2] & 0xf) == UNIT_ATTENTION) { - if(rscsi_disks[DEVICE_NR(SCpnt->request.rq_dev)].device->removable) { - /* detected disc change. set a bit and quietly refuse - * further access. - */ - rscsi_disks[DEVICE_NR(SCpnt->request.rq_dev)].device->changed = 1; - SCpnt = end_scsi_request(SCpnt, 0, this_count); - requeue_sd_request(SCpnt); - return; - } - else - { - /* - * Must have been a power glitch, or a bus reset. - * Could not have been a media change, so we just retry - * the request and see what happens. - */ - requeue_sd_request(SCpnt); - return; - } - } - } - - - /* If we had an ILLEGAL REQUEST returned, then we may have - * performed an unsupported command. The only thing this should be - * would be a ten byte read where only a six byte read was supported. - * Also, on a system where READ CAPACITY failed, we have have read - * past the end of the disk. - */ - - if (SCpnt->sense_buffer[2] == ILLEGAL_REQUEST) { - if (rscsi_disks[DEVICE_NR(SCpnt->request.rq_dev)].ten) { - rscsi_disks[DEVICE_NR(SCpnt->request.rq_dev)].ten = 0; - requeue_sd_request(SCpnt); - result = 0; - } else { - /* ???? */ - } - } - } /* driver byte != 0 */ - if (result) { - printk("SCSI disk error : host %d channel %d id %d lun %d return code = %x\n", - rscsi_disks[DEVICE_NR(SCpnt->request.rq_dev)].device->host->host_no, - rscsi_disks[DEVICE_NR(SCpnt->request.rq_dev)].device->channel, - rscsi_disks[DEVICE_NR(SCpnt->request.rq_dev)].device->id, - rscsi_disks[DEVICE_NR(SCpnt->request.rq_dev)].device->lun, result); - - if (driver_byte(result) & DRIVER_SENSE) - print_sense("sd", SCpnt); - SCpnt = end_scsi_request(SCpnt, 0, SCpnt->request.current_nr_sectors); - requeue_sd_request(SCpnt); - return; - } -} - -/* - * requeue_sd_request() is the request handler function for the sd driver. - * Its function in life is to take block device requests, and translate - * them to SCSI commands. - */ - -static void do_sd_request (void) -{ - Scsi_Cmnd * SCpnt = NULL; - Scsi_Device * SDev; - struct request * req = NULL; - unsigned long flags; - int flag = 0; - - save_flags(flags); - while (1==1){ - cli(); - if (CURRENT != NULL && CURRENT->rq_status == RQ_INACTIVE) { - restore_flags(flags); - return; - }; - - INIT_SCSI_REQUEST; - SDev = rscsi_disks[DEVICE_NR(CURRENT->rq_dev)].device; - - /* - * I am not sure where the best place to do this is. We need - * to hook in a place where we are likely to come if in user - * space. - */ - if( SDev->was_reset ) - { - /* - * We need to relock the door, but we might - * be in an interrupt handler. Only do this - * from user space, since we do not want to - * sleep from an interrupt. - */ - if( SDev->removable && !intr_count ) - { - scsi_ioctl(SDev, SCSI_IOCTL_DOORLOCK, 0); - } - SDev->was_reset = 0; - } - - /* We have to be careful here. allocate_device will get a free pointer, - * but there is no guarantee that it is queueable. In normal usage, - * we want to call this, because other types of devices may have the - * host all tied up, and we want to make sure that we have at least - * one request pending for this type of device. We can also come - * through here while servicing an interrupt, because of the need to - * start another command. If we call allocate_device more than once, - * then the system can wedge if the command is not queueable. The - * request_queueable function is safe because it checks to make sure - * that the host is able to take another command before it returns - * a pointer. - */ - - if (flag++ == 0) - SCpnt = allocate_device(&CURRENT, - rscsi_disks[DEVICE_NR(CURRENT->rq_dev)].device, 0); - else SCpnt = NULL; - - /* - * The following restore_flags leads to latency problems. FIXME. - * Using a "sti()" gets rid of the latency problems but causes - * race conditions and crashes. - */ - restore_flags(flags); - - /* This is a performance enhancement. We dig down into the request - * list and try and find a queueable request (i.e. device not busy, - * and host able to accept another command. If we find one, then we - * queue it. This can make a big difference on systems with more than - * one disk drive. We want to have the interrupts off when monkeying - * with the request list, because otherwise the kernel might try and - * slip in a request in between somewhere. - */ - - if (!SCpnt && sd_template.nr_dev > 1){ - struct request *req1; - req1 = NULL; - cli(); - req = CURRENT; - while(req){ - SCpnt = request_queueable(req, rscsi_disks[DEVICE_NR(req->rq_dev)].device); - if(SCpnt) break; - req1 = req; - req = req->next; - }; - if (SCpnt && req->rq_status == RQ_INACTIVE) { - if (req == CURRENT) - CURRENT = CURRENT->next; - else - req1->next = req->next; - }; - restore_flags(flags); - }; - - if (!SCpnt) return; /* Could not find anything to do */ - - /* Queue command */ - requeue_sd_request(SCpnt); - }; /* While */ -} - -static void requeue_sd_request (Scsi_Cmnd * SCpnt) -{ - int dev, devm, block, this_count; - unsigned char cmd[10]; - int bounce_size, contiguous; - int max_sg; - struct buffer_head * bh, *bhp; - char * buff, *bounce_buffer; - - repeat: - - if(!SCpnt || SCpnt->request.rq_status == RQ_INACTIVE) { - do_sd_request(); - return; - } - - devm = MINOR(SCpnt->request.rq_dev); - dev = DEVICE_NR(SCpnt->request.rq_dev); - - block = SCpnt->request.sector; - this_count = 0; - -#ifdef DEBUG - printk("Doing sd request, dev = %d, block = %d\n", devm, block); -#endif - - if (devm >= (sd_template.dev_max << 4) || - !rscsi_disks[dev].device || - block + SCpnt->request.nr_sectors > sd[devm].nr_sects) - { - SCpnt = end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors); - goto repeat; - } - - block += sd[devm].start_sect; - - if (rscsi_disks[dev].device->changed) - { - /* - * quietly refuse to do anything to a changed disc until the changed - * bit has been reset - */ - /* printk("SCSI disk has been changed. Prohibiting further I/O.\n"); */ - SCpnt = end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors); - goto repeat; - } - -#ifdef DEBUG - printk("sd%c : real dev = /dev/sd%c, block = %d\n", - 'a' + devm, dev, block); -#endif - - /* - * If we have a 1K hardware sectorsize, prevent access to single - * 512 byte sectors. In theory we could handle this - in fact - * the scsi cdrom driver must be able to handle this because - * we typically use 1K blocksizes, and cdroms typically have - * 2K hardware sectorsizes. Of course, things are simpler - * with the cdrom, since it is read-only. For performance - * reasons, the filesystems should be able to handle this - * and not force the scsi disk driver to use bounce buffers - * for this. - */ - if (rscsi_disks[dev].sector_size == 1024) - if((block & 1) || (SCpnt->request.nr_sectors & 1)) { - printk("sd.c:Bad block number requested"); - SCpnt = end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors); - goto repeat; - } - - switch (SCpnt->request.cmd) - { - case WRITE : - if (!rscsi_disks[dev].device->writeable) - { - SCpnt = end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors); - goto repeat; - } - cmd[0] = WRITE_6; - break; - case READ : - cmd[0] = READ_6; - break; - default : - panic ("Unknown sd command %d\n", SCpnt->request.cmd); - } - - SCpnt->this_count = 0; - - /* If the host adapter can deal with very large scatter-gather - * requests, it is a waste of time to cluster - */ - contiguous = (!CLUSTERABLE_DEVICE(SCpnt) ? 0 :1); - bounce_buffer = NULL; - bounce_size = (SCpnt->request.nr_sectors << 9); - - /* First see if we need a bounce buffer for this request. If we do, make - * sure that we can allocate a buffer. Do not waste space by allocating - * a bounce buffer if we are straddling the 16Mb line - */ - if (contiguous && SCpnt->request.bh && - ((long) SCpnt->request.bh->b_data) - + (SCpnt->request.nr_sectors << 9) - 1 > ISA_DMA_THRESHOLD - && SCpnt->host->unchecked_isa_dma) { - if(((long) SCpnt->request.bh->b_data) > ISA_DMA_THRESHOLD) - bounce_buffer = (char *) scsi_malloc(bounce_size); - if(!bounce_buffer) contiguous = 0; - }; - - if(contiguous && SCpnt->request.bh && SCpnt->request.bh->b_reqnext) - for(bh = SCpnt->request.bh, bhp = bh->b_reqnext; bhp; bh = bhp, - bhp = bhp->b_reqnext) { - if(!CONTIGUOUS_BUFFERS(bh,bhp)) { - if(bounce_buffer) scsi_free(bounce_buffer, bounce_size); - contiguous = 0; - break; - } - }; - if (!SCpnt->request.bh || contiguous) { - - /* case of page request (i.e. raw device), or unlinked buffer */ - this_count = SCpnt->request.nr_sectors; - buff = SCpnt->request.buffer; - SCpnt->use_sg = 0; - - } else if (SCpnt->host->sg_tablesize == 0 || - (need_isa_buffer && dma_free_sectors <= 10)) { - - /* Case of host adapter that cannot scatter-gather. We also - * come here if we are running low on DMA buffer memory. We set - * a threshold higher than that we would need for this request so - * we leave room for other requests. Even though we would not need - * it all, we need to be conservative, because if we run low enough - * we have no choice but to panic. - */ - if (SCpnt->host->sg_tablesize != 0 && - need_isa_buffer && - dma_free_sectors <= 10) - printk("Warning: SCSI DMA buffer space running low. Using non scatter-gather I/O.\n"); - - this_count = SCpnt->request.current_nr_sectors; - buff = SCpnt->request.buffer; - SCpnt->use_sg = 0; - - } else { - - /* Scatter-gather capable host adapter */ - struct scatterlist * sgpnt; - int count, this_count_max; - int counted; - - bh = SCpnt->request.bh; - this_count = 0; - this_count_max = (rscsi_disks[dev].ten ? 0xffff : 0xff); - count = 0; - bhp = NULL; - while(bh) { - if ((this_count + (bh->b_size >> 9)) > this_count_max) break; - if(!bhp || !CONTIGUOUS_BUFFERS(bhp,bh) || - !CLUSTERABLE_DEVICE(SCpnt) || - (SCpnt->host->unchecked_isa_dma && - ((unsigned long) bh->b_data-1) == ISA_DMA_THRESHOLD)) { - if (count < SCpnt->host->sg_tablesize) count++; - else break; - }; - this_count += (bh->b_size >> 9); - bhp = bh; - bh = bh->b_reqnext; - }; -#if 0 - if(SCpnt->host->unchecked_isa_dma && - ((unsigned int) SCpnt->request.bh->b_data-1) == ISA_DMA_THRESHOLD) count--; -#endif - SCpnt->use_sg = count; /* Number of chains */ - count = 512;/* scsi_malloc can only allocate in chunks of 512 bytes */ - while( count < (SCpnt->use_sg * sizeof(struct scatterlist))) - count = count << 1; - SCpnt->sglist_len = count; - max_sg = count / sizeof(struct scatterlist); - if(SCpnt->host->sg_tablesize < max_sg) - max_sg = SCpnt->host->sg_tablesize; - sgpnt = (struct scatterlist * ) scsi_malloc(count); - if (!sgpnt) { - printk("Warning - running *really* short on DMA buffers\n"); - SCpnt->use_sg = 0; /* No memory left - bail out */ - this_count = SCpnt->request.current_nr_sectors; - buff = SCpnt->request.buffer; - } else { - memset(sgpnt, 0, count); /* Zero so it is easy to fill, but only - * if memory is available - */ - buff = (char *) sgpnt; - counted = 0; - for(count = 0, bh = SCpnt->request.bh, bhp = bh->b_reqnext; - count < SCpnt->use_sg && bh; - count++, bh = bhp) { - - bhp = bh->b_reqnext; - - if(!sgpnt[count].address) sgpnt[count].address = bh->b_data; - sgpnt[count].length += bh->b_size; - counted += bh->b_size >> 9; - - if (((long) sgpnt[count].address) + sgpnt[count].length - 1 > - ISA_DMA_THRESHOLD && (SCpnt->host->unchecked_isa_dma) && - !sgpnt[count].alt_address) { - sgpnt[count].alt_address = sgpnt[count].address; - /* We try and avoid exhausting the DMA pool, since it is - * easier to control usage here. In other places we might - * have a more pressing need, and we would be screwed if - * we ran out */ - if(dma_free_sectors < (sgpnt[count].length >> 9) + 10) { - sgpnt[count].address = NULL; - } else { - sgpnt[count].address = - (char *) scsi_malloc(sgpnt[count].length); - }; - /* If we start running low on DMA buffers, we abort the - * scatter-gather operation, and free all of the memory - * we have allocated. We want to ensure that all scsi - * operations are able to do at least a non-scatter/gather - * operation */ - if(sgpnt[count].address == NULL){ /* Out of dma memory */ -#if 0 - printk("Warning: Running low on SCSI DMA buffers"); - /* Try switching back to a non s-g operation. */ - while(--count >= 0){ - if(sgpnt[count].alt_address) - scsi_free(sgpnt[count].address, - sgpnt[count].length); - }; - this_count = SCpnt->request.current_nr_sectors; - buff = SCpnt->request.buffer; - SCpnt->use_sg = 0; - scsi_free(sgpnt, SCpnt->sglist_len); -#endif - SCpnt->use_sg = count; - this_count = counted -= bh->b_size >> 9; - break; - }; - - }; - - /* Only cluster buffers if we know that we can supply DMA - * buffers large enough to satisfy the request. Do not cluster - * a new request if this would mean that we suddenly need to - * start using DMA bounce buffers */ - if(bhp && CONTIGUOUS_BUFFERS(bh,bhp) - && CLUSTERABLE_DEVICE(SCpnt)) { - char * tmp; - - if (((long) sgpnt[count].address) + sgpnt[count].length + - bhp->b_size - 1 > ISA_DMA_THRESHOLD && - (SCpnt->host->unchecked_isa_dma) && - !sgpnt[count].alt_address) continue; - - if(!sgpnt[count].alt_address) {count--; continue; } - if(dma_free_sectors > 10) - tmp = (char *) scsi_malloc(sgpnt[count].length - + bhp->b_size); - else { - tmp = NULL; - max_sg = SCpnt->use_sg; - }; - if(tmp){ - scsi_free(sgpnt[count].address, sgpnt[count].length); - sgpnt[count].address = tmp; - count--; - continue; - }; - - /* If we are allowed another sg chain, then increment - * counter so we can insert it. Otherwise we will end - up truncating */ - - if (SCpnt->use_sg < max_sg) SCpnt->use_sg++; - }; /* contiguous buffers */ - }; /* for loop */ - - /* This is actually how many we are going to transfer */ - this_count = counted; - - if(count < SCpnt->use_sg || SCpnt->use_sg - > SCpnt->host->sg_tablesize){ - bh = SCpnt->request.bh; - printk("Use sg, count %d %x %d\n", - SCpnt->use_sg, count, dma_free_sectors); - printk("maxsg = %x, counted = %d this_count = %d\n", - max_sg, counted, this_count); - while(bh){ - printk("[%p %lx] ", bh->b_data, bh->b_size); - bh = bh->b_reqnext; - }; - if(SCpnt->use_sg < 16) - for(count=0; count<SCpnt->use_sg; count++) - printk("{%d:%p %p %d} ", count, - sgpnt[count].address, - sgpnt[count].alt_address, - sgpnt[count].length); - panic("Ooops"); - }; - - if (SCpnt->request.cmd == WRITE) - for(count=0; count<SCpnt->use_sg; count++) - if(sgpnt[count].alt_address) - memcpy(sgpnt[count].address, sgpnt[count].alt_address, - sgpnt[count].length); - }; /* Able to malloc sgpnt */ - }; /* Host adapter capable of scatter-gather */ - - /* Now handle the possibility of DMA to addresses > 16Mb */ - - if(SCpnt->use_sg == 0){ - if (((long) buff) + (this_count << 9) - 1 > ISA_DMA_THRESHOLD && - (SCpnt->host->unchecked_isa_dma)) { - if(bounce_buffer) - buff = bounce_buffer; - else - buff = (char *) scsi_malloc(this_count << 9); - if(buff == NULL) { /* Try backing off a bit if we are low on mem*/ - this_count = SCpnt->request.current_nr_sectors; - buff = (char *) scsi_malloc(this_count << 9); - if(!buff) panic("Ran out of DMA buffers."); - }; - if (SCpnt->request.cmd == WRITE) - memcpy(buff, (char *)SCpnt->request.buffer, this_count << 9); - }; - }; -#ifdef DEBUG - printk("sd%c : %s %d/%d 512 byte blocks.\n", - 'a' + devm, - (SCpnt->request.cmd == WRITE) ? "writing" : "reading", - this_count, SCpnt->request.nr_sectors); -#endif - - cmd[1] = (SCpnt->lun << 5) & 0xe0; - - if (rscsi_disks[dev].sector_size == 1024){ - if(block & 1) panic("sd.c:Bad block number requested"); - if(this_count & 1) panic("sd.c:Bad block number requested"); - block = block >> 1; - this_count = this_count >> 1; - }; - - if (rscsi_disks[dev].sector_size == 256){ - block = block << 1; - this_count = this_count << 1; - }; - - if (((this_count > 0xff) || (block > 0x1fffff)) && rscsi_disks[dev].ten) - { - if (this_count > 0xffff) - this_count = 0xffff; - - cmd[0] += READ_10 - READ_6 ; - cmd[2] = (unsigned char) (block >> 24) & 0xff; - cmd[3] = (unsigned char) (block >> 16) & 0xff; - cmd[4] = (unsigned char) (block >> 8) & 0xff; - cmd[5] = (unsigned char) block & 0xff; - cmd[6] = cmd[9] = 0; - cmd[7] = (unsigned char) (this_count >> 8) & 0xff; - cmd[8] = (unsigned char) this_count & 0xff; - } - else - { - if (this_count > 0xff) - this_count = 0xff; - - cmd[1] |= (unsigned char) ((block >> 16) & 0x1f); - cmd[2] = (unsigned char) ((block >> 8) & 0xff); - cmd[3] = (unsigned char) block & 0xff; - cmd[4] = (unsigned char) this_count; - cmd[5] = 0; - } - - /* - * We shouldn't disconnect in the middle of a sector, so with a dumb - * host adapter, it's safe to assume that we can at least transfer - * this many bytes between each connect / disconnect. - */ - - SCpnt->transfersize = rscsi_disks[dev].sector_size; - SCpnt->underflow = this_count << 9; - scsi_do_cmd (SCpnt, (void *) cmd, buff, - this_count * rscsi_disks[dev].sector_size, - rw_intr, - (SCpnt->device->type == TYPE_DISK ? - SD_TIMEOUT : SD_MOD_TIMEOUT), - MAX_RETRIES); -} - -static int check_scsidisk_media_change(kdev_t full_dev){ - int retval; - int target; - struct inode inode; - int flag = 0; - - target = DEVICE_NR(full_dev); - - if (target >= sd_template.dev_max || - !rscsi_disks[target].device) { - printk("SCSI disk request error: invalid device.\n"); - return 0; - }; - - if(!rscsi_disks[target].device->removable) return 0; - - inode.i_rdev = full_dev; /* This is all we really need here */ - retval = sd_ioctl(&inode, NULL, SCSI_IOCTL_TEST_UNIT_READY, 0); - - if(retval){ /* Unable to test, unit probably not ready. This usually - * means there is no disc in the drive. Mark as changed, - * and we will figure it out later once the drive is - * available again. */ - - rscsi_disks[target].ready = 0; - rscsi_disks[target].device->changed = 1; - return 1; /* This will force a flush, if called from - * check_disk_change */ - }; - - /* - * for removable scsi disk ( FLOPTICAL ) we have to recognise the - * presence of disk in the drive. This is kept in the Scsi_Disk - * struct and tested at open ! Daniel Roche ( dan@lectra.fr ) - */ - - rscsi_disks[target].ready = 1; /* FLOPTICAL */ - - retval = rscsi_disks[target].device->changed; - if(!flag) rscsi_disks[target].device->changed = 0; - return retval; -} - -static void sd_init_done (Scsi_Cmnd * SCpnt) -{ - struct request * req; - - req = &SCpnt->request; - req->rq_status = RQ_SCSI_DONE; /* Busy, but indicate request done */ - - if (req->sem != NULL) { - up(req->sem); - } -} - -static int sd_init_onedisk(int i) -{ - unsigned char cmd[10]; - unsigned char *buffer; - unsigned long spintime; - int the_result, retries; - Scsi_Cmnd * SCpnt; - - /* We need to retry the READ_CAPACITY because a UNIT_ATTENTION is - * considered a fatal error, and many devices report such an error - * just after a scsi bus reset. - */ - - SCpnt = allocate_device(NULL, rscsi_disks[i].device, 1); - buffer = (unsigned char *) scsi_malloc(512); - - spintime = 0; - - /* Spin up drives, as required. Only do this at boot time */ - if (!MODULE_FLAG){ - do{ - retries = 0; - while(retries < 3) - { - cmd[0] = TEST_UNIT_READY; - cmd[1] = (rscsi_disks[i].device->lun << 5) & 0xe0; - memset ((void *) &cmd[2], 0, 8); - SCpnt->cmd_len = 0; - SCpnt->sense_buffer[0] = 0; - SCpnt->sense_buffer[2] = 0; - - { - struct semaphore sem = MUTEX_LOCKED; - /* Mark as really busy again */ - SCpnt->request.rq_status = RQ_SCSI_BUSY; - SCpnt->request.sem = &sem; - scsi_do_cmd (SCpnt, - (void *) cmd, (void *) buffer, - 512, sd_init_done, SD_TIMEOUT, - MAX_RETRIES); - down(&sem); - } - - the_result = SCpnt->result; - retries++; - if( the_result == 0 - || SCpnt->sense_buffer[2] != UNIT_ATTENTION) - break; - } - - /* Look for non-removable devices that return NOT_READY. - * Issue command to spin up drive for these cases. */ - if(the_result && !rscsi_disks[i].device->removable && - SCpnt->sense_buffer[2] == NOT_READY) { - int time1; - if(!spintime){ - printk( "sd%c: Spinning up disk...", 'a' + i ); - cmd[0] = START_STOP; - cmd[1] = (rscsi_disks[i].device->lun << 5) & 0xe0; - cmd[1] |= 1; /* Return immediately */ - memset ((void *) &cmd[2], 0, 8); - cmd[4] = 1; /* Start spin cycle */ - SCpnt->cmd_len = 0; - SCpnt->sense_buffer[0] = 0; - SCpnt->sense_buffer[2] = 0; - - { - struct semaphore sem = MUTEX_LOCKED; - /* Mark as really busy again */ - SCpnt->request.rq_status = RQ_SCSI_BUSY; - SCpnt->request.sem = &sem; - scsi_do_cmd (SCpnt, - (void *) cmd, (void *) buffer, - 512, sd_init_done, SD_TIMEOUT, - MAX_RETRIES); - down(&sem); - } - - spintime = jiffies; - } - - time1 = jiffies; - while(jiffies < time1 + HZ); /* Wait 1 second for next try */ - printk( "." ); - }; - } while(the_result && spintime && spintime+100*HZ > jiffies); - if (spintime) { - if (the_result) - printk( "not responding...\n" ); - else - printk( "ready\n" ); - } - }; /* !MODULE_FLAG */ - - - retries = 3; - do { - cmd[0] = READ_CAPACITY; - cmd[1] = (rscsi_disks[i].device->lun << 5) & 0xe0; - memset ((void *) &cmd[2], 0, 8); - memset ((void *) buffer, 0, 8); - SCpnt->cmd_len = 0; - SCpnt->sense_buffer[0] = 0; - SCpnt->sense_buffer[2] = 0; - - { - struct semaphore sem = MUTEX_LOCKED; - /* Mark as really busy again */ - SCpnt->request.rq_status = RQ_SCSI_BUSY; - SCpnt->request.sem = &sem; - scsi_do_cmd (SCpnt, - (void *) cmd, (void *) buffer, - 8, sd_init_done, SD_TIMEOUT, - MAX_RETRIES); - down(&sem); /* sleep until it is ready */ - } - - the_result = SCpnt->result; - retries--; - - } while(the_result && retries); - - SCpnt->request.rq_status = RQ_INACTIVE; /* Mark as not busy */ - - wake_up(&SCpnt->device->device_wait); - - /* Wake up a process waiting for device */ - - /* - * The SCSI standard says: - * "READ CAPACITY is necessary for self configuring software" - * While not mandatory, support of READ CAPACITY is strongly encouraged. - * We used to die if we couldn't successfully do a READ CAPACITY. - * But, now we go on about our way. The side effects of this are - * - * 1. We can't know block size with certainty. I have said "512 bytes - * is it" as this is most common. - * - * 2. Recovery from when some one attempts to read past the end of the - * raw device will be slower. - */ - - if (the_result) - { - printk ("sd%c : READ CAPACITY failed.\n" - "sd%c : status = %x, message = %02x, host = %d, driver = %02x \n", - 'a' + i, 'a' + i, - status_byte(the_result), - msg_byte(the_result), - host_byte(the_result), - driver_byte(the_result) - ); - if (driver_byte(the_result) & DRIVER_SENSE) - printk("sd%c : extended sense code = %1x \n", - 'a' + i, SCpnt->sense_buffer[2] & 0xf); - else - printk("sd%c : sense not available. \n", 'a' + i); - - printk("sd%c : block size assumed to be 512 bytes, disk size 1GB. \n", - 'a' + i); - rscsi_disks[i].capacity = 0x1fffff; - rscsi_disks[i].sector_size = 512; - - /* Set dirty bit for removable devices if not ready - sometimes drives - * will not report this properly. */ - if(rscsi_disks[i].device->removable && - SCpnt->sense_buffer[2] == NOT_READY) - rscsi_disks[i].device->changed = 1; - - } - else - { - /* - * FLOPTICAL , if read_capa is ok , drive is assumed to be ready - */ - rscsi_disks[i].ready = 1; - - rscsi_disks[i].capacity = (buffer[0] << 24) | - (buffer[1] << 16) | - (buffer[2] << 8) | - buffer[3]; - - rscsi_disks[i].sector_size = (buffer[4] << 24) | - (buffer[5] << 16) | (buffer[6] << 8) | buffer[7]; - - if (rscsi_disks[i].sector_size == 0) { - rscsi_disks[i].sector_size = 512; - printk("sd%c : sector size 0 reported, assuming 512.\n", 'a' + i); - } - - - if (rscsi_disks[i].sector_size != 512 && - rscsi_disks[i].sector_size != 1024 && - rscsi_disks[i].sector_size != 256) - { - printk ("sd%c : unsupported sector size %d.\n", - 'a' + i, rscsi_disks[i].sector_size); - if(rscsi_disks[i].device->removable){ - rscsi_disks[i].capacity = 0; - } else { - printk ("scsi : deleting disk entry.\n"); - rscsi_disks[i].device = NULL; - sd_template.nr_dev--; - return i; - }; - } - { - /* - * The msdos fs need to know the hardware sector size - * So I have created this table. See ll_rw_blk.c - * Jacques Gelinas (Jacques@solucorp.qc.ca) - */ - int m; - int hard_sector = rscsi_disks[i].sector_size; - /* There is 16 minor allocated for each devices */ - for (m=i<<4; m<((i+1)<<4); m++){ - sd_hardsizes[m] = hard_sector; - } - printk ("SCSI Hardware sector size is %d bytes on device sd%c\n", - hard_sector,i+'a'); - } - if(rscsi_disks[i].sector_size == 1024) - rscsi_disks[i].capacity <<= 1; /* Change into 512 byte sectors */ - if(rscsi_disks[i].sector_size == 256) - rscsi_disks[i].capacity >>= 1; /* Change into 512 byte sectors */ - } - - - /* - * Unless otherwise specified, this is not write protected. - */ - rscsi_disks[i].write_prot = 0; - if ( rscsi_disks[i].device->removable && rscsi_disks[i].ready ) { - /* FLOPTICAL */ - - /* - * for removable scsi disk ( FLOPTICAL ) we have to recognise - * the Write Protect Flag. This flag is kept in the Scsi_Disk struct - * and tested at open ! - * Daniel Roche ( dan@lectra.fr ) - */ - - memset ((void *) &cmd[0], 0, 8); - cmd[0] = MODE_SENSE; - cmd[1] = (rscsi_disks[i].device->lun << 5) & 0xe0; - cmd[2] = 1; /* page code 1 ?? */ - cmd[4] = 12; - SCpnt->cmd_len = 0; - SCpnt->sense_buffer[0] = 0; - SCpnt->sense_buffer[2] = 0; - - /* same code as READCAPA !! */ - { - struct semaphore sem = MUTEX_LOCKED; - SCpnt->request.rq_status = RQ_SCSI_BUSY; /* Mark as really busy again */ - SCpnt->request.sem = &sem; - scsi_do_cmd (SCpnt, - (void *) cmd, (void *) buffer, - 512, sd_init_done, SD_TIMEOUT, - MAX_RETRIES); - down(&sem); - } - - the_result = SCpnt->result; - SCpnt->request.rq_status = RQ_INACTIVE; /* Mark as not busy */ - wake_up(&SCpnt->device->device_wait); - - if ( the_result ) { - printk ("sd%c: test WP failed, assume Write Protected\n",i+'a'); - rscsi_disks[i].write_prot = 1; - } else { - rscsi_disks[i].write_prot = ((buffer[2] & 0x80) != 0); - printk ("sd%c: Write Protect is %s\n",i+'a', - rscsi_disks[i].write_prot ? "on" : "off"); - } - - } /* check for write protect */ - - rscsi_disks[i].ten = 1; - rscsi_disks[i].remap = 1; - scsi_free(buffer, 512); - return i; -} - -/* - * The sd_init() function looks at all SCSI drives present, determines - * their size, and reads partition table entries for them. - */ - -static int sd_registered = 0; - -static int sd_init() -{ - int i; - - if (sd_template.dev_noticed == 0) return 0; - - if(!sd_registered) { - if (register_blkdev(MAJOR_NR,"sd",&sd_fops)) { - printk("Unable to get major %d for SCSI disk\n",MAJOR_NR); - return 1; - } - sd_registered++; - } - - /* We do not support attaching loadable devices yet. */ - if(rscsi_disks) return 0; - - sd_template.dev_max = sd_template.dev_noticed + SD_EXTRA_DEVS; - - rscsi_disks = (Scsi_Disk *) - scsi_init_malloc(sd_template.dev_max * sizeof(Scsi_Disk), GFP_ATOMIC); - memset(rscsi_disks, 0, sd_template.dev_max * sizeof(Scsi_Disk)); - - sd_sizes = (int *) scsi_init_malloc((sd_template.dev_max << 4) * - sizeof(int), GFP_ATOMIC); - memset(sd_sizes, 0, (sd_template.dev_max << 4) * sizeof(int)); - - sd_blocksizes = (int *) scsi_init_malloc((sd_template.dev_max << 4) * - sizeof(int), GFP_ATOMIC); - - sd_hardsizes = (int *) scsi_init_malloc((sd_template.dev_max << 4) * - sizeof(int), GFP_ATOMIC); - - for(i=0;i<(sd_template.dev_max << 4);i++){ - sd_blocksizes[i] = 1024; - sd_hardsizes[i] = 512; - } - blksize_size[MAJOR_NR] = sd_blocksizes; - hardsect_size[MAJOR_NR] = sd_hardsizes; - sd = (struct hd_struct *) scsi_init_malloc((sd_template.dev_max << 4) * - sizeof(struct hd_struct), - GFP_ATOMIC); - - - sd_gendisk.max_nr = sd_template.dev_max; - sd_gendisk.part = sd; - sd_gendisk.sizes = sd_sizes; - sd_gendisk.real_devices = (void *) rscsi_disks; - return 0; -} - -static void sd_finish() -{ - int i; - - blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST; - - sd_gendisk.next = gendisk_head; - gendisk_head = &sd_gendisk; - - for (i = 0; i < sd_template.dev_max; ++i) - if (!rscsi_disks[i].capacity && - rscsi_disks[i].device) - { - if (MODULE_FLAG - && !rscsi_disks[i].has_part_table) { - sd_sizes[i << 4] = rscsi_disks[i].capacity; - /* revalidate does sd_init_onedisk via MAYBE_REINIT*/ - revalidate_scsidisk(MKDEV(MAJOR_NR, i << 4), 0); - } - else - i=sd_init_onedisk(i); - rscsi_disks[i].has_part_table = 1; - } - - /* If our host adapter is capable of scatter-gather, then we increase - * the read-ahead to 16 blocks (32 sectors). If not, we use - * a two block (4 sector) read ahead. - */ - if(rscsi_disks[0].device && rscsi_disks[0].device->host->sg_tablesize) - read_ahead[MAJOR_NR] = 120; /* 120 sector read-ahead */ - else - read_ahead[MAJOR_NR] = 4; /* 4 sector read-ahead */ - - return; -} - -static int sd_detect(Scsi_Device * SDp){ - if(SDp->type != TYPE_DISK && SDp->type != TYPE_MOD) return 0; - - printk("Detected scsi disk sd%c at scsi%d, channel %d, id %d, lun %d\n", - 'a'+ (sd_template.dev_noticed++), - SDp->host->host_no, SDp->channel, SDp->id, SDp->lun); - - return 1; -} - -static int sd_attach(Scsi_Device * SDp){ - Scsi_Disk * dpnt; - int i; - - if(SDp->type != TYPE_DISK && SDp->type != TYPE_MOD) return 0; - - if(sd_template.nr_dev >= sd_template.dev_max) { - SDp->attached--; - return 1; - } - - for(dpnt = rscsi_disks, i=0; i<sd_template.dev_max; i++, dpnt++) - if(!dpnt->device) break; - - if(i >= sd_template.dev_max) panic ("scsi_devices corrupt (sd)"); - - SDp->scsi_request_fn = do_sd_request; - rscsi_disks[i].device = SDp; - rscsi_disks[i].has_part_table = 0; - sd_template.nr_dev++; - sd_gendisk.nr_real++; - return 0; -} - -#define DEVICE_BUSY rscsi_disks[target].device->busy -#define USAGE rscsi_disks[target].device->access_count -#define CAPACITY rscsi_disks[target].capacity -#define MAYBE_REINIT sd_init_onedisk(target) -#define GENDISK_STRUCT sd_gendisk - -/* This routine is called to flush all partitions and partition tables - * for a changed scsi disk, and then re-read the new partition table. - * If we are revalidating a disk because of a media change, then we - * enter with usage == 0. If we are using an ioctl, we automatically have - * usage == 1 (we need an open channel to use an ioctl :-), so this - * is our limit. - */ -int revalidate_scsidisk(kdev_t dev, int maxusage){ - int target; - struct gendisk * gdev; - unsigned long flags; - int max_p; - int start; - int i; - - target = DEVICE_NR(dev); - gdev = &GENDISK_STRUCT; - - save_flags(flags); - cli(); - if (DEVICE_BUSY || USAGE > maxusage) { - restore_flags(flags); - printk("Device busy for revalidation (usage=%d)\n", USAGE); - return -EBUSY; - }; - DEVICE_BUSY = 1; - restore_flags(flags); - - max_p = gdev->max_p; - start = target << gdev->minor_shift; - - for (i=max_p - 1; i >=0 ; i--) { - int minor = start+i; - kdev_t devi = MKDEV(MAJOR_NR, minor); - sync_dev(devi); - invalidate_inodes(devi); - invalidate_buffers(devi); - gdev->part[minor].start_sect = 0; - gdev->part[minor].nr_sects = 0; - /* - * Reset the blocksize for everything so that we can read - * the partition table. - */ - blksize_size[MAJOR_NR][minor] = 1024; - }; - -#ifdef MAYBE_REINIT - MAYBE_REINIT; -#endif - - gdev->part[start].nr_sects = CAPACITY; - resetup_one_dev(gdev, target); - - DEVICE_BUSY = 0; - return 0; -} - -static int fop_revalidate_scsidisk(kdev_t dev){ - return revalidate_scsidisk(dev, 0); -} - - -static void sd_detach(Scsi_Device * SDp) -{ - Scsi_Disk * dpnt; - int i; - int max_p; - int start; - - for(dpnt = rscsi_disks, i=0; i<sd_template.dev_max; i++, dpnt++) - if(dpnt->device == SDp) { - - /* If we are disconnecting a disk driver, sync and invalidate - * everything */ - max_p = sd_gendisk.max_p; - start = i << sd_gendisk.minor_shift; - - for (i=max_p - 1; i >=0 ; i--) { - int minor = start+i; - kdev_t devi = MKDEV(MAJOR_NR, minor); - sync_dev(devi); - invalidate_inodes(devi); - invalidate_buffers(devi); - sd_gendisk.part[minor].start_sect = 0; - sd_gendisk.part[minor].nr_sects = 0; - sd_sizes[minor] = 0; - }; - - dpnt->has_part_table = 0; - dpnt->device = NULL; - dpnt->capacity = 0; - SDp->attached--; - sd_template.dev_noticed--; - sd_template.nr_dev--; - sd_gendisk.nr_real--; - return; - } - return; -} - -#ifdef MODULE - -int init_module(void) { - sd_template.usage_count = &mod_use_count_; - return scsi_register_module(MODULE_SCSI_DEV, &sd_template); -} - -void cleanup_module( void) -{ - struct gendisk * prev_sdgd; - struct gendisk * sdgd; - - scsi_unregister_module(MODULE_SCSI_DEV, &sd_template); - unregister_blkdev(SCSI_DISK_MAJOR, "sd"); - sd_registered--; - if( rscsi_disks != NULL ) - { - scsi_init_free((char *) rscsi_disks, - (sd_template.dev_noticed + SD_EXTRA_DEVS) - * sizeof(Scsi_Disk)); - - scsi_init_free((char *) sd_sizes, sd_template.dev_max * sizeof(int)); - scsi_init_free((char *) sd_blocksizes, sd_template.dev_max * sizeof(int)); - scsi_init_free((char *) sd_hardsizes, sd_template.dev_max * sizeof(int)); - scsi_init_free((char *) sd, - (sd_template.dev_max << 4) * sizeof(struct hd_struct)); - /* - * Now remove sd_gendisk from the linked list - */ - sdgd = gendisk_head; - prev_sdgd = NULL; - while(sdgd != &sd_gendisk) - { - prev_sdgd = sdgd; - sdgd = sdgd->next; - } - - if(sdgd != &sd_gendisk) - printk("sd_gendisk not in disk chain.\n"); - else { - if(prev_sdgd != NULL) - prev_sdgd->next = sdgd->next; - else - gendisk_head = sdgd->next; - } - } - - blksize_size[MAJOR_NR] = NULL; - blk_dev[MAJOR_NR].request_fn = NULL; - blk_size[MAJOR_NR] = NULL; - hardsect_size[MAJOR_NR] = NULL; - read_ahead[MAJOR_NR] = 0; - sd_template.dev_max = 0; -} -#endif /* MODULE */ - -/* - * Overrides for Emacs so that we almost follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 4 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -4 - * c-argdecl-indent: 4 - * c-label-offset: -4 - * c-continued-statement-offset: 4 - * c-continued-brace-offset: 0 - * indent-tabs-mode: nil - * tab-width: 8 - * End: - */ diff --git a/i386/i386at/gpl/linux/scsi/sd.h b/i386/i386at/gpl/linux/scsi/sd.h deleted file mode 100644 index 7a8219b7..00000000 --- a/i386/i386at/gpl/linux/scsi/sd.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * sd.h Copyright (C) 1992 Drew Eckhardt - * SCSI disk driver header file by - * Drew Eckhardt - * - * <drew@colorado.edu> - * - * Modified by Eric Youngdale eric@aib.com to - * add scatter-gather, multiple outstanding request, and other - * enhancements. - */ -#ifndef _SD_H -#define _SD_H -/* - $Header: cvs/gnumach/i386/i386at/gpl/linux/scsi/Attic/sd.h,v 1.1.1.1 1997/02/25 21:27:52 thomas Exp $ -*/ - -#ifndef _SCSI_H -#include "scsi.h" -#endif - -#ifndef _GENDISK_H -#include <linux/genhd.h> -#endif - -extern struct hd_struct * sd; - -typedef struct scsi_disk { - unsigned capacity; /* size in blocks */ - unsigned sector_size; /* size in bytes */ - Scsi_Device *device; - unsigned char ready; /* flag ready for FLOPTICAL */ - unsigned char write_prot; /* flag write_protect for rmvable dev */ - unsigned char sector_bit_size; /* sector_size = 2 to the bit size power */ - unsigned char sector_bit_shift; /* power of 2 sectors per FS block */ - unsigned ten:1; /* support ten byte read / write */ - unsigned remap:1; /* support remapping */ - unsigned has_part_table:1; /* has partition table */ -} Scsi_Disk; - -extern Scsi_Disk * rscsi_disks; - -extern int revalidate_scsidisk(kdev_t dev, int maxusage); - -#endif - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 4 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -4 - * c-argdecl-indent: 4 - * c-label-offset: -4 - * c-continued-statement-offset: 4 - * c-continued-brace-offset: 0 - * indent-tabs-mode: nil - * tab-width: 8 - * End: - */ - diff --git a/i386/i386at/gpl/linux/scsi/sd_ioctl.c b/i386/i386at/gpl/linux/scsi/sd_ioctl.c deleted file mode 100644 index 1898af61..00000000 --- a/i386/i386at/gpl/linux/scsi/sd_ioctl.c +++ /dev/null @@ -1,94 +0,0 @@ -/* - * drivers/scsi/sd_ioctl.c - * - * ioctl handling for SCSI disks - */ - -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/mm.h> -#include <linux/fs.h> -#include <linux/hdreg.h> -#include <linux/errno.h> - -#include <asm/segment.h> - -#include <linux/blk.h> -#include "scsi.h" -#include "scsi_ioctl.h" -#include "hosts.h" -#include "sd.h" - -int sd_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg) -{ - kdev_t dev = inode->i_rdev; - int error; - struct Scsi_Host * host; - int diskinfo[4]; - struct hd_geometry *loc = (struct hd_geometry *) arg; - - switch (cmd) { - case HDIO_GETGEO: /* Return BIOS disk parameters */ - if (!loc) return -EINVAL; - error = verify_area(VERIFY_WRITE, loc, sizeof(*loc)); - if (error) - return error; - host = rscsi_disks[MINOR(dev) >> 4].device->host; - diskinfo[0] = 0; - diskinfo[1] = 0; - diskinfo[2] = 0; - if(host->hostt->bios_param != NULL) - host->hostt->bios_param(&rscsi_disks[MINOR(dev) >> 4], - dev, - &diskinfo[0]); - put_user(diskinfo[0], &loc->heads); - put_user(diskinfo[1], &loc->sectors); - put_user(diskinfo[2], &loc->cylinders); - put_user(sd[MINOR(inode->i_rdev)].start_sect, &loc->start); - return 0; - case BLKGETSIZE: /* Return device size */ - if (!arg) return -EINVAL; - error = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long)); - if (error) - return error; - put_user(sd[MINOR(inode->i_rdev)].nr_sects, - (long *) arg); - return 0; - case BLKRASET: - if(!suser()) return -EACCES; - if(!(inode->i_rdev)) return -EINVAL; - if(arg > 0xff) return -EINVAL; - read_ahead[MAJOR(inode->i_rdev)] = arg; - return 0; - case BLKFLSBUF: - if(!suser()) return -EACCES; - if(!(inode->i_rdev)) return -EINVAL; - fsync_dev(inode->i_rdev); - invalidate_buffers(inode->i_rdev); - return 0; - - case BLKRRPART: /* Re-read partition tables */ - return revalidate_scsidisk(dev, 1); - default: - return scsi_ioctl(rscsi_disks[MINOR(dev) >> 4].device , cmd, (void *) arg); - } -} - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 4 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -4 - * c-argdecl-indent: 4 - * c-label-offset: -4 - * c-continued-statement-offset: 4 - * c-continued-brace-offset: 0 - * indent-tabs-mode: nil - * tab-width: 8 - * End: - */ diff --git a/i386/i386at/gpl/linux/scsi/seagate.c b/i386/i386at/gpl/linux/scsi/seagate.c deleted file mode 100644 index 5b25a833..00000000 --- a/i386/i386at/gpl/linux/scsi/seagate.c +++ /dev/null @@ -1,1744 +0,0 @@ -/* - * seagate.c Copyright (C) 1992, 1993 Drew Eckhardt - * low level scsi driver for ST01/ST02, Future Domain TMC-885, - * TMC-950 by - * - * Drew Eckhardt - * - * <drew@colorado.edu> - * - * Note : TMC-880 boards don't work because they have two bits in - * the status register flipped, I'll fix this "RSN" - * - * This card does all the I/O via memory mapped I/O, so there is no need - * to check or allocate a region of the I/O address space. - */ - -/* - * Configuration : - * To use without BIOS -DOVERRIDE=base_address -DCONTROLLER=FD or SEAGATE - * -DIRQ will override the default of 5. - * Note: You can now set these options from the kernel's "command line". - * The syntax is: - * - * st0x=ADDRESS,IRQ (for a Seagate controller) - * or: - * tmc8xx=ADDRESS,IRQ (for a TMC-8xx or TMC-950 controller) - * eg: - * tmc8xx=0xC8000,15 - * - * will configure the driver for a TMC-8xx style controller using IRQ 15 - * with a base address of 0xC8000. - * - * -DFAST or -DFAST32 will use blind transfers where possible - * - * -DARBITRATE will cause the host adapter to arbitrate for the - * bus for better SCSI-II compatibility, rather than just - * waiting for BUS FREE and then doing its thing. Should - * let us do one command per Lun when I integrate my - * reorganization changes into the distribution sources. - * - * -DSLOW_HANDSHAKE will allow compatibility with broken devices that don't - * handshake fast enough (ie, some CD ROM's) for the Seagate - * code. - * - * -DSLOW_RATE=x, x some number will let you specify a default - * transfer rate if handshaking isn't working correctly. - */ - -#include <linux/module.h> - -#include <asm/io.h> -#include <asm/system.h> -#include <linux/signal.h> -#include <linux/sched.h> -#include <linux/string.h> -#include <linux/config.h> -#include <linux/proc_fs.h> - -#include <linux/blk.h> -#include "scsi.h" -#include "hosts.h" -#include "seagate.h" -#include "constants.h" -#include<linux/stat.h> - -struct proc_dir_entry proc_scsi_seagate = { - PROC_SCSI_SEAGATE, 7, "seagate", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - - -#ifndef IRQ -#define IRQ 5 -#endif - -#if (defined(FAST32) && !defined(FAST)) -#define FAST -#endif - -#if defined(SLOW_RATE) && !defined(SLOW_HANDSHAKE) -#define SLOW_HANDSHAKE -#endif - -#if defined(SLOW_HANDSHAKE) && !defined(SLOW_RATE) -#define SLOW_RATE 50 -#endif - - -#if defined(LINKED) -#undef LINKED /* Linked commands are currently broken ! */ -#endif - -static int internal_command(unsigned char target, unsigned char lun, - const void *cmnd, - void *buff, int bufflen, int reselect); - -static int incommand; /* - set if arbitration has finished and we are - in some command phase. - */ - -static const void *base_address = NULL; /* - Where the card ROM starts, - used to calculate memory mapped - register location. - */ -#ifdef notyet -static volatile int abort_confirm = 0; -#endif - -static volatile void *st0x_cr_sr; /* - control register write, - status register read. - 256 bytes in length. - - Read is status of SCSI BUS, - as per STAT masks. - - */ - - -static volatile void *st0x_dr; /* - data register, read write - 256 bytes in length. - */ - - -static volatile int st0x_aborted=0; /* - set when we are aborted, ie by a time out, etc. - */ - -static unsigned char controller_type = 0; /* set to SEAGATE for ST0x boards or FD for TMC-8xx boards */ -static unsigned char irq = IRQ; - -#define retcode(result) (((result) << 16) | (message << 8) | status) -#define STATUS (*(volatile unsigned char *) st0x_cr_sr) -#define CONTROL STATUS -#define DATA (*(volatile unsigned char *) st0x_dr) - -void st0x_setup (char *str, int *ints) { - controller_type = SEAGATE; - base_address = (void *) ints[1]; - irq = ints[2]; -} - -void tmc8xx_setup (char *str, int *ints) { - controller_type = FD; - base_address = (void *) ints[1]; - irq = ints[2]; -} - - -#ifndef OVERRIDE -static const char * seagate_bases[] = { - (char *) 0xc8000, (char *) 0xca000, (char *) 0xcc000, - (char *) 0xce000, (char *) 0xdc000, (char *) 0xde000 -}; - -typedef struct { - const char *signature ; - unsigned offset; - unsigned length; - unsigned char type; -} Signature; - -static const Signature signatures[] = { -#ifdef CONFIG_SCSI_SEAGATE -{"ST01 v1.7 (C) Copyright 1987 Seagate", 15, 37, SEAGATE}, -{"SCSI BIOS 2.00 (C) Copyright 1987 Seagate", 15, 40, SEAGATE}, - -/* - * The following two lines are NOT mistakes. One detects ROM revision - * 3.0.0, the other 3.2. Since seagate has only one type of SCSI adapter, - * and this is not going to change, the "SEAGATE" and "SCSI" together - * are probably "good enough" - */ - -{"SEAGATE SCSI BIOS ",16, 17, SEAGATE}, -{"SEAGATE SCSI BIOS ",17, 17, SEAGATE}, - -/* - * However, future domain makes several incompatible SCSI boards, so specific - * signatures must be used. - */ - -{"FUTURE DOMAIN CORP. (C) 1986-1989 V5.0C2/14/89", 5, 46, FD}, -{"FUTURE DOMAIN CORP. (C) 1986-1989 V6.0A7/28/89", 5, 46, FD}, -{"FUTURE DOMAIN CORP. (C) 1986-1990 V6.0105/31/90",5, 47, FD}, -{"FUTURE DOMAIN CORP. (C) 1986-1990 V6.0209/18/90",5, 47, FD}, -{"FUTURE DOMAIN CORP. (C) 1986-1990 V7.009/18/90", 5, 46, FD}, -{"FUTURE DOMAIN CORP. (C) 1992 V8.00.004/02/92", 5, 44, FD}, -{"IBM F1 BIOS V1.1004/30/92", 5, 25, FD}, -{"FUTURE DOMAIN TMC-950", 5, 21, FD}, -#endif /* CONFIG_SCSI_SEAGATE */ -} -; - -#define NUM_SIGNATURES (sizeof(signatures) / sizeof(Signature)) -#endif /* n OVERRIDE */ - -/* - * hostno stores the hostnumber, as told to us by the init routine. - */ - -static int hostno = -1; -static void seagate_reconnect_intr(int, struct pt_regs *); - -#ifdef FAST -static int fast = 1; -#endif - -#ifdef SLOW_HANDSHAKE -/* - * Support for broken devices : - * The Seagate board has a handshaking problem. Namely, a lack - * thereof for slow devices. You can blast 600K/second through - * it if you are polling for each byte, more if you do a blind - * transfer. In the first case, with a fast device, REQ will - * transition high-low or high-low-high before your loop restarts - * and you'll have no problems. In the second case, the board - * will insert wait states for up to 13.2 usecs for REQ to - * transition low->high, and everything will work. - * - * However, there's nothing in the state machine that says - * you *HAVE* to see a high-low-high set of transitions before - * sending the next byte, and slow things like the Trantor CD ROMS - * will break because of this. - * - * So, we need to slow things down, which isn't as simple as it - * seems. We can't slow things down period, because then people - * who don't recompile their kernels will shoot me for ruining - * their performance. We need to do it on a case per case basis. - * - * The best for performance will be to, only for borken devices - * (this is stored on a per-target basis in the scsi_devices array) - * - * Wait for a low->high transition before continuing with that - * transfer. If we timeout, continue anyways. We don't need - * a long timeout, because REQ should only be asserted until the - * corresponding ACK is received and processed. - * - * Note that we can't use the system timer for this, because of - * resolution, and we *really* can't use the timer chip since - * gettimeofday() and the beeper routines use that. So, - * the best thing for us to do will be to calibrate a timing - * loop in the initialization code using the timer chip before - * gettimeofday() can screw with it. - */ - -static int borken_calibration = 0; -static void borken_init (void) { - register int count = 0, start = jiffies + 1, stop = start + 25; - - while (jiffies < start); - for (;jiffies < stop; ++count); - -/* - * Ok, we now have a count for .25 seconds. Convert to a - * count per second and divide by transfer rate in K. - */ - - borken_calibration = (count * 4) / (SLOW_RATE*1024); - - if (borken_calibration < 1) - borken_calibration = 1; -#if (DEBUG & DEBUG_BORKEN) - printk("scsi%d : borken calibrated to %dK/sec, %d cycles per transfer\n", - hostno, BORKEN_RATE, borken_calibration); -#endif -} - -static inline void borken_wait(void) { - register int count; - for (count = borken_calibration; count && (STATUS & STAT_REQ); - --count); -#if (DEBUG & DEBUG_BORKEN) - if (count) - printk("scsi%d : borken timeout\n", hostno); -#endif -} - -#endif /* def SLOW_HANDSHAKE */ - -int seagate_st0x_detect (Scsi_Host_Template * tpnt) - { - struct Scsi_Host *instance; -#ifndef OVERRIDE - int i,j; -#endif - - tpnt->proc_dir = &proc_scsi_seagate; -/* - * First, we try for the manual override. - */ -#ifdef DEBUG - printk("Autodetecting ST0x / TMC-8xx\n"); -#endif - - if (hostno != -1) - { - printk ("ERROR : seagate_st0x_detect() called twice.\n"); - return 0; - } - - /* If the user specified the controller type from the command line, - controller_type will be non-zero, so don't try and detect one */ - - if (!controller_type) { -#ifdef OVERRIDE - base_address = (void *) OVERRIDE; - -/* CONTROLLER is used to override controller (SEAGATE or FD). PM: 07/01/93 */ -#ifdef CONTROLLER - controller_type = CONTROLLER; -#else -#error Please use -DCONTROLLER=SEAGATE or -DCONTROLLER=FD to override controller type -#endif /* CONTROLLER */ -#ifdef DEBUG - printk("Base address overridden to %x, controller type is %s\n", - base_address,controller_type == SEAGATE ? "SEAGATE" : "FD"); -#endif -#else /* OVERRIDE */ -/* - * To detect this card, we simply look for the signature - * from the BIOS version notice in all the possible locations - * of the ROM's. This has a nice side effect of not trashing - * any register locations that might be used by something else. - * - * XXX - note that we probably should be probing the address - * space for the on-board RAM instead. - */ - - for (i = 0; i < (sizeof (seagate_bases) / sizeof (char * )); ++i) - for (j = 0; !base_address && j < NUM_SIGNATURES; ++j) - if (!memcmp ((const void *) (seagate_bases[i] + - signatures[j].offset), (const void *) signatures[j].signature, - signatures[j].length)) { - base_address = (const void *) seagate_bases[i]; - controller_type = signatures[j].type; - } -#endif /* OVERRIDE */ - } /* (! controller_type) */ - - tpnt->this_id = (controller_type == SEAGATE) ? 7 : 6; - tpnt->name = (controller_type == SEAGATE) ? ST0X_ID_STR : FD_ID_STR; - - if (base_address) - { - st0x_cr_sr =(void *) (((const unsigned char *) base_address) + (controller_type == SEAGATE ? 0x1a00 : 0x1c00)); - st0x_dr = (void *) (((const unsigned char *) base_address ) + (controller_type == SEAGATE ? 0x1c00 : 0x1e00)); -#ifdef DEBUG - printk("%s detected. Base address = %x, cr = %x, dr = %x\n", tpnt->name, base_address, st0x_cr_sr, st0x_dr); -#endif -/* - * At all times, we will use IRQ 5. Should also check for IRQ3 if we - * loose our first interrupt. - */ - instance = scsi_register(tpnt, 0); - hostno = instance->host_no; - if (request_irq((int) irq, seagate_reconnect_intr, SA_INTERRUPT, - (controller_type == SEAGATE) ? "seagate" : "tmc-8xx")) { - printk("scsi%d : unable to allocate IRQ%d\n", - hostno, (int) irq); - return 0; - } - instance->irq = irq; - instance->io_port = (unsigned int) base_address; -#ifdef SLOW_HANDSHAKE - borken_init(); -#endif - - printk("%s options:" -#ifdef ARBITRATE - " ARBITRATE" -#endif -#ifdef SLOW_HANDSHAKE - " SLOW_HANDSHAKE" -#endif -#ifdef FAST -#ifdef FAST32 - " FAST32" -#else - " FAST" -#endif -#endif -#ifdef LINKED - " LINKED" -#endif - "\n", tpnt->name); - return 1; - } - else - { -#ifdef DEBUG - printk("ST0x / TMC-8xx not detected.\n"); -#endif - return 0; - } - } - -const char *seagate_st0x_info(struct Scsi_Host * shpnt) { - static char buffer[64]; - sprintf(buffer, "%s at irq %d, address 0x%05X", - (controller_type == SEAGATE) ? ST0X_ID_STR : FD_ID_STR, - irq, (unsigned int)base_address); - return buffer; -} - -int seagate_st0x_proc_info(char *buffer, char **start, off_t offset, - int length, int hostno, int inout) -{ - const char *info = seagate_st0x_info(NULL); - int len; - int pos; - int begin; - - if (inout) return(-ENOSYS); - - begin = 0; - strcpy(buffer,info); - strcat(buffer,"\n"); - - pos = len = strlen(buffer); - - if (pos<offset) { - len = 0; - begin = pos; - } - - *start = buffer + (offset - begin); - len -= (offset - begin); - if ( len > length ) len = length; - return(len); -} - -/* - * These are our saved pointers for the outstanding command that is - * waiting for a reconnect - */ - -static unsigned char current_target, current_lun; -static unsigned char *current_cmnd, *current_data; -static int current_nobuffs; -static struct scatterlist *current_buffer; -static int current_bufflen; - -#ifdef LINKED - -/* - * linked_connected indicates whether or not we are currently connected to - * linked_target, linked_lun and in an INFORMATION TRANSFER phase, - * using linked commands. - */ - -static int linked_connected = 0; -static unsigned char linked_target, linked_lun; -#endif - - -static void (*done_fn)(Scsi_Cmnd *) = NULL; -static Scsi_Cmnd * SCint = NULL; - -/* - * These control whether or not disconnect / reconnect will be attempted, - * or are being attempted. - */ - -#define NO_RECONNECT 0 -#define RECONNECT_NOW 1 -#define CAN_RECONNECT 2 - -#ifdef LINKED - -/* - * LINKED_RIGHT indicates that we are currently connected to the correct target - * for this command, LINKED_WRONG indicates that we are connected to the wrong - * target. Note that these imply CAN_RECONNECT. - */ - -#define LINKED_RIGHT 3 -#define LINKED_WRONG 4 -#endif - -/* - * This determines if we are expecting to reconnect or not. - */ - -static int should_reconnect = 0; - -/* - * The seagate_reconnect_intr routine is called when a target reselects the - * host adapter. This occurs on the interrupt triggered by the target - * asserting SEL. - */ - -static void seagate_reconnect_intr(int irq, struct pt_regs * regs) - { - int temp; - Scsi_Cmnd * SCtmp; - -/* enable all other interrupts. */ - sti(); -#if (DEBUG & PHASE_RESELECT) - printk("scsi%d : seagate_reconnect_intr() called\n", hostno); -#endif - - if (!should_reconnect) - printk("scsi%d: unexpected interrupt.\n", hostno); - else { - should_reconnect = 0; - -#if (DEBUG & PHASE_RESELECT) - printk("scsi%d : internal_command(" - "%d, %08x, %08x, %d, RECONNECT_NOW\n", hostno, - current_target, current_data, current_bufflen); -#endif - - temp = internal_command (current_target, current_lun, - current_cmnd, current_data, current_bufflen, - RECONNECT_NOW); - - if (msg_byte(temp) != DISCONNECT) { - if (done_fn) { -#if (DEBUG & PHASE_RESELECT) - printk("scsi%d : done_fn(%d,%08x)", hostno, - hostno, temp); -#endif - if(!SCint) panic("SCint == NULL in seagate"); - SCtmp = SCint; - SCint = NULL; - SCtmp->result = temp; - done_fn (SCtmp); - } else - printk("done_fn() not defined.\n"); - } - } - } - -/* - * The seagate_st0x_queue_command() function provides a queued interface - * to the seagate SCSI driver. Basically, it just passes control onto the - * seagate_command() function, after fixing it so that the done_fn() - * is set to the one passed to the function. We have to be very careful, - * because there are some commands on some devices that do not disconnect, - * and if we simply call the done_fn when the command is done then another - * command is started and queue_command is called again... We end up - * overflowing the kernel stack, and this tends not to be such a good idea. - */ - -static int recursion_depth = 0; - -int seagate_st0x_queue_command (Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) - { - int result, reconnect; - Scsi_Cmnd * SCtmp; - - done_fn = done; - current_target = SCpnt->target; - current_lun = SCpnt->lun; - (const void *) current_cmnd = SCpnt->cmnd; - current_data = (unsigned char *) SCpnt->request_buffer; - current_bufflen = SCpnt->request_bufflen; - SCint = SCpnt; - if(recursion_depth) { - return 0; - }; - recursion_depth++; - do{ -#ifdef LINKED -/* - * Set linked command bit in control field of SCSI command. - */ - - current_cmnd[SCpnt->cmd_len] |= 0x01; - if (linked_connected) { -#if (DEBUG & DEBUG_LINKED) - printk("scsi%d : using linked commands, current I_T_L nexus is ", - hostno); -#endif - if ((linked_target == current_target) && - (linked_lun == current_lun)) { -#if (DEBUG & DEBUG_LINKED) - printk("correct\n"); -#endif - reconnect = LINKED_RIGHT; - } else { -#if (DEBUG & DEBUG_LINKED) - printk("incorrect\n"); -#endif - reconnect = LINKED_WRONG; - } - } else -#endif /* LINKED */ - reconnect = CAN_RECONNECT; - - - - - - result = internal_command (SCint->target, SCint->lun, SCint->cmnd, SCint->request_buffer, - SCint->request_bufflen, - reconnect); - if (msg_byte(result) == DISCONNECT) break; - SCtmp = SCint; - SCint = NULL; - SCtmp->result = result; - done_fn (SCtmp); - } while(SCint); - recursion_depth--; - return 0; - } - -int seagate_st0x_command (Scsi_Cmnd * SCpnt) { - return internal_command (SCpnt->target, SCpnt->lun, SCpnt->cmnd, SCpnt->request_buffer, - SCpnt->request_bufflen, - (int) NO_RECONNECT); -} - -static int internal_command(unsigned char target, unsigned char lun, const void *cmnd, - void *buff, int bufflen, int reselect) { - int len = 0; - unsigned char *data = NULL; - struct scatterlist *buffer = NULL; - int nobuffs = 0; - int clock; - int temp; -#ifdef SLOW_HANDSHAKE - int borken; /* Does the current target require Very Slow I/O ? */ -#endif - - -#if (DEBUG & PHASE_DATAIN) || (DEBUG & PHASE_DATOUT) - int transfered = 0; -#endif - -#if (((DEBUG & PHASE_ETC) == PHASE_ETC) || (DEBUG & PRINT_COMMAND) || \ - (DEBUG & PHASE_EXIT)) - int i; -#endif - -#if ((DEBUG & PHASE_ETC) == PHASE_ETC) - int phase=0, newphase; -#endif - - int done = 0; - unsigned char status = 0; - unsigned char message = 0; - register unsigned char status_read; - - unsigned transfersize = 0, underflow = 0; - - incommand = 0; - st0x_aborted = 0; - -#ifdef SLOW_HANDSHAKE - borken = (int) SCint->device->borken; -#endif - -#if (DEBUG & PRINT_COMMAND) - printk ("scsi%d : target = %d, command = ", hostno, target); - print_command((unsigned char *) cmnd); - printk("\n"); -#endif - -#if (DEBUG & PHASE_RESELECT) - switch (reselect) { - case RECONNECT_NOW : - printk("scsi%d : reconnecting\n", hostno); - break; -#ifdef LINKED - case LINKED_RIGHT : - printk("scsi%d : connected, can reconnect\n", hostno); - break; - case LINKED_WRONG : - printk("scsi%d : connected to wrong target, can reconnect\n", - hostno); - break; -#endif - case CAN_RECONNECT : - printk("scsi%d : allowed to reconnect\n", hostno); - break; - default : - printk("scsi%d : not allowed to reconnect\n", hostno); - } -#endif - - - if (target == (controller_type == SEAGATE ? 7 : 6)) - return DID_BAD_TARGET; - -/* - * We work it differently depending on if this is is "the first time," - * or a reconnect. If this is a reselect phase, then SEL will - * be asserted, and we must skip selection / arbitration phases. - */ - - switch (reselect) { - case RECONNECT_NOW: -#if (DEBUG & PHASE_RESELECT) - printk("scsi%d : phase RESELECT \n", hostno); -#endif - -/* - * At this point, we should find the logical or of our ID and the original - * target's ID on the BUS, with BSY, SEL, and I/O signals asserted. - * - * After ARBITRATION phase is completed, only SEL, BSY, and the - * target ID are asserted. A valid initiator ID is not on the bus - * until IO is asserted, so we must wait for that. - */ - clock = jiffies + 10; - for (;;) { - temp = STATUS; - if ((temp & STAT_IO) && !(temp & STAT_BSY)) - break; - - if (jiffies > clock) { -#if (DEBUG & PHASE_RESELECT) - printk("scsi%d : RESELECT timed out while waiting for IO .\n", - hostno); -#endif - return (DID_BAD_INTR << 16); - } - } - -/* - * After I/O is asserted by the target, we can read our ID and its - * ID off of the BUS. - */ - - if (!((temp = DATA) & (controller_type == SEAGATE ? 0x80 : 0x40))) - { -#if (DEBUG & PHASE_RESELECT) - printk("scsi%d : detected reconnect request to different target.\n" - "\tData bus = %d\n", hostno, temp); -#endif - return (DID_BAD_INTR << 16); - } - - if (!(temp & (1 << current_target))) - { - printk("scsi%d : Unexpected reselect interrupt. Data bus = %d\n", - hostno, temp); - return (DID_BAD_INTR << 16); - } - - buffer=current_buffer; - cmnd=current_cmnd; /* WDE add */ - data=current_data; /* WDE add */ - len=current_bufflen; /* WDE add */ - nobuffs=current_nobuffs; - -/* - * We have determined that we have been selected. At this point, - * we must respond to the reselection by asserting BSY ourselves - */ - -#if 1 - CONTROL = (BASE_CMD | CMD_DRVR_ENABLE | CMD_BSY); -#else - CONTROL = (BASE_CMD | CMD_BSY); -#endif - -/* - * The target will drop SEL, and raise BSY, at which time we must drop - * BSY. - */ - - for (clock = jiffies + 10; (jiffies < clock) && (STATUS & STAT_SEL);); - - if (jiffies >= clock) - { - CONTROL = (BASE_CMD | CMD_INTR); -#if (DEBUG & PHASE_RESELECT) - printk("scsi%d : RESELECT timed out while waiting for SEL.\n", - hostno); -#endif - return (DID_BAD_INTR << 16); - } - - CONTROL = BASE_CMD; - -/* - * At this point, we have connected with the target and can get - * on with our lives. - */ - break; - case CAN_RECONNECT: - -#ifdef LINKED -/* - * This is a bletcherous hack, just as bad as the Unix #! interpreter stuff. - * If it turns out we are using the wrong I_T_L nexus, the easiest way to deal - * with it is to go into our INFORMATION TRANSFER PHASE code, send a ABORT - * message on MESSAGE OUT phase, and then loop back to here. - */ - -connect_loop : - -#endif - -#if (DEBUG & PHASE_BUS_FREE) - printk ("scsi%d : phase = BUS FREE \n", hostno); -#endif - -/* - * BUS FREE PHASE - * - * On entry, we make sure that the BUS is in a BUS FREE - * phase, by insuring that both BSY and SEL are low for - * at least one bus settle delay. Several reads help - * eliminate wire glitch. - */ - - clock = jiffies + ST0X_BUS_FREE_DELAY; - -#if !defined (ARBITRATE) - while (((STATUS | STATUS | STATUS) & - (STAT_BSY | STAT_SEL)) && - (!st0x_aborted) && (jiffies < clock)); - - if (jiffies > clock) - return retcode(DID_BUS_BUSY); - else if (st0x_aborted) - return retcode(st0x_aborted); -#endif - -#if (DEBUG & PHASE_SELECTION) - printk("scsi%d : phase = SELECTION\n", hostno); -#endif - - clock = jiffies + ST0X_SELECTION_DELAY; - -/* - * Arbitration/selection procedure : - * 1. Disable drivers - * 2. Write HOST adapter address bit - * 3. Set start arbitration. - * 4. We get either ARBITRATION COMPLETE or SELECT at this - * point. - * 5. OR our ID and targets on bus. - * 6. Enable SCSI drivers and asserted SEL and ATTN - */ - -#if defined(ARBITRATE) - cli(); - CONTROL = 0; - DATA = (controller_type == SEAGATE) ? 0x80 : 0x40; - CONTROL = CMD_START_ARB; - sti(); - while (!((status_read = STATUS) & (STAT_ARB_CMPL | STAT_SEL)) && - (jiffies < clock) && !st0x_aborted); - - if (!(status_read & STAT_ARB_CMPL)) { -#if (DEBUG & PHASE_SELECTION) - if (status_read & STAT_SEL) - printk("scsi%d : arbitration lost\n", hostno); - else - printk("scsi%d : arbitration timeout.\n", hostno); -#endif - CONTROL = BASE_CMD; - return retcode(DID_NO_CONNECT); - }; - -#if (DEBUG & PHASE_SELECTION) - printk("scsi%d : arbitration complete\n", hostno); -#endif -#endif - - -/* - * When the SCSI device decides that we're gawking at it, it will - * respond by asserting BUSY on the bus. - * - * Note : the Seagate ST-01/02 product manual says that we should - * twiddle the DATA register before the control register. However, - * this does not work reliably so we do it the other way around. - * - * Probably could be a problem with arbitration too, we really should - * try this with a SCSI protocol or logic analyzer to see what is - * going on. - */ - cli(); - DATA = (unsigned char) ((1 << target) | (controller_type == SEAGATE ? 0x80 : 0x40)); - CONTROL = BASE_CMD | CMD_DRVR_ENABLE | CMD_SEL | - (reselect ? CMD_ATTN : 0); - sti(); - while (!((status_read = STATUS) & STAT_BSY) && - (jiffies < clock) && !st0x_aborted) - -#if 0 && (DEBUG & PHASE_SELECTION) - { - temp = clock - jiffies; - - if (!(jiffies % 5)) - printk("seagate_st0x_timeout : %d \r",temp); - - } - printk("Done. \n"); - printk("scsi%d : status = %02x, seagate_st0x_timeout = %d, aborted = %02x \n", - hostno, status_read, temp, st0x_aborted); -#else - ; -#endif - - - if ((jiffies >= clock) && !(status_read & STAT_BSY)) - { -#if (DEBUG & PHASE_SELECTION) - printk ("scsi%d : NO CONNECT with target %d, status = %x \n", - hostno, target, STATUS); -#endif - return retcode(DID_NO_CONNECT); - } - -/* - * If we have been aborted, and we have a command in progress, IE the - * target still has BSY asserted, then we will reset the bus, and - * notify the midlevel driver to expect sense. - */ - - if (st0x_aborted) { - CONTROL = BASE_CMD; - if (STATUS & STAT_BSY) { - printk("scsi%d : BST asserted after we've been aborted.\n", - hostno); - seagate_st0x_reset(NULL); - return retcode(DID_RESET); - } - return retcode(st0x_aborted); - } - -/* Establish current pointers. Take into account scatter / gather */ - - if ((nobuffs = SCint->use_sg)) { -#if (DEBUG & DEBUG_SG) - { - int i; - printk("scsi%d : scatter gather requested, using %d buffers.\n", - hostno, nobuffs); - for (i = 0; i < nobuffs; ++i) - printk("scsi%d : buffer %d address = %08x length = %d\n", - hostno, i, buffer[i].address, buffer[i].length); - } -#endif - - buffer = (struct scatterlist *) SCint->buffer; - len = buffer->length; - data = (unsigned char *) buffer->address; - } else { -#if (DEBUG & DEBUG_SG) - printk("scsi%d : scatter gather not requested.\n", hostno); -#endif - buffer = NULL; - len = SCint->request_bufflen; - data = (unsigned char *) SCint->request_buffer; - } - -#if (DEBUG & (PHASE_DATAIN | PHASE_DATAOUT)) - printk("scsi%d : len = %d\n", hostno, len); -#endif - - break; -#ifdef LINKED - case LINKED_RIGHT: - break; - case LINKED_WRONG: - break; -#endif - } - -/* - * There are several conditions under which we wish to send a message : - * 1. When we are allowing disconnect / reconnect, and need to establish - * the I_T_L nexus via an IDENTIFY with the DiscPriv bit set. - * - * 2. When we are doing linked commands, are have the wrong I_T_L nexus - * established and want to send an ABORT message. - */ - - - CONTROL = BASE_CMD | CMD_DRVR_ENABLE | - (((reselect == CAN_RECONNECT) -#ifdef LINKED - || (reselect == LINKED_WRONG) -#endif - ) ? CMD_ATTN : 0) ; - -/* - * INFORMATION TRANSFER PHASE - * - * The nasty looking read / write inline assembler loops we use for - * DATAIN and DATAOUT phases are approximately 4-5 times as fast as - * the 'C' versions - since we're moving 1024 bytes of data, this - * really adds up. - */ - -#if ((DEBUG & PHASE_ETC) == PHASE_ETC) - printk("scsi%d : phase = INFORMATION TRANSFER\n", hostno); -#endif - - incommand = 1; - transfersize = SCint->transfersize; - underflow = SCint->underflow; - - -/* - * Now, we poll the device for status information, - * and handle any requests it makes. Note that since we are unsure of - * how much data will be flowing across the system, etc and cannot - * make reasonable timeouts, that we will instead have the midlevel - * driver handle any timeouts that occur in this phase. - */ - - while (((status_read = STATUS) & STAT_BSY) && !st0x_aborted && !done) - { -#ifdef PARITY - if (status_read & STAT_PARITY) - { - printk("scsi%d : got parity error\n", hostno); - st0x_aborted = DID_PARITY; - } -#endif - - if (status_read & STAT_REQ) - { -#if ((DEBUG & PHASE_ETC) == PHASE_ETC) - if ((newphase = (status_read & REQ_MASK)) != phase) - { - phase = newphase; - switch (phase) - { - case REQ_DATAOUT: - printk("scsi%d : phase = DATA OUT\n", - hostno); - break; - case REQ_DATAIN : - printk("scsi%d : phase = DATA IN\n", - hostno); - break; - case REQ_CMDOUT : - printk("scsi%d : phase = COMMAND OUT\n", - hostno); - break; - case REQ_STATIN : - printk("scsi%d : phase = STATUS IN\n", - hostno); - break; - case REQ_MSGOUT : - printk("scsi%d : phase = MESSAGE OUT\n", - hostno); - break; - case REQ_MSGIN : - printk("scsi%d : phase = MESSAGE IN\n", - hostno); - break; - default : - printk("scsi%d : phase = UNKNOWN\n", - hostno); - st0x_aborted = DID_ERROR; - } - } -#endif - switch (status_read & REQ_MASK) - { - case REQ_DATAOUT : -/* - * If we are in fast mode, then we simply splat the data out - * in word-sized chunks as fast as we can. - */ - -#ifdef FAST -if (!len) { -#if 0 - printk("scsi%d: underflow to target %d lun %d \n", - hostno, target, lun); - st0x_aborted = DID_ERROR; - fast = 0; -#endif - break; -} - -if (fast && transfersize && !(len % transfersize) && (len >= transfersize) -#ifdef FAST32 - && !(transfersize % 4) -#endif - ) { -#if (DEBUG & DEBUG_FAST) - printk("scsi%d : FAST transfer, underflow = %d, transfersize = %d\n" - " len = %d, data = %08x\n", hostno, SCint->underflow, - SCint->transfersize, len, data); -#endif - - __asm__(" - cld; -" -#ifdef FAST32 -" shr $2, %%ecx; -1: lodsl; - movl %%eax, (%%edi); -" -#else -"1: lodsb; - movb %%al, (%%edi); -" -#endif -" loop 1b;" : : - /* input */ - "D" (st0x_dr), "S" (data), "c" (SCint->transfersize) : - /* clobbered */ - "eax", "ecx", "esi" ); - - len -= transfersize; - data += transfersize; - -#if (DEBUG & DEBUG_FAST) - printk("scsi%d : FAST transfer complete len = %d data = %08x\n", - hostno, len, data); -#endif - - -} else -#endif - -{ -/* - * We loop as long as we are in a data out phase, there is data to send, - * and BSY is still active. - */ - __asm__ ( - -/* - Local variables : - len = ecx - data = esi - st0x_cr_sr = ebx - st0x_dr = edi - - Test for any data here at all. -*/ - "\torl %%ecx, %%ecx - jz 2f - - cld - - movl " SYMBOL_NAME_STR(st0x_cr_sr) ", %%ebx - movl " SYMBOL_NAME_STR(st0x_dr) ", %%edi - -1: movb (%%ebx), %%al\n" -/* - Test for BSY -*/ - - "\ttest $1, %%al - jz 2f\n" - -/* - Test for data out phase - STATUS & REQ_MASK should be REQ_DATAOUT, which is 0. -*/ - "\ttest $0xe, %%al - jnz 2f \n" -/* - Test for REQ -*/ - "\ttest $0x10, %%al - jz 1b - lodsb - movb %%al, (%%edi) - loop 1b - -2: - ": -/* output */ -"=S" (data), "=c" (len) : -/* input */ -"0" (data), "1" (len) : -/* clobbered */ -"eax", "ebx", "edi"); -} - - if (!len && nobuffs) { - --nobuffs; - ++buffer; - len = buffer->length; - data = (unsigned char *) buffer->address; -#if (DEBUG & DEBUG_SG) - printk("scsi%d : next scatter-gather buffer len = %d address = %08x\n", - hostno, len, data); -#endif - } - break; - - case REQ_DATAIN : -#ifdef SLOW_HANDSHAKE - if (borken) { -#if (DEBUG & (PHASE_DATAIN)) - transfered += len; -#endif - for (; len && (STATUS & (REQ_MASK | STAT_REQ)) == (REQ_DATAIN | - STAT_REQ); --len) { - *data++ = DATA; - borken_wait(); -} -#if (DEBUG & (PHASE_DATAIN)) - transfered -= len; -#endif - } else -#endif -#ifdef FAST -if (fast && transfersize && !(len % transfersize) && (len >= transfersize) -#ifdef FAST32 - && !(transfersize % 4) -#endif - ) { -#if (DEBUG & DEBUG_FAST) - printk("scsi%d : FAST transfer, underflow = %d, transfersize = %d\n" - " len = %d, data = %08x\n", hostno, SCint->underflow, - SCint->transfersize, len, data); -#endif - __asm__(" - cld; -" -#ifdef FAST32 -" shr $2, %%ecx; -1: movl (%%esi), %%eax; - stosl; -" -#else -"1: movb (%%esi), %%al; - stosb; -" -#endif - -" loop 1b;" : : - /* input */ - "S" (st0x_dr), "D" (data), "c" (SCint->transfersize) : - /* clobbered */ - "eax", "ecx", "edi"); - - len -= transfersize; - data += transfersize; - -#if (DEBUG & PHASE_DATAIN) - printk("scsi%d: transfered += %d\n", hostno, transfersize); - transfered += transfersize; -#endif - -#if (DEBUG & DEBUG_FAST) - printk("scsi%d : FAST transfer complete len = %d data = %08x\n", - hostno, len, data); -#endif - -} else -#endif -{ - -#if (DEBUG & PHASE_DATAIN) - printk("scsi%d: transfered += %d\n", hostno, len); - transfered += len; /* Assume we'll transfer it all, then - subtract what we *didn't* transfer */ -#endif - -/* - * We loop as long as we are in a data in phase, there is room to read, - * and BSY is still active - */ - - __asm__ ( -/* - Local variables : - ecx = len - edi = data - esi = st0x_cr_sr - ebx = st0x_dr - - Test for room to read -*/ - "\torl %%ecx, %%ecx - jz 2f - - cld - movl " SYMBOL_NAME_STR(st0x_cr_sr) ", %%esi - movl " SYMBOL_NAME_STR(st0x_dr) ", %%ebx - -1: movb (%%esi), %%al\n" -/* - Test for BSY -*/ - - "\ttest $1, %%al - jz 2f\n" - -/* - Test for data in phase - STATUS & REQ_MASK should be REQ_DATAIN, = STAT_IO, which is 4. -*/ - "\tmovb $0xe, %%ah - andb %%al, %%ah - cmpb $0x04, %%ah - jne 2f\n" - -/* - Test for REQ -*/ - "\ttest $0x10, %%al - jz 1b - - movb (%%ebx), %%al - stosb - loop 1b\n" - -"2:\n" - : -/* output */ -"=D" (data), "=c" (len) : -/* input */ -"0" (data), "1" (len) : -/* clobbered */ -"eax","ebx", "esi"); - -#if (DEBUG & PHASE_DATAIN) - printk("scsi%d: transfered -= %d\n", hostno, len); - transfered -= len; /* Since we assumed all of Len got - * transfered, correct our mistake */ -#endif -} - - if (!len && nobuffs) { - --nobuffs; - ++buffer; - len = buffer->length; - data = (unsigned char *) buffer->address; -#if (DEBUG & DEBUG_SG) - printk("scsi%d : next scatter-gather buffer len = %d address = %08x\n", - hostno, len, data); -#endif - } - - break; - - case REQ_CMDOUT : - while (((status_read = STATUS) & STAT_BSY) && - ((status_read & REQ_MASK) == REQ_CMDOUT)) - if (status_read & STAT_REQ) { - DATA = *(const unsigned char *) cmnd; - cmnd = 1+(const unsigned char *) cmnd; -#ifdef SLOW_HANDSHAKE - if (borken) - borken_wait(); -#endif - } - break; - - case REQ_STATIN : - status = DATA; - break; - - case REQ_MSGOUT : -/* - * We can only have sent a MSG OUT if we requested to do this - * by raising ATTN. So, we must drop ATTN. - */ - - CONTROL = BASE_CMD | CMD_DRVR_ENABLE; -/* - * If we are reconnecting, then we must send an IDENTIFY message in - * response to MSGOUT. - */ - switch (reselect) { - case CAN_RECONNECT: - DATA = IDENTIFY(1, lun); - -#if (DEBUG & (PHASE_RESELECT | PHASE_MSGOUT)) - printk("scsi%d : sent IDENTIFY message.\n", hostno); -#endif - break; -#ifdef LINKED - case LINKED_WRONG: - DATA = ABORT; - linked_connected = 0; - reselect = CAN_RECONNECT; - goto connect_loop; -#if (DEBUG & (PHASE_MSGOUT | DEBUG_LINKED)) - printk("scsi%d : sent ABORT message to cancel incorrect I_T_L nexus.\n", hostno); -#endif -#endif /* LINKED */ -#if (DEBUG & DEBUG_LINKED) - printk("correct\n"); -#endif - default: - DATA = NOP; - printk("scsi%d : target %d requested MSGOUT, sent NOP message.\n", hostno, target); - } - break; - - case REQ_MSGIN : - switch (message = DATA) { - case DISCONNECT : - should_reconnect = 1; - current_data = data; /* WDE add */ - current_buffer = buffer; - current_bufflen = len; /* WDE add */ - current_nobuffs = nobuffs; -#ifdef LINKED - linked_connected = 0; -#endif - done=1; -#if (DEBUG & (PHASE_RESELECT | PHASE_MSGIN)) - printk("scsi%d : disconnected.\n", hostno); -#endif - break; - -#ifdef LINKED - case LINKED_CMD_COMPLETE: - case LINKED_FLG_CMD_COMPLETE: -#endif - case COMMAND_COMPLETE : -/* - * Note : we should check for underflow here. - */ -#if (DEBUG & PHASE_MSGIN) - printk("scsi%d : command complete.\n", hostno); -#endif - done = 1; - break; - case ABORT : -#if (DEBUG & PHASE_MSGIN) - printk("scsi%d : abort message.\n", hostno); -#endif - done=1; - break; - case SAVE_POINTERS : - current_buffer = buffer; - current_bufflen = len; /* WDE add */ - current_data = data; /* WDE mod */ - current_nobuffs = nobuffs; -#if (DEBUG & PHASE_MSGIN) - printk("scsi%d : pointers saved.\n", hostno); -#endif - break; - case RESTORE_POINTERS: - buffer=current_buffer; - cmnd=current_cmnd; - data=current_data; /* WDE mod */ - len=current_bufflen; - nobuffs=current_nobuffs; -#if (DEBUG & PHASE_MSGIN) - printk("scsi%d : pointers restored.\n", hostno); -#endif - break; - default: - -/* - * IDENTIFY distinguishes itself from the other messages by setting the - * high byte. - * - * Note : we need to handle at least one outstanding command per LUN, - * and need to hash the SCSI command for that I_T_L nexus based on the - * known ID (at this point) and LUN. - */ - - if (message & 0x80) { -#if (DEBUG & PHASE_MSGIN) - printk("scsi%d : IDENTIFY message received from id %d, lun %d.\n", - hostno, target, message & 7); -#endif - } else { - -/* - * We should go into a MESSAGE OUT phase, and send a MESSAGE_REJECT - * if we run into a message that we don't like. The seagate driver - * needs some serious restructuring first though. - */ - -#if (DEBUG & PHASE_MSGIN) - printk("scsi%d : unknown message %d from target %d.\n", - hostno, message, target); -#endif - } - } - break; - - default : - printk("scsi%d : unknown phase.\n", hostno); - st0x_aborted = DID_ERROR; - } - -#ifdef SLOW_HANDSHAKE -/* - * I really don't care to deal with borken devices in each single - * byte transfer case (ie, message in, message out, status), so - * I'll do the wait here if necessary. - */ - if (borken) - borken_wait(); -#endif - - } /* if ends */ - } /* while ends */ - -#if (DEBUG & (PHASE_DATAIN | PHASE_DATAOUT | PHASE_EXIT)) - printk("scsi%d : Transfered %d bytes\n", hostno, transfered); -#endif - -#if (DEBUG & PHASE_EXIT) -#if 0 /* Doesn't work for scatter / gather */ - printk("Buffer : \n"); - for (i = 0; i < 20; ++i) - printk ("%02x ", ((unsigned char *) data)[i]); /* WDE mod */ - printk("\n"); -#endif - printk("scsi%d : status = ", hostno); - print_status(status); - printk("message = %02x\n", message); -#endif - - -/* We shouldn't reach this until *after* BSY has been deasserted */ -#ifdef notyet - if (st0x_aborted) { - if (STATUS & STAT_BSY) { - seagate_st0x_reset(NULL); - st0x_aborted = DID_RESET; - } - abort_confirm = 1; - } -#endif - -#ifdef LINKED -else { -/* - * Fix the message byte so that unsuspecting high level drivers don't - * puke when they see a LINKED COMMAND message in place of the COMMAND - * COMPLETE they may be expecting. Shouldn't be necessary, but it's - * better to be on the safe side. - * - * A non LINKED* message byte will indicate that the command completed, - * and we are now disconnected. - */ - - switch (message) { - case LINKED_CMD_COMPLETE : - case LINKED_FLG_CMD_COMPLETE : - message = COMMAND_COMPLETE; - linked_target = current_target; - linked_lun = current_lun; - linked_connected = 1; -#if (DEBUG & DEBUG_LINKED) - printk("scsi%d : keeping I_T_L nexus established for linked command.\n", - hostno); -#endif -/* - * We also will need to adjust status to accommodate intermediate conditions. - */ - if ((status == INTERMEDIATE_GOOD) || - (status == INTERMEDIATE_C_GOOD)) - status = GOOD; - - break; -/* - * We should also handle what are "normal" termination messages - * here (ABORT, BUS_DEVICE_RESET?, and COMMAND_COMPLETE individually, - * and flake if things aren't right. - */ - - default : -#if (DEBUG & DEBUG_LINKED) - printk("scsi%d : closing I_T_L nexus.\n", hostno); -#endif - linked_connected = 0; - } - } -#endif /* LINKED */ - - - - - if (should_reconnect) { -#if (DEBUG & PHASE_RESELECT) - printk("scsi%d : exiting seagate_st0x_queue_command() with reconnect enabled.\n", - hostno); -#endif - CONTROL = BASE_CMD | CMD_INTR ; - } else - CONTROL = BASE_CMD; - - return retcode (st0x_aborted); - } - -int seagate_st0x_abort (Scsi_Cmnd * SCpnt) - { - st0x_aborted = DID_ABORT; - - return SCSI_ABORT_PENDING; - } - -/* - the seagate_st0x_reset function resets the SCSI bus -*/ - -int seagate_st0x_reset (Scsi_Cmnd * SCpnt) - { - unsigned clock; - /* - No timeouts - this command is going to fail because - it was reset. - */ - -#ifdef DEBUG - printk("In seagate_st0x_reset()\n"); -#endif - - - /* assert RESET signal on SCSI bus. */ - - CONTROL = BASE_CMD | CMD_RST; - clock=jiffies+2; - - - /* Wait. */ - - while (jiffies < clock); - - CONTROL = BASE_CMD; - - st0x_aborted = DID_RESET; - -#ifdef DEBUG - printk("SCSI bus reset.\n"); -#endif - return SCSI_RESET_WAKEUP; - } - -#include <asm/segment.h> -#include "sd.h" -#include "scsi_ioctl.h" - -int seagate_st0x_biosparam(Disk * disk, kdev_t dev, int* ip) { - unsigned char buf[256 + sizeof(int) * 2], cmd[6], *data, *page; - int *sizes, result, formatted_sectors, total_sectors; - int cylinders, heads, sectors; - -/* - * Only SCSI-I CCS drives and later implement the necessary mode sense - * pages. - */ - - if (disk->device->scsi_level < 2) - return -1; - - sizes = (int *) buf; - data = (unsigned char *) (sizes + 2); - - cmd[0] = MODE_SENSE; - cmd[1] = (disk->device->lun << 5) & 0xe5; - cmd[2] = 0x04; /* Read page 4, rigid disk geometry page current values */ - cmd[3] = 0; - cmd[4] = 255; - cmd[5] = 0; - -/* - * We are transferring 0 bytes in the out direction, and expect to get back - * 24 bytes for each mode page. - */ - - sizes[0] = 0; - sizes[1] = 256; - - memcpy (data, cmd, 6); - - if (!(result = kernel_scsi_ioctl (disk->device, SCSI_IOCTL_SEND_COMMAND, (void *) buf))) { -/* - * The mode page lies beyond the MODE SENSE header, with length 4, and - * the BLOCK DESCRIPTOR, with length header[3]. - */ - - page = data + 4 + data[3]; - heads = (int) page[5]; - cylinders = (page[2] << 16) | (page[3] << 8) | page[4]; - - cmd[2] = 0x03; /* Read page 3, format page current values */ - memcpy (data, cmd, 6); - - if (!(result = kernel_scsi_ioctl (disk->device, SCSI_IOCTL_SEND_COMMAND, (void *) buf))) { - page = data + 4 + data[3]; - sectors = (page[10] << 8) | page[11]; - - -/* - * Get the total number of formatted sectors from the block descriptor, - * so we can tell how many are being used for alternates. - */ - - formatted_sectors = (data[4 + 1] << 16) | (data[4 + 2] << 8) | - data[4 + 3] ; - - total_sectors = (heads * cylinders * sectors); - -/* - * Adjust the real geometry by subtracting - * (spare sectors / (heads * tracks)) cylinders from the number of cylinders. - * - * It appears that the CE cylinder CAN be a partial cylinder. - */ - - -printk("scsi%d : heads = %d cylinders = %d sectors = %d total = %d formatted = %d\n", - hostno, heads, cylinders, sectors, total_sectors, formatted_sectors); - - if (!heads || !sectors || !cylinders) - result = -1; - else - cylinders -= ((total_sectors - formatted_sectors) / (heads * sectors)); - -/* - * Now, we need to do a sanity check on the geometry to see if it is - * BIOS compatible. The maximum BIOS geometry is 1024 cylinders * - * 256 heads * 64 sectors. - */ - - if ((cylinders > 1024) || (sectors > 64)) - result = -1; - else { - ip[0] = heads; - ip[1] = sectors; - ip[2] = cylinders; - } - -/* - * There should be an alternate mapping for things the seagate doesn't - * understand, but I couldn't say what it is with reasonable certainty. - */ - - } - } - - return result; -} - -#ifdef MODULE -/* Eventually this will go into an include file, but this will be later */ -Scsi_Host_Template driver_template = SEAGATE_ST0X; - -#include "scsi_module.c" -#endif diff --git a/i386/i386at/gpl/linux/scsi/seagate.h b/i386/i386at/gpl/linux/scsi/seagate.h deleted file mode 100644 index 8d9e1a42..00000000 --- a/i386/i386at/gpl/linux/scsi/seagate.h +++ /dev/null @@ -1,139 +0,0 @@ -/* - * seagate.h Copyright (C) 1992 Drew Eckhardt - * low level scsi driver header for ST01/ST02 by - * Drew Eckhardt - * - * <drew@colorado.edu> - */ - -#ifndef _SEAGATE_H - #define SEAGATE_H -/* - $Header -*/ -#ifndef ASM -int seagate_st0x_detect(Scsi_Host_Template *); -int seagate_st0x_command(Scsi_Cmnd *); -int seagate_st0x_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); - -int seagate_st0x_abort(Scsi_Cmnd *); -const char *seagate_st0x_info(struct Scsi_Host *); -int seagate_st0x_reset(Scsi_Cmnd *); -int seagate_st0x_proc_info(char *,char **,off_t,int,int,int); - -#ifndef NULL - #define NULL 0 -#endif - -#include <linux/kdev_t.h> -int seagate_st0x_biosparam(Disk *, kdev_t, int*); - -#define SEAGATE_ST0X { NULL, NULL, NULL, seagate_st0x_proc_info, \ - NULL, seagate_st0x_detect, \ - NULL, \ - seagate_st0x_info, seagate_st0x_command, \ - seagate_st0x_queue_command, seagate_st0x_abort, \ - seagate_st0x_reset, NULL, seagate_st0x_biosparam, \ - 1, 7, SG_ALL, 1, 0, 0, DISABLE_CLUSTERING} -#endif - - -/* - defining PARITY causes parity data to be checked -*/ - -#define PARITY - - -/* - Thanks to Brian Antoine for the example code in his Messy-Loss ST-01 - driver, and Mitsugu Suzuki for information on the ST-01 - SCSI host. -*/ - -/* - CONTROL defines -*/ - -#define CMD_RST 0x01 -#define CMD_SEL 0x02 -#define CMD_BSY 0x04 -#define CMD_ATTN 0x08 -#define CMD_START_ARB 0x10 -#define CMD_EN_PARITY 0x20 -#define CMD_INTR 0x40 -#define CMD_DRVR_ENABLE 0x80 - -/* - STATUS -*/ - -#define STAT_BSY 0x01 -#define STAT_MSG 0x02 -#define STAT_IO 0x04 -#define STAT_CD 0x08 -#define STAT_REQ 0x10 -#define STAT_SEL 0x20 -#define STAT_PARITY 0x40 -#define STAT_ARB_CMPL 0x80 - -/* - REQUESTS -*/ - -#define REQ_MASK (STAT_CD | STAT_IO | STAT_MSG) -#define REQ_DATAOUT 0 -#define REQ_DATAIN STAT_IO -#define REQ_CMDOUT STAT_CD -#define REQ_STATIN (STAT_CD | STAT_IO) -#define REQ_MSGOUT (STAT_MSG | STAT_CD) -#define REQ_MSGIN (STAT_MSG | STAT_CD | STAT_IO) - -extern volatile int seagate_st0x_timeout; - -#ifdef PARITY - #define BASE_CMD CMD_EN_PARITY -#else - #define BASE_CMD 0 -#endif - -/* - Debugging code -*/ - -#define PHASE_BUS_FREE 1 -#define PHASE_ARBITRATION 2 -#define PHASE_SELECTION 4 -#define PHASE_DATAIN 8 -#define PHASE_DATAOUT 0x10 -#define PHASE_CMDOUT 0x20 -#define PHASE_MSGIN 0x40 -#define PHASE_MSGOUT 0x80 -#define PHASE_STATUSIN 0x100 -#define PHASE_ETC (PHASE_DATAIN | PHASE_DATA_OUT | PHASE_CMDOUT | PHASE_MSGIN | PHASE_MSGOUT | PHASE_STATUSIN) -#define PRINT_COMMAND 0x200 -#define PHASE_EXIT 0x400 -#define PHASE_RESELECT 0x800 -#define DEBUG_FAST 0x1000 -#define DEBUG_SG 0x2000 -#define DEBUG_LINKED 0x4000 -#define DEBUG_BORKEN 0x8000 - -/* - * Control options - these are timeouts specified in .01 seconds. - */ - -/* 30, 20 work */ -#define ST0X_BUS_FREE_DELAY 25 -#define ST0X_SELECTION_DELAY 25 - -#define eoi() __asm__("push %%eax\nmovb $0x20, %%al\noutb %%al, $0x20\npop %%eax"::) - -#define SEAGATE 1 /* these determine the type of the controller */ -#define FD 2 - -#define ST0X_ID_STR "Seagate ST-01/ST-02" -#define FD_ID_STR "TMC-8XX/TMC-950" - -#endif - diff --git a/i386/i386at/gpl/linux/scsi/sr.c b/i386/i386at/gpl/linux/scsi/sr.c deleted file mode 100644 index dc15cf58..00000000 --- a/i386/i386at/gpl/linux/scsi/sr.c +++ /dev/null @@ -1,1191 +0,0 @@ -/* - * sr.c Copyright (C) 1992 David Giller - * Copyright (C) 1993, 1994, 1995 Eric Youngdale - * - * adapted from: - * sd.c Copyright (C) 1992 Drew Eckhardt - * Linux scsi disk driver by - * Drew Eckhardt <drew@colorado.edu> - * - * Modified by Eric Youngdale ericy@cais.com to - * add scatter-gather, multiple outstanding request, and other - * enhancements. - * - * Modified by Eric Youngdale eric@aib.com to support loadable - * low-level scsi drivers. - * - * Modified by Thomas Quinot thomas@melchior.cuivre.fdn.fr to - * provide auto-eject. - * - */ - -#include <linux/module.h> - -#include <linux/fs.h> -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/mm.h> -#include <linux/string.h> -#include <linux/errno.h> -#include <linux/cdrom.h> -#include <asm/system.h> - -#define MAJOR_NR SCSI_CDROM_MAJOR -#include <linux/blk.h> -#include "scsi.h" -#include "hosts.h" -#include "sr.h" -#include "scsi_ioctl.h" /* For the door lock/unlock commands */ -#include "constants.h" - -#define MAX_RETRIES 3 -#define SR_TIMEOUT (150 * HZ) - -static int sr_init(void); -static void sr_finish(void); -static int sr_attach(Scsi_Device *); -static int sr_detect(Scsi_Device *); -static void sr_detach(Scsi_Device *); - -struct Scsi_Device_Template sr_template = {NULL, "cdrom", "sr", NULL, TYPE_ROM, - SCSI_CDROM_MAJOR, 0, 0, 0, 1, - sr_detect, sr_init, - sr_finish, sr_attach, sr_detach}; - -Scsi_CD * scsi_CDs = NULL; -static int * sr_sizes; - -static int * sr_blocksizes; - -static int sr_open(struct inode *, struct file *); -static void get_sectorsize(int); - -extern int sr_ioctl(struct inode *, struct file *, unsigned int, unsigned long); - -void requeue_sr_request (Scsi_Cmnd * SCpnt); -static int check_cdrom_media_change(kdev_t); - -static void sr_release(struct inode * inode, struct file * file) -{ - sync_dev(inode->i_rdev); - if(! --scsi_CDs[MINOR(inode->i_rdev)].device->access_count) - { - sr_ioctl(inode, NULL, SCSI_IOCTL_DOORUNLOCK, 0); - if (scsi_CDs[MINOR(inode->i_rdev)].auto_eject) - sr_ioctl(inode, NULL, CDROMEJECT, 0); - } - if (scsi_CDs[MINOR(inode->i_rdev)].device->host->hostt->usage_count) - (*scsi_CDs[MINOR(inode->i_rdev)].device->host->hostt->usage_count)--; - if(sr_template.usage_count) (*sr_template.usage_count)--; -} - -static struct file_operations sr_fops = -{ - NULL, /* lseek - default */ - block_read, /* read - general block-dev read */ - block_write, /* write - general block-dev write */ - NULL, /* readdir - bad */ - NULL, /* select */ - sr_ioctl, /* ioctl */ - NULL, /* mmap */ - sr_open, /* special open code */ - sr_release, /* release */ - NULL, /* fsync */ - NULL, /* fasync */ - check_cdrom_media_change, /* Disk change */ - NULL /* revalidate */ -}; - -/* - * This function checks to see if the media has been changed in the - * CDROM drive. It is possible that we have already sensed a change, - * or the drive may have sensed one and not yet reported it. We must - * be ready for either case. This function always reports the current - * value of the changed bit. If flag is 0, then the changed bit is reset. - * This function could be done as an ioctl, but we would need to have - * an inode for that to work, and we do not always have one. - */ - -int check_cdrom_media_change(kdev_t full_dev){ - int retval, target; - struct inode inode; - int flag = 0; - - target = MINOR(full_dev); - - if (target >= sr_template.nr_dev) { - printk("CD-ROM request error: invalid device.\n"); - return 0; - }; - - inode.i_rdev = full_dev; /* This is all we really need here */ - retval = sr_ioctl(&inode, NULL, SCSI_IOCTL_TEST_UNIT_READY, 0); - - if(retval){ /* Unable to test, unit probably not ready. This usually - * means there is no disc in the drive. Mark as changed, - * and we will figure it out later once the drive is - * available again. */ - - scsi_CDs[target].device->changed = 1; - return 1; /* This will force a flush, if called from - * check_disk_change */ - }; - - retval = scsi_CDs[target].device->changed; - if(!flag) { - scsi_CDs[target].device->changed = 0; - /* If the disk changed, the capacity will now be different, - * so we force a re-read of this information */ - if (retval) scsi_CDs[target].needs_sector_size = 1; - }; - return retval; -} - -/* - * rw_intr is the interrupt routine for the device driver. It will be notified on the - * end of a SCSI read / write, and will take on of several actions based on success or failure. - */ - -static void rw_intr (Scsi_Cmnd * SCpnt) -{ - int result = SCpnt->result; - int this_count = SCpnt->this_count; - -#ifdef DEBUG - printk("sr.c done: %x %x\n",result, SCpnt->request.bh->b_data); -#endif - if (!result) - { /* No error */ - if (SCpnt->use_sg == 0) { - if (SCpnt->buffer != SCpnt->request.buffer) - { - int offset; - offset = (SCpnt->request.sector % 4) << 9; - memcpy((char *)SCpnt->request.buffer, - (char *)SCpnt->buffer + offset, - this_count << 9); - /* Even though we are not using scatter-gather, we look - * ahead and see if there is a linked request for the - * other half of this buffer. If there is, then satisfy - * it. */ - if((offset == 0) && this_count == 2 && - SCpnt->request.nr_sectors > this_count && - SCpnt->request.bh && - SCpnt->request.bh->b_reqnext && - SCpnt->request.bh->b_reqnext->b_size == 1024) { - memcpy((char *)SCpnt->request.bh->b_reqnext->b_data, - (char *)SCpnt->buffer + 1024, - 1024); - this_count += 2; - }; - - scsi_free(SCpnt->buffer, 2048); - } - } else { - struct scatterlist * sgpnt; - int i; - sgpnt = (struct scatterlist *) SCpnt->buffer; - for(i=0; i<SCpnt->use_sg; i++) { - if (sgpnt[i].alt_address) { - if (sgpnt[i].alt_address != sgpnt[i].address) { - memcpy(sgpnt[i].alt_address, sgpnt[i].address, sgpnt[i].length); - }; - scsi_free(sgpnt[i].address, sgpnt[i].length); - }; - }; - scsi_free(SCpnt->buffer, SCpnt->sglist_len); /* Free list of scatter-gather pointers */ - if(SCpnt->request.sector % 4) this_count -= 2; - /* See if there is a padding record at the end that needs to be removed */ - if(this_count > SCpnt->request.nr_sectors) - this_count -= 2; - }; - -#ifdef DEBUG - printk("(%x %x %x) ",SCpnt->request.bh, SCpnt->request.nr_sectors, - this_count); -#endif - if (SCpnt->request.nr_sectors > this_count) - { - SCpnt->request.errors = 0; - if (!SCpnt->request.bh) - panic("sr.c: linked page request (%lx %x)", - SCpnt->request.sector, this_count); - } - - SCpnt = end_scsi_request(SCpnt, 1, this_count); /* All done */ - requeue_sr_request(SCpnt); - return; - } /* Normal completion */ - - /* We only come through here if we have an error of some kind */ - - /* Free up any indirection buffers we allocated for DMA purposes. */ - if (SCpnt->use_sg) { - struct scatterlist * sgpnt; - int i; - sgpnt = (struct scatterlist *) SCpnt->buffer; - for(i=0; i<SCpnt->use_sg; i++) { - if (sgpnt[i].alt_address) { - scsi_free(sgpnt[i].address, sgpnt[i].length); - }; - }; - scsi_free(SCpnt->buffer, SCpnt->sglist_len); /* Free list of scatter-gather pointers */ - } else { - if (SCpnt->buffer != SCpnt->request.buffer) - scsi_free(SCpnt->buffer, SCpnt->bufflen); - }; - - if (driver_byte(result) != 0) { - if ((SCpnt->sense_buffer[0] & 0x7f) == 0x70) { - if ((SCpnt->sense_buffer[2] & 0xf) == UNIT_ATTENTION) { - /* detected disc change. set a bit and quietly refuse - * further access. */ - - scsi_CDs[DEVICE_NR(SCpnt->request.rq_dev)].device->changed = 1; - SCpnt = end_scsi_request(SCpnt, 0, this_count); - requeue_sr_request(SCpnt); - return; - } - } - - if (SCpnt->sense_buffer[2] == ILLEGAL_REQUEST) { - printk("CD-ROM error: "); - print_sense("sr", SCpnt); - printk("command was: "); - print_command(SCpnt->cmnd); - if (scsi_CDs[DEVICE_NR(SCpnt->request.rq_dev)].ten) { - scsi_CDs[DEVICE_NR(SCpnt->request.rq_dev)].ten = 0; - requeue_sr_request(SCpnt); - result = 0; - return; - } else { - SCpnt = end_scsi_request(SCpnt, 0, this_count); - requeue_sr_request(SCpnt); /* Do next request */ - return; - } - - } - - if (SCpnt->sense_buffer[2] == NOT_READY) { - printk("CDROM not ready. Make sure you have a disc in the drive.\n"); - SCpnt = end_scsi_request(SCpnt, 0, this_count); - requeue_sr_request(SCpnt); /* Do next request */ - return; - }; - } - - /* We only get this far if we have an error we have not recognized */ - if(result) { - printk("SCSI CD error : host %d id %d lun %d return code = %03x\n", - scsi_CDs[DEVICE_NR(SCpnt->request.rq_dev)].device->host->host_no, - scsi_CDs[DEVICE_NR(SCpnt->request.rq_dev)].device->id, - scsi_CDs[DEVICE_NR(SCpnt->request.rq_dev)].device->lun, - result); - - if (status_byte(result) == CHECK_CONDITION) - print_sense("sr", SCpnt); - - SCpnt = end_scsi_request(SCpnt, 0, SCpnt->request.current_nr_sectors); - requeue_sr_request(SCpnt); - } -} - -/* - * Here I tried to implement better support for PhotoCD's. - * - * Much of this has do be done with vendor-specific SCSI-commands. - * So I have to complete it step by step. Useful information is welcome. - * - * Actually works: - * - NEC: Detection and support of multisession CD's. Special handling - * for XA-disks is not necessary. - * - * - TOSHIBA: setting density is done here now, mounting PhotoCD's should - * work now without running the program "set_density" - * Multisession CD's are supported too. - * - * kraxel@cs.tu-berlin.de (Gerd Knorr) - */ -/* - * 19950704 operator@melchior.cuivre.fdn.fr (Thomas Quinot) - * - * - SONY: Same as Nec. - * - * - PIONEER: works with SONY code - */ - -static void sr_photocd(struct inode *inode) -{ - unsigned long sector,min,sec,frame; - unsigned char buf[40]; /* the buffer for the ioctl */ - unsigned char *cmd; /* the scsi-command */ - unsigned char *send; /* the data we send to the drive ... */ - unsigned char *rec; /* ... and get back */ - int rc,is_xa,no_multi; - - if (scsi_CDs[MINOR(inode->i_rdev)].xa_flags & 0x02) { -#ifdef DEBUG - printk("sr_photocd: CDROM and/or the driver does not support multisession CD's"); -#endif - return; - } - - if (!suser()) { - /* I'm not the superuser, so SCSI_IOCTL_SEND_COMMAND isn't allowed for me. - * That's why mpcd_sector will be initialized with zero, because I'm not - * able to get the right value. Necessary only if access_count is 1, else - * no disk change happened since the last call of this function and we can - * keep the old value. - */ - if (1 == scsi_CDs[MINOR(inode->i_rdev)].device->access_count) { - scsi_CDs[MINOR(inode->i_rdev)].mpcd_sector = 0; - scsi_CDs[MINOR(inode->i_rdev)].xa_flags &= ~0x01; - } - return; - } - - sector = 0; - is_xa = 0; - no_multi = 0; - cmd = rec = &buf[8]; - - switch(scsi_CDs[MINOR(inode->i_rdev)].device->manufacturer) { - - case SCSI_MAN_NEC: -#ifdef DEBUG - printk("sr_photocd: use NEC code\n"); -#endif - memset(buf,0,40); - *((unsigned long*)buf) = 0x0; /* we send nothing... */ - *((unsigned long*)buf+1) = 0x16; /* and receive 0x16 bytes */ - cmd[0] = 0xde; - cmd[1] = 0x03; - cmd[2] = 0xb0; - rc = kernel_scsi_ioctl(scsi_CDs[MINOR(inode->i_rdev)].device, - SCSI_IOCTL_SEND_COMMAND, buf); - if (rc != 0) { - printk("sr_photocd: ioctl error (NEC): 0x%x\n",rc); - break; - } - if (rec[14] != 0 && rec[14] != 0xb0) { - printk("sr_photocd: (NEC) Hmm, seems the CDROM doesn't support multisession CD's\n"); - no_multi = 1; - break; - } - min = (unsigned long) rec[15]/16*10 + (unsigned long) rec[15]%16; - sec = (unsigned long) rec[16]/16*10 + (unsigned long) rec[16]%16; - frame = (unsigned long) rec[17]/16*10 + (unsigned long) rec[17]%16; - sector = min*CD_SECS*CD_FRAMES + sec*CD_FRAMES + frame; - is_xa = (rec[14] == 0xb0); -#ifdef DEBUG - if (sector) { - printk("sr_photocd: multisession CD detected. start: %lu\n",sector); - } -#endif - break; - - case SCSI_MAN_TOSHIBA: -#ifdef DEBUG - printk("sr_photocd: use TOSHIBA code\n"); -#endif - - /* we request some disc information (is it a XA-CD ?, - * where starts the last session ?) */ - memset(buf,0,40); - *((unsigned long*)buf) = 0; - *((unsigned long*)buf+1) = 4; /* we receive 4 bytes from the drive */ - cmd[0] = 0xc7; - cmd[1] = 3; - rc = kernel_scsi_ioctl(scsi_CDs[MINOR(inode->i_rdev)].device, - SCSI_IOCTL_SEND_COMMAND, buf); - if (rc != 0) { - if (rc == 0x28000002) { - /* Got a "not ready" - error. No chance to find out if this is - * because there is no CD in the drive or because the drive - * don't knows multisession CD's. So I need to do an extra check... */ - if (kernel_scsi_ioctl(scsi_CDs[MINOR(inode->i_rdev)].device, - SCSI_IOCTL_TEST_UNIT_READY, NULL)) { - printk("sr_photocd: drive not ready\n"); - } else { - printk("sr_photocd: (TOSHIBA) Hmm, seems the CDROM doesn't support multisession CD's\n"); - no_multi = 1; - } - } else - printk("sr_photocd: ioctl error (TOSHIBA #1): 0x%x\n",rc); - break; /* if the first ioctl fails, we don't call the second one */ - } - is_xa = (rec[0] == 0x20); - min = (unsigned long) rec[1]/16*10 + (unsigned long) rec[1]%16; - sec = (unsigned long) rec[2]/16*10 + (unsigned long) rec[2]%16; - frame = (unsigned long) rec[3]/16*10 + (unsigned long) rec[3]%16; - sector = min*CD_SECS*CD_FRAMES + sec*CD_FRAMES + frame; - if (sector) { - sector -= CD_BLOCK_OFFSET; -#ifdef DEBUG - printk("sr_photocd: multisession CD detected: start: %lu\n",sector); -#endif - } - - /* now we do a get_density... */ - memset(buf,0,40); - *((unsigned long*)buf) = 0; - *((unsigned long*)buf+1) = 12; - cmd[0] = 0x1a; - cmd[2] = 1; - cmd[4] = 12; - rc = kernel_scsi_ioctl(scsi_CDs[MINOR(inode->i_rdev)].device, - SCSI_IOCTL_SEND_COMMAND, buf); - if (rc != 0) { - printk("sr_photocd: ioctl error (TOSHIBA #2): 0x%x\n",rc); - break; - } -#ifdef DEBUG - printk("sr_photocd: get_density: 0x%x\n",rec[4]); -#endif - - /* ...and only if necessary a set_density */ - if ((rec[4] != 0x81 && is_xa) || (rec[4] != 0 && !is_xa)) { -#ifdef DEBUG - printk("sr_photocd: doing set_density\n"); -#endif - memset(buf,0,40); - *((unsigned long*)buf) = 12; /* sending 12 bytes... */ - *((unsigned long*)buf+1) = 0; - cmd[0] = 0x15; - cmd[1] = (1 << 4); - cmd[4] = 12; - send = &cmd[6]; /* this is a 6-Byte command */ - send[ 3] = 0x08; /* the data for the command */ - send[ 4] = (is_xa) ? 0x81 : 0; /* density 0x81 for XA-CD's, 0 else */ - send[10] = 0x08; - rc = kernel_scsi_ioctl(scsi_CDs[MINOR(inode->i_rdev)].device, - SCSI_IOCTL_SEND_COMMAND, buf); - if (rc != 0) { - printk("sr_photocd: ioctl error (TOSHIBA #3): 0x%x\n",rc); - } - /* The set_density command may have changed the sector size or capacity. */ - scsi_CDs[MINOR(inode->i_rdev)].needs_sector_size = 1; - } - break; - - case SCSI_MAN_SONY: /* Thomas QUINOT <thomas@melchior.cuivre.fdn.fr> */ - case SCSI_MAN_PIONEER: -#ifdef DEBUG - printk("sr_photocd: use SONY/PIONEER code\n"); -#endif - memset(buf,0,40); - *((unsigned long*)buf) = 0x0; /* we send nothing... */ - *((unsigned long*)buf+1) = 0x0c; /* and receive 0x0c bytes */ - cmd[0] = 0x43; /* Read TOC */ - cmd[8] = 0x0c; - cmd[9] = 0x40; - rc = kernel_scsi_ioctl(scsi_CDs[MINOR(inode->i_rdev)].device, - SCSI_IOCTL_SEND_COMMAND, buf); - - if (rc != 0) { - printk("sr_photocd: ioctl error (SONY): 0x%x\n",rc); - break; - } - if ((rec[0] << 8) + rec[1] != 0x0a) { - printk("sr_photocd: (SONY) Hmm, seems the CDROM doesn't support multisession CD's\n"); - no_multi = 1; - break; - } - sector = rec[11] + (rec[10] << 8) + (rec[9] << 16) + (rec[8] << 24); - is_xa = !!sector; -#ifdef DEBUG - if (sector) - printk ("sr_photocd: multisession CD detected. start: %lu\n",sector); -#endif - break; - - case SCSI_MAN_NEC_OLDCDR: - case SCSI_MAN_UNKNOWN: - default: - sector = 0; - no_multi = 1; - break; } - - scsi_CDs[MINOR(inode->i_rdev)].mpcd_sector = sector; - if (is_xa) - scsi_CDs[MINOR(inode->i_rdev)].xa_flags |= 0x01; - else - scsi_CDs[MINOR(inode->i_rdev)].xa_flags &= ~0x01; - if (no_multi) - scsi_CDs[MINOR(inode->i_rdev)].xa_flags |= 0x02; - return; -} - -static int sr_open(struct inode * inode, struct file * filp) -{ - if(MINOR(inode->i_rdev) >= sr_template.nr_dev || - !scsi_CDs[MINOR(inode->i_rdev)].device) return -ENXIO; /* No such device */ - - if (filp->f_mode & 2) - return -EROFS; - - check_disk_change(inode->i_rdev); - - if(!scsi_CDs[MINOR(inode->i_rdev)].device->access_count++) - sr_ioctl(inode, NULL, SCSI_IOCTL_DOORLOCK, 0); - if (scsi_CDs[MINOR(inode->i_rdev)].device->host->hostt->usage_count) - (*scsi_CDs[MINOR(inode->i_rdev)].device->host->hostt->usage_count)++; - if(sr_template.usage_count) (*sr_template.usage_count)++; - - sr_photocd(inode); - - /* If this device did not have media in the drive at boot time, then - * we would have been unable to get the sector size. Check to see if - * this is the case, and try again. - */ - - if(scsi_CDs[MINOR(inode->i_rdev)].needs_sector_size) - get_sectorsize(MINOR(inode->i_rdev)); - - return 0; -} - - -/* - * do_sr_request() is the request handler function for the sr driver. - * Its function in life is to take block device requests, and - * translate them to SCSI commands. - */ - -static void do_sr_request (void) -{ - Scsi_Cmnd * SCpnt = NULL; - struct request * req = NULL; - Scsi_Device * SDev; - unsigned long flags; - int flag = 0; - - while (1==1){ - save_flags(flags); - cli(); - if (CURRENT != NULL && CURRENT->rq_status == RQ_INACTIVE) { - restore_flags(flags); - return; - }; - - INIT_SCSI_REQUEST; - - SDev = scsi_CDs[DEVICE_NR(CURRENT->rq_dev)].device; - - /* - * I am not sure where the best place to do this is. We need - * to hook in a place where we are likely to come if in user - * space. - */ - if( SDev->was_reset ) - { - /* - * We need to relock the door, but we might - * be in an interrupt handler. Only do this - * from user space, since we do not want to - * sleep from an interrupt. - */ - if( SDev->removable && !intr_count ) - { - scsi_ioctl(SDev, SCSI_IOCTL_DOORLOCK, 0); - } - SDev->was_reset = 0; - } - - if (flag++ == 0) - SCpnt = allocate_device(&CURRENT, - scsi_CDs[DEVICE_NR(CURRENT->rq_dev)].device, 0); - else SCpnt = NULL; - restore_flags(flags); - - /* This is a performance enhancement. We dig down into the request list and - * try and find a queueable request (i.e. device not busy, and host able to - * accept another command. If we find one, then we queue it. This can - * make a big difference on systems with more than one disk drive. We want - * to have the interrupts off when monkeying with the request list, because - * otherwise the kernel might try and slip in a request in between somewhere. */ - - if (!SCpnt && sr_template.nr_dev > 1){ - struct request *req1; - req1 = NULL; - save_flags(flags); - cli(); - req = CURRENT; - while(req){ - SCpnt = request_queueable(req, - scsi_CDs[DEVICE_NR(req->rq_dev)].device); - if(SCpnt) break; - req1 = req; - req = req->next; - }; - if (SCpnt && req->rq_status == RQ_INACTIVE) { - if (req == CURRENT) - CURRENT = CURRENT->next; - else - req1->next = req->next; - }; - restore_flags(flags); - }; - - if (!SCpnt) - return; /* Could not find anything to do */ - - wake_up(&wait_for_request); - - /* Queue command */ - requeue_sr_request(SCpnt); - }; /* While */ -} - -void requeue_sr_request (Scsi_Cmnd * SCpnt) -{ - unsigned int dev, block, realcount; - unsigned char cmd[10], *buffer, tries; - int this_count, start, end_rec; - - tries = 2; - - repeat: - if(!SCpnt || SCpnt->request.rq_status == RQ_INACTIVE) { - do_sr_request(); - return; - } - - dev = MINOR(SCpnt->request.rq_dev); - block = SCpnt->request.sector; - buffer = NULL; - this_count = 0; - - if (dev >= sr_template.nr_dev) { - /* printk("CD-ROM request error: invalid device.\n"); */ - SCpnt = end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors); - tries = 2; - goto repeat; - } - - if (!scsi_CDs[dev].use) { - /* printk("CD-ROM request error: device marked not in use.\n"); */ - SCpnt = end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors); - tries = 2; - goto repeat; - } - - if (scsi_CDs[dev].device->changed) { - /* - * quietly refuse to do anything to a changed disc - * until the changed bit has been reset - */ - /* printk("CD-ROM has been changed. Prohibiting further I/O.\n"); */ - SCpnt = end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors); - tries = 2; - goto repeat; - } - - switch (SCpnt->request.cmd) - { - case WRITE: - SCpnt = end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors); - goto repeat; - break; - case READ : - cmd[0] = READ_6; - break; - default : - panic ("Unknown sr command %d\n", SCpnt->request.cmd); - } - - cmd[1] = (SCpnt->lun << 5) & 0xe0; - - /* - * Now do the grungy work of figuring out which sectors we need, and - * where in memory we are going to put them. - * - * The variables we need are: - * - * this_count= number of 512 byte sectors being read - * block = starting cdrom sector to read. - * realcount = # of cdrom sectors to read - * - * The major difference between a scsi disk and a scsi cdrom - * is that we will always use scatter-gather if we can, because we can - * work around the fact that the buffer cache has a block size of 1024, - * and we have 2048 byte sectors. This code should work for buffers that - * are any multiple of 512 bytes long. - */ - - SCpnt->use_sg = 0; - - if (SCpnt->host->sg_tablesize > 0 && - (!need_isa_buffer || - dma_free_sectors >= 10)) { - struct buffer_head * bh; - struct scatterlist * sgpnt; - int count, this_count_max; - bh = SCpnt->request.bh; - this_count = 0; - count = 0; - this_count_max = (scsi_CDs[dev].ten ? 0xffff : 0xff) << 4; - /* Calculate how many links we can use. First see if we need - * a padding record at the start */ - this_count = SCpnt->request.sector % 4; - if(this_count) count++; - while(bh && count < SCpnt->host->sg_tablesize) { - if ((this_count + (bh->b_size >> 9)) > this_count_max) break; - this_count += (bh->b_size >> 9); - count++; - bh = bh->b_reqnext; - }; - /* Fix up in case of an odd record at the end */ - end_rec = 0; - if(this_count % 4) { - if (count < SCpnt->host->sg_tablesize) { - count++; - end_rec = (4 - (this_count % 4)) << 9; - this_count += 4 - (this_count % 4); - } else { - count--; - this_count -= (this_count % 4); - }; - }; - SCpnt->use_sg = count; /* Number of chains */ - count = 512;/* scsi_malloc can only allocate in chunks of 512 bytes*/ - while( count < (SCpnt->use_sg * sizeof(struct scatterlist))) - count = count << 1; - SCpnt->sglist_len = count; - sgpnt = (struct scatterlist * ) scsi_malloc(count); - if (!sgpnt) { - printk("Warning - running *really* short on DMA buffers\n"); - SCpnt->use_sg = 0; /* No memory left - bail out */ - } else { - buffer = (unsigned char *) sgpnt; - count = 0; - bh = SCpnt->request.bh; - if(SCpnt->request.sector % 4) { - sgpnt[count].length = (SCpnt->request.sector % 4) << 9; - sgpnt[count].address = (char *) scsi_malloc(sgpnt[count].length); - if(!sgpnt[count].address) panic("SCSI DMA pool exhausted."); - sgpnt[count].alt_address = sgpnt[count].address; /* Flag to delete - if needed */ - count++; - }; - for(bh = SCpnt->request.bh; count < SCpnt->use_sg; - count++, bh = bh->b_reqnext) { - if (bh) { /* Need a placeholder at the end of the record? */ - sgpnt[count].address = bh->b_data; - sgpnt[count].length = bh->b_size; - sgpnt[count].alt_address = NULL; - } else { - sgpnt[count].address = (char *) scsi_malloc(end_rec); - if(!sgpnt[count].address) panic("SCSI DMA pool exhausted."); - sgpnt[count].length = end_rec; - sgpnt[count].alt_address = sgpnt[count].address; - if (count+1 != SCpnt->use_sg) panic("Bad sr request list"); - break; - }; - if (((long) sgpnt[count].address) + sgpnt[count].length > ISA_DMA_THRESHOLD && - SCpnt->host->unchecked_isa_dma) { - sgpnt[count].alt_address = sgpnt[count].address; - /* We try and avoid exhausting the DMA pool, since it is easier - * to control usage here. In other places we might have a more - * pressing need, and we would be screwed if we ran out */ - if(dma_free_sectors < (sgpnt[count].length >> 9) + 5) { - sgpnt[count].address = NULL; - } else { - sgpnt[count].address = (char *) scsi_malloc(sgpnt[count].length); - }; - /* If we start running low on DMA buffers, we abort the scatter-gather - * operation, and free all of the memory we have allocated. We want to - * ensure that all scsi operations are able to do at least a non-scatter/gather - * operation */ - if(sgpnt[count].address == NULL){ /* Out of dma memory */ - printk("Warning: Running low on SCSI DMA buffers"); - /* Try switching back to a non scatter-gather operation. */ - while(--count >= 0){ - if(sgpnt[count].alt_address) - scsi_free(sgpnt[count].address, sgpnt[count].length); - }; - SCpnt->use_sg = 0; - scsi_free(buffer, SCpnt->sglist_len); - break; - }; /* if address == NULL */ - }; /* if need DMA fixup */ - }; /* for loop to fill list */ -#ifdef DEBUG - printk("SR: %d %d %d %d %d *** ",SCpnt->use_sg, SCpnt->request.sector, - this_count, - SCpnt->request.current_nr_sectors, - SCpnt->request.nr_sectors); - for(count=0; count<SCpnt->use_sg; count++) - printk("SGlist: %d %x %x %x\n", count, - sgpnt[count].address, - sgpnt[count].alt_address, - sgpnt[count].length); -#endif - }; /* Able to allocate scatter-gather list */ - }; - - if (SCpnt->use_sg == 0){ - /* We cannot use scatter-gather. Do this the old fashion way */ - if (!SCpnt->request.bh) - this_count = SCpnt->request.nr_sectors; - else - this_count = (SCpnt->request.bh->b_size >> 9); - - start = block % 4; - if (start) - { - this_count = ((this_count > 4 - start) ? - (4 - start) : (this_count)); - buffer = (unsigned char *) scsi_malloc(2048); - } - else if (this_count < 4) - { - buffer = (unsigned char *) scsi_malloc(2048); - } - else - { - this_count -= this_count % 4; - buffer = (unsigned char *) SCpnt->request.buffer; - if (((long) buffer) + (this_count << 9) > ISA_DMA_THRESHOLD && - SCpnt->host->unchecked_isa_dma) - buffer = (unsigned char *) scsi_malloc(this_count << 9); - } - }; - - if (scsi_CDs[dev].sector_size == 2048) - block = block >> 2; /* These are the sectors that the cdrom uses */ - else - block = block & 0xfffffffc; - - realcount = (this_count + 3) / 4; - - if (scsi_CDs[dev].sector_size == 512) realcount = realcount << 2; - - if (((realcount > 0xff) || (block > 0x1fffff)) && scsi_CDs[dev].ten) - { - if (realcount > 0xffff) - { - realcount = 0xffff; - this_count = realcount * (scsi_CDs[dev].sector_size >> 9); - } - - cmd[0] += READ_10 - READ_6 ; - cmd[2] = (unsigned char) (block >> 24) & 0xff; - cmd[3] = (unsigned char) (block >> 16) & 0xff; - cmd[4] = (unsigned char) (block >> 8) & 0xff; - cmd[5] = (unsigned char) block & 0xff; - cmd[6] = cmd[9] = 0; - cmd[7] = (unsigned char) (realcount >> 8) & 0xff; - cmd[8] = (unsigned char) realcount & 0xff; - } - else - { - if (realcount > 0xff) - { - realcount = 0xff; - this_count = realcount * (scsi_CDs[dev].sector_size >> 9); - } - - cmd[1] |= (unsigned char) ((block >> 16) & 0x1f); - cmd[2] = (unsigned char) ((block >> 8) & 0xff); - cmd[3] = (unsigned char) block & 0xff; - cmd[4] = (unsigned char) realcount; - cmd[5] = 0; - } - -#ifdef DEBUG - { - int i; - printk("ReadCD: %d %d %d %d\n",block, realcount, buffer, this_count); - printk("Use sg: %d\n", SCpnt->use_sg); - printk("Dumping command: "); - for(i=0; i<12; i++) printk("%2.2x ", cmd[i]); - printk("\n"); - }; -#endif - - /* Some dumb host adapters can speed transfers by knowing the - * minimum transfersize in advance. - * - * We shouldn't disconnect in the middle of a sector, but the cdrom - * sector size can be larger than the size of a buffer and the - * transfer may be split to the size of a buffer. So it's safe to - * assume that we can at least transfer the minimum of the buffer - * size (1024) and the sector size between each connect / disconnect. - */ - - SCpnt->transfersize = (scsi_CDs[dev].sector_size > 1024) ? - 1024 : scsi_CDs[dev].sector_size; - - SCpnt->this_count = this_count; - scsi_do_cmd (SCpnt, (void *) cmd, buffer, - realcount * scsi_CDs[dev].sector_size, - rw_intr, SR_TIMEOUT, MAX_RETRIES); -} - -static int sr_detect(Scsi_Device * SDp){ - - if(SDp->type != TYPE_ROM && SDp->type != TYPE_WORM) return 0; - - printk("Detected scsi CD-ROM sr%d at scsi%d, channel %d, id %d, lun %d\n", - sr_template.dev_noticed++, - SDp->host->host_no, SDp->channel, SDp->id, SDp->lun); - - return 1; -} - -static int sr_attach(Scsi_Device * SDp){ - Scsi_CD * cpnt; - int i; - - if(SDp->type != TYPE_ROM && SDp->type != TYPE_WORM) return 1; - - if (sr_template.nr_dev >= sr_template.dev_max) - { - SDp->attached--; - return 1; - } - - for(cpnt = scsi_CDs, i=0; i<sr_template.dev_max; i++, cpnt++) - if(!cpnt->device) break; - - if(i >= sr_template.dev_max) panic ("scsi_devices corrupt (sr)"); - - SDp->scsi_request_fn = do_sr_request; - scsi_CDs[i].device = SDp; - sr_template.nr_dev++; - if(sr_template.nr_dev > sr_template.dev_max) - panic ("scsi_devices corrupt (sr)"); - return 0; -} - - -static void sr_init_done (Scsi_Cmnd * SCpnt) -{ - struct request * req; - - req = &SCpnt->request; - req->rq_status = RQ_SCSI_DONE; /* Busy, but indicate request done */ - - if (req->sem != NULL) { - up(req->sem); - } -} - -static void get_sectorsize(int i){ - unsigned char cmd[10]; - unsigned char *buffer; - int the_result, retries; - Scsi_Cmnd * SCpnt; - - buffer = (unsigned char *) scsi_malloc(512); - SCpnt = allocate_device(NULL, scsi_CDs[i].device, 1); - - retries = 3; - do { - cmd[0] = READ_CAPACITY; - cmd[1] = (scsi_CDs[i].device->lun << 5) & 0xe0; - memset ((void *) &cmd[2], 0, 8); - SCpnt->request.rq_status = RQ_SCSI_BUSY; /* Mark as really busy */ - SCpnt->cmd_len = 0; - - memset(buffer, 0, 8); - - /* Do the command and wait.. */ - { - struct semaphore sem = MUTEX_LOCKED; - SCpnt->request.sem = &sem; - scsi_do_cmd (SCpnt, - (void *) cmd, (void *) buffer, - 512, sr_init_done, SR_TIMEOUT, - MAX_RETRIES); - down(&sem); - } - - the_result = SCpnt->result; - retries--; - - } while(the_result && retries); - - SCpnt->request.rq_status = RQ_INACTIVE; /* Mark as not busy */ - - wake_up(&SCpnt->device->device_wait); - - if (the_result) { - scsi_CDs[i].capacity = 0x1fffff; - scsi_CDs[i].sector_size = 2048; /* A guess, just in case */ - scsi_CDs[i].needs_sector_size = 1; - } else { - scsi_CDs[i].capacity = (buffer[0] << 24) | - (buffer[1] << 16) | (buffer[2] << 8) | buffer[3]; - scsi_CDs[i].sector_size = (buffer[4] << 24) | - (buffer[5] << 16) | (buffer[6] << 8) | buffer[7]; - if(scsi_CDs[i].sector_size == 0) scsi_CDs[i].sector_size = 2048; - /* Work around bug/feature in HP 4020i CD-Recorder... */ - if(scsi_CDs[i].sector_size == 2340) scsi_CDs[i].sector_size = 2048; - if(scsi_CDs[i].sector_size != 2048 && - scsi_CDs[i].sector_size != 512) { - printk ("scd%d : unsupported sector size %d.\n", - i, scsi_CDs[i].sector_size); - scsi_CDs[i].capacity = 0; - scsi_CDs[i].needs_sector_size = 1; - }; - if(scsi_CDs[i].sector_size == 2048) - scsi_CDs[i].capacity *= 4; - scsi_CDs[i].needs_sector_size = 0; - sr_sizes[i] = scsi_CDs[i].capacity; - }; - scsi_free(buffer, 512); -} - -static int sr_registered = 0; - -static int sr_init() -{ - int i; - - if(sr_template.dev_noticed == 0) return 0; - - if(!sr_registered) { - if (register_blkdev(MAJOR_NR,"sr",&sr_fops)) { - printk("Unable to get major %d for SCSI-CD\n",MAJOR_NR); - return 1; - } - sr_registered++; - } - - - if (scsi_CDs) return 0; - sr_template.dev_max = sr_template.dev_noticed + SR_EXTRA_DEVS; - scsi_CDs = (Scsi_CD *) scsi_init_malloc(sr_template.dev_max * sizeof(Scsi_CD), GFP_ATOMIC); - memset(scsi_CDs, 0, sr_template.dev_max * sizeof(Scsi_CD)); - - sr_sizes = (int *) scsi_init_malloc(sr_template.dev_max * sizeof(int), GFP_ATOMIC); - memset(sr_sizes, 0, sr_template.dev_max * sizeof(int)); - - sr_blocksizes = (int *) scsi_init_malloc(sr_template.dev_max * - sizeof(int), GFP_ATOMIC); - for(i=0;i<sr_template.dev_max;i++) sr_blocksizes[i] = 2048; - blksize_size[MAJOR_NR] = sr_blocksizes; - return 0; -} - -void sr_finish() -{ - int i; - - blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST; - blk_size[MAJOR_NR] = sr_sizes; - - for (i = 0; i < sr_template.nr_dev; ++i) - { - /* If we have already seen this, then skip it. Comes up - * with loadable modules. */ - if (scsi_CDs[i].capacity) continue; - scsi_CDs[i].capacity = 0x1fffff; - scsi_CDs[i].sector_size = 2048; /* A guess, just in case */ - scsi_CDs[i].needs_sector_size = 1; -#if 0 - /* seems better to leave this for later */ - get_sectorsize(i); - printk("Scd sectorsize = %d bytes.\n", scsi_CDs[i].sector_size); -#endif - scsi_CDs[i].use = 1; - scsi_CDs[i].ten = 1; - scsi_CDs[i].remap = 1; - scsi_CDs[i].auto_eject = 0; /* Default is not to eject upon unmount. */ - sr_sizes[i] = scsi_CDs[i].capacity; - } - - - /* If our host adapter is capable of scatter-gather, then we increase - * the read-ahead to 16 blocks (32 sectors). If not, we use - * a two block (4 sector) read ahead. */ - if(scsi_CDs[0].device && scsi_CDs[0].device->host->sg_tablesize) - read_ahead[MAJOR_NR] = 32; /* 32 sector read-ahead. Always removable. */ - else - read_ahead[MAJOR_NR] = 4; /* 4 sector read-ahead */ - - return; -} - -static void sr_detach(Scsi_Device * SDp) -{ - Scsi_CD * cpnt; - int i; - - for(cpnt = scsi_CDs, i=0; i<sr_template.dev_max; i++, cpnt++) - if(cpnt->device == SDp) { - kdev_t devi = MKDEV(MAJOR_NR, i); - - /* - * Since the cdrom is read-only, no need to sync the device. - * We should be kind to our buffer cache, however. - */ - invalidate_inodes(devi); - invalidate_buffers(devi); - - /* - * Reset things back to a sane state so that one can re-load a new - * driver (perhaps the same one). - */ - cpnt->device = NULL; - cpnt->capacity = 0; - SDp->attached--; - sr_template.nr_dev--; - sr_template.dev_noticed--; - sr_sizes[i] = 0; - return; - } - return; -} - - -#ifdef MODULE - -int init_module(void) { - sr_template.usage_count = &mod_use_count_; - return scsi_register_module(MODULE_SCSI_DEV, &sr_template); -} - -void cleanup_module( void) -{ - scsi_unregister_module(MODULE_SCSI_DEV, &sr_template); - unregister_blkdev(SCSI_CDROM_MAJOR, "sr"); - sr_registered--; - if(scsi_CDs != NULL) { - scsi_init_free((char *) scsi_CDs, - (sr_template.dev_noticed + SR_EXTRA_DEVS) - * sizeof(Scsi_CD)); - - scsi_init_free((char *) sr_sizes, sr_template.dev_max * sizeof(int)); - scsi_init_free((char *) sr_blocksizes, sr_template.dev_max * sizeof(int)); - } - - blksize_size[MAJOR_NR] = NULL; - blk_dev[MAJOR_NR].request_fn = NULL; - blk_size[MAJOR_NR] = NULL; - read_ahead[MAJOR_NR] = 0; - - sr_template.dev_max = 0; -} -#endif /* MODULE */ - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 4 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -4 - * c-argdecl-indent: 4 - * c-label-offset: -4 - * c-continued-statement-offset: 4 - * c-continued-brace-offset: 0 - * indent-tabs-mode: nil - * tab-width: 8 - * End: - */ diff --git a/i386/i386at/gpl/linux/scsi/sr.h b/i386/i386at/gpl/linux/scsi/sr.h deleted file mode 100644 index 381678a6..00000000 --- a/i386/i386at/gpl/linux/scsi/sr.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * sr.h by David Giller - * CD-ROM disk driver header file - * - * adapted from: - * sd.h Copyright (C) 1992 Drew Eckhardt - * SCSI disk driver header file by - * Drew Eckhardt - * - * <drew@colorado.edu> - * - * Modified by Eric Youngdale eric@aib.com to - * add scatter-gather, multiple outstanding request, and other - * enhancements. - */ - -#ifndef _SR_H -#define _SR_H - -#include "scsi.h" - -typedef struct - { - unsigned capacity; /* size in blocks */ - unsigned sector_size; /* size in bytes */ - Scsi_Device *device; - unsigned long mpcd_sector; /* for reading multisession-CD's */ - char xa_flags; /* some flags for handling XA-CD's */ - unsigned char sector_bit_size; /* sector size = 2^sector_bit_size */ - unsigned char sector_bit_shift; /* sectors/FS block = 2^sector_bit_shift*/ - unsigned needs_sector_size:1; /* needs to get sector size */ - unsigned ten:1; /* support ten byte commands */ - unsigned remap:1; /* support remapping */ - unsigned use:1; /* is this device still supportable */ - unsigned auto_eject:1; /* auto-eject medium on last release. */ - } Scsi_CD; - -extern Scsi_CD * scsi_CDs; - -#endif diff --git a/i386/i386at/gpl/linux/scsi/sr_ioctl.c b/i386/i386at/gpl/linux/scsi/sr_ioctl.c deleted file mode 100644 index 2313cf8c..00000000 --- a/i386/i386at/gpl/linux/scsi/sr_ioctl.c +++ /dev/null @@ -1,489 +0,0 @@ -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/mm.h> -#include <linux/fs.h> -#include <asm/segment.h> -#include <linux/errno.h> - -#include <linux/blk.h> -#include "scsi.h" -#include "hosts.h" -#include "sr.h" -#include "scsi_ioctl.h" - -#include <linux/cdrom.h> - -#define IOCTL_RETRIES 3 -/* The CDROM is fairly slow, so we need a little extra time */ -/* In fact, it is very slow if it has to spin up first */ -#define IOCTL_TIMEOUT 3000 - -static void sr_ioctl_done(Scsi_Cmnd * SCpnt) -{ - struct request * req; - - req = &SCpnt->request; - req->rq_status = RQ_SCSI_DONE; /* Busy, but indicate request done */ - - if (req->sem != NULL) { - up(req->sem); - } -} - -/* We do our own retries because we want to know what the specific - error code is. Normally the UNIT_ATTENTION code will automatically - clear after one error */ - -static int do_ioctl(int target, unsigned char * sr_cmd, void * buffer, unsigned buflength) -{ - Scsi_Cmnd * SCpnt; - int result; - - SCpnt = allocate_device(NULL, scsi_CDs[target].device, 1); - { - struct semaphore sem = MUTEX_LOCKED; - SCpnt->request.sem = &sem; - scsi_do_cmd(SCpnt, - (void *) sr_cmd, buffer, buflength, sr_ioctl_done, - IOCTL_TIMEOUT, IOCTL_RETRIES); - down(&sem); - } - - result = SCpnt->result; - - /* Minimal error checking. Ignore cases we know about, and report the rest. */ - if(driver_byte(result) != 0) - switch(SCpnt->sense_buffer[2] & 0xf) { - case UNIT_ATTENTION: - scsi_CDs[target].device->changed = 1; - printk("Disc change detected.\n"); - break; - case NOT_READY: /* This happens if there is no disc in drive */ - printk("CDROM not ready. Make sure there is a disc in the drive.\n"); - break; - case ILLEGAL_REQUEST: - printk("CDROM (ioctl) reports ILLEGAL REQUEST.\n"); - break; - default: - printk("SCSI CD error: host %d id %d lun %d return code = %03x\n", - scsi_CDs[target].device->host->host_no, - scsi_CDs[target].device->id, - scsi_CDs[target].device->lun, - result); - printk("\tSense class %x, sense error %x, extended sense %x\n", - sense_class(SCpnt->sense_buffer[0]), - sense_error(SCpnt->sense_buffer[0]), - SCpnt->sense_buffer[2] & 0xf); - - }; - - result = SCpnt->result; - SCpnt->request.rq_status = RQ_INACTIVE; /* Deallocate */ - wake_up(&SCpnt->device->device_wait); - /* Wake up a process waiting for device*/ - return result; -} - -int sr_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg) -{ - u_char sr_cmd[10]; - - kdev_t dev = inode->i_rdev; - int result, target, err; - - target = MINOR(dev); - - if (target >= sr_template.nr_dev || - !scsi_CDs[target].device) return -ENXIO; - - switch (cmd) - { - /* Sun-compatible */ - case CDROMPAUSE: - - sr_cmd[0] = SCMD_PAUSE_RESUME; - sr_cmd[1] = scsi_CDs[target].device->lun << 5; - sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = 0; - sr_cmd[5] = sr_cmd[6] = sr_cmd[7] = 0; - sr_cmd[8] = 0; - sr_cmd[9] = 0; - - result = do_ioctl(target, sr_cmd, NULL, 255); - return result; - - case CDROMRESUME: - - sr_cmd[0] = SCMD_PAUSE_RESUME; - sr_cmd[1] = scsi_CDs[target].device->lun << 5; - sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = 0; - sr_cmd[5] = sr_cmd[6] = sr_cmd[7] = 0; - sr_cmd[8] = 1; - sr_cmd[9] = 0; - - result = do_ioctl(target, sr_cmd, NULL, 255); - - return result; - - case CDROMPLAYMSF: - { - struct cdrom_msf msf; - - err = verify_area (VERIFY_READ, (void *) arg, sizeof (msf)); - if (err) return err; - - memcpy_fromfs(&msf, (void *) arg, sizeof(msf)); - - sr_cmd[0] = SCMD_PLAYAUDIO_MSF; - sr_cmd[1] = scsi_CDs[target].device->lun << 5; - sr_cmd[2] = 0; - sr_cmd[3] = msf.cdmsf_min0; - sr_cmd[4] = msf.cdmsf_sec0; - sr_cmd[5] = msf.cdmsf_frame0; - sr_cmd[6] = msf.cdmsf_min1; - sr_cmd[7] = msf.cdmsf_sec1; - sr_cmd[8] = msf.cdmsf_frame1; - sr_cmd[9] = 0; - - result = do_ioctl(target, sr_cmd, NULL, 255); - return result; - } - - case CDROMPLAYBLK: - { - struct cdrom_blk blk; - - err = verify_area (VERIFY_READ, (void *) arg, sizeof (blk)); - if (err) return err; - - memcpy_fromfs(&blk, (void *) arg, sizeof(blk)); - - sr_cmd[0] = SCMD_PLAYAUDIO10; - sr_cmd[1] = scsi_CDs[target].device->lun << 5; - sr_cmd[2] = blk.from >> 24; - sr_cmd[3] = blk.from >> 16; - sr_cmd[4] = blk.from >> 8; - sr_cmd[5] = blk.from; - sr_cmd[6] = 0; - sr_cmd[7] = blk.len >> 8; - sr_cmd[8] = blk.len; - sr_cmd[9] = 0; - - result = do_ioctl(target, sr_cmd, NULL, 255); - return result; - } - - case CDROMPLAYTRKIND: - { - struct cdrom_ti ti; - - err = verify_area (VERIFY_READ, (void *) arg, sizeof (ti)); - if (err) return err; - - memcpy_fromfs(&ti, (void *) arg, sizeof(ti)); - - sr_cmd[0] = SCMD_PLAYAUDIO_TI; - sr_cmd[1] = scsi_CDs[target].device->lun << 5; - sr_cmd[2] = 0; - sr_cmd[3] = 0; - sr_cmd[4] = ti.cdti_trk0; - sr_cmd[5] = ti.cdti_ind0; - sr_cmd[6] = 0; - sr_cmd[7] = ti.cdti_trk1; - sr_cmd[8] = ti.cdti_ind1; - sr_cmd[9] = 0; - - result = do_ioctl(target, sr_cmd, NULL, 255); - - return result; - } - - case CDROMREADTOCHDR: - { - struct cdrom_tochdr tochdr; - char * buffer; - - sr_cmd[0] = SCMD_READ_TOC; - sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 0x02; /* MSF format */ - sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = sr_cmd[5] = 0; - sr_cmd[6] = 0; - sr_cmd[7] = 0; /* MSB of length (12) */ - sr_cmd[8] = 12; /* LSB of length */ - sr_cmd[9] = 0; - - buffer = (unsigned char *) scsi_malloc(512); - if(!buffer) return -ENOMEM; - - result = do_ioctl(target, sr_cmd, buffer, 12); - - tochdr.cdth_trk0 = buffer[2]; - tochdr.cdth_trk1 = buffer[3]; - - scsi_free(buffer, 512); - - err = verify_area (VERIFY_WRITE, (void *) arg, sizeof (struct cdrom_tochdr)); - if (err) - return err; - memcpy_tofs ((void *) arg, &tochdr, sizeof (struct cdrom_tochdr)); - - return result; - } - - case CDROMREADTOCENTRY: - { - struct cdrom_tocentry tocentry; - char * buffer; - - err = verify_area (VERIFY_READ, (void *) arg, sizeof (struct cdrom_tocentry)); - if (err) return err; - - memcpy_fromfs (&tocentry, (void *) arg, sizeof (struct cdrom_tocentry)); - - sr_cmd[0] = SCMD_READ_TOC; - sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 0x02; /* MSF format */ - sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = sr_cmd[5] = 0; - sr_cmd[6] = tocentry.cdte_track; - sr_cmd[7] = 0; /* MSB of length (12) */ - sr_cmd[8] = 12; /* LSB of length */ - sr_cmd[9] = 0; - - buffer = (unsigned char *) scsi_malloc(512); - if(!buffer) return -ENOMEM; - - result = do_ioctl (target, sr_cmd, buffer, 12); - - if (tocentry.cdte_format == CDROM_MSF) { - tocentry.cdte_addr.msf.minute = buffer[9]; - tocentry.cdte_addr.msf.second = buffer[10]; - tocentry.cdte_addr.msf.frame = buffer[11]; - tocentry.cdte_ctrl = buffer[5] & 0xf; - } - else - tocentry.cdte_addr.lba = (int) buffer[0]; - - scsi_free(buffer, 512); - - err = verify_area (VERIFY_WRITE, (void *) arg, sizeof (struct cdrom_tocentry)); - if (err) - return err; - memcpy_tofs ((void *) arg, &tocentry, sizeof (struct cdrom_tocentry)); - - return result; - } - - case CDROMSTOP: - sr_cmd[0] = START_STOP; - sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 1; - sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0; - sr_cmd[4] = 0; - - result = do_ioctl(target, sr_cmd, NULL, 255); - return result; - - case CDROMSTART: - sr_cmd[0] = START_STOP; - sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 1; - sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0; - sr_cmd[4] = 1; - - result = do_ioctl(target, sr_cmd, NULL, 255); - return result; - - case CDROMEJECT: - /* - * Allow 0 for access count for auto-eject feature. - */ - if (scsi_CDs[target].device -> access_count > 1) - return -EBUSY; - - sr_ioctl (inode, NULL, SCSI_IOCTL_DOORUNLOCK, 0); - sr_cmd[0] = START_STOP; - sr_cmd[1] = ((scsi_CDs[target].device -> lun) << 5) | 1; - sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0; - sr_cmd[4] = 0x02; - - if (!(result = do_ioctl(target, sr_cmd, NULL, 255))) - scsi_CDs[target].device -> changed = 1; - - return result; - - case CDROMEJECT_SW: - scsi_CDs[target].auto_eject = !!arg; - return 0; - - case CDROMVOLCTRL: - { - char * buffer, * mask; - struct cdrom_volctrl volctrl; - - err = verify_area (VERIFY_READ, (void *) arg, sizeof (struct cdrom_volctrl)); - if (err) return err; - - memcpy_fromfs (&volctrl, (void *) arg, sizeof (struct cdrom_volctrl)); - - /* First we get the current params so we can just twiddle the volume */ - - sr_cmd[0] = MODE_SENSE; - sr_cmd[1] = (scsi_CDs[target].device -> lun) << 5; - sr_cmd[2] = 0xe; /* Want mode page 0xe, CDROM audio params */ - sr_cmd[3] = 0; - sr_cmd[4] = 28; - sr_cmd[5] = 0; - - buffer = (unsigned char *) scsi_malloc(512); - if(!buffer) return -ENOMEM; - - if ((result = do_ioctl (target, sr_cmd, buffer, 28))) { - printk ("Hosed while obtaining audio mode page\n"); - scsi_free(buffer, 512); - return result; - } - - sr_cmd[0] = MODE_SENSE; - sr_cmd[1] = (scsi_CDs[target].device -> lun) << 5; - sr_cmd[2] = 0x4e; /* Want the mask for mode page 0xe */ - sr_cmd[3] = 0; - sr_cmd[4] = 28; - sr_cmd[5] = 0; - - mask = (unsigned char *) scsi_malloc(512); - if(!mask) { - scsi_free(buffer, 512); - return -ENOMEM; - }; - - if ((result = do_ioctl (target, sr_cmd, mask, 28))) { - printk ("Hosed while obtaining mask for audio mode page\n"); - scsi_free(buffer, 512); - scsi_free(mask, 512); - return result; - } - - /* Now mask and substitute our own volume and reuse the rest */ - buffer[0] = 0; /* Clear reserved field */ - - buffer[21] = volctrl.channel0 & mask[21]; - buffer[23] = volctrl.channel1 & mask[23]; - buffer[25] = volctrl.channel2 & mask[25]; - buffer[27] = volctrl.channel3 & mask[27]; - - sr_cmd[0] = MODE_SELECT; - sr_cmd[1] = ((scsi_CDs[target].device -> lun) << 5) | 0x10; /* Params are SCSI-2 */ - sr_cmd[2] = sr_cmd[3] = 0; - sr_cmd[4] = 28; - sr_cmd[5] = 0; - - result = do_ioctl (target, sr_cmd, buffer, 28); - scsi_free(buffer, 512); - scsi_free(mask, 512); - return result; - } - - case CDROMSUBCHNL: - { - struct cdrom_subchnl subchnl; - char * buffer; - - sr_cmd[0] = SCMD_READ_SUBCHANNEL; - sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 0x02; /* MSF format */ - sr_cmd[2] = 0x40; /* I do want the subchannel info */ - sr_cmd[3] = 0x01; /* Give me current position info */ - sr_cmd[4] = sr_cmd[5] = 0; - sr_cmd[6] = 0; - sr_cmd[7] = 0; - sr_cmd[8] = 16; - sr_cmd[9] = 0; - - buffer = (unsigned char*) scsi_malloc(512); - if(!buffer) return -ENOMEM; - - result = do_ioctl(target, sr_cmd, buffer, 16); - - subchnl.cdsc_audiostatus = buffer[1]; - subchnl.cdsc_format = CDROM_MSF; - subchnl.cdsc_ctrl = buffer[5] & 0xf; - subchnl.cdsc_trk = buffer[6]; - subchnl.cdsc_ind = buffer[7]; - - subchnl.cdsc_reladdr.msf.minute = buffer[13]; - subchnl.cdsc_reladdr.msf.second = buffer[14]; - subchnl.cdsc_reladdr.msf.frame = buffer[15]; - subchnl.cdsc_absaddr.msf.minute = buffer[9]; - subchnl.cdsc_absaddr.msf.second = buffer[10]; - subchnl.cdsc_absaddr.msf.frame = buffer[11]; - - scsi_free(buffer, 512); - - err = verify_area (VERIFY_WRITE, (void *) arg, sizeof (struct cdrom_subchnl)); - if (err) - return err; - memcpy_tofs ((void *) arg, &subchnl, sizeof (struct cdrom_subchnl)); - return result; - } - - case CDROMREADMODE2: - return -EINVAL; - case CDROMREADMODE1: - return -EINVAL; - - /* block-copy from ../block/sbpcd.c with some adjustments... */ - case CDROMMULTISESSION: /* tell start-of-last-session to user */ - { - struct cdrom_multisession ms_info; - long lba; - - err = verify_area(VERIFY_READ, (void *) arg, - sizeof(struct cdrom_multisession)); - if (err) return (err); - - memcpy_fromfs(&ms_info, (void *) arg, sizeof(struct cdrom_multisession)); - - if (ms_info.addr_format==CDROM_MSF) { /* MSF-bin requested */ - lba = scsi_CDs[target].mpcd_sector+CD_BLOCK_OFFSET; - ms_info.addr.msf.minute = lba / (CD_SECS*CD_FRAMES); - lba %= CD_SECS*CD_FRAMES; - ms_info.addr.msf.second = lba / CD_FRAMES; - ms_info.addr.msf.frame = lba % CD_FRAMES; - } else if (ms_info.addr_format==CDROM_LBA) /* lba requested */ - ms_info.addr.lba=scsi_CDs[target].mpcd_sector; - else return (-EINVAL); - - ms_info.xa_flag=scsi_CDs[target].xa_flags & 0x01; - - err=verify_area(VERIFY_WRITE,(void *) arg, - sizeof(struct cdrom_multisession)); - if (err) return (err); - - memcpy_tofs((void *) arg, &ms_info, sizeof(struct cdrom_multisession)); - return (0); - } - - case BLKRASET: - if(!suser()) return -EACCES; - if(!(inode->i_rdev)) return -EINVAL; - if(arg > 0xff) return -EINVAL; - read_ahead[MAJOR(inode->i_rdev)] = arg; - return 0; - RO_IOCTLS(dev,arg); - default: - return scsi_ioctl(scsi_CDs[target].device,cmd,(void *) arg); - } -} - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 4 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -4 - * c-argdecl-indent: 4 - * c-label-offset: -4 - * c-continued-statement-offset: 4 - * c-continued-brace-offset: 0 - * indent-tabs-mode: nil - * tab-width: 8 - * End: - */ diff --git a/i386/i386at/gpl/linux/scsi/t128.c b/i386/i386at/gpl/linux/scsi/t128.c deleted file mode 100644 index 9212b61e..00000000 --- a/i386/i386at/gpl/linux/scsi/t128.c +++ /dev/null @@ -1,413 +0,0 @@ -#define AUTOSENSE -#define PSEUDO_DMA - -/* - * Trantor T128/T128F/T228 driver - * Note : architecturally, the T100 and T130 are different and won't - * work - * - * Copyright 1993, Drew Eckhardt - * Visionary Computing - * (Unix and Linux consulting and custom programming) - * drew@colorado.edu - * +1 (303) 440-4894 - * - * DISTRIBUTION RELEASE 3. - * - * For more information, please consult - * - * Trantor Systems, Ltd. - * T128/T128F/T228 SCSI Host Adapter - * Hardware Specifications - * - * Trantor Systems, Ltd. - * 5415 Randall Place - * Fremont, CA 94538 - * 1+ (415) 770-1400, FAX 1+ (415) 770-9910 - * - * and - * - * NCR 5380 Family - * SCSI Protocol Controller - * Databook - * - * NCR Microelectronics - * 1635 Aeroplaza Drive - * Colorado Springs, CO 80916 - * 1+ (719) 578-3400 - * 1+ (800) 334-5454 - */ - -/* - * Options : - * AUTOSENSE - if defined, REQUEST SENSE will be performed automatically - * for commands that return with a CHECK CONDITION status. - * - * PSEUDO_DMA - enables PSEUDO-DMA hardware, should give a 3-4X performance - * increase compared to polled I/O. - * - * PARITY - enable parity checking. Not supported. - * - * SCSI2 - enable support for SCSI-II tagged queueing. Untested. - * - * - * UNSAFE - leave interrupts enabled during pseudo-DMA transfers. You - * only really want to use this if you're having a problem with - * dropped characters during high speed communications, and even - * then, you're going to be better off twiddling with transfersize. - * - * USLEEP - enable support for devices that don't disconnect. Untested. - * - * The card is detected and initialized in one of several ways : - * 1. Autoprobe (default) - since the board is memory mapped, - * a BIOS signature is scanned for to locate the registers. - * An interrupt is triggered to autoprobe for the interrupt - * line. - * - * 2. With command line overrides - t128=address,irq may be - * used on the LILO command line to override the defaults. - * - * 3. With the T128_OVERRIDE compile time define. This is - * specified as an array of address, irq tuples. Ie, for - * one board at the default 0xcc000 address, IRQ5, I could say - * -DT128_OVERRIDE={{0xcc000, 5}} - * - * Note that if the override methods are used, place holders must - * be specified for other boards in the system. - * - * T128/T128F jumper/dipswitch settings (note : on my sample, the switches - * were epoxy'd shut, meaning I couldn't change the 0xcc000 base address) : - * - * T128 Sw7 Sw8 Sw6 = 0ws Sw5 = boot - * T128F Sw6 Sw7 Sw5 = 0ws Sw4 = boot Sw8 = floppy disable - * cc000 off off - * c8000 off on - * dc000 on off - * d8000 on on - * - * - * Interrupts - * There is a 12 pin jumper block, jp1, numbered as follows : - * T128 (JP1) T128F (J5) - * 2 4 6 8 10 12 11 9 7 5 3 1 - * 1 3 5 7 9 11 12 10 8 6 4 2 - * - * 3 2-4 - * 5 1-3 - * 7 3-5 - * T128F only - * 10 8-10 - * 12 7-9 - * 14 10-12 - * 15 9-11 - */ - -/* - * $Log: t128.c,v $ - * Revision 1.1.1.1 1996/10/30 01:40:07 thomas - * Imported from UK22 - * - * Revision 1.1 1996/03/25 20:25:52 goel - * Linux driver merge. - * - */ - -#include <asm/system.h> -#include <linux/signal.h> -#include <linux/sched.h> -#include <asm/io.h> -#include <linux/blk.h> -#include "scsi.h" -#include "hosts.h" -#include "t128.h" -#define AUTOPROBE_IRQ -#include "NCR5380.h" -#include "constants.h" -#include "sd.h" -#include<linux/stat.h> - -struct proc_dir_entry proc_scsi_t128 = { - PROC_SCSI_T128, 4, "t128", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - - -static struct override { - unsigned char *address; - int irq; -} overrides -#ifdef T128_OVERRIDE - [] = T128_OVERRIDE; -#else - [4] = {{NULL,IRQ_AUTO}, {NULL,IRQ_AUTO}, {NULL,IRQ_AUTO}, - {NULL,IRQ_AUTO}}; -#endif - -#define NO_OVERRIDES (sizeof(overrides) / sizeof(struct override)) - -static struct base { - unsigned char *address; - int noauto; -} bases[] = {{(unsigned char *) 0xcc000, 0}, {(unsigned char *) 0xc8000, 0}, - {(unsigned char *) 0xdc000, 0}, {(unsigned char *) 0xd8000, 0}}; - -#define NO_BASES (sizeof (bases) / sizeof (struct base)) - -static const struct signature { - const char *string; - int offset; -} signatures[] = { -{"TSROM: SCSI BIOS, Version 1.12", 0x36}, -}; - -#define NO_SIGNATURES (sizeof (signatures) / sizeof (struct signature)) - -/* - * Function : t128_setup(char *str, int *ints) - * - * Purpose : LILO command line initialization of the overrides array, - * - * Inputs : str - unused, ints - array of integer parameters with ints[0] - * equal to the number of ints. - * - */ - -void t128_setup(char *str, int *ints) { - static int commandline_current = 0; - int i; - if (ints[0] != 2) - printk("t128_setup : usage t128=address,irq\n"); - else - if (commandline_current < NO_OVERRIDES) { - overrides[commandline_current].address = (unsigned char *) ints[1]; - overrides[commandline_current].irq = ints[2]; - for (i = 0; i < NO_BASES; ++i) - if (bases[i].address == (unsigned char *) ints[1]) { - bases[i].noauto = 1; - break; - } - ++commandline_current; - } -} - -/* - * Function : int t128_detect(Scsi_Host_Template * tpnt) - * - * Purpose : detects and initializes T128,T128F, or T228 controllers - * that were autoprobed, overridden on the LILO command line, - * or specified at compile time. - * - * Inputs : tpnt - template for this SCSI adapter. - * - * Returns : 1 if a host adapter was found, 0 if not. - * - */ - -int t128_detect(Scsi_Host_Template * tpnt) { - static int current_override = 0, current_base = 0; - struct Scsi_Host *instance; - unsigned char *base; - int sig, count; - - tpnt->proc_dir = &proc_scsi_t128; - - for (count = 0; current_override < NO_OVERRIDES; ++current_override) { - base = NULL; - - if (overrides[current_override].address) - base = overrides[current_override].address; - else - for (; !base && (current_base < NO_BASES); ++current_base) { -#if (TDEBUG & TDEBUG_INIT) - printk("scsi : probing address %08x\n", (unsigned int) bases[current_base].address); -#endif - for (sig = 0; sig < NO_SIGNATURES; ++sig) - if (!bases[current_base].noauto && !memcmp - (bases[current_base].address + signatures[sig].offset, - signatures[sig].string, strlen(signatures[sig].string))) { - base = bases[current_base].address; -#if (TDEBUG & TDEBUG_INIT) - printk("scsi-t128 : detected board.\n"); -#endif - break; - } - } - -#if defined(TDEBUG) && (TDEBUG & TDEBUG_INIT) - printk("scsi-t128 : base = %08x\n", (unsigned int) base); -#endif - - if (!base) - break; - - instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata)); - instance->base = base; - - NCR5380_init(instance, 0); - - if (overrides[current_override].irq != IRQ_AUTO) - instance->irq = overrides[current_override].irq; - else - instance->irq = NCR5380_probe_irq(instance, T128_IRQS); - - if (instance->irq != IRQ_NONE) - if (request_irq(instance->irq, t128_intr, SA_INTERRUPT, "t128")) { - printk("scsi%d : IRQ%d not free, interrupts disabled\n", - instance->host_no, instance->irq); - instance->irq = IRQ_NONE; - } - - if (instance->irq == IRQ_NONE) { - printk("scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no); - printk("scsi%d : please jumper the board for a free IRQ.\n", instance->host_no); - } - -#if defined(TDEBUG) && (TDEBUG & TDEBUG_INIT) - printk("scsi%d : irq = %d\n", instance->host_no, instance->irq); -#endif - - printk("scsi%d : at 0x%08x", instance->host_no, (int) - instance->base); - if (instance->irq == IRQ_NONE) - printk (" interrupts disabled"); - else - printk (" irq %d", instance->irq); - printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d", - CAN_QUEUE, CMD_PER_LUN, T128_PUBLIC_RELEASE); - NCR5380_print_options(instance); - printk("\n"); - - ++current_override; - ++count; - } - return count; -} - -/* - * Function : int t128_biosparam(Disk * disk, kdev_t dev, int *ip) - * - * Purpose : Generates a BIOS / DOS compatible H-C-S mapping for - * the specified device / size. - * - * Inputs : size = size of device in sectors (512 bytes), dev = block device - * major / minor, ip[] = {heads, sectors, cylinders} - * - * Returns : always 0 (success), initializes ip - * - */ - -/* - * XXX Most SCSI boards use this mapping, I could be incorrect. Some one - * using hard disks on a trantor should verify that this mapping corresponds - * to that used by the BIOS / ASPI driver by running the linux fdisk program - * and matching the H_C_S coordinates to what DOS uses. - */ - -int t128_biosparam(Disk * disk, kdev_t dev, int * ip) -{ - int size = disk->capacity; - ip[0] = 64; - ip[1] = 32; - ip[2] = size >> 11; - return 0; -} - -/* - * Function : int NCR5380_pread (struct Scsi_Host *instance, - * unsigned char *dst, int len) - * - * Purpose : Fast 5380 pseudo-dma read function, transfers len bytes to - * dst - * - * Inputs : dst = destination, len = length in bytes - * - * Returns : 0 on success, non zero on a failure such as a watchdog - * timeout. - */ - -static inline int NCR5380_pread (struct Scsi_Host *instance, unsigned char *dst, - int len) { - register unsigned char *reg = (unsigned char *) (instance->base + - T_DATA_REG_OFFSET), *d = dst; - register i = len; - - -#if 0 - for (; i; --i) { - while (!(instance->base[T_STATUS_REG_OFFSET]) & T_ST_RDY) barrier(); -#else - while (!(instance->base[T_STATUS_REG_OFFSET]) & T_ST_RDY) barrier(); - for (; i; --i) { -#endif - *d++ = *reg; - } - - if (*(instance->base + T_STATUS_REG_OFFSET) & T_ST_TIM) { - unsigned char tmp; - volatile unsigned char *foo; - foo = instance->base + T_CONTROL_REG_OFFSET; - tmp = *foo; - *foo = tmp | T_CR_CT; - *foo = tmp; - printk("scsi%d : watchdog timer fired in NCR5380_pread()\n", - instance->host_no); - return -1; - } else - return 0; -} - -/* - * Function : int NCR5380_pwrite (struct Scsi_Host *instance, - * unsigned char *src, int len) - * - * Purpose : Fast 5380 pseudo-dma write function, transfers len bytes from - * src - * - * Inputs : src = source, len = length in bytes - * - * Returns : 0 on success, non zero on a failure such as a watchdog - * timeout. - */ - -static inline int NCR5380_pwrite (struct Scsi_Host *instance, unsigned char *src, - int len) { - register unsigned char *reg = (unsigned char *) (instance->base + - T_DATA_REG_OFFSET), *s = src; - register i = len; - -#if 0 - for (; i; --i) { - while (!(instance->base[T_STATUS_REG_OFFSET]) & T_ST_RDY) barrier(); -#else - while (!(instance->base[T_STATUS_REG_OFFSET]) & T_ST_RDY) barrier(); - for (; i; --i) { -#endif - *reg = *s++; - } - - if (*(instance->base + T_STATUS_REG_OFFSET) & T_ST_TIM) { - unsigned char tmp; - volatile unsigned char *foo; - foo = instance->base + T_CONTROL_REG_OFFSET; - tmp = *foo; - *foo = tmp | T_CR_CT; - *foo = tmp; - printk("scsi%d : watchdog timer fired in NCR5380_pwrite()\n", - instance->host_no); - return -1; - } else - return 0; -} - -#ifdef MACH -#include "NCR5380.src" -#else -#include "NCR5380.c" -#endif - -#ifdef MODULE -/* Eventually this will go into an include file, but this will be later */ -Scsi_Host_Template driver_template = TRANTOR_T128; - -#include "scsi_module.c" -#endif diff --git a/i386/i386at/gpl/linux/scsi/t128.h b/i386/i386at/gpl/linux/scsi/t128.h deleted file mode 100644 index 8c7cb579..00000000 --- a/i386/i386at/gpl/linux/scsi/t128.h +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Trantor T128/T128F/T228 defines - * Note : architecturally, the T100 and T128 are different and won't work - * - * Copyright 1993, Drew Eckhardt - * Visionary Computing - * (Unix and Linux consulting and custom programming) - * drew@colorado.edu - * +1 (303) 440-4894 - * - * DISTRIBUTION RELEASE 3. - * - * For more information, please consult - * - * Trantor Systems, Ltd. - * T128/T128F/T228 SCSI Host Adapter - * Hardware Specifications - * - * Trantor Systems, Ltd. - * 5415 Randall Place - * Fremont, CA 94538 - * 1+ (415) 770-1400, FAX 1+ (415) 770-9910 - * - * and - * - * NCR 5380 Family - * SCSI Protocol Controller - * Databook - * - * NCR Microelectronics - * 1635 Aeroplaza Drive - * Colorado Springs, CO 80916 - * 1+ (719) 578-3400 - * 1+ (800) 334-5454 - */ - -/* - * $Log: t128.h,v $ - * Revision 1.1.1.1 1996/10/30 01:40:07 thomas - * Imported from UK22 - * - * Revision 1.1 1996/03/25 20:25:52 goel - * Linux driver merge. - * - */ - -#ifndef T128_H -#define T128_H - -#define T128_PUBLIC_RELEASE 3 - -#define TDEBUG_INIT 0x1 -#define TDEBUG_TRANSFER 0x2 - -/* - * The trantor boards are memory mapped. They use an NCR5380 or - * equivalent (my sample board had part second sourced from ZILOG). - * NCR's recommended "Pseudo-DMA" architecture is used, where - * a PAL drives the DMA signals on the 5380 allowing fast, blind - * transfers with proper handshaking. - */ - -/* - * Note : a boot switch is provided for the purpose of informing the - * firmware to boot or not boot from attached SCSI devices. So, I imagine - * there are fewer people who've yanked the ROM like they do on the Seagate - * to make bootup faster, and I'll probably use this for autodetection. - */ -#define T_ROM_OFFSET 0 - -/* - * Note : my sample board *WAS NOT* populated with the SRAM, so this - * can't be used for autodetection without a ROM present. - */ -#define T_RAM_OFFSET 0x1800 - -/* - * All of the registers are allocated 32 bytes of address space, except - * for the data register (read/write to/from the 5380 in pseudo-DMA mode) - */ -#define T_CONTROL_REG_OFFSET 0x1c00 /* rw */ -#define T_CR_INT 0x10 /* Enable interrupts */ -#define T_CR_CT 0x02 /* Reset watchdog timer */ - -#define T_STATUS_REG_OFFSET 0x1c20 /* ro */ -#define T_ST_BOOT 0x80 /* Boot switch */ -#define T_ST_S3 0x40 /* User settable switches, */ -#define T_ST_S2 0x20 /* read 0 when switch is on, 1 off */ -#define T_ST_S1 0x10 -#define T_ST_PS2 0x08 /* Set for Microchannel 228 */ -#define T_ST_RDY 0x04 /* 5380 DRQ */ -#define T_ST_TIM 0x02 /* indicates 40us watchdog timer fired */ -#define T_ST_ZERO 0x01 /* Always zero */ - -#define T_5380_OFFSET 0x1d00 /* 8 registers here, see NCR5380.h */ - -#define T_DATA_REG_OFFSET 0x1e00 /* rw 512 bytes long */ - -#ifndef ASM -int t128_abort(Scsi_Cmnd *); -int t128_biosparam(Disk *, kdev_t, int*); -int t128_detect(Scsi_Host_Template *); -int t128_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); -int t128_reset(Scsi_Cmnd *); - -#ifndef NULL -#define NULL 0 -#endif - -#ifndef CMD_PER_LUN -#define CMD_PER_LUN 2 -#endif - -#ifndef CAN_QUEUE -#define CAN_QUEUE 32 -#endif - -/* - * I hadn't thought of this with the earlier drivers - but to prevent - * macro definition conflicts, we shouldn't define all of the internal - * macros when this is being used solely for the host stub. - */ - -#if defined(HOSTS_C) || defined(MODULE) - -#define TRANTOR_T128 {NULL, NULL, NULL, NULL, \ - "Trantor T128/T128F/T228", t128_detect, NULL, \ - NULL, \ - NULL, t128_queue_command, t128_abort, t128_reset, NULL, \ - t128_biosparam, \ - /* can queue */ CAN_QUEUE, /* id */ 7, SG_ALL, \ - /* cmd per lun */ CMD_PER_LUN , 0, 0, DISABLE_CLUSTERING} - -#endif - -#ifndef(HOSTS_C) - -#define NCR5380_implementation_fields \ - volatile unsigned char *base - -#define NCR5380_local_declare() \ - volatile unsigned char *base - -#define NCR5380_setup(instance) \ - base = (volatile unsigned char *) (instance)->base - -#define T128_address(reg) (base + T_5380_OFFSET + ((reg) * 0x20)) - -#if !(TDEBUG & TDEBUG_TRANSFER) -#define NCR5380_read(reg) (*(T128_address(reg))) -#define NCR5380_write(reg, value) (*(T128_address(reg)) = (value)) -#else -#define NCR5380_read(reg) \ - (((unsigned char) printk("scsi%d : read register %d at address %08x\n"\ - , instance->hostno, (reg), T128_address(reg))), *(T128_address(reg))) - -#define NCR5380_write(reg, value) { \ - printk("scsi%d : write %02x to register %d at address %08x\n", \ - instance->hostno, (value), (reg), T128_address(reg)); \ - *(T128_address(reg)) = (value); \ -} -#endif - -#define NCR5380_intr t128_intr -#define NCR5380_queue_command t128_queue_command -#define NCR5380_abort t128_abort -#define NCR5380_reset t128_reset - -/* 15 14 12 10 7 5 3 - 1101 0100 1010 1000 */ - -#define T128_IRQS 0xc4a8 - -#endif /* else def HOSTS_C */ -#endif /* ndef ASM */ -#endif /* T128_H */ diff --git a/i386/i386at/gpl/linux/scsi/u14-34f.c b/i386/i386at/gpl/linux/scsi/u14-34f.c deleted file mode 100644 index ce0e378e..00000000 --- a/i386/i386at/gpl/linux/scsi/u14-34f.c +++ /dev/null @@ -1,1044 +0,0 @@ -/* - * u14-34f.c - Low-level driver for UltraStor 14F/34F SCSI host adapters. - * - * 13 Jun 1995 rev. 2.01 for linux 1.2.10 - * HAVE_OLD_UX4F_FIRMWARE should be defined for U34F boards when - * the firmware prom is not the lastest one (28008-006). - * - * 11 Mar 1995 rev. 2.00 for linux 1.2.0 - * Fixed a bug which prevented media change detection for removable - * disk drives. - * - * 23 Feb 1995 rev. 1.18 for linux 1.1.94 - * Added a check for scsi_register returning NULL. - * - * 11 Feb 1995 rev. 1.17 for linux 1.1.91 - * U14F qualified to run with 32 sglists. - * Now DEBUG_RESET is disabled by default. - * - * 9 Feb 1995 rev. 1.16 for linux 1.1.90 - * Use host->wish_block instead of host->block. - * - * 8 Feb 1995 rev. 1.15 for linux 1.1.89 - * Cleared target_time_out counter while performing a reset. - * - * 28 Jan 1995 rev. 1.14 for linux 1.1.86 - * Added module support. - * Log and do a retry when a disk drive returns a target status - * different from zero on a recovered error. - * Auto detects if U14F boards have an old firmware revision. - * Max number of scatter/gather lists set to 16 for all boards - * (most installation run fine using 33 sglists, while other - * has problems when using more then 16). - * - * 16 Jan 1995 rev. 1.13 for linux 1.1.81 - * Display a message if check_region detects a port address - * already in use. - * - * 15 Dec 1994 rev. 1.12 for linux 1.1.74 - * The host->block flag is set for all the detected ISA boards. - * - * 30 Nov 1994 rev. 1.11 for linux 1.1.68 - * Redo i/o on target status CHECK_CONDITION for TYPE_DISK only. - * Added optional support for using a single board at a time. - * - * 14 Nov 1994 rev. 1.10 for linux 1.1.63 - * - * 28 Oct 1994 rev. 1.09 for linux 1.1.58 Final BETA release. - * 16 Jul 1994 rev. 1.00 for linux 1.1.29 Initial ALPHA release. - * - * This driver is a total replacement of the original UltraStor - * scsi driver, but it supports ONLY the 14F and 34F boards. - * It can be configured in the same kernel in which the original - * ultrastor driver is configured to allow the original U24F - * support. - * - * Multiple U14F and/or U34F host adapters are supported. - * - * Copyright (C) 1994, 1995 Dario Ballabio (dario@milano.europe.dg.com) - * - * WARNING: if your 14/34F board has an old firmware revision (see below) - * you must change "#undef" into "#define" in the following - * statement. - */ -#undef HAVE_OLD_UX4F_FIRMWARE -/* - * The UltraStor 14F, 24F, and 34F are a family of intelligent, high - * performance SCSI-2 host adapters. - * Here is the scoop on the various models: - * - * 14F - ISA first-party DMA HA with floppy support and WD1003 emulation. - * 24F - EISA Bus Master HA with floppy support and WD1003 emulation. - * 34F - VESA Local-Bus Bus Master HA (no WD1003 emulation). - * - * This code has been tested with up to two U14F boards, using both - * firmware 28004-005/38004-004 (BIOS rev. 2.00) and the latest firmware - * 28004-006/38004-005 (BIOS rev. 2.01). - * - * The latest firmware is required in order to get reliable operations when - * clustering is enabled. ENABLE_CLUSTERING provides a performance increase - * up to 50% on sequential access. - * - * Since the Scsi_Host_Template structure is shared among all 14F and 34F, - * the last setting of use_clustering is in effect for all of these boards. - * - * Here a sample configuration using two U14F boards: - * - U14F0: PORT 0x330, BIOS 0xc8000, IRQ 11, DMA 5, SG 32, Mbox 16, CmdLun 2, C1. - U14F1: PORT 0x340, BIOS 0x00000, IRQ 10, DMA 6, SG 32, Mbox 16, CmdLun 2, C1. - * - * The boot controller must have its BIOS enabled, while other boards can - * have their BIOS disabled, or enabled to an higher address. - * Boards are named Ux4F0, Ux4F1..., according to the port address order in - * the io_port[] array. - * - * The following facts are based on real testing results (not on - * documentation) on the above U14F board. - * - * - The U14F board should be jumpered for bus on time less or equal to 7 - * microseconds, while the default is 11 microseconds. This is order to - * get acceptable performance while using floppy drive and hard disk - * together. The jumpering for 7 microseconds is: JP13 pin 15-16, - * JP14 pin 7-8 and pin 9-10. - * The reduction has a little impact on scsi performance. - * - * - If scsi bus length exceeds 3m., the scsi bus speed needs to be reduced - * from 10Mhz to 5Mhz (do this by inserting a jumper on JP13 pin 7-8). - * - * - If U14F on board firmware is older than 28004-006/38004-005, - * the U14F board is unable to provide reliable operations if the scsi - * request length exceeds 16Kbyte. When this length is exceeded the - * behavior is: - * - adapter_status equal 0x96 or 0xa3 or 0x93 or 0x94; - * - adapter_status equal 0 and target_status equal 2 on for all targets - * in the next operation following the reset. - * This sequence takes a long time (>3 seconds), so in the meantime - * the SD_TIMEOUT in sd.c could expire giving rise to scsi aborts - * (SD_TIMEOUT has been increased from 3 to 6 seconds in 1.1.31). - * Because of this I had to DISABLE_CLUSTERING and to work around the - * bus reset in the interrupt service routine, returning DID_BUS_BUSY - * so that the operations are retried without complains from the scsi.c - * code. - * Any reset of the scsi bus is going to kill tape operations, since - * no retry is allowed for tapes. Bus resets are more likely when the - * scsi bus is under heavy load. - * Requests using scatter/gather have a maximum length of 16 x 1024 bytes - * when DISABLE_CLUSTERING is in effect, but unscattered requests could be - * larger than 16Kbyte. - * - * The new firmware has fixed all the above problems. - * - * For U34F boards the latest bios prom is 38008-002 (BIOS rev. 2.01), - * the latest firmware prom is 28008-006. Older firmware 28008-005 has - * problems when using more then 16 scatter/gather lists. - * - * In order to support multiple ISA boards in a reliable way, - * the driver sets host->wish_block = TRUE for all ISA boards. - */ - -#if defined(MODULE) -#include <linux/module.h> -#include <linux/version.h> -#endif - -#include <linux/string.h> -#include <linux/sched.h> -#include <linux/kernel.h> -#include <linux/ioport.h> -#include <asm/io.h> -#include <asm/system.h> -#include <linux/proc_fs.h> -#include <linux/blk.h> -#include "scsi.h" -#include "hosts.h" -#include "sd.h" -#include <asm/dma.h> -#include <asm/irq.h> -#include "u14-34f.h" -#include<linux/stat.h> - -struct proc_dir_entry proc_scsi_u14_34f = { - PROC_SCSI_U14_34F, 6, "u14_34f", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - -/* Values for the PRODUCT_ID ports for the 14/34F */ -#define PRODUCT_ID1 0x56 -#define PRODUCT_ID2 0x40 /* NOTE: Only upper nibble is used */ - -/* Subversion values */ -#define ISA 0 -#define ESA 1 - -#define OP_HOST_ADAPTER 0x1 -#define OP_SCSI 0x2 -#define OP_RESET 0x4 -#define DTD_SCSI 0x0 -#define DTD_IN 0x1 -#define DTD_OUT 0x2 -#define DTD_NONE 0x3 -#define HA_CMD_INQUIRY 0x1 -#define HA_CMD_SELF_DIAG 0x2 -#define HA_CMD_READ_BUFF 0x3 -#define HA_CMD_WRITE_BUFF 0x4 - -#undef DEBUG_DETECT -#undef DEBUG_INTERRUPT -#undef DEBUG_STATISTICS -#undef DEBUG_RESET - -#define MAX_TARGET 8 -#define MAX_IRQ 16 -#define MAX_BOARDS 4 -#define MAX_MAILBOXES 16 -#define MAX_SGLIST 32 -#define MAX_SAFE_SGLIST 16 -#define MAX_CMD_PER_LUN 2 - -#define FALSE 0 -#define TRUE 1 -#define FREE 0 -#define IN_USE 1 -#define LOCKED 2 -#define IN_RESET 3 -#define IGNORE 4 -#define NO_IRQ 0xff -#define NO_DMA 0xff -#define MAXLOOP 200000 - -#define REG_LCL_MASK 0 -#define REG_LCL_INTR 1 -#define REG_SYS_MASK 2 -#define REG_SYS_INTR 3 -#define REG_PRODUCT_ID1 4 -#define REG_PRODUCT_ID2 5 -#define REG_CONFIG1 6 -#define REG_CONFIG2 7 -#define REG_OGM 8 -#define REG_ICM 12 -#define REGION_SIZE 13 -#define BSY_ASSERTED 0x01 -#define IRQ_ASSERTED 0x01 -#define CMD_RESET 0xc0 -#define CMD_OGM_INTR 0x01 -#define CMD_CLR_INTR 0x01 -#define CMD_ENA_INTR 0x81 -#define ASOK 0x00 -#define ASST 0x91 - -#define PACKED __attribute__((packed)) - -/* MailBox SCSI Command Packet */ -struct mscp { - unsigned char opcode: 3; /* type of command */ - unsigned char xdir: 2; /* data transfer direction */ - unsigned char dcn: 1; /* disable disconnect */ - unsigned char ca: 1; /* use cache (if available) */ - unsigned char sg: 1; /* scatter/gather operation */ - unsigned char target: 3; /* target SCSI id */ - unsigned char ch_no: 2; /* SCSI channel (always 0 for 14f) */ - unsigned char lun: 3; /* logical unit number */ - unsigned int data_address PACKED; /* transfer data pointer */ - unsigned int data_len PACKED; /* length in bytes */ - unsigned int command_link PACKED; /* for linking command chains */ - unsigned char scsi_command_link_id; /* identifies command in chain */ - unsigned char use_sg; /* (if sg is set) 8 bytes per list */ - unsigned char sense_len; - unsigned char scsi_cdbs_len; /* 6, 10, or 12 */ - unsigned char scsi_cdbs[12]; /* SCSI commands */ - unsigned char adapter_status; /* non-zero indicates HA error */ - unsigned char target_status; /* non-zero indicates target error */ - unsigned int sense_addr PACKED; - - Scsi_Cmnd *SCpnt; - - struct sg_list { - unsigned int address; /* Segment Address */ - unsigned int num_bytes; /* Segment Length */ - } sglist[MAX_SGLIST]; - - unsigned int index; /* cp index */ - }; - -struct hostdata { - struct mscp cp[MAX_MAILBOXES]; /* Mailboxes for this board */ - unsigned int cp_stat[MAX_MAILBOXES]; /* FREE, IN_USE, LOCKED, IN_RESET */ - unsigned int last_cp_used; /* Index of last mailbox used */ - unsigned int iocount; /* Total i/o done for this board */ - unsigned int multicount; /* Total ... in second ihdlr loop */ - int board_number; /* Number of this board */ - char board_name[16]; /* Name of this board */ - char board_id[256]; /* data from INQUIRY on this board */ - int in_reset; /* True if board is doing a reset */ - int target_time_out[MAX_TARGET]; /* N. of timeout errors on target */ - int target_reset[MAX_TARGET]; /* If TRUE redo operation on target */ - unsigned char subversion; /* Bus type, either ISA or ESA */ - unsigned char heads; - unsigned char sectors; - - /* slot != 0 for the U24F, slot == 0 for both the U14F and U34F */ - unsigned char slot; - }; - -static struct Scsi_Host * sh[MAX_BOARDS + 1]; -static const char* driver_name = "Ux4F"; -static unsigned int irqlist[MAX_IRQ], calls[MAX_IRQ]; - -#define HD(board) ((struct hostdata *) &sh[board]->hostdata) -#define BN(board) (HD(board)->board_name) - -static void u14_34f_interrupt_handler(int, struct pt_regs *); -static int do_trace = FALSE; - -static inline unchar wait_on_busy(ushort iobase) { - unsigned int loop = MAXLOOP; - - while (inb(iobase + REG_LCL_INTR) & BSY_ASSERTED) - if (--loop == 0) return TRUE; - - return FALSE; -} - -static int board_inquiry(unsigned int j) { - struct mscp *cpp; - unsigned int time, limit = 0; - - cpp = &HD(j)->cp[0]; - memset(cpp, 0, sizeof(struct mscp)); - cpp->opcode = OP_HOST_ADAPTER; - cpp->xdir = DTD_IN; - cpp->data_address = (unsigned int) HD(j)->board_id; - cpp->data_len = sizeof(HD(j)->board_id); - cpp->scsi_cdbs_len = 6; - cpp->scsi_cdbs[0] = HA_CMD_INQUIRY; - - if (wait_on_busy(sh[j]->io_port)) { - printk("%s: board_inquiry, adapter busy.\n", BN(j)); - return TRUE; - } - - HD(j)->cp_stat[0] = IGNORE; - - /* Clear the interrupt indication */ - outb(CMD_CLR_INTR, sh[j]->io_port + REG_SYS_INTR); - - /* Store pointer in OGM address bytes */ - outl((unsigned int)cpp, sh[j]->io_port + REG_OGM); - - /* Issue OGM interrupt */ - outb(CMD_OGM_INTR, sh[j]->io_port + REG_LCL_INTR); - - sti(); - time = jiffies; - while (jiffies < (time + 100) && limit++ < 100000000); - cli(); - - if (cpp->adapter_status || HD(j)->cp_stat[0] != FREE) { - HD(j)->cp_stat[0] = FREE; - printk("%s: board_inquiry, err 0x%x.\n", BN(j), cpp->adapter_status); - return TRUE; - } - - return FALSE; -} - -static inline int port_detect(ushort *port_base, unsigned int j, - Scsi_Host_Template * tpnt) { - unsigned char irq, dma_channel, subversion; - unsigned char in_byte; - - /* Allowed BIOS base addresses (NULL indicates reserved) */ - void *bios_segment_table[8] = { - NULL, - (void *) 0xc4000, (void *) 0xc8000, (void *) 0xcc000, (void *) 0xd0000, - (void *) 0xd4000, (void *) 0xd8000, (void *) 0xdc000 - }; - - /* Allowed IRQs */ - unsigned char interrupt_table[4] = { 15, 14, 11, 10 }; - - /* Allowed DMA channels for ISA (0 indicates reserved) */ - unsigned char dma_channel_table[4] = { 5, 6, 7, 0 }; - - /* Head/sector mappings */ - struct { - unsigned char heads; - unsigned char sectors; - } mapping_table[4] = { - { 16, 63 }, { 64, 32 }, { 64, 63 }, { 64, 32 } - }; - - struct config_1 { - unsigned char bios_segment: 3; - unsigned char removable_disks_as_fixed: 1; - unsigned char interrupt: 2; - unsigned char dma_channel: 2; - } config_1; - - struct config_2 { - unsigned char ha_scsi_id: 3; - unsigned char mapping_mode: 2; - unsigned char bios_drive_number: 1; - unsigned char tfr_port: 2; - } config_2; - - char name[16]; - - sprintf(name, "%s%d", driver_name, j); - - if(check_region(*port_base, REGION_SIZE)) { - printk("%s: address 0x%03x in use, skipping probe.\n", - name, *port_base); - return FALSE; - } - - if (inb(*port_base + REG_PRODUCT_ID1) != PRODUCT_ID1) return FALSE; - - in_byte = inb(*port_base + REG_PRODUCT_ID2); - - if ((in_byte & 0xf0) != PRODUCT_ID2) return FALSE; - - *(char *)&config_1 = inb(*port_base + REG_CONFIG1); - *(char *)&config_2 = inb(*port_base + REG_CONFIG2); - - irq = interrupt_table[config_1.interrupt]; - dma_channel = dma_channel_table[config_1.dma_channel]; - subversion = (in_byte & 0x0f); - - /* Board detected, allocate its IRQ if not already done */ - if ((irq >= MAX_IRQ) || ((irqlist[irq] == NO_IRQ) && request_irq - (irq, u14_34f_interrupt_handler, SA_INTERRUPT, driver_name))) { - printk("%s: unable to allocate IRQ %u, detaching.\n", name, irq); - return FALSE; - } - - if (subversion == ISA && request_dma(dma_channel, driver_name)) { - printk("%s: unable to allocate DMA channel %u, detaching.\n", - name, dma_channel); - free_irq(irq); - return FALSE; - } - - sh[j] = scsi_register(tpnt, sizeof(struct hostdata)); - - if (sh[j] == NULL) { - printk("%s: unable to register host, detaching.\n", name); - - if (irqlist[irq] == NO_IRQ) free_irq(irq); - - if (subversion == ISA) free_dma(dma_channel); - - return FALSE; - } - - sh[j]->io_port = *port_base; - sh[j]->n_io_port = REGION_SIZE; - sh[j]->base = bios_segment_table[config_1.bios_segment]; - sh[j]->irq = irq; - sh[j]->sg_tablesize = MAX_SGLIST; - sh[j]->this_id = config_2.ha_scsi_id; - sh[j]->can_queue = MAX_MAILBOXES; - sh[j]->cmd_per_lun = MAX_CMD_PER_LUN; - -#if defined(DEBUG_DETECT) - { - unsigned char sys_mask, lcl_mask; - - sys_mask = inb(sh[j]->io_port + REG_SYS_MASK); - lcl_mask = inb(sh[j]->io_port + REG_LCL_MASK); - printk("SYS_MASK 0x%x, LCL_MASK 0x%x.\n", sys_mask, lcl_mask); - } -#endif - - /* If BIOS is disabled, force enable interrupts */ - if (sh[j]->base == 0) outb(CMD_ENA_INTR, sh[j]->io_port + REG_SYS_MASK); - - /* Register the I/O space that we use */ - request_region(sh[j]->io_port, REGION_SIZE, driver_name); - - memset(HD(j), 0, sizeof(struct hostdata)); - HD(j)->heads = mapping_table[config_2.mapping_mode].heads; - HD(j)->sectors = mapping_table[config_2.mapping_mode].sectors; - HD(j)->subversion = subversion; - HD(j)->board_number = j; - irqlist[irq] = j; - - if (HD(j)->subversion == ESA) { - -#if defined (HAVE_OLD_UX4F_FIRMWARE) - sh[j]->sg_tablesize = MAX_SAFE_SGLIST; -#endif - - sh[j]->dma_channel = NO_DMA; - sh[j]->unchecked_isa_dma = FALSE; - sprintf(BN(j), "U34F%d", j); - } - else { - sh[j]->wish_block = TRUE; - -#if defined (HAVE_OLD_UX4F_FIRMWARE) - sh[j]->hostt->use_clustering = DISABLE_CLUSTERING; - sh[j]->sg_tablesize = MAX_SAFE_SGLIST; -#endif - - sh[j]->dma_channel = dma_channel; - sh[j]->unchecked_isa_dma = TRUE; - sprintf(BN(j), "U14F%d", j); - disable_dma(dma_channel); - clear_dma_ff(dma_channel); - set_dma_mode(dma_channel, DMA_MODE_CASCADE); - enable_dma(dma_channel); - } - - if (HD(j)->subversion == ISA && !board_inquiry(j)) { - HD(j)->board_id[40] = 0; - - if (strcmp(&HD(j)->board_id[32], "06000600")) { - printk("%s: %s.\n", BN(j), &HD(j)->board_id[8]); - printk("%s: firmware %s is outdated, FW PROM should be 28004-006.\n", - BN(j), &HD(j)->board_id[32]); - sh[j]->hostt->use_clustering = DISABLE_CLUSTERING; - sh[j]->sg_tablesize = MAX_SAFE_SGLIST; - } - } - - printk("%s: PORT 0x%03x, BIOS 0x%05x, IRQ %u, DMA %u, SG %d, "\ - "Mbox %d, CmdLun %d, C%d.\n", BN(j), sh[j]->io_port, - (int)sh[j]->base, sh[j]->irq, - sh[j]->dma_channel, sh[j]->sg_tablesize, - sh[j]->can_queue, sh[j]->cmd_per_lun, - sh[j]->hostt->use_clustering); - return TRUE; -} - -int u14_34f_detect (Scsi_Host_Template * tpnt) { - unsigned int j = 0, k, flags; - - ushort io_port[] = { - 0x330, 0x340, 0x230, 0x240, 0x210, 0x130, 0x140, 0x0 - }; - - ushort *port_base = io_port; - - tpnt->proc_dir = &proc_scsi_u14_34f; - - save_flags(flags); - cli(); - - for (k = 0; k < MAX_IRQ; k++) { - irqlist[k] = NO_IRQ; - calls[k] = 0; - } - - for (k = 0; k < MAX_BOARDS + 1; k++) sh[k] = NULL; - - while (*port_base) { - - if (j < MAX_BOARDS && port_detect(port_base, j, tpnt)) j++; - - port_base++; - } - - if (j > 0) - printk("UltraStor 14F/34F: Copyright (C) 1994, 1995 Dario Ballabio.\n"); - - restore_flags(flags); - return j; -} - -static inline void build_sg_list(struct mscp *cpp, Scsi_Cmnd *SCpnt) { - unsigned int k, data_len = 0; - struct scatterlist * sgpnt; - - sgpnt = (struct scatterlist *) SCpnt->request_buffer; - - for (k = 0; k < SCpnt->use_sg; k++) { - cpp->sglist[k].address = (unsigned int) sgpnt[k].address; - cpp->sglist[k].num_bytes = sgpnt[k].length; - data_len += sgpnt[k].length; - } - - cpp->use_sg = SCpnt->use_sg; - cpp->data_address = (unsigned int) cpp->sglist; - cpp->data_len = data_len; -} - -int u14_34f_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { - unsigned int i, j, k, flags; - struct mscp *cpp; - - save_flags(flags); - cli(); - /* j is the board number */ - j = ((struct hostdata *) SCpnt->host->hostdata)->board_number; - - if (!done) panic("%s: qcomm, pid %ld, null done.\n", BN(j), SCpnt->pid); - - /* i is the mailbox number, look for the first free mailbox - starting from last_cp_used */ - i = HD(j)->last_cp_used + 1; - - for (k = 0; k < sh[j]->can_queue; k++, i++) { - - if (i >= sh[j]->can_queue) i = 0; - - if (HD(j)->cp_stat[i] == FREE) { - HD(j)->last_cp_used = i; - break; - } - } - - if (k == sh[j]->can_queue) { - printk("%s: qcomm, no free mailbox, resetting.\n", BN(j)); - - if (HD(j)->in_reset) - printk("%s: qcomm, already in reset.\n", BN(j)); - else if (u14_34f_reset(SCpnt) == SCSI_RESET_SUCCESS) - panic("%s: qcomm, SCSI_RESET_SUCCESS.\n", BN(j)); - - SCpnt->result = DID_BUS_BUSY << 16; - SCpnt->host_scribble = NULL; - printk("%s: qcomm, pid %ld, DID_BUS_BUSY, done.\n", BN(j), SCpnt->pid); - restore_flags(flags); - done(SCpnt); - return 0; - } - - /* Set pointer to control packet structure */ - cpp = &HD(j)->cp[i]; - - memset(cpp, 0, sizeof(struct mscp)); - SCpnt->scsi_done = done; - cpp->index = i; - SCpnt->host_scribble = (unsigned char *) &cpp->index; - - if (do_trace) printk("%s: qcomm, mbox %d, target %d, pid %ld.\n", - BN(j), i, SCpnt->target, SCpnt->pid); - - cpp->opcode = OP_SCSI; - cpp->xdir = DTD_SCSI; - cpp->target = SCpnt->target; - cpp->lun = SCpnt->lun; - cpp->SCpnt = SCpnt; - cpp->sense_addr = (unsigned int) SCpnt->sense_buffer; - cpp->sense_len = sizeof SCpnt->sense_buffer; - - if (SCpnt->use_sg) { - cpp->sg = TRUE; - build_sg_list(cpp, SCpnt); - } - else { - cpp->data_address = (unsigned int)SCpnt->request_buffer; - cpp->data_len = SCpnt->request_bufflen; - } - - cpp->scsi_cdbs_len = SCpnt->cmd_len; - memcpy(cpp->scsi_cdbs, SCpnt->cmnd, cpp->scsi_cdbs_len); - - if (wait_on_busy(sh[j]->io_port)) { - SCpnt->result = DID_ERROR << 16; - SCpnt->host_scribble = NULL; - printk("%s: qcomm, target %d, pid %ld, adapter busy, DID_ERROR, done.\n", - BN(j), SCpnt->target, SCpnt->pid); - restore_flags(flags); - done(SCpnt); - return 0; - } - - /* Store pointer in OGM address bytes */ - outl((unsigned int)cpp, sh[j]->io_port + REG_OGM); - - /* Issue OGM interrupt */ - outb(CMD_OGM_INTR, sh[j]->io_port + REG_LCL_INTR); - - HD(j)->cp_stat[i] = IN_USE; - restore_flags(flags); - return 0; -} - -int u14_34f_abort(Scsi_Cmnd *SCarg) { - unsigned int i, j, flags; - - save_flags(flags); - cli(); - j = ((struct hostdata *) SCarg->host->hostdata)->board_number; - - if (SCarg->host_scribble == NULL) { - printk("%s: abort, target %d, pid %ld inactive.\n", - BN(j), SCarg->target, SCarg->pid); - restore_flags(flags); - return SCSI_ABORT_NOT_RUNNING; - } - - i = *(unsigned int *)SCarg->host_scribble; - printk("%s: abort, mbox %d, target %d, pid %ld.\n", - BN(j), i, SCarg->target, SCarg->pid); - - if (i >= sh[j]->can_queue) - panic("%s: abort, invalid SCarg->host_scribble.\n", BN(j)); - - if (wait_on_busy(sh[j]->io_port)) { - printk("%s: abort, timeout error.\n", BN(j)); - restore_flags(flags); - return SCSI_ABORT_ERROR; - } - - if (HD(j)->cp_stat[i] == FREE) { - printk("%s: abort, mbox %d is free.\n", BN(j), i); - restore_flags(flags); - return SCSI_ABORT_NOT_RUNNING; - } - - if (HD(j)->cp_stat[i] == IN_USE) { - printk("%s: abort, mbox %d is in use.\n", BN(j), i); - - if (SCarg != HD(j)->cp[i].SCpnt) - panic("%s: abort, mbox %d, SCarg %p, cp SCpnt %p.\n", - BN(j), i, SCarg, HD(j)->cp[i].SCpnt); - - restore_flags(flags); - return SCSI_ABORT_SNOOZE; - } - - if (HD(j)->cp_stat[i] == IN_RESET) { - printk("%s: abort, mbox %d is in reset.\n", BN(j), i); - restore_flags(flags); - return SCSI_ABORT_ERROR; - } - - if (HD(j)->cp_stat[i] == LOCKED) { - printk("%s: abort, mbox %d is locked.\n", BN(j), i); - restore_flags(flags); - return SCSI_ABORT_NOT_RUNNING; - } - restore_flags(flags); - panic("%s: abort, mbox %d, invalid cp_stat.\n", BN(j), i); -} - -int u14_34f_reset(Scsi_Cmnd * SCarg) { - unsigned int i, j, flags, time, k, limit = 0; - int arg_done = FALSE; - Scsi_Cmnd *SCpnt; - - save_flags(flags); - cli(); - j = ((struct hostdata *) SCarg->host->hostdata)->board_number; - printk("%s: reset, enter, target %d, pid %ld.\n", - BN(j), SCarg->target, SCarg->pid); - - if (SCarg->host_scribble == NULL) - printk("%s: reset, pid %ld inactive.\n", BN(j), SCarg->pid); - - if (HD(j)->in_reset) { - printk("%s: reset, exit, already in reset.\n", BN(j)); - restore_flags(flags); - return SCSI_RESET_ERROR; - } - - if (wait_on_busy(sh[j]->io_port)) { - printk("%s: reset, exit, timeout error.\n", BN(j)); - restore_flags(flags); - return SCSI_RESET_ERROR; - } - - for (k = 0; k < MAX_TARGET; k++) HD(j)->target_reset[k] = TRUE; - - for (k = 0; k < MAX_TARGET; k++) HD(j)->target_time_out[k] = 0; - - for (i = 0; i < sh[j]->can_queue; i++) { - - if (HD(j)->cp_stat[i] == FREE) continue; - - if (HD(j)->cp_stat[i] == LOCKED) { - HD(j)->cp_stat[i] = FREE; - printk("%s: reset, locked mbox %d forced free.\n", BN(j), i); - continue; - } - - SCpnt = HD(j)->cp[i].SCpnt; - HD(j)->cp_stat[i] = IN_RESET; - printk("%s: reset, mbox %d in reset, pid %ld.\n", - BN(j), i, SCpnt->pid); - - if (SCpnt == NULL) - panic("%s: reset, mbox %d, SCpnt == NULL.\n", BN(j), i); - - if (SCpnt->host_scribble == NULL) - panic("%s: reset, mbox %d, garbled SCpnt.\n", BN(j), i); - - if (*(unsigned int *)SCpnt->host_scribble != i) - panic("%s: reset, mbox %d, index mismatch.\n", BN(j), i); - - if (SCpnt->scsi_done == NULL) - panic("%s: reset, mbox %d, SCpnt->scsi_done == NULL.\n", BN(j), i); - - if (SCpnt == SCarg) arg_done = TRUE; - } - - if (wait_on_busy(sh[j]->io_port)) { - printk("%s: reset, cannot reset, timeout error.\n", BN(j)); - restore_flags(flags); - return SCSI_RESET_ERROR; - } - - outb(CMD_RESET, sh[j]->io_port + REG_LCL_INTR); - printk("%s: reset, board reset done, enabling interrupts.\n", BN(j)); - -#if defined (DEBUG_RESET) - do_trace = TRUE; -#endif - - HD(j)->in_reset = TRUE; - sti(); - time = jiffies; - while (jiffies < (time + 100) && limit++ < 100000000); - cli(); - printk("%s: reset, interrupts disabled, loops %d.\n", BN(j), limit); - - for (i = 0; i < sh[j]->can_queue; i++) { - - /* Skip mailboxes already set free by interrupt */ - if (HD(j)->cp_stat[i] != IN_RESET) continue; - - SCpnt = HD(j)->cp[i].SCpnt; - SCpnt->result = DID_RESET << 16; - SCpnt->host_scribble = NULL; - - /* This mailbox is still waiting for its interrupt */ - HD(j)->cp_stat[i] = LOCKED; - - printk("%s, reset, mbox %d locked, DID_RESET, pid %ld done.\n", - BN(j), i, SCpnt->pid); - restore_flags(flags); - SCpnt->scsi_done(SCpnt); - cli(); - } - - HD(j)->in_reset = FALSE; - do_trace = FALSE; - restore_flags(flags); - - if (arg_done) { - printk("%s: reset, exit, success.\n", BN(j)); - return SCSI_RESET_SUCCESS; - } - else { - printk("%s: reset, exit, wakeup.\n", BN(j)); - return SCSI_RESET_PUNT; - } -} - -int u14_34f_biosparam(Disk * disk, kdev_t dev, int * dkinfo) { - unsigned int j = 0; - int size = disk->capacity; - - dkinfo[0] = HD(j)->heads; - dkinfo[1] = HD(j)->sectors; - dkinfo[2] = size / (HD(j)->heads * HD(j)->sectors); - return 0; -} - -static void u14_34f_interrupt_handler(int irq, struct pt_regs * regs) { - Scsi_Cmnd *SCpnt; - unsigned int i, j, k, flags, status, tstatus, loops, total_loops = 0; - struct mscp *spp; - - save_flags(flags); - cli(); - - if (irqlist[irq] == NO_IRQ) { - printk("%s, ihdlr, irq %d, unexpected interrupt.\n", driver_name, irq); - restore_flags(flags); - return; - } - - if (do_trace) printk("%s: ihdlr, enter, irq %d, calls %d.\n", - driver_name, irq, calls[irq]); - - /* Service all the boards configured on this irq */ - for (j = 0; sh[j] != NULL; j++) { - - if (sh[j]->irq != irq) continue; - - loops = 0; - - /* Loop until all interrupts for a board are serviced */ - while (inb(sh[j]->io_port + REG_SYS_INTR) & IRQ_ASSERTED) { - total_loops++; - loops++; - - if (do_trace) printk("%s: ihdlr, start service, count %d.\n", - BN(j), HD(j)->iocount); - - spp = (struct mscp *)inl(sh[j]->io_port + REG_ICM); - - /* Clear interrupt pending flag */ - outb(CMD_CLR_INTR, sh[j]->io_port + REG_SYS_INTR); - - i = spp - HD(j)->cp; - - if (i >= sh[j]->can_queue) - panic("%s: ihdlr, invalid mscp address.\n", BN(j)); - - if (HD(j)->cp_stat[i] == IGNORE) { - HD(j)->cp_stat[i] = FREE; - continue; - } - else if (HD(j)->cp_stat[i] == LOCKED) { - HD(j)->cp_stat[i] = FREE; - printk("%s: ihdlr, mbox %d unlocked, count %d.\n", - BN(j), i, HD(j)->iocount); - continue; - } - else if (HD(j)->cp_stat[i] == FREE) { - printk("%s: ihdlr, mbox %d is free, count %d.\n", - BN(j), i, HD(j)->iocount); - continue; - } - else if (HD(j)->cp_stat[i] == IN_RESET) - printk("%s: ihdlr, mbox %d is in reset.\n", BN(j), i); - else if (HD(j)->cp_stat[i] != IN_USE) - panic("%s: ihdlr, mbox %d, invalid cp_stat.\n", BN(j), i); - - HD(j)->cp_stat[i] = FREE; - SCpnt = spp->SCpnt; - - if (SCpnt == NULL) - panic("%s: ihdlr, mbox %d, SCpnt == NULL.\n", BN(j), i); - - if (SCpnt->host_scribble == NULL) - panic("%s: ihdlr, mbox %d, pid %ld, SCpnt %p garbled.\n", - BN(j), i, SCpnt->pid, SCpnt); - - if (*(unsigned int *)SCpnt->host_scribble != i) - panic("%s: ihdlr, mbox %d, pid %ld, index mismatch %d,"\ - " irq %d.\n", BN(j), i, SCpnt->pid, - *(unsigned int *)SCpnt->host_scribble, irq); - - tstatus = status_byte(spp->target_status); - - switch (spp->adapter_status) { - case ASOK: /* status OK */ - - /* Forces a reset if a disk drive keeps returning BUSY */ - if (tstatus == BUSY && SCpnt->device->type != TYPE_TAPE) - status = DID_ERROR << 16; - - /* If there was a bus reset, redo operation on each target */ - else if (tstatus != GOOD - && SCpnt->device->type == TYPE_DISK - && HD(j)->target_reset[SCpnt->target]) - status = DID_BUS_BUSY << 16; - - /* Works around a flaw in scsi.c */ - else if (tstatus == CHECK_CONDITION - && SCpnt->device->type == TYPE_DISK - && (SCpnt->sense_buffer[2] & 0xf) == RECOVERED_ERROR) - status = DID_BUS_BUSY << 16; - - else - status = DID_OK << 16; - - if (tstatus == GOOD) - HD(j)->target_reset[SCpnt->target] = FALSE; - - if (spp->target_status && SCpnt->device->type == TYPE_DISK) - printk("%s: ihdlr, target %d:%d, pid %ld, target_status "\ - "0x%x, sense key 0x%x.\n", BN(j), - SCpnt->target, SCpnt->lun, SCpnt->pid, - spp->target_status, SCpnt->sense_buffer[2]); - - HD(j)->target_time_out[SCpnt->target] = 0; - - break; - case ASST: /* Selection Time Out */ - - if (HD(j)->target_time_out[SCpnt->target] > 1) - status = DID_ERROR << 16; - else { - status = DID_TIME_OUT << 16; - HD(j)->target_time_out[SCpnt->target]++; - } - - break; - case 0x92: /* Data over/under-run */ - case 0x93: /* Unexpected bus free */ - case 0x94: /* Target bus phase sequence failure */ - case 0x96: /* Illegal SCSI command */ - case 0xa3: /* SCSI bus reset error */ - - if (SCpnt->device->type != TYPE_TAPE) - status = DID_BUS_BUSY << 16; - else - status = DID_ERROR << 16; - - for (k = 0; k < MAX_TARGET; k++) - HD(j)->target_reset[k] = TRUE; - - break; - case 0x01: /* Invalid command */ - case 0x02: /* Invalid parameters */ - case 0x03: /* Invalid data list */ - case 0x84: /* SCSI bus abort error */ - case 0x9b: /* Auto request sense error */ - case 0x9f: /* Unexpected command complete message error */ - case 0xff: /* Invalid parameter in the S/G list */ - default: - status = DID_ERROR << 16; - break; - } - - SCpnt->result = status | spp->target_status; - HD(j)->iocount++; - - if (loops > 1) HD(j)->multicount++; - -#if defined (DEBUG_INTERRUPT) - if (SCpnt->result || do_trace) -#else - if ((spp->adapter_status != ASOK && HD(j)->iocount > 1000) || - (spp->adapter_status != ASOK && - spp->adapter_status != ASST && HD(j)->iocount <= 1000) || - do_trace) -#endif - printk("%s: ihdlr, mbox %d, err 0x%x:%x,"\ - " target %d:%d, pid %ld, count %d.\n", - BN(j), i, spp->adapter_status, spp->target_status, - SCpnt->target, SCpnt->lun, SCpnt->pid, HD(j)->iocount); - - /* Set the command state to inactive */ - SCpnt->host_scribble = NULL; - - restore_flags(flags); - SCpnt->scsi_done(SCpnt); - cli(); - - } /* Multiple command loop */ - - } /* Boards loop */ - - calls[irq]++; - - if (total_loops == 0) - printk("%s: ihdlr, irq %d, no command completed, calls %d.\n", - driver_name, irq, calls[irq]); - - if (do_trace) printk("%s: ihdlr, exit, irq %d, calls %d.\n", - driver_name, irq, calls[irq]); - -#if defined (DEBUG_STATISTICS) - if ((calls[irq] % 100000) == 10000) - for (j = 0; sh[j] != NULL; j++) - printk("%s: ihdlr, calls %d, count %d, multi %d.\n", BN(j), - calls[(sh[j]->irq)], HD(j)->iocount, HD(j)->multicount); -#endif - - restore_flags(flags); - return; -} - -#if defined(MODULE) -Scsi_Host_Template driver_template = ULTRASTOR_14_34F; - -#include "scsi_module.c" -#endif diff --git a/i386/i386at/gpl/linux/scsi/u14-34f.h b/i386/i386at/gpl/linux/scsi/u14-34f.h deleted file mode 100644 index 2988824e..00000000 --- a/i386/i386at/gpl/linux/scsi/u14-34f.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * u14-34f.h - used by the low-level driver for UltraStor 14F/34F - */ -#ifndef _U14_34F_H -#define _U14_34F_H - -int u14_34f_detect(Scsi_Host_Template *); -int u14_34f_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); -int u14_34f_abort(Scsi_Cmnd *); -int u14_34f_reset(Scsi_Cmnd *); -int u14_34f_biosparam(Disk *, kdev_t, int *); - -#define U14_34F_VERSION "2.01.00" - -#define ULTRASTOR_14_34F { \ - NULL, /* Ptr for modules */ \ - NULL, /* usage count for modules */ \ - NULL, \ - NULL, \ - "UltraStor 14F/34F rev. " U14_34F_VERSION " ", \ - u14_34f_detect, \ - NULL, /* Release */ \ - NULL, \ - NULL, \ - u14_34f_queuecommand, \ - u14_34f_abort, \ - u14_34f_reset, \ - NULL, \ - u14_34f_biosparam, \ - 0, /* can_queue, reset by detect */ \ - 7, /* this_id, reset by detect */ \ - 0, /* sg_tablesize, reset by detect */ \ - 0, /* cmd_per_lun, reset by detect */ \ - 0, /* number of boards present */ \ - 1, /* unchecked isa dma, reset by detect */ \ - ENABLE_CLUSTERING \ - } -#endif diff --git a/i386/i386at/gpl/linux/scsi/ultrastor.c b/i386/i386at/gpl/linux/scsi/ultrastor.c deleted file mode 100644 index 23e94a91..00000000 --- a/i386/i386at/gpl/linux/scsi/ultrastor.c +++ /dev/null @@ -1,1160 +0,0 @@ -/* - * ultrastor.c Copyright (C) 1992 David B. Gentzel - * Low-level SCSI driver for UltraStor 14F, 24F, and 34F - * by David B. Gentzel, Whitfield Software Services, Carnegie, PA - * (gentzel@nova.enet.dec.com) - * scatter/gather added by Scott Taylor (n217cg@tamuts.tamu.edu) - * 24F and multiple command support by John F. Carr (jfc@athena.mit.edu) - * John's work modified by Caleb Epstein (cae@jpmorgan.com) and - * Eric Youngdale (ericy@cais.com). - * Thanks to UltraStor for providing the necessary documentation - */ - -/* - * TODO: - * 1. Find out why scatter/gather is limited to 16 requests per command. - * This is fixed, at least on the 24F, as of version 1.12 - CAE. - * 2. Look at command linking (mscp.command_link and - * mscp.command_link_id). (Does not work with many disks, - * and no performance increase. ERY). - * 3. Allow multiple adapters. - */ - -/* - * NOTES: - * The UltraStor 14F, 24F, and 34F are a family of intelligent, high - * performance SCSI-2 host adapters. They all support command queueing - * and scatter/gather I/O. Some of them can also emulate the standard - * WD1003 interface for use with OS's which don't support SCSI. Here - * is the scoop on the various models: - * 14F - ISA first-party DMA HA with floppy support and WD1003 emulation. - * 14N - ISA HA with floppy support. I think that this is a non-DMA - * HA. Nothing further known. - * 24F - EISA Bus Master HA with floppy support and WD1003 emulation. - * 34F - VL-Bus Bus Master HA with floppy support (no WD1003 emulation). - * - * The 14F, 24F, and 34F are supported by this driver. - * - * Places flagged with a triple question-mark are things which are either - * unfinished, questionable, or wrong. - */ - -/* Changes from version 1.11 alpha to 1.12 - * - * Increased the size of the scatter-gather list to 33 entries for - * the 24F adapter (it was 16). I don't have the specs for the 14F - * or the 34F, so they may support larger s-g lists as well. - * - * Caleb Epstein <cae@jpmorgan.com> - */ - -/* Changes from version 1.9 to 1.11 - * - * Patches to bring this driver up to speed with the default kernel - * driver which supports only the 14F and 34F adapters. This version - * should compile cleanly into 0.99.13, 0.99.12 and probably 0.99.11. - * - * Fixes from Eric Youngdale to fix a few possible race conditions and - * several problems with bit testing operations (insufficient - * parentheses). - * - * Removed the ultrastor_abort() and ultrastor_reset() functions - * (enclosed them in #if 0 / #endif). These functions, at least on - * the 24F, cause the SCSI bus to do odd things and generally lead to - * kernel panics and machine hangs. This is like the Adaptec code. - * - * Use check/snarf_region for 14f, 34f to avoid I/O space address conflicts. - */ - -/* Changes from version 1.8 to version 1.9 - * - * 0.99.11 patches (cae@jpmorgan.com) */ - -/* Changes from version 1.7 to version 1.8 - * - * Better error reporting. - */ - -/* Changes from version 1.6 to version 1.7 - * - * Removed CSIR command code. - * - * Better race condition avoidance (xchgb function added). - * - * Set ICM and OGM status to zero at probe (24F) - * - * reset sends soft reset to UltraStor adapter - * - * reset adapter if adapter interrupts with an invalid MSCP address - * - * handle aborted command interrupt (24F) - * - */ - -/* Changes from version 1.5 to version 1.6: - * - * Read MSCP address from ICM _before_ clearing the interrupt flag. - * This fixes a race condition. - */ - -/* Changes from version 1.4 to version 1.5: - * - * Abort now calls done when multiple commands are enabled. - * - * Clear busy when aborted command finishes, not when abort is called. - * - * More debugging messages for aborts. - */ - -/* Changes from version 1.3 to version 1.4: - * - * Enable automatic request of sense data on error (requires newer version - * of scsi.c to be useful). - * - * Fix PORT_OVERRIDE for 14F. - * - * Fix abort and reset to work properly (config.aborted wasn't cleared - * after it was tested, so after a command abort no further commands would - * work). - * - * Boot time test to enable SCSI bus reset (defaults to not allowing reset). - * - * Fix test for OGM busy -- the busy bit is in different places on the 24F. - * - * Release ICM slot by clearing first byte on 24F. - */ - -#ifdef MODULE -#include <linux/module.h> -#endif - -#include <linux/stddef.h> -#include <linux/string.h> -#include <linux/sched.h> -#include <linux/kernel.h> -#include <linux/ioport.h> -#include <linux/proc_fs.h> -#include <asm/io.h> -#include <asm/bitops.h> -#include <asm/system.h> -#include <asm/dma.h> - -#define ULTRASTOR_PRIVATE /* Get the private stuff from ultrastor.h */ -#include <linux/blk.h> -#include "scsi.h" -#include "hosts.h" -#include "ultrastor.h" -#include "sd.h" -#include<linux/stat.h> - -struct proc_dir_entry proc_scsi_ultrastor = { - PROC_SCSI_ULTRASTOR, 9, "ultrastor", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - -#define FALSE 0 -#define TRUE 1 - -#ifndef ULTRASTOR_DEBUG -#define ULTRASTOR_DEBUG (UD_ABORT|UD_CSIR|UD_RESET) -#endif - -#define VERSION "1.12" - -#define ARRAY_SIZE(arr) (sizeof (arr) / sizeof (arr)[0]) - -#define PACKED __attribute__((packed)) -#define ALIGNED(x) __attribute__((aligned(x))) - - -/* The 14F uses an array of 4-byte ints for its scatter/gather list. - The data can be unaligned, but need not be. It's easier to give - the list normal alignment since it doesn't need to fit into a - packed structure. */ - -typedef struct { - unsigned int address; - unsigned int num_bytes; -} ultrastor_sg_list; - - -/* MailBox SCSI Command Packet. Basic command structure for communicating - with controller. */ -struct mscp { - unsigned char opcode: 3; /* type of command */ - unsigned char xdir: 2; /* data transfer direction */ - unsigned char dcn: 1; /* disable disconnect */ - unsigned char ca: 1; /* use cache (if available) */ - unsigned char sg: 1; /* scatter/gather operation */ - unsigned char target_id: 3; /* target SCSI id */ - unsigned char ch_no: 2; /* SCSI channel (always 0 for 14f) */ - unsigned char lun: 3; /* logical unit number */ - unsigned int transfer_data PACKED; /* transfer data pointer */ - unsigned int transfer_data_length PACKED; /* length in bytes */ - unsigned int command_link PACKED; /* for linking command chains */ - unsigned char scsi_command_link_id; /* identifies command in chain */ - unsigned char number_of_sg_list; /* (if sg is set) 8 bytes per list */ - unsigned char length_of_sense_byte; - unsigned char length_of_scsi_cdbs; /* 6, 10, or 12 */ - unsigned char scsi_cdbs[12]; /* SCSI commands */ - unsigned char adapter_status; /* non-zero indicates HA error */ - unsigned char target_status; /* non-zero indicates target error */ - unsigned int sense_data PACKED; - /* The following fields are for software only. They are included in - the MSCP structure because they are associated with SCSI requests. */ - void (*done)(Scsi_Cmnd *); - Scsi_Cmnd *SCint; - ultrastor_sg_list sglist[ULTRASTOR_24F_MAX_SG]; /* use larger size for 24F */ -}; - - -/* Port addresses (relative to the base address) */ -#define U14F_PRODUCT_ID(port) ((port) + 0x4) -#define CONFIG(port) ((port) + 0x6) - -/* Port addresses relative to the doorbell base address. */ -#define LCL_DOORBELL_MASK(port) ((port) + 0x0) -#define LCL_DOORBELL_INTR(port) ((port) + 0x1) -#define SYS_DOORBELL_MASK(port) ((port) + 0x2) -#define SYS_DOORBELL_INTR(port) ((port) + 0x3) - - -/* Used to store configuration info read from config i/o registers. Most of - this is not used yet, but might as well save it. - - This structure also holds port addresses that are not at the same offset - on the 14F and 24F. - - This structure holds all data that must be duplicated to support multiple - adapters. */ - -static struct ultrastor_config -{ - unsigned short port_address; /* base address of card */ - unsigned short doorbell_address; /* base address of doorbell CSRs */ - unsigned short ogm_address; /* base address of OGM */ - unsigned short icm_address; /* base address of ICM */ - const void *bios_segment; - unsigned char interrupt: 4; - unsigned char dma_channel: 3; - unsigned char bios_drive_number: 1; - unsigned char heads; - unsigned char sectors; - unsigned char ha_scsi_id: 3; - unsigned char subversion: 4; - unsigned char revision; - /* The slot number is used to distinguish the 24F (slot != 0) from - the 14F and 34F (slot == 0). */ - unsigned char slot; - -#ifdef PRINT_U24F_VERSION - volatile int csir_done; -#endif - - /* A pool of MSCP structures for this adapter, and a bitmask of - busy structures. (If ULTRASTOR_14F_MAX_CMDS == 1, a 1 byte - busy flag is used instead.) */ - -#if ULTRASTOR_MAX_CMDS == 1 - unsigned char mscp_busy; -#else - unsigned short mscp_free; -#endif - volatile unsigned char aborted[ULTRASTOR_MAX_CMDS]; - struct mscp mscp[ULTRASTOR_MAX_CMDS]; -} config = {0}; - -/* Set this to 1 to reset the SCSI bus on error. */ -int ultrastor_bus_reset = 0; - - -/* Allowed BIOS base addresses (NULL indicates reserved) */ -static const void *const bios_segment_table[8] = { - NULL, (void *)0xC4000, (void *)0xC8000, (void *)0xCC000, - (void *)0xD0000, (void *)0xD4000, (void *)0xD8000, (void *)0xDC000, -}; - -/* Allowed IRQs for 14f */ -static const unsigned char interrupt_table_14f[4] = { 15, 14, 11, 10 }; - -/* Allowed DMA channels for 14f (0 indicates reserved) */ -static const unsigned char dma_channel_table_14f[4] = { 5, 6, 7, 0 }; - -/* Head/sector mappings allowed by 14f */ -static const struct { - unsigned char heads; - unsigned char sectors; -} mapping_table[4] = { { 16, 63 }, { 64, 32 }, { 64, 63 }, { 64, 32 } }; - -#ifndef PORT_OVERRIDE -/* ??? A probe of address 0x310 screws up NE2000 cards */ -static const unsigned short ultrastor_ports_14f[] = { - 0x330, 0x340, /*0x310,*/ 0x230, 0x240, 0x210, 0x130, 0x140, -}; -#endif - -static void ultrastor_interrupt(int, struct pt_regs *); -static inline void build_sg_list(struct mscp *, Scsi_Cmnd *SCpnt); - - -static inline int find_and_clear_bit_16(unsigned short *field) -{ - int rv; - unsigned long flags; - - save_flags(flags); - cli(); - if (*field == 0) panic("No free mscp"); - asm("xorl %0,%0\n0:\tbsfw %1,%w0\n\tbtr %0,%1\n\tjnc 0b" - : "=&r" (rv), "=m" (*field) : "1" (*field)); - restore_flags(flags); - return rv; -} - -/* This has been re-implemented with the help of Richard Earnshaw, - <rwe@pegasus.esprit.ec.org> and works with gcc-2.5.8 and gcc-2.6.0. - The instability noted by jfc below appears to be a bug in - gcc-2.5.x when compiling w/o optimization. --Caleb - - This asm is fragile: it doesn't work without the casts and it may - not work without optimization. Maybe I should add a swap builtin - to gcc. --jfc */ -static inline unsigned char xchgb(unsigned char reg, - volatile unsigned char *mem) -{ - __asm__ ("xchgb %0,%1" : "=q" (reg), "=m" (*mem) : "0" (reg)); - return reg; -} - -#if ULTRASTOR_DEBUG & (UD_COMMAND | UD_ABORT) - -static void log_ultrastor_abort(register struct ultrastor_config *config, - int command) -{ - static char fmt[80] = "abort %d (%x); MSCP free pool: %x;"; - register int i; - int flags; - save_flags(flags); - cli(); - - for (i = 0; i < ULTRASTOR_MAX_CMDS; i++) - { - fmt[20 + i*2] = ' '; - if (! (config->mscp_free & (1 << i))) - fmt[21 + i*2] = '0' + config->mscp[i].target_id; - else - fmt[21 + i*2] = '-'; - } - fmt[20 + ULTRASTOR_MAX_CMDS * 2] = '\n'; - fmt[21 + ULTRASTOR_MAX_CMDS * 2] = 0; - printk(fmt, command, &config->mscp[command], config->mscp_free); - restore_flags(flags); -} -#endif - -static int ultrastor_14f_detect(Scsi_Host_Template * tpnt) -{ - size_t i; - unsigned char in_byte, version_byte = 0; - struct config_1 { - unsigned char bios_segment: 3; - unsigned char removable_disks_as_fixed: 1; - unsigned char interrupt: 2; - unsigned char dma_channel: 2; - } config_1; - struct config_2 { - unsigned char ha_scsi_id: 3; - unsigned char mapping_mode: 2; - unsigned char bios_drive_number: 1; - unsigned char tfr_port: 2; - } config_2; - -#if (ULTRASTOR_DEBUG & UD_DETECT) - printk("US14F: detect: called\n"); -#endif - - /* If a 24F has already been configured, don't look for a 14F. */ - if (config.bios_segment) - return FALSE; - -#ifdef PORT_OVERRIDE - if(check_region(PORT_OVERRIDE, 0xc)) { - printk("Ultrastor I/O space already in use\n"); - return FALSE; - }; - config.port_address = PORT_OVERRIDE; -#else - for (i = 0; i < ARRAY_SIZE(ultrastor_ports_14f); i++) { - if(check_region(ultrastor_ports_14f[i], 0x0c)) continue; - config.port_address = ultrastor_ports_14f[i]; -#endif - -#if (ULTRASTOR_DEBUG & UD_DETECT) - printk("US14F: detect: testing port address %03X\n", config.port_address); -#endif - - in_byte = inb(U14F_PRODUCT_ID(config.port_address)); - if (in_byte != US14F_PRODUCT_ID_0) { -#if (ULTRASTOR_DEBUG & UD_DETECT) -# ifdef PORT_OVERRIDE - printk("US14F: detect: wrong product ID 0 - %02X\n", in_byte); -# else - printk("US14F: detect: no adapter at port %03X\n", config.port_address); -# endif -#endif -#ifdef PORT_OVERRIDE - return FALSE; -#else - continue; -#endif - } - in_byte = inb(U14F_PRODUCT_ID(config.port_address) + 1); - /* Only upper nibble is significant for Product ID 1 */ - if ((in_byte & 0xF0) != US14F_PRODUCT_ID_1) { -#if (ULTRASTOR_DEBUG & UD_DETECT) -# ifdef PORT_OVERRIDE - printk("US14F: detect: wrong product ID 1 - %02X\n", in_byte); -# else - printk("US14F: detect: no adapter at port %03X\n", config.port_address); -# endif -#endif -#ifdef PORT_OVERRIDE - return FALSE; -#else - continue; -#endif - } - version_byte = in_byte; -#ifndef PORT_OVERRIDE - break; - } - if (i == ARRAY_SIZE(ultrastor_ports_14f)) { -# if (ULTRASTOR_DEBUG & UD_DETECT) - printk("US14F: detect: no port address found!\n"); -# endif - return FALSE; - } -#endif - -#if (ULTRASTOR_DEBUG & UD_DETECT) - printk("US14F: detect: adapter found at port address %03X\n", - config.port_address); -#endif - - /* Set local doorbell mask to disallow bus reset unless - ultrastor_bus_reset is true. */ - outb(ultrastor_bus_reset ? 0xc2 : 0x82, LCL_DOORBELL_MASK(config.port_address)); - - /* All above tests passed, must be the right thing. Get some useful - info. */ - - request_region(config.port_address, 0x0c,"ultrastor"); - /* Register the I/O space that we use */ - - *(char *)&config_1 = inb(CONFIG(config.port_address + 0)); - *(char *)&config_2 = inb(CONFIG(config.port_address + 1)); - config.bios_segment = bios_segment_table[config_1.bios_segment]; - config.doorbell_address = config.port_address; - config.ogm_address = config.port_address + 0x8; - config.icm_address = config.port_address + 0xC; - config.interrupt = interrupt_table_14f[config_1.interrupt]; - config.ha_scsi_id = config_2.ha_scsi_id; - config.heads = mapping_table[config_2.mapping_mode].heads; - config.sectors = mapping_table[config_2.mapping_mode].sectors; - config.bios_drive_number = config_2.bios_drive_number; - config.subversion = (version_byte & 0x0F); - if (config.subversion == U34F) - config.dma_channel = 0; - else - config.dma_channel = dma_channel_table_14f[config_1.dma_channel]; - - if (!config.bios_segment) { -#if (ULTRASTOR_DEBUG & UD_DETECT) - printk("US14F: detect: not detected.\n"); -#endif - return FALSE; - } - - /* Final consistency check, verify previous info. */ - if (config.subversion != U34F) - if (!config.dma_channel || !(config_2.tfr_port & 0x2)) { -#if (ULTRASTOR_DEBUG & UD_DETECT) - printk("US14F: detect: consistency check failed\n"); -#endif - return FALSE; - } - - /* If we were TRULY paranoid, we could issue a host adapter inquiry - command here and verify the data returned. But frankly, I'm - exhausted! */ - - /* Finally! Now I'm satisfied... */ -#if (ULTRASTOR_DEBUG & UD_DETECT) - printk("US14F: detect: detect succeeded\n" - " Port address: %03X\n" - " BIOS segment: %05X\n" - " Interrupt: %u\n" - " DMA channel: %u\n" - " H/A SCSI ID: %u\n" - " Subversion: %u\n", - config.port_address, config.bios_segment, config.interrupt, - config.dma_channel, config.ha_scsi_id, config.subversion); -#endif - tpnt->this_id = config.ha_scsi_id; - tpnt->unchecked_isa_dma = (config.subversion != U34F); - -#if ULTRASTOR_MAX_CMDS > 1 - config.mscp_free = ~0; -#endif - - if (request_irq(config.interrupt, ultrastor_interrupt, 0, "Ultrastor")) { - printk("Unable to allocate IRQ%u for UltraStor controller.\n", - config.interrupt); - return FALSE; - } - if (config.dma_channel && request_dma(config.dma_channel,"Ultrastor")) { - printk("Unable to allocate DMA channel %u for UltraStor controller.\n", - config.dma_channel); - free_irq(config.interrupt); - return FALSE; - } - tpnt->sg_tablesize = ULTRASTOR_14F_MAX_SG; - printk("UltraStor driver version" VERSION ". Using %d SG lists.\n", - ULTRASTOR_14F_MAX_SG); - - return TRUE; -} - -static int ultrastor_24f_detect(Scsi_Host_Template * tpnt) -{ - register int i; - struct Scsi_Host * shpnt = NULL; - -#if (ULTRASTOR_DEBUG & UD_DETECT) - printk("US24F: detect"); -#endif - - /* probe each EISA slot at slot address C80 */ - for (i = 1; i < 15; i++) - { - unsigned char config_1, config_2; - unsigned short addr = (i << 12) | ULTRASTOR_24F_PORT; - - if (inb(addr) != US24F_PRODUCT_ID_0 && - inb(addr+1) != US24F_PRODUCT_ID_1 && - inb(addr+2) != US24F_PRODUCT_ID_2) - continue; - - config.revision = inb(addr+3); - config.slot = i; - if (! (inb(addr+4) & 1)) - { -#if (ULTRASTOR_DEBUG & UD_DETECT) - printk("U24F: found disabled card in slot %u\n", i); -#endif - continue; - } -#if (ULTRASTOR_DEBUG & UD_DETECT) - printk("U24F: found card in slot %u\n", i); -#endif - config_1 = inb(addr + 5); - config.bios_segment = bios_segment_table[config_1 & 7]; - switch(config_1 >> 4) - { - case 1: - config.interrupt = 15; - break; - case 2: - config.interrupt = 14; - break; - case 4: - config.interrupt = 11; - break; - case 8: - config.interrupt = 10; - break; - default: - printk("U24F: invalid IRQ\n"); - return FALSE; - } - if (request_irq(config.interrupt, ultrastor_interrupt, 0, "Ultrastor")) - { - printk("Unable to allocate IRQ%u for UltraStor controller.\n", - config.interrupt); - return FALSE; - } - /* BIOS addr set */ - /* base port set */ - config.port_address = addr; - config.doorbell_address = addr + 12; - config.ogm_address = addr + 0x17; - config.icm_address = addr + 0x1C; - config_2 = inb(addr + 7); - config.ha_scsi_id = config_2 & 7; - config.heads = mapping_table[(config_2 >> 3) & 3].heads; - config.sectors = mapping_table[(config_2 >> 3) & 3].sectors; -#if (ULTRASTOR_DEBUG & UD_DETECT) - printk("US24F: detect: detect succeeded\n" - " Port address: %03X\n" - " BIOS segment: %05X\n" - " Interrupt: %u\n" - " H/A SCSI ID: %u\n", - config.port_address, config.bios_segment, - config.interrupt, config.ha_scsi_id); -#endif - tpnt->this_id = config.ha_scsi_id; - tpnt->unchecked_isa_dma = 0; - tpnt->sg_tablesize = ULTRASTOR_24F_MAX_SG; - - shpnt = scsi_register(tpnt, 0); - shpnt->irq = config.interrupt; - shpnt->dma_channel = config.dma_channel; - shpnt->io_port = config.port_address; - -#if ULTRASTOR_MAX_CMDS > 1 - config.mscp_free = ~0; -#endif - /* Mark ICM and OGM free */ - outb(0, addr + 0x16); - outb(0, addr + 0x1B); - - /* Set local doorbell mask to disallow bus reset unless - ultrastor_bus_reset is true. */ - outb(ultrastor_bus_reset ? 0xc2 : 0x82, LCL_DOORBELL_MASK(addr+12)); - outb(0x02, SYS_DOORBELL_MASK(addr+12)); - printk("UltraStor driver version " VERSION ". Using %d SG lists.\n", - tpnt->sg_tablesize); - return TRUE; - } - return FALSE; -} - -int ultrastor_detect(Scsi_Host_Template * tpnt) -{ - tpnt->proc_dir = &proc_scsi_ultrastor; - return ultrastor_14f_detect(tpnt) || ultrastor_24f_detect(tpnt); -} - -const char *ultrastor_info(struct Scsi_Host * shpnt) -{ - static char buf[64]; - - if (config.slot) - sprintf(buf, "UltraStor 24F SCSI @ Slot %u IRQ%u\n", - config.slot, config.interrupt); - else if (config.subversion) - sprintf(buf, "UltraStor 34F SCSI @ Port %03X BIOS %05X IRQ%u\n", - config.port_address, (int)config.bios_segment, - config.interrupt); - else - sprintf(buf, "UltraStor 14F SCSI @ Port %03X BIOS %05X IRQ%u DMA%u\n", - config.port_address, (int)config.bios_segment, - config.interrupt, config.dma_channel); - return buf; -} - -static inline void build_sg_list(register struct mscp *mscp, Scsi_Cmnd *SCpnt) -{ - struct scatterlist *sl; - long transfer_length = 0; - int i, max; - - sl = (struct scatterlist *) SCpnt->request_buffer; - max = SCpnt->use_sg; - for (i = 0; i < max; i++) { - mscp->sglist[i].address = (unsigned int)sl[i].address; - mscp->sglist[i].num_bytes = sl[i].length; - transfer_length += sl[i].length; - } - mscp->number_of_sg_list = max; - mscp->transfer_data = (unsigned int)mscp->sglist; - /* ??? May not be necessary. Docs are unclear as to whether transfer - length field is ignored or whether it should be set to the total - number of bytes of the transfer. */ - mscp->transfer_data_length = transfer_length; -} - -int ultrastor_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) -{ - register struct mscp *my_mscp; -#if ULTRASTOR_MAX_CMDS > 1 - int mscp_index; -#endif - unsigned int status; - int flags; - - /* Next test is for debugging; "can't happen" */ - if ((config.mscp_free & ((1U << ULTRASTOR_MAX_CMDS) - 1)) == 0) - panic("ultrastor_queuecommand: no free MSCP\n"); - mscp_index = find_and_clear_bit_16(&config.mscp_free); - - /* Has the command been aborted? */ - if (xchgb(0xff, &config.aborted[mscp_index]) != 0) - { - status = DID_ABORT << 16; - goto aborted; - } - - my_mscp = &config.mscp[mscp_index]; - -#if 1 - /* This way is faster. */ - *(unsigned char *)my_mscp = OP_SCSI | (DTD_SCSI << 3); -#else - my_mscp->opcode = OP_SCSI; - my_mscp->xdir = DTD_SCSI; - my_mscp->dcn = FALSE; -#endif - /* Tape drives don't work properly if the cache is used. The SCSI - READ command for a tape doesn't have a block offset, and the adapter - incorrectly assumes that all reads from the tape read the same - blocks. Results will depend on read buffer size and other disk - activity. - - ??? Which other device types should never use the cache? */ - my_mscp->ca = SCpnt->device->type != TYPE_TAPE; - my_mscp->target_id = SCpnt->target; - my_mscp->ch_no = 0; - my_mscp->lun = SCpnt->lun; - if (SCpnt->use_sg) { - /* Set scatter/gather flag in SCSI command packet */ - my_mscp->sg = TRUE; - build_sg_list(my_mscp, SCpnt); - } else { - /* Unset scatter/gather flag in SCSI command packet */ - my_mscp->sg = FALSE; - my_mscp->transfer_data = (unsigned int)SCpnt->request_buffer; - my_mscp->transfer_data_length = SCpnt->request_bufflen; - } - my_mscp->command_link = 0; /*???*/ - my_mscp->scsi_command_link_id = 0; /*???*/ - my_mscp->length_of_sense_byte = sizeof SCpnt->sense_buffer; - my_mscp->length_of_scsi_cdbs = SCpnt->cmd_len; - memcpy(my_mscp->scsi_cdbs, SCpnt->cmnd, my_mscp->length_of_scsi_cdbs); - my_mscp->adapter_status = 0; - my_mscp->target_status = 0; - my_mscp->sense_data = (unsigned int)&SCpnt->sense_buffer; - my_mscp->done = done; - my_mscp->SCint = SCpnt; - SCpnt->host_scribble = (unsigned char *)my_mscp; - - /* Find free OGM slot. On 24F, look for OGM status byte == 0. - On 14F and 34F, wait for local interrupt pending flag to clear. */ - - retry: - if (config.slot) - while (inb(config.ogm_address - 1) != 0 && - config.aborted[mscp_index] == 0xff) barrier(); - - /* else??? */ - - while ((inb(LCL_DOORBELL_INTR(config.doorbell_address)) & - (config.slot ? 2 : 1)) - && config.aborted[mscp_index] == 0xff) barrier(); - - /* To avoid race conditions, make the code to write to the adapter - atomic. This simplifies the abort code. */ - - save_flags(flags); - cli(); - - if (inb(LCL_DOORBELL_INTR(config.doorbell_address)) & - (config.slot ? 2 : 1)) - { - restore_flags(flags); - goto retry; - } - - status = xchgb(0, &config.aborted[mscp_index]); - if (status != 0xff) { - restore_flags(flags); - -#if ULTRASTOR_DEBUG & (UD_COMMAND | UD_ABORT) - printk("USx4F: queuecommand: aborted\n"); -#if ULTRASTOR_MAX_CMDS > 1 - log_ultrastor_abort(&config, mscp_index); -#endif -#endif - status <<= 16; - - aborted: - set_bit(mscp_index, &config.mscp_free); - /* If the driver queues commands, call the done proc here. Otherwise - return an error. */ -#if ULTRASTOR_MAX_CMDS > 1 - SCpnt->result = status; - done(SCpnt); - return 0; -#else - return status; -#endif - } - - /* Store pointer in OGM address bytes */ - outl((unsigned int)my_mscp, config.ogm_address); - - /* Issue OGM interrupt */ - if (config.slot) { - /* Write OGM command register on 24F */ - outb(1, config.ogm_address - 1); - outb(0x2, LCL_DOORBELL_INTR(config.doorbell_address)); - } else { - outb(0x1, LCL_DOORBELL_INTR(config.doorbell_address)); - } - - restore_flags(flags); - -#if (ULTRASTOR_DEBUG & UD_COMMAND) - printk("USx4F: queuecommand: returning\n"); -#endif - - return 0; -} - -/* This code must deal with 2 cases: - - 1. The command has not been written to the OGM. In this case, set - the abort flag and return. - - 2. The command has been written to the OGM and is stuck somewhere in - the adapter. - - 2a. On a 24F, ask the adapter to abort the command. It will interrupt - when it does. - - 2b. Call the command's done procedure. - - */ - -int ultrastor_abort(Scsi_Cmnd *SCpnt) -{ -#if ULTRASTOR_DEBUG & UD_ABORT - char out[108]; - unsigned char icm_status = 0, ogm_status = 0; - unsigned int icm_addr = 0, ogm_addr = 0; -#endif - unsigned int mscp_index; - unsigned char old_aborted; - void (*done)(Scsi_Cmnd *); - - if(config.slot) - return SCSI_ABORT_SNOOZE; /* Do not attempt an abort for the 24f */ - - /* Simple consistency checking */ - if(!SCpnt->host_scribble) - return SCSI_ABORT_NOT_RUNNING; - - mscp_index = ((struct mscp *)SCpnt->host_scribble) - config.mscp; - if (mscp_index >= ULTRASTOR_MAX_CMDS) - panic("Ux4F aborting invalid MSCP"); - -#if ULTRASTOR_DEBUG & UD_ABORT - if (config.slot) - { - int port0 = (config.slot << 12) | 0xc80; - int i; - int flags; - save_flags(flags); - cli(); - strcpy(out, "OGM %d:%x ICM %d:%x ports: "); - for (i = 0; i < 16; i++) - { - unsigned char p = inb(port0 + i); - out[28 + i * 3] = "0123456789abcdef"[p >> 4]; - out[29 + i * 3] = "0123456789abcdef"[p & 15]; - out[30 + i * 3] = ' '; - } - out[28 + i * 3] = '\n'; - out[29 + i * 3] = 0; - ogm_status = inb(port0 + 22); - ogm_addr = inl(port0 + 23); - icm_status = inb(port0 + 27); - icm_addr = inl(port0 + 28); - restore_flags(flags); - } - - /* First check to see if an interrupt is pending. I suspect the SiS - chipset loses interrupts. (I also suspect is mangles data, but - one bug at a time... */ - if (config.slot ? inb(config.icm_address - 1) == 2 : - (inb(SYS_DOORBELL_INTR(config.doorbell_address)) & 1)) - { - int flags; - save_flags(flags); - printk("Ux4F: abort while completed command pending\n"); - restore_flags(flags); - cli(); - ultrastor_interrupt(0, NULL); - restore_flags(flags); - return SCSI_ABORT_SUCCESS; /* FIXME - is this correct? -ERY */ - } -#endif - - old_aborted = xchgb(DID_ABORT, &config.aborted[mscp_index]); - - /* aborted == 0xff is the signal that queuecommand has not yet sent - the command. It will notice the new abort flag and fail. */ - if (old_aborted == 0xff) - return SCSI_ABORT_SUCCESS; - - /* On 24F, send an abort MSCP request. The adapter will interrupt - and the interrupt handler will call done. */ - if (config.slot && inb(config.ogm_address - 1) == 0) - { - int flags; - - save_flags(flags); - cli(); - outl((int)&config.mscp[mscp_index], config.ogm_address); - inb(0xc80); /* delay */ - outb(0x80, config.ogm_address - 1); - outb(0x2, LCL_DOORBELL_INTR(config.doorbell_address)); -#if ULTRASTOR_DEBUG & UD_ABORT - log_ultrastor_abort(&config, mscp_index); - printk(out, ogm_status, ogm_addr, icm_status, icm_addr); -#endif - restore_flags(flags); - return SCSI_ABORT_PENDING; - } - -#if ULTRASTOR_DEBUG & UD_ABORT - log_ultrastor_abort(&config, mscp_index); -#endif - - /* Can't request a graceful abort. Either this is not a 24F or - the OGM is busy. Don't free the command -- the adapter might - still be using it. Setting SCint = 0 causes the interrupt - handler to ignore the command. */ - - /* FIXME - devices that implement soft resets will still be running - the command after a bus reset. We would probably rather leave - the command in the queue. The upper level code will automatically - leave the command in the active state instead of requeueing it. ERY */ - -#if ULTRASTOR_DEBUG & UD_ABORT - if (config.mscp[mscp_index].SCint != SCpnt) - printk("abort: command mismatch, %p != %p\n", - config.mscp[mscp_index].SCint, SCpnt); -#endif - if (config.mscp[mscp_index].SCint == 0) - return SCSI_ABORT_NOT_RUNNING; - - if (config.mscp[mscp_index].SCint != SCpnt) panic("Bad abort"); - config.mscp[mscp_index].SCint = 0; - done = config.mscp[mscp_index].done; - config.mscp[mscp_index].done = 0; - SCpnt->result = DID_ABORT << 16; - /* I worry about reentrancy in scsi.c */ - done(SCpnt); - - /* Need to set a timeout here in case command never completes. */ - return SCSI_ABORT_SUCCESS; -} - -int ultrastor_reset(Scsi_Cmnd * SCpnt) -{ - int flags; - register int i; -#if (ULTRASTOR_DEBUG & UD_RESET) - printk("US14F: reset: called\n"); -#endif - - if(config.slot) - return SCSI_RESET_PUNT; /* Do not attempt a reset for the 24f */ - - save_flags(flags); - cli(); - - /* Reset the adapter and SCSI bus. The SCSI bus reset can be - inhibited by clearing ultrastor_bus_reset before probe. */ - outb(0xc0, LCL_DOORBELL_INTR(config.doorbell_address)); - if (config.slot) - { - outb(0, config.ogm_address - 1); - outb(0, config.icm_address - 1); - } - -#if ULTRASTOR_MAX_CMDS == 1 - if (config.mscp_busy && config.mscp->done && config.mscp->SCint) - { - config.mscp->SCint->result = DID_RESET << 16; - config.mscp->done(config.mscp->SCint); - } - config.mscp->SCint = 0; -#else - for (i = 0; i < ULTRASTOR_MAX_CMDS; i++) - { - if (! (config.mscp_free & (1 << i)) && - config.mscp[i].done && config.mscp[i].SCint) - { - config.mscp[i].SCint->result = DID_RESET << 16; - config.mscp[i].done(config.mscp[i].SCint); - config.mscp[i].done = 0; - } - config.mscp[i].SCint = 0; - } -#endif - - /* FIXME - if the device implements soft resets, then the command - will still be running. ERY */ - - memset((unsigned char *)config.aborted, 0, sizeof config.aborted); -#if ULTRASTOR_MAX_CMDS == 1 - config.mscp_busy = 0; -#else - config.mscp_free = ~0; -#endif - - restore_flags(flags); - return SCSI_RESET_SUCCESS; - -} - -int ultrastor_biosparam(Disk * disk, kdev_t dev, int * dkinfo) -{ - int size = disk->capacity; - unsigned int s = config.heads * config.sectors; - - dkinfo[0] = config.heads; - dkinfo[1] = config.sectors; - dkinfo[2] = size / s; /* Ignore partial cylinders */ -#if 0 - if (dkinfo[2] > 1024) - dkinfo[2] = 1024; -#endif - return 0; -} - -static void ultrastor_interrupt(int irq, struct pt_regs *regs) -{ - unsigned int status; -#if ULTRASTOR_MAX_CMDS > 1 - unsigned int mscp_index; -#endif - register struct mscp *mscp; - void (*done)(Scsi_Cmnd *); - Scsi_Cmnd *SCtmp; - -#if ULTRASTOR_MAX_CMDS == 1 - mscp = &config.mscp[0]; -#else - mscp = (struct mscp *)inl(config.icm_address); - mscp_index = mscp - config.mscp; - if (mscp_index >= ULTRASTOR_MAX_CMDS) { - printk("Ux4F interrupt: bad MSCP address %x\n", (unsigned int) mscp); - /* A command has been lost. Reset and report an error - for all commands. */ - ultrastor_reset(NULL); - return; - } -#endif - - /* Clean ICM slot (set ICMINT bit to 0) */ - if (config.slot) { - unsigned char icm_status = inb(config.icm_address - 1); -#if ULTRASTOR_DEBUG & (UD_INTERRUPT|UD_ERROR|UD_ABORT) - if (icm_status != 1 && icm_status != 2) - printk("US24F: ICM status %x for MSCP %d (%x)\n", icm_status, - mscp_index, (unsigned int) mscp); -#endif - /* The manual says clear interrupt then write 0 to ICM status. - This seems backwards, but I'll do it anyway. --jfc */ - outb(2, SYS_DOORBELL_INTR(config.doorbell_address)); - outb(0, config.icm_address - 1); - if (icm_status == 4) { - printk("UltraStor abort command failed\n"); - return; - } - if (icm_status == 3) { - void (*done)(Scsi_Cmnd *) = mscp->done; - if (done) { - mscp->done = 0; - mscp->SCint->result = DID_ABORT << 16; - done(mscp->SCint); - } - return; - } - } else { - outb(1, SYS_DOORBELL_INTR(config.doorbell_address)); - } - - SCtmp = mscp->SCint; - mscp->SCint = NULL; - - if (SCtmp == 0) - { -#if ULTRASTOR_DEBUG & (UD_ABORT|UD_INTERRUPT) - printk("MSCP %d (%x): no command\n", mscp_index, (unsigned int) mscp); -#endif -#if ULTRASTOR_MAX_CMDS == 1 - config.mscp_busy = FALSE; -#else - set_bit(mscp_index, &config.mscp_free); -#endif - config.aborted[mscp_index] = 0; - return; - } - - /* Save done locally and zero before calling. This is needed as - once we call done, we may get another command queued before this - interrupt service routine can return. */ - done = mscp->done; - mscp->done = 0; - - /* Let the higher levels know that we're done */ - switch (mscp->adapter_status) - { - case 0: - status = DID_OK << 16; - break; - case 0x01: /* invalid command */ - case 0x02: /* invalid parameters */ - case 0x03: /* invalid data list */ - default: - status = DID_ERROR << 16; - break; - case 0x84: /* SCSI bus abort */ - status = DID_ABORT << 16; - break; - case 0x91: - status = DID_TIME_OUT << 16; - break; - } - - SCtmp->result = status | mscp->target_status; - - SCtmp->host_scribble = 0; - - /* Free up mscp block for next command */ -#if ULTRASTOR_MAX_CMDS == 1 - config.mscp_busy = FALSE; -#else - set_bit(mscp_index, &config.mscp_free); -#endif - -#if ULTRASTOR_DEBUG & (UD_ABORT|UD_INTERRUPT) - if (config.aborted[mscp_index]) - printk("Ux4 interrupt: MSCP %d (%x) aborted = %d\n", - mscp_index, (unsigned int) mscp, config.aborted[mscp_index]); -#endif - config.aborted[mscp_index] = 0; - - if (done) - done(SCtmp); - else - printk("US14F: interrupt: unexpected interrupt\n"); - - if (config.slot ? inb(config.icm_address - 1) : (inb(SYS_DOORBELL_INTR(config.doorbell_address)) & 1)) - printk("Ux4F: multiple commands completed\n"); - -#if (ULTRASTOR_DEBUG & UD_INTERRUPT) - printk("USx4F: interrupt: returning\n"); -#endif -} - -#ifdef MODULE -/* Eventually this will go into an include file, but this will be later */ -Scsi_Host_Template driver_template = ULTRASTOR_14F; - -#include "scsi_module.c" -#endif diff --git a/i386/i386at/gpl/linux/scsi/ultrastor.h b/i386/i386at/gpl/linux/scsi/ultrastor.h deleted file mode 100644 index 10cf63f2..00000000 --- a/i386/i386at/gpl/linux/scsi/ultrastor.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * ultrastor.c (C) 1991 David B. Gentzel - * Low-level scsi driver for UltraStor 14F - * by David B. Gentzel, Whitfield Software Services, Carnegie, PA - * (gentzel@nova.enet.dec.com) - * scatter/gather added by Scott Taylor (n217cg@tamuts.tamu.edu) - * 24F support by John F. Carr (jfc@athena.mit.edu) - * John's work modified by Caleb Epstein (cae@jpmorgan.com) and - * Eric Youngdale (eric@tantalus.nrl.navy.mil). - * Thanks to UltraStor for providing the necessary documentation - */ - -#ifndef _ULTRASTOR_H -#define _ULTRASTOR_H -#include <linux/kdev_t.h> - -int ultrastor_detect(Scsi_Host_Template *); -const char *ultrastor_info(struct Scsi_Host * shpnt); -int ultrastor_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); -int ultrastor_abort(Scsi_Cmnd *); -int ultrastor_reset(Scsi_Cmnd *); -int ultrastor_biosparam(Disk *, kdev_t, int *); - - -#define ULTRASTOR_14F_MAX_SG 16 -#define ULTRASTOR_24F_MAX_SG 33 - -#define ULTRASTOR_MAX_CMDS_PER_LUN 5 -#define ULTRASTOR_MAX_CMDS 16 - -#define ULTRASTOR_24F_PORT 0xC80 - - -#define ULTRASTOR_14F { NULL, NULL, /* Ptr for modules*/ \ - NULL, \ - NULL, \ - "UltraStor 14F/24F/34F", \ - ultrastor_detect, \ - NULL, /* Release */ \ - ultrastor_info, \ - 0, \ - ultrastor_queuecommand, \ - ultrastor_abort, \ - ultrastor_reset, \ - 0, \ - ultrastor_biosparam, \ - ULTRASTOR_MAX_CMDS, \ - 0, \ - ULTRASTOR_14F_MAX_SG, \ - ULTRASTOR_MAX_CMDS_PER_LUN, \ - 0, \ - 1, \ - ENABLE_CLUSTERING } - - -#ifdef ULTRASTOR_PRIVATE - -#define UD_ABORT 0x0001 -#define UD_COMMAND 0x0002 -#define UD_DETECT 0x0004 -#define UD_INTERRUPT 0x0008 -#define UD_RESET 0x0010 -#define UD_MULTI_CMD 0x0020 -#define UD_CSIR 0x0040 -#define UD_ERROR 0x0080 - -/* #define PORT_OVERRIDE 0x330 */ - -/* Values for the PRODUCT_ID ports for the 14F */ -#define US14F_PRODUCT_ID_0 0x56 -#define US14F_PRODUCT_ID_1 0x40 /* NOTE: Only upper nibble is used */ - -#define US24F_PRODUCT_ID_0 0x56 -#define US24F_PRODUCT_ID_1 0x63 -#define US24F_PRODUCT_ID_2 0x02 - -/* Subversion values */ -#define U14F 0 -#define U34F 1 - -/* MSCP field values */ - -/* Opcode */ -#define OP_HOST_ADAPTER 0x1 -#define OP_SCSI 0x2 -#define OP_RESET 0x4 - -/* Date Transfer Direction */ -#define DTD_SCSI 0x0 -#define DTD_IN 0x1 -#define DTD_OUT 0x2 -#define DTD_NONE 0x3 - -/* Host Adapter command subcodes */ -#define HA_CMD_INQUIRY 0x1 -#define HA_CMD_SELF_DIAG 0x2 -#define HA_CMD_READ_BUFF 0x3 -#define HA_CMD_WRITE_BUFF 0x4 - -#endif - -#endif diff --git a/i386/i386at/gpl/linux/scsi/wd7000.c b/i386/i386at/gpl/linux/scsi/wd7000.c deleted file mode 100644 index 61d92b10..00000000 --- a/i386/i386at/gpl/linux/scsi/wd7000.c +++ /dev/null @@ -1,1237 +0,0 @@ -/* $Id: wd7000.c,v 1.1.1.1 1997/02/25 21:27:53 thomas Exp $ - * linux/drivers/scsi/wd7000.c - * - * Copyright (C) 1992 Thomas Wuensche - * closely related to the aha1542 driver from Tommy Thorn - * ( as close as different hardware allows on a lowlevel-driver :-) ) - * - * Revised (and renamed) by John Boyd <boyd@cis.ohio-state.edu> to - * accommodate Eric Youngdale's modifications to scsi.c. Nov 1992. - * - * Additional changes to support scatter/gather. Dec. 1992. tw/jb - * - * No longer tries to reset SCSI bus at boot (it wasn't working anyway). - * Rewritten to support multiple host adapters. - * Miscellaneous cleanup. - * So far, still doesn't do reset or abort correctly, since I have no idea - * how to do them with this board (8^(. Jan 1994 jb - * - * This driver now supports both of the two standard configurations (per - * the 3.36 Owner's Manual, my latest reference) by the same method as - * before; namely, by looking for a BIOS signature. Thus, the location of - * the BIOS signature determines the board configuration. Until I have - * time to do something more flexible, users should stick to one of the - * following: - * - * Standard configuration for single-adapter systems: - * - BIOS at CE00h - * - I/O base address 350h - * - IRQ level 15 - * - DMA channel 6 - * Standard configuration for a second adapter in a system: - * - BIOS at C800h - * - I/O base address 330h - * - IRQ level 11 - * - DMA channel 5 - * - * Anyone who can recompile the kernel is welcome to add others as need - * arises, but unpredictable results may occur if there are conflicts. - * In any event, if there are multiple adapters in a system, they MUST - * use different I/O bases, IRQ levels, and DMA channels, since they will be - * indistinguishable (and in direct conflict) otherwise. - * - * As a point of information, the NO_OP command toggles the CMD_RDY bit - * of the status port, and this fact could be used as a test for the I/O - * base address (or more generally, board detection). There is an interrupt - * status port, so IRQ probing could also be done. I suppose the full - * DMA diagnostic could be used to detect the DMA channel being used. I - * haven't done any of this, though, because I think there's too much of - * a chance that such explorations could be destructive, if some other - * board's resources are used inadvertently. So, call me a wimp, but I - * don't want to try it. The only kind of exploration I trust is memory - * exploration, since it's more certain that reading memory won't be - * destructive. - * - * More to my liking would be a LILO boot command line specification, such - * as is used by the aha152x driver (and possibly others). I'll look into - * it, as I have time... - * - * I get mail occasionally from people who either are using or are - * considering using a WD7000 with Linux. There is a variety of - * nomenclature describing WD7000's. To the best of my knowledge, the - * following is a brief summary (from an old WD doc - I don't work for - * them or anything like that): - * - * WD7000-FASST2: This is a WD7000 board with the real-mode SST ROM BIOS - * installed. Last I heard, the BIOS was actually done by Columbia - * Data Products. The BIOS is only used by this driver (and thus - * by Linux) to identify the board; none of it can be executed under - * Linux. - * - * WD7000-ASC: This is the original adapter board, with or without BIOS. - * The board uses a WD33C93 or WD33C93A SBIC, which in turn is - * controlled by an onboard Z80 processor. The board interface - * visible to the host CPU is defined effectively by the Z80's - * firmware, and it is this firmware's revision level that is - * determined and reported by this driver. (The version of the - * on-board BIOS is of no interest whatsoever.) The host CPU has - * no access to the SBIC; hence the fact that it is a WD33C93 is - * also of no interest to this driver. - * - * WD7000-AX: - * WD7000-MX: - * WD7000-EX: These are newer versions of the WD7000-ASC. The -ASC is - * largely built from discrete components; these boards use more - * integration. The -AX is an ISA bus board (like the -ASC), - * the -MX is an MCA (i.e., PS/2) bus board), and the -EX is an - * EISA bus board. - * - * At the time of my documentation, the -?X boards were "future" products, - * and were not yet available. However, I vaguely recall that Thomas - * Wuensche had an -AX, so I believe at least it is supported by this - * driver. I have no personal knowledge of either -MX or -EX boards. - * - * P.S. Just recently, I've discovered (directly from WD and Future - * Domain) that all but the WD7000-EX have been out of production for - * two years now. FD has production rights to the 7000-EX, and are - * producing it under a new name, and with a new BIOS. If anyone has - * one of the FD boards, it would be nice to come up with a signature - * for it. - * J.B. Jan 1994. - */ - -#ifdef MODULE -#include <linux/module.h> -#endif - -#include <stdarg.h> -#include <linux/kernel.h> -#include <linux/head.h> -#include <linux/types.h> -#include <linux/string.h> -#include <linux/sched.h> -#include <linux/malloc.h> -#include <asm/system.h> -#include <asm/dma.h> -#include <asm/io.h> -#include <linux/ioport.h> -#include <linux/proc_fs.h> -#include <linux/blk.h> -#include "scsi.h" -#include "hosts.h" -#include "sd.h" - -#define ANY2SCSI_INLINE /* undef this to use old macros */ -#undef DEBUG - -#include "wd7000.h" - -#include<linux/stat.h> - -struct proc_dir_entry proc_scsi_wd7000 = { - PROC_SCSI_7000FASST, 6, "wd7000", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - - -/* - * Mailbox structure sizes. - * I prefer to keep the number of ICMBs much larger than the number of - * OGMBs. OGMBs are used very quickly by the driver to start one or - * more commands, while ICMBs are used by the host adapter per command. - */ -#define OGMB_CNT 16 -#define ICMB_CNT 32 - -/* - * Scb's are shared by all active adapters. So, if they all become busy, - * callers may be made to wait in alloc_scbs for them to free. That can - * be avoided by setting MAX_SCBS to NUM_CONFIG * WD7000_Q. If you'd - * rather conserve memory, use a smaller number (> 0, of course) - things - * will should still work OK. - */ -#define MAX_SCBS 32 - -/* - * WD7000-specific mailbox structure - * - */ -typedef volatile struct mailbox{ - unchar status; - unchar scbptr[3]; /* SCSI-style - MSB first (big endian) */ -} Mailbox; - -/* - * This structure should contain all per-adapter global data. I.e., any - * new global per-adapter data should put in here. - * - */ -typedef struct adapter { - struct Scsi_Host *sh; /* Pointer to Scsi_Host structure */ - int iobase; /* This adapter's I/O base address */ - int irq; /* This adapter's IRQ level */ - int dma; /* This adapter's DMA channel */ - struct { /* This adapter's mailboxes */ - Mailbox ogmb[OGMB_CNT]; /* Outgoing mailboxes */ - Mailbox icmb[ICMB_CNT]; /* Incoming mailboxes */ - } mb; - int next_ogmb; /* to reduce contention at mailboxes */ - unchar control; /* shadows CONTROL port value */ - unchar rev1, rev2; /* filled in by wd7000_revision */ -} Adapter; - -/* - * The following is set up by wd7000_detect, and used thereafter by - * wd7000_intr_handle to map the irq level to the corresponding Adapter. - * Note that if SA_INTERRUPT is not used, wd7000_intr_handle must be - * changed to pick up the IRQ level correctly. - */ -Adapter *irq2host[16] = {NULL}; /* Possible IRQs are 0-15 */ - -/* - * Standard Adapter Configurations - used by wd7000_detect - */ -typedef struct { - const void *bios; /* (linear) base address for ROM BIOS */ - int iobase; /* I/O ports base address */ - int irq; /* IRQ level */ - int dma; /* DMA channel */ -} Config; - -static const Config configs[] = { - {(void *) 0xce000, 0x350, 15, 6}, /* defaults for single adapter */ - {(void *) 0xc8000, 0x330, 11, 5}, /* defaults for second adapter */ - {(void *) 0xd8000, 0x350, 15, 6}, /* Arghhh.... who added this ? */ -}; -#define NUM_CONFIGS (sizeof(configs)/sizeof(Config)) - -/* - * The following list defines strings to look for in the BIOS that identify - * it as the WD7000-FASST2 SST BIOS. I suspect that something should be - * added for the Future Domain version. - */ -typedef struct signature { - const void *sig; /* String to look for */ - unsigned ofs; /* offset from BIOS base address */ - unsigned len; /* length of string */ -} Signature; - -static const Signature signatures[] = { - {"SSTBIOS",0x0000d,7} /* "SSTBIOS" @ offset 0x0000d */ -}; -#define NUM_SIGNATURES (sizeof(signatures)/sizeof(Signature)) - - -/* - * I/O Port Offsets and Bit Definitions - * 4 addresses are used. Those not defined here are reserved. - */ -#define ASC_STAT 0 /* Status, Read */ -#define ASC_COMMAND 0 /* Command, Write */ -#define ASC_INTR_STAT 1 /* Interrupt Status, Read */ -#define ASC_INTR_ACK 1 /* Acknowledge, Write */ -#define ASC_CONTROL 2 /* Control, Write */ - -/* ASC Status Port - */ -#define INT_IM 0x80 /* Interrupt Image Flag */ -#define CMD_RDY 0x40 /* Command Port Ready */ -#define CMD_REJ 0x20 /* Command Port Byte Rejected */ -#define ASC_INIT 0x10 /* ASC Initialized Flag */ -#define ASC_STATMASK 0xf0 /* The lower 4 Bytes are reserved */ - -/* COMMAND opcodes - * - * Unfortunately, I have no idea how to properly use some of these commands, - * as the OEM manual does not make it clear. I have not been able to use - * enable/disable unsolicited interrupts or the reset commands with any - * discernible effect whatsoever. I think they may be related to certain - * ICB commands, but again, the OEM manual doesn't make that clear. - */ -#define NO_OP 0 /* NO-OP toggles CMD_RDY bit in ASC_STAT */ -#define INITIALIZATION 1 /* initialization (10 bytes) */ -#define DISABLE_UNS_INTR 2 /* disable unsolicited interrupts */ -#define ENABLE_UNS_INTR 3 /* enable unsolicited interrupts */ -#define INTR_ON_FREE_OGMB 4 /* interrupt on free OGMB */ -#define SOFT_RESET 5 /* SCSI bus soft reset */ -#define HARD_RESET_ACK 6 /* SCSI bus hard reset acknowledge */ -#define START_OGMB 0x80 /* start command in OGMB (n) */ -#define SCAN_OGMBS 0xc0 /* start multiple commands, signature (n) */ - /* where (n) = lower 6 bits */ -/* For INITIALIZATION: - */ -typedef struct initCmd { - unchar op; /* command opcode (= 1) */ - unchar ID; /* Adapter's SCSI ID */ - unchar bus_on; /* Bus on time, x 125ns (see below) */ - unchar bus_off; /* Bus off time, "" "" */ - unchar rsvd; /* Reserved */ - unchar mailboxes[3]; /* Address of Mailboxes, MSB first */ - unchar ogmbs; /* Number of outgoing MBs, max 64, 0,1 = 1 */ - unchar icmbs; /* Number of incoming MBs, "" "" */ -} InitCmd; - -#define BUS_ON 64 /* x 125ns = 8000ns (BIOS default) */ -#define BUS_OFF 15 /* x 125ns = 1875ns (BIOS default) */ - -/* Interrupt Status Port - also returns diagnostic codes at ASC reset - * - * if msb is zero, the lower bits are diagnostic status - * Diagnostics: - * 01 No diagnostic error occurred - * 02 RAM failure - * 03 FIFO R/W failed - * 04 SBIC register read/write failed - * 05 Initialization D-FF failed - * 06 Host IRQ D-FF failed - * 07 ROM checksum error - * Interrupt status (bitwise): - * 10NNNNNN outgoing mailbox NNNNNN is free - * 11NNNNNN incoming mailbox NNNNNN needs service - */ -#define MB_INTR 0xC0 /* Mailbox Service possible/required */ -#define IMB_INTR 0x40 /* 1 Incoming / 0 Outgoing */ -#define MB_MASK 0x3f /* mask for mailbox number */ - -/* CONTROL port bits - */ -#define INT_EN 0x08 /* Interrupt Enable */ -#define DMA_EN 0x04 /* DMA Enable */ -#define SCSI_RES 0x02 /* SCSI Reset */ -#define ASC_RES 0x01 /* ASC Reset */ - -/* - Driver data structures: - - mb and scbs are required for interfacing with the host adapter. - An SCB has extra fields not visible to the adapter; mb's - _cannot_ do this, since the adapter assumes they are contiguous in - memory, 4 bytes each, with ICMBs following OGMBs, and uses this fact - to access them. - - An icb is for host-only (non-SCSI) commands. ICBs are 16 bytes each; - the additional bytes are used only by the driver. - - For now, a pool of SCBs are kept in global storage by this driver, - and are allocated and freed as needed. - - The 7000-FASST2 marks OGMBs empty as soon as it has _started_ a command, - not when it has finished. Since the SCB must be around for completion, - problems arise when SCBs correspond to OGMBs, which may be reallocated - earlier (or delayed unnecessarily until a command completes). - Mailboxes are used as transient data structures, simply for - carrying SCB addresses to/from the 7000-FASST2. - - Note also since SCBs are not "permanently" associated with mailboxes, - there is no need to keep a global list of Scsi_Cmnd pointers indexed - by OGMB. Again, SCBs reference their Scsi_Cmnds directly, so mailbox - indices need not be involved. -*/ - -/* - * WD7000-specific scatter/gather element structure - */ -typedef struct sgb { - unchar len[3]; - unchar ptr[3]; /* Also SCSI-style - MSB first */ -} Sgb; - -typedef struct scb { /* Command Control Block 5.4.1 */ - unchar op; /* Command Control Block Operation Code */ - unchar idlun; /* op=0,2:Target Id, op=1:Initiator Id */ - /* Outbound data transfer, length is checked*/ - /* Inbound data transfer, length is checked */ - /* Logical Unit Number */ - unchar cdb[12]; /* SCSI Command Block */ - volatile unchar status; /* SCSI Return Status */ - volatile unchar vue; /* Vendor Unique Error Code */ - unchar maxlen[3]; /* Maximum Data Transfer Length */ - unchar dataptr[3]; /* SCSI Data Block Pointer */ - unchar linkptr[3]; /* Next Command Link Pointer */ - unchar direc; /* Transfer Direction */ - unchar reserved2[6]; /* SCSI Command Descriptor Block */ - /* end of hardware SCB */ - Scsi_Cmnd *SCpnt; /* Scsi_Cmnd using this SCB */ - Sgb sgb[WD7000_SG]; /* Scatter/gather list for this SCB */ - Adapter *host; /* host adapter */ - struct scb *next; /* for lists of scbs */ -} Scb; - -/* - * This driver is written to allow host-only commands to be executed. - * These use a 16-byte block called an ICB. The format is extended by the - * driver to 18 bytes, to support the status returned in the ICMB and - * an execution phase code. - * - * There are other formats besides these; these are the ones I've tried - * to use. Formats for some of the defined ICB opcodes are not defined - * (notably, get/set unsolicited interrupt status) in my copy of the OEM - * manual, and others are ambiguous/hard to follow. - */ -#define ICB_OP_MASK 0x80 /* distinguishes scbs from icbs */ -#define ICB_OP_OPEN_RBUF 0x80 /* open receive buffer */ -#define ICB_OP_RECV_CMD 0x81 /* receive command from initiator */ -#define ICB_OP_RECV_DATA 0x82 /* receive data from initiator */ -#define ICB_OP_RECV_SDATA 0x83 /* receive data with status from init. */ -#define ICB_OP_SEND_DATA 0x84 /* send data with status to initiator */ -#define ICB_OP_SEND_STAT 0x86 /* send command status to initiator */ - /* 0x87 is reserved */ -#define ICB_OP_READ_INIT 0x88 /* read initialization bytes */ -#define ICB_OP_READ_ID 0x89 /* read adapter's SCSI ID */ -#define ICB_OP_SET_UMASK 0x8A /* set unsolicited interrupt mask */ -#define ICB_OP_GET_UMASK 0x8B /* read unsolicited interrupt mask */ -#define ICB_OP_GET_REVISION 0x8C /* read firmware revision level */ -#define ICB_OP_DIAGNOSTICS 0x8D /* execute diagnostics */ -#define ICB_OP_SET_EPARMS 0x8E /* set execution parameters */ -#define ICB_OP_GET_EPARMS 0x8F /* read execution parameters */ - -typedef struct icbRecvCmd { - unchar op; - unchar IDlun; /* Initiator SCSI ID/lun */ - unchar len[3]; /* command buffer length */ - unchar ptr[3]; /* command buffer address */ - unchar rsvd[7]; /* reserved */ - volatile unchar vue; /* vendor-unique error code */ - volatile unchar status; /* returned (icmb) status */ - volatile unchar phase; /* used by interrupt handler */ -} IcbRecvCmd; - -typedef struct icbSendStat { - unchar op; - unchar IDlun; /* Target SCSI ID/lun */ - unchar stat; /* (outgoing) completion status byte 1 */ - unchar rsvd[12]; /* reserved */ - volatile unchar vue; /* vendor-unique error code */ - volatile unchar status; /* returned (icmb) status */ - volatile unchar phase; /* used by interrupt handler */ -} IcbSendStat; - -typedef struct icbRevLvl { - unchar op; - volatile unchar primary; /* primary revision level (returned) */ - volatile unchar secondary; /* secondary revision level (returned) */ - unchar rsvd[12]; /* reserved */ - volatile unchar vue; /* vendor-unique error code */ - volatile unchar status; /* returned (icmb) status */ - volatile unchar phase; /* used by interrupt handler */ -} IcbRevLvl; - -typedef struct icbUnsMask { /* I'm totally guessing here */ - unchar op; - volatile unchar mask[14]; /* mask bits */ -#ifdef 0 - unchar rsvd[12]; /* reserved */ -#endif - volatile unchar vue; /* vendor-unique error code */ - volatile unchar status; /* returned (icmb) status */ - volatile unchar phase; /* used by interrupt handler */ -} IcbUnsMask; - -typedef struct icbDiag { - unchar op; - unchar type; /* diagnostics type code (0-3) */ - unchar len[3]; /* buffer length */ - unchar ptr[3]; /* buffer address */ - unchar rsvd[7]; /* reserved */ - volatile unchar vue; /* vendor-unique error code */ - volatile unchar status; /* returned (icmb) status */ - volatile unchar phase; /* used by interrupt handler */ -} IcbDiag; - -#define ICB_DIAG_POWERUP 0 /* Power-up diags only */ -#define ICB_DIAG_WALKING 1 /* walking 1's pattern */ -#define ICB_DIAG_DMA 2 /* DMA - system memory diags */ -#define ICB_DIAG_FULL 3 /* do both 1 & 2 */ - -typedef struct icbParms { - unchar op; - unchar rsvd1; /* reserved */ - unchar len[3]; /* parms buffer length */ - unchar ptr[3]; /* parms buffer address */ - unchar idx[2]; /* index (MSB-LSB) */ - unchar rsvd2[5]; /* reserved */ - volatile unchar vue; /* vendor-unique error code */ - volatile unchar status; /* returned (icmb) status */ - volatile unchar phase; /* used by interrupt handler */ -} IcbParms; - -typedef struct icbAny { - unchar op; - unchar data[14]; /* format-specific data */ - volatile unchar vue; /* vendor-unique error code */ - volatile unchar status; /* returned (icmb) status */ - volatile unchar phase; /* used by interrupt handler */ -} IcbAny; - -typedef union icb { - unchar op; /* ICB opcode */ - IcbRecvCmd recv_cmd; /* format for receive command */ - IcbSendStat send_stat; /* format for send status */ - IcbRevLvl rev_lvl; /* format for get revision level */ - IcbDiag diag; /* format for execute diagnostics */ - IcbParms eparms; /* format for get/set exec parms */ - IcbAny icb; /* generic format */ - unchar data[18]; -} Icb; - - -/* - * Driver SCB structure pool. - * - * The SCBs declared here are shared by all host adapters; hence, this - * structure is not part of the Adapter structure. - */ -static Scb scbs[MAX_SCBS]; -static Scb *scbfree = NULL; /* free list */ -static int freescbs = MAX_SCBS; /* free list counter */ - -/* - * END of data/declarations - code follows. - */ - - -#ifdef ANY2SCSI_INLINE -/* - Since they're used a lot, I've redone the following from the macros - formerly in wd7000.h, hopefully to speed them up by getting rid of - all the shifting (it may not matter; GCC might have done as well anyway). - - xany2scsi and xscsi2int were not being used, and are no longer defined. - (They were simply 4-byte versions of these routines). -*/ - -typedef union { /* let's cheat... */ - int i; - unchar u[sizeof(int)]; /* the sizeof(int) makes it more portable */ -} i_u; - - -static inline void any2scsi( unchar *scsi, int any ) -{ - *scsi++ = ((i_u) any).u[2]; - *scsi++ = ((i_u) any).u[1]; - *scsi++ = ((i_u) any).u[0]; -} - - -static inline int scsi2int( unchar *scsi ) -{ - i_u result; - - result.i = 0; /* clears unused bytes */ - *(result.u+2) = *scsi++; - *(result.u+1) = *scsi++; - *(result.u) = *scsi++; - return result.i; -} -#else -/* - These are the old ones - I've just moved them here... -*/ -#undef any2scsi -#define any2scsi(up, p) \ -(up)[0] = (((unsigned long)(p)) >> 16); \ -(up)[1] = ((unsigned long)(p)) >> 8; \ -(up)[2] = ((unsigned long)(p)); - -#undef scsi2int -#define scsi2int(up) ( (((unsigned long)*(up)) << 16) + \ - (((unsigned long)(up)[1]) << 8) + ((unsigned long)(up)[2]) ) -#endif - - -static inline void wd7000_enable_intr(Adapter *host) -{ - host->control |= INT_EN; - outb(host->control, host->iobase+ASC_CONTROL); -} - - -static inline void wd7000_enable_dma(Adapter *host) -{ - host->control |= DMA_EN; - outb(host->control,host->iobase+ASC_CONTROL); - set_dma_mode(host->dma, DMA_MODE_CASCADE); - enable_dma(host->dma); -} - - -#define WAITnexttimeout 200 /* 2 seconds */ - -#define WAIT(port, mask, allof, noneof) \ - { register volatile unsigned WAITbits; \ - register unsigned long WAITtimeout = jiffies + WAITnexttimeout; \ - while (1) { \ - WAITbits = inb(port) & (mask); \ - if ((WAITbits & (allof)) == (allof) && ((WAITbits & (noneof)) == 0)) \ - break; \ - if (jiffies > WAITtimeout) goto fail; \ - } \ - } - - -static inline void delay( unsigned how_long ) -{ - register unsigned long time = jiffies + how_long; - - while (jiffies < time); -} - - -static inline int command_out(Adapter *host, unchar *cmd, int len) -{ - WAIT(host->iobase+ASC_STAT,ASC_STATMASK,CMD_RDY,0); - while (len--) { - do { - outb(*cmd, host->iobase+ASC_COMMAND); - WAIT(host->iobase+ASC_STAT, ASC_STATMASK, CMD_RDY, 0); - } while (inb(host->iobase+ASC_STAT) & CMD_REJ); - cmd++; - } - return 1; - -fail: - printk("wd7000 command_out: WAIT failed(%d)\n", len+1); - return 0; -} - - -/* - * This version of alloc_scbs is in preparation for supporting multiple - * commands per lun and command chaining, by queueing pending commands. - * We will need to allocate Scbs in blocks since they will wait to be - * executed so there is the possibility of deadlock otherwise. - * Also, to keep larger requests from being starved by smaller requests, - * we limit access to this routine with an internal busy flag, so that - * the satisfiability of a request is not dependent on the size of the - * request. - */ -static inline Scb *alloc_scbs(int needed) -{ - register Scb *scb, *p; - register unsigned long flags; - register unsigned long timeout = jiffies + WAITnexttimeout; - register unsigned long now; - static int busy = 0; - int i; - - if (needed <= 0) return NULL; /* sanity check */ - - save_flags(flags); - cli(); - while (busy) { /* someone else is allocating */ - sti(); /* Yes this is really needed here */ - now = jiffies; while (jiffies == now) /* wait a jiffy */; - cli(); - } - busy = 1; /* not busy now; it's our turn */ - - while (freescbs < needed) { - timeout = jiffies + WAITnexttimeout; - do { - sti(); /* Yes this is really needed here */ - now = jiffies; while (jiffies == now) /* wait a jiffy */; - cli(); - } while (freescbs < needed && jiffies <= timeout); - /* - * If we get here with enough free Scbs, we can take them. - * Otherwise, we timed out and didn't get enough. - */ - if (freescbs < needed) { - busy = 0; - panic("wd7000: can't get enough free SCBs.\n"); - restore_flags(flags); - return NULL; - } - } - scb = scbfree; freescbs -= needed; - for (i = 0; i < needed; i++) { p = scbfree; scbfree = p->next; } - p->next = NULL; - - busy = 0; /* we're done */ - - restore_flags(flags); - - return scb; -} - - -static inline void free_scb( Scb *scb ) -{ - register unsigned long flags; - - save_flags(flags); - cli(); - - memset(scb, 0, sizeof(Scb)); - scb->next = scbfree; scbfree = scb; - freescbs++; - - restore_flags(flags); -} - - -static inline void init_scbs(void) -{ - int i; - unsigned long flags; - - save_flags(flags); - cli(); - - scbfree = &(scbs[0]); - memset(scbs, 0, sizeof(scbs)); - for (i = 0; i < MAX_SCBS-1; i++) { - scbs[i].next = &(scbs[i+1]); scbs[i].SCpnt = NULL; - } - scbs[MAX_SCBS-1].next = NULL; - scbs[MAX_SCBS-1].SCpnt = NULL; - - restore_flags(flags); -} - - -static int mail_out( Adapter *host, Scb *scbptr ) -/* - * Note: this can also be used for ICBs; just cast to the parm type. - */ -{ - register int i, ogmb; - register unsigned long flags; - unchar start_ogmb; - Mailbox *ogmbs = host->mb.ogmb; - int *next_ogmb = &(host->next_ogmb); -#ifdef DEBUG - printk("wd7000 mail_out: %06x",(unsigned int) scbptr); -#endif - /* We first look for a free outgoing mailbox */ - save_flags(flags); - cli(); - ogmb = *next_ogmb; - for (i = 0; i < OGMB_CNT; i++) { - if (ogmbs[ogmb].status == 0) { -#ifdef DEBUG - printk(" using OGMB %x",ogmb); -#endif - ogmbs[ogmb].status = 1; - any2scsi((unchar *) ogmbs[ogmb].scbptr, (int) scbptr); - - *next_ogmb = (ogmb+1) % OGMB_CNT; - break; - } else - ogmb = (++ogmb) % OGMB_CNT; - } - restore_flags(flags); -#ifdef DEBUG - printk(", scb is %x",(unsigned int) scbptr); -#endif - if (i >= OGMB_CNT) { - /* - * Alternatively, we might issue the "interrupt on free OGMB", - * and sleep, but it must be ensured that it isn't the init - * task running. Instead, this version assumes that the caller - * will be persistent, and try again. Since it's the adapter - * that marks OGMB's free, waiting even with interrupts off - * should work, since they are freed very quickly in most cases. - */ - #ifdef DEBUG - printk(", no free OGMBs.\n"); -#endif - return 0; - } - - wd7000_enable_intr(host); - - start_ogmb = START_OGMB | ogmb; - command_out( host, &start_ogmb, 1 ); -#ifdef DEBUG - printk(", awaiting interrupt.\n"); -#endif - return 1; -} - - -int make_code(unsigned hosterr, unsigned scsierr) -{ -#ifdef DEBUG - int in_error = hosterr; -#endif - - switch ((hosterr>>8)&0xff){ - case 0: /* Reserved */ - hosterr = DID_ERROR; - break; - case 1: /* Command Complete, no errors */ - hosterr = DID_OK; - break; - case 2: /* Command complete, error logged in scb status (scsierr) */ - hosterr = DID_OK; - break; - case 4: /* Command failed to complete - timeout */ - hosterr = DID_TIME_OUT; - break; - case 5: /* Command terminated; Bus reset by external device */ - hosterr = DID_RESET; - break; - case 6: /* Unexpected Command Received w/ host as target */ - hosterr = DID_BAD_TARGET; - break; - case 80: /* Unexpected Reselection */ - case 81: /* Unexpected Selection */ - hosterr = DID_BAD_INTR; - break; - case 82: /* Abort Command Message */ - hosterr = DID_ABORT; - break; - case 83: /* SCSI Bus Software Reset */ - case 84: /* SCSI Bus Hardware Reset */ - hosterr = DID_RESET; - break; - default: /* Reserved */ - hosterr = DID_ERROR; - break; - } -#ifdef DEBUG - if (scsierr||hosterr) - printk("\nSCSI command error: SCSI %02x host %04x return %d", - scsierr,in_error,hosterr); -#endif - return scsierr | (hosterr << 16); -} - - -static void wd7000_scsi_done(Scsi_Cmnd * SCpnt) -{ -#ifdef DEBUG - printk("wd7000_scsi_done: %06x\n",(unsigned int) SCpnt); -#endif - SCpnt->SCp.phase = 0; -} - - -#define wd7000_intr_ack(host) outb(0,host->iobase+ASC_INTR_ACK) - -void wd7000_intr_handle(int irq, struct pt_regs * regs) -{ - register int flag, icmb, errstatus, icmb_status; - register int host_error, scsi_error; - register Scb *scb; /* for SCSI commands */ - register IcbAny *icb; /* for host commands */ - register Scsi_Cmnd *SCpnt; - Adapter *host = irq2host[irq]; /* This MUST be set!!! */ - Mailbox *icmbs = host->mb.icmb; - -#ifdef DEBUG - printk("wd7000_intr_handle: irq = %d, host = %06x\n", irq, host); -#endif - - flag = inb(host->iobase+ASC_INTR_STAT); -#ifdef DEBUG - printk("wd7000_intr_handle: intr stat = %02x\n",flag); -#endif - - if (!(inb(host->iobase+ASC_STAT) & INT_IM)) { - /* NB: these are _very_ possible if IRQ 15 is being used, since - it's the "garbage collector" on the 2nd 8259 PIC. Specifically, - any interrupt signal into the 8259 which can't be identified - comes out as 7 from the 8259, which is 15 to the host. Thus, it - is a good thing the WD7000 has an interrupt status port, so we - can sort these out. Otherwise, electrical noise and other such - problems would be indistinguishable from valid interrupts... - */ -#ifdef DEBUG - printk("wd7000_intr_handle: phantom interrupt...\n"); -#endif - wd7000_intr_ack(host); - return; - } - - if (flag & MB_INTR) { - /* The interrupt is for a mailbox */ - if (!(flag & IMB_INTR)) { -#ifdef DEBUG - printk("wd7000_intr_handle: free outgoing mailbox"); -#endif - /* - * If sleep_on() and the "interrupt on free OGMB" command are - * used in mail_out(), wake_up() should correspondingly be called - * here. For now, we don't need to do anything special. - */ - wd7000_intr_ack(host); - return; - } else { - /* The interrupt is for an incoming mailbox */ - icmb = flag & MB_MASK; - icmb_status = icmbs[icmb].status; - if (icmb_status & 0x80) { /* unsolicited - result in ICMB */ -#ifdef DEBUG - printk("wd7000_intr_handle: unsolicited interrupt %02xh\n", - icmb_status); -#endif - wd7000_intr_ack(host); - return; - } - scb = (struct scb *) scsi2int((unchar *)icmbs[icmb].scbptr); - icmbs[icmb].status = 0; - if (!(scb->op & ICB_OP_MASK)) { /* an SCB is done */ - SCpnt = scb->SCpnt; - if (--(SCpnt->SCp.phase) <= 0) { /* all scbs are done */ - host_error = scb->vue | (icmb_status << 8); - scsi_error = scb->status; - errstatus = make_code(host_error,scsi_error); - SCpnt->result = errstatus; - - free_scb(scb); - - SCpnt->scsi_done(SCpnt); - } - } else { /* an ICB is done */ - icb = (IcbAny *) scb; - icb->status = icmb_status; - icb->phase = 0; - } - } /* incoming mailbox */ - } - - wd7000_intr_ack(host); - return; -} - - -int wd7000_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) -{ - register Scb *scb; - register Sgb *sgb; - register unchar *cdb = (unchar *) SCpnt->cmnd; - register unchar idlun; - register short cdblen; - Adapter *host = (Adapter *) SCpnt->host->hostdata; - - cdblen = SCpnt->cmd_len; - idlun = ((SCpnt->target << 5) & 0xe0) | (SCpnt->lun & 7); - SCpnt->scsi_done = done; - SCpnt->SCp.phase = 1; - scb = alloc_scbs(1); - scb->idlun = idlun; - memcpy(scb->cdb, cdb, cdblen); - scb->direc = 0x40; /* Disable direction check */ - - scb->SCpnt = SCpnt; /* so we can find stuff later */ - SCpnt->host_scribble = (unchar *) scb; - scb->host = host; - - if (SCpnt->use_sg) { - struct scatterlist *sg = (struct scatterlist *) SCpnt->request_buffer; - unsigned i; - - if (SCpnt->host->sg_tablesize == SG_NONE) { - panic("wd7000_queuecommand: scatter/gather not supported.\n"); - } -#ifdef DEBUG - printk("Using scatter/gather with %d elements.\n",SCpnt->use_sg); -#endif - - sgb = scb->sgb; - scb->op = 1; - any2scsi(scb->dataptr, (int) sgb); - any2scsi(scb->maxlen, SCpnt->use_sg * sizeof (Sgb) ); - - for (i = 0; i < SCpnt->use_sg; i++) { - any2scsi(sgb[i].ptr, (int) sg[i].address); - any2scsi(sgb[i].len, sg[i].length); - } - } else { - scb->op = 0; - any2scsi(scb->dataptr, (int) SCpnt->request_buffer); - any2scsi(scb->maxlen, SCpnt->request_bufflen); - } - while (!mail_out(host, scb)) /* keep trying */; - - return 1; -} - - -int wd7000_command(Scsi_Cmnd *SCpnt) -{ - wd7000_queuecommand(SCpnt, wd7000_scsi_done); - - while (SCpnt->SCp.phase > 0) barrier(); /* phase counts scbs down to 0 */ - - return SCpnt->result; -} - - -int wd7000_diagnostics( Adapter *host, int code ) -{ - static IcbDiag icb = {ICB_OP_DIAGNOSTICS}; - static unchar buf[256]; - unsigned long timeout; - - icb.type = code; - any2scsi(icb.len, sizeof(buf)); - any2scsi(icb.ptr, (int) &buf); - icb.phase = 1; - /* - * This routine is only called at init, so there should be OGMBs - * available. I'm assuming so here. If this is going to - * fail, I can just let the timeout catch the failure. - */ - mail_out(host, (struct scb *) &icb); - timeout = jiffies + WAITnexttimeout; /* wait up to 2 seconds */ - while (icb.phase && jiffies < timeout) - barrier(); /* wait for completion */ - - if (icb.phase) { - printk("wd7000_diagnostics: timed out.\n"); - return 0; - } - if (make_code(icb.vue|(icb.status << 8),0)) { - printk("wd7000_diagnostics: failed (%02x,%02x)\n", - icb.vue, icb.status); - return 0; - } - - return 1; -} - - -int wd7000_init( Adapter *host ) -{ - InitCmd init_cmd = { - INITIALIZATION, 7, BUS_ON, BUS_OFF, 0, {0,0,0}, OGMB_CNT, ICMB_CNT - }; - int diag; - - /* - Reset the adapter - only. The SCSI bus was initialized at power-up, - and we need to do this just so we control the mailboxes, etc. - */ - outb(ASC_RES, host->iobase+ASC_CONTROL); - delay(1); /* reset pulse: this is 10ms, only need 25us */ - outb(0,host->iobase+ASC_CONTROL); - host->control = 0; /* this must always shadow ASC_CONTROL */ - WAIT(host->iobase+ASC_STAT, ASC_STATMASK, CMD_RDY, 0); - - if ((diag = inb(host->iobase+ASC_INTR_STAT)) != 1) { - printk("wd7000_init: "); - switch (diag) { - case 2: - printk("RAM failure.\n"); - break; - case 3: - printk("FIFO R/W failed\n"); - break; - case 4: - printk("SBIC register R/W failed\n"); - break; - case 5: - printk("Initialization D-FF failed.\n"); - break; - case 6: - printk("Host IRQ D-FF failed.\n"); - break; - case 7: - printk("ROM checksum error.\n"); - break; - default: - printk("diagnostic code %02Xh received.\n", diag); - break; - } - return 0; - } - - /* Clear mailboxes */ - memset(&(host->mb), 0, sizeof(host->mb)); - - /* Execute init command */ - any2scsi((unchar *) &(init_cmd.mailboxes), (int) &(host->mb)); - if (!command_out(host, (unchar *) &init_cmd, sizeof(init_cmd))) { - printk("wd7000_init: adapter initialization failed.\n"); - return 0; - } - WAIT(host->iobase+ASC_STAT, ASC_STATMASK, ASC_INIT, 0); - - if (request_irq(host->irq, wd7000_intr_handle, SA_INTERRUPT, "wd7000")) { - printk("wd7000_init: can't get IRQ %d.\n", host->irq); - return 0; - } - if (request_dma(host->dma,"wd7000")) { - printk("wd7000_init: can't get DMA channel %d.\n", host->dma); - free_irq(host->irq); - return 0; - } - wd7000_enable_dma(host); - wd7000_enable_intr(host); - - if (!wd7000_diagnostics(host,ICB_DIAG_FULL)) { - free_dma(host->dma); - free_irq(host->irq); - return 0; - } - - return 1; - - fail: - printk("wd7000_init: WAIT timed out.\n"); - return 0; /* 0 = not ok */ -} - - -void wd7000_revision(Adapter *host) -{ - static IcbRevLvl icb = {ICB_OP_GET_REVISION}; - - icb.phase = 1; - /* - * Like diagnostics, this is only done at init time, in fact, from - * wd7000_detect, so there should be OGMBs available. If it fails, - * the only damage will be that the revision will show up as 0.0, - * which in turn means that scatter/gather will be disabled. - */ - mail_out(host, (struct scb *) &icb); - while (icb.phase) - barrier(); /* wait for completion */ - host->rev1 = icb.primary; - host->rev2 = icb.secondary; -} - - -int wd7000_detect(Scsi_Host_Template * tpnt) -/* - * Returns the number of adapters this driver is supporting. - * - * The source for hosts.c says to wait to call scsi_register until 100% - * sure about an adapter. We need to do it a little sooner here; we - * need the storage set up by scsi_register before wd7000_init, and - * changing the location of an Adapter structure is more trouble than - * calling scsi_unregister. - * - */ -{ - int i,j, present = 0; - const Config *cfg; - const Signature *sig; - Adapter *host = NULL; - struct Scsi_Host *sh; - - tpnt->proc_dir = &proc_scsi_wd7000; - - /* Set up SCB free list, which is shared by all adapters */ - init_scbs(); - - cfg = configs; - for (i = 0; i < NUM_CONFIGS; i++) { - sig = signatures; - for (j = 0; j < NUM_SIGNATURES; j++) { - if (!memcmp(cfg->bios+sig->ofs, sig->sig, sig->len)) { - /* matched this one */ -#ifdef DEBUG - printk("WD-7000 SST BIOS detected at %04X: checking...\n", - (int) cfg->bios); -#endif - /* - * We won't explicitly test the configuration (in this - * version); instead, we'll just see if it works to - * setup the adapter; if it does, we'll use it. - */ - if (check_region(cfg->iobase, 4)) { /* ports in use */ - printk("IO %xh already in use.\n", host->iobase); - continue; - } - /* - * We register here, to get a pointer to the extra space, - * which we'll use as the Adapter structure (host) for - * this adapter. It is located just after the registered - * Scsi_Host structure (sh), and is located by the empty - * array hostdata. - */ - sh = scsi_register(tpnt, sizeof(Adapter) ); - host = (Adapter *) sh->hostdata; -#ifdef DEBUG - printk("wd7000_detect: adapter allocated at %06x\n", - (int)host); -#endif - memset( host, 0, sizeof(Adapter) ); - host->sh = sh; - host->irq = cfg->irq; - host->iobase = cfg->iobase; - host->dma = cfg->dma; - irq2host[host->irq] = host; - - if (!wd7000_init(host)) { /* Initialization failed */ - scsi_unregister (sh); - continue; - } - - /* - * OK from here - we'll use this adapter/configuration. - */ - wd7000_revision(host); /* important for scatter/gather */ - - printk("Western Digital WD-7000 (%d.%d) ", - host->rev1, host->rev2); - printk("using IO %xh IRQ %d DMA %d.\n", - host->iobase, host->irq, host->dma); - - request_region(host->iobase, 4,"wd7000"); /* Register our ports */ - /* - * For boards before rev 6.0, scatter/gather isn't supported. - */ - if (host->rev1 < 6) sh->sg_tablesize = SG_NONE; - - present++; /* count it */ - break; /* don't try any more sigs */ - } - sig++; /* try next signature with this configuration */ - } - cfg++; /* try next configuration */ - } - - return present; -} - - -/* - * I have absolutely NO idea how to do an abort with the WD7000... - */ -int wd7000_abort(Scsi_Cmnd * SCpnt) -{ - Adapter *host = (Adapter *) SCpnt->host->hostdata; - - if (inb(host->iobase+ASC_STAT) & INT_IM) { - printk("wd7000_abort: lost interrupt\n"); - wd7000_intr_handle(host->irq, NULL); - return SCSI_ABORT_SUCCESS; - } - - return SCSI_ABORT_SNOOZE; -} - - -/* - * I also have no idea how to do a reset... - */ -int wd7000_reset(Scsi_Cmnd * SCpnt) -{ - return SCSI_RESET_PUNT; -} - - -/* - * This was borrowed directly from aha1542.c, but my disks are organized - * this way, so I think it will work OK. Someone who is ambitious can - * borrow a newer or more complete version from another driver. - */ -int wd7000_biosparam(Disk * disk, kdev_t dev, int* ip) -{ - int size = disk->capacity; - ip[0] = 64; - ip[1] = 32; - ip[2] = size >> 11; -/* if (ip[2] >= 1024) ip[2] = 1024; */ - return 0; -} - -#ifdef MODULE -/* Eventually this will go into an include file, but this will be later */ -Scsi_Host_Template driver_template = WD7000; - -#include "scsi_module.c" -#endif diff --git a/i386/i386at/gpl/linux/scsi/wd7000.h b/i386/i386at/gpl/linux/scsi/wd7000.h deleted file mode 100644 index 5a194dbc..00000000 --- a/i386/i386at/gpl/linux/scsi/wd7000.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef _WD7000_H - -/* $Id: wd7000.h,v 1.1.1.1 1997/02/25 21:27:53 thomas Exp $ - * - * Header file for the WD-7000 driver for Linux - * - * John Boyd <boyd@cis.ohio-state.edu> Jan 1994: - * This file has been reduced to only the definitions needed for the - * WD7000 host structure. - * - */ - -#include <linux/types.h> -#include <linux/kdev_t.h> - -int wd7000_detect(Scsi_Host_Template *); -int wd7000_command(Scsi_Cmnd *); -int wd7000_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); -int wd7000_abort(Scsi_Cmnd *); -int wd7000_reset(Scsi_Cmnd *); -int wd7000_biosparam(Disk *, kdev_t, int *); - -#ifndef NULL -#define NULL 0L -#endif - -/* - * In this version, sg_tablesize now defaults to WD7000_SG, and will - * be set to SG_NONE for older boards. This is the reverse of the - * previous default, and was changed so that the driver-level - * Scsi_Host_Template would reflect the driver's support for scatter/ - * gather. - * - * Also, it has been reported that boards at Revision 6 support scatter/ - * gather, so the new definition of an "older" board has been changed - * accordingly. - */ -#define WD7000_Q 16 -#define WD7000_SG 16 - -#define WD7000 { NULL, NULL, \ - NULL, \ - NULL, \ - "Western Digital WD-7000", \ - wd7000_detect, \ - NULL, \ - NULL, \ - wd7000_command, \ - wd7000_queuecommand, \ - wd7000_abort, \ - wd7000_reset, \ - NULL, \ - wd7000_biosparam, \ - WD7000_Q, 7, WD7000_SG, 1, 0, 1, ENABLE_CLUSTERING} -#endif |