diff -u --recursive --new-file v2.1.27/linux/Documentation/Configure.help linux/Documentation/Configure.help --- v2.1.27/linux/Documentation/Configure.help Thu Feb 27 10:57:29 1997 +++ linux/Documentation/Configure.help Fri Feb 28 15:15:42 1997 @@ -543,7 +543,7 @@ choices: ** Avanti: This is for Mustang (AS200), M3 (AS250), Avanti (AS400) and XL (a.k.a. "Windows NT Dream Machine" :-) AlphaStations. - These usually come with a TGA graphics adaptor, so you'll want to + These usually come with a TGA graphics adapter, so you'll want to say Y to "TGA Console support", below, if you have one of these. ** Jensen: a.k.a. DEC 2000 a.k.a. DECpc AXP 150, the oldest Alpha PC; it sports an EISA bus. The boot process on Jensen machines is @@ -595,11 +595,52 @@ corresponds to a serial port; this could be useful if you attached a terminal or printer to that port. +Non-standard serial port support +CONFIG_SERIAL_NONSTANDARD + Say Y here if you have any non-standard serial boards --- boards + which aren't supported using the standard "dumb" serial driver. + This includes intelligent serial boards such as Cyclades, + Digiboards, etc. + +Extended dumb serial driver options +CONFIG_SERIAL_EXTENDED + If you wish to use any non-standard features of the standard "dumb" + driver, say Y here. This includes HUB6 support, shared serial + interrupts, special multiport support, support for more than the + four COM 1/2/3/4 boards, etc. + +Support more than 4 serial ports +CONFIG_SERIAL_MANY_PORTS + Enable this option if you have dumb serial boards other than the + four standard COM 1/2/3/4 ports. This may happen if you have an AST + FourPort, Accent Async, Boca, or other custom serial port hardware + which acts similar to standard serial port hardware. If you only + use the standard COM 1/2/3/4 ports, you can say N here to save some + memory. + +Support for sharing serial interrupts +CONFIG_SERIAL_SHARE_IRQ + Some serial boards have hardware support which allows multiple dumb + serial ports on the same board to share a single IRQ. To enable + support for this in the serial driver, say Y here. + +Support special multiport boards +CONFIG_SERIAL_MULTIPORT + Some multiport serial ports have special ports which are used to + signal when there are any serial ports on the board which need + servicing. Say Y here to enable the serial driver to take advantage + of those special I/O ports. + +Support the Bell Technologies HUB6 card +CONFIG_HUB6 + Say Y here to enable support in the dumb serial driver to support + the HUB6 card. + TGA Console Support CONFIG_TGA_CONSOLE Many Alpha systems (e.g the Multia) are shipped with a graphics card that implements the TGA interface (much like the VGA standard, but - older TGA adaptors are *not* VGA compatible). On such systems, you + older TGA adapters are *not* VGA compatible). On such systems, you should say Y here so that the TGA driver rather than the standard VGA driver is used. Note that, at this time, there is no X server for these systems. If unsure, try N. @@ -1393,7 +1434,7 @@ CONFIG_SCSI If you want to use a SCSI harddisk, SCSI tapedrive, SCSI CDROM or any other SCSI device under Linux, say Y and make sure that you know - the name of your SCSI host adaptor (the card inside your computer + the name of your SCSI host adapter (the card inside your computer that "speaks" the SCSI protocol), because you will be asked for it. You also need to say Y here if you want support for the parallel port version of the 100MB IOMEGA ZIP drive. Please read the @@ -1480,7 +1521,7 @@ AdvanSys SCSI support CONFIG_SCSI_ADVANSYS - This is a driver for all SCSI host adaptors manufactured by + This is a driver for all SCSI host adapters manufactured by AdvanSys. It is documented in the kernel source in drivers/scsi/advansys.c. This driver is also available as a module ( = code which can be inserted in and removed from the running kernel @@ -1491,7 +1532,7 @@ Adaptec AHA152X/2825 support CONFIG_SCSI_AHA152X This is support for the AHA-1510, AHA-1520, AHA-1522, and AHA-2825 - SCSI host adaptors. It is explained in section 3.3 of the + SCSI host adapters. It is explained in section 3.3 of the SCSI-HOWTO, available via ftp (user: anonymous) at sunsite.unc.edu:/pub/Linux/docs/HOWTO. You might also want to read the comments at the top of drivers/scsi/aha152x.c. This driver is @@ -1502,7 +1543,7 @@ Adaptec AHA1542 support CONFIG_SCSI_AHA1542 - This is support for a SCSI host adaptor. It is explained in section + This is support for a SCSI host adapter. It is explained in section 3.4 of the SCSI-HOWTO, available via ftp (user: anonymous) at sunsite.unc.edu:/pub/Linux/docs/HOWTO. Note that Trantor was recently purchased by Adaptec, and some former Trantor products are @@ -1515,7 +1556,7 @@ Adaptec AHA1740 support CONFIG_SCSI_AHA1740 - This is support for a SCSI host adaptor. It is explained in section + This is support for a SCSI host adapter. It is explained in section 3.5 of the SCSI-HOWTO, available via ftp (user: anonymous) at sunsite.unc.edu:/pub/Linux/docs/HOWTO. If it doesn't work out of the box, you may have to change some settings in @@ -1527,7 +1568,7 @@ Adaptec AHA274X/284X/294X support CONFIG_SCSI_AIC7XXX - Information about this SCSI host adaptor is contained in + Information about this SCSI host adapter is contained in drivers/scsi/README.aic7xxx and in the SCSI-HOWTO, available via ftp (user: anonymous) at sunsite.unc.edu:/pub/Linux/docs/HOWTO. If it doesn't work out of the box, you may have to change some settings in @@ -1538,24 +1579,25 @@ BusLogic SCSI support CONFIG_SCSI_BUSLOGIC - This is support for BusLogic MultiMaster SCSI Host Adaptors. - Consult the SCSI-HOWTO, available via anonymous ftp from - sunsite.unc.edu:/pub/Linux/docs/HOWTO and the file - drivers/scsi/README.BusLogic for more information. BusLogic - FlashPoint SCSI Host Adapters are not supported by this driver, but - BusLogic has initiated an upgrade program which allows you to get a - better adaptor for few $$. Read about it in - drivers/scsi/README.FlashPoint. If this driver does not work - correctly without modification, please contact the author. You can - build this driver also as a module ( = code which can be inserted in - and removed from the running kernel whenever you want), but only a - single instance may be loaded. The module will be called - BusLogic.o. If you want to compile it as a module, say M here and - read Documentation/modules.txt. + This is support for BusLogic MultiMaster and FlashPoint SCSI Host Adapters. + Consult the SCSI-HOWTO, available via anonymous ftp from sunsite.unc.edu in + /pub/Linux/docs/HOWTO, and the files README.BusLogic and README.FlashPoint in + drivers/scsi for more information. If this driver does not work correctly + without modification, please contact the author, Leonard N. Zubkoff, by email + to lnz@dandelion.com. You can also build this driver as a module ( = code + which can be inserted in and removed from the running kernel whenever you + want), but only a single instance may be loaded. If you want to compile it + as a module, say M here and read Documentation/modules.txt. + +Omit BusLogic SCSI FlashPoint support +CONFIG_SCSI_OMIT_FLASHPOINT + This option allows you to omit the FlashPoint support from the BusLogic + SCSI driver. The FlashPoint SCCB Manager code is substantial, so users of + MultiMaster Host Adapters may wish to omit it. DTC3180/3280 SCSI support CONFIG_SCSI_DTC3280 - This is support for DTC 3180/3280 SCSI Host Adaptors. Please read + This is support for DTC 3180/3280 SCSI Host Adapters. Please read the SCSI-HOWTO, available via ftp (user: anonymous) at sunsite.unc.edu:/pub/Linux/docs/HOWTO and the file drivers/scsi/README.dtc3x80. This driver is also available as a @@ -1567,7 +1609,7 @@ EATA-DMA (DPT, NEC, AT&T, SNI, AST, Olivetti, Alphatronix) support CONFIG_SCSI_EATA_DMA This is support for the EATA-DMA protocol compliant SCSI Host - Adaptors like the SmartCache III/IV, SmartRAID controller families + Adapters like the SmartCache III/IV, SmartRAID controller families and the DPT PM2011B and PM2012B controllers. Note that there is also another driver for the same hardware: "EATA ISA/EISA/PCI support". You should only say Y to one of them. Please read the @@ -1581,8 +1623,8 @@ EATA-PIO (old DPT PM2001, PM2012A) support CONFIG_SCSI_EATA_PIO This driver supports all EATA-PIO protocol compliant SCSI Host - Adaptors like the DPT PM2001 and the PM2012A. EATA-DMA compliant - host adaptors could also use this driver but are discouraged from + Adapters like the DPT PM2001 and the PM2012A. EATA-DMA compliant + host adapters could also use this driver but are discouraged from doing so, since this driver only supports harddisks and lacks numerous features. You might want to have a look at the SCSI-HOWTO, available via ftp (user: anonymous) at @@ -1609,7 +1651,7 @@ enable linked commands CONFIG_SCSI_U14_34F_LINKED_COMMANDS This is a feature of SCSI-2 which improves performance: the host - adaptor can send a whole list of commands to a device in one + adapter can send a whole list of commands to a device in one batch. Some SCSI devices might not implement this properly, so the save answer is N. @@ -1621,9 +1663,9 @@ Future Domain 16xx SCSI support CONFIG_SCSI_FUTURE_DOMAIN - This is support for Future Domain's 16-bit SCSI host adaptors + This is support for Future Domain's 16-bit SCSI host adapters (TMC-1660/1680, TMC-1650/1670, TMC-3260, TMC-1610M/MER/MEX) and - other adaptors based on the Future Domain chipsets (Quantum + other adapters based on the Future Domain chipsets (Quantum ISA-200S, ISA-250MG; Adaptec AHA-2920; and at least one IBM board). It is explained in section 3.7 of the SCSI-HOWTO, available via ftp (user: anonymous) at sunsite.unc.edu:/pub/Linux/docs/HOWTO. This @@ -1682,7 +1724,7 @@ allow FAST-SCSI [10MHz] CONFIG_SCSI_NCR53C7xx_FAST This will enable 10MHz FAST-SCSI transfers with your host - adaptor. Some systems have problems with that speed, so it's safest + adapter. Some systems have problems with that speed, so it's safest to say N here. allow DISCONNECT @@ -1779,7 +1821,7 @@ Always IN2000 SCSI support CONFIG_SCSI_IN2000 - This is support for an ISA bus SCSI host adaptor. You'll find more + This is support for an ISA bus SCSI host adapter. You'll find more information in drivers/scsi/in2000.readme. If it doesn't work out of the box, you may have to change the jumpers for IRQ or address selection. If you want to compile this as a module ( = code which @@ -1789,7 +1831,7 @@ PAS16 SCSI support CONFIG_SCSI_PAS16 - This is support for a SCSI host adaptor. It is explained in section + This is support for a SCSI host adapter. It is explained in section 3.10 of the SCSI-HOWTO, available via ftp (user: anonymous) at sunsite.unc.edu:/pub/Linux/docs/HOWTO. If it doesn't work out of the box, you may have to change some settings in drivers/scsi/pas16.h. @@ -1816,7 +1858,7 @@ Qlogic ISP SCSI support (EXPERIMENTAL) CONFIG_SCSI_QLOGIC_ISP - This driver works for all QLogic PCI SCSI host adaptors (IQ-PCI, + This driver works for all QLogic PCI SCSI host adapters (IQ-PCI, IQ-PCI-10, IQ_PCI-D) except for the PCI-basic card. (This latter card is supported by the "AM53/79C974 PCI SCSI" driver). If you say Y here, make sure to say Y to "PCI BIOS support" as well. More @@ -1843,7 +1885,7 @@ Trantor T128/T128F/T228 SCSI support CONFIG_SCSI_T128 - This is support for a SCSI host adaptor. It is explained in section + This is support for a SCSI host adapter. It is explained in section 3.11 of the SCSI-HOWTO, available via ftp (user: anonymous) at sunsite.unc.edu:/pub/Linux/docs/HOWTO. If it doesn't work out of the box, you may have to change some settings in @@ -1857,7 +1899,7 @@ UltraStor SCSI support CONFIG_SCSI_ULTRASTOR This is support for the UltraStor 14F, 24F and 34F SCSI-2 host - adaptor family. This driver is explained in section 3.12 of the + adapter family. This driver is explained in section 3.12 of the SCSI-HOWTO, available via ftp (user: anonymous) at sunsite.unc.edu:/pub/Linux/docs/HOWTO. If it doesn't work out of the box, you may have to change some settings in @@ -1870,7 +1912,7 @@ 7000FASST SCSI support CONFIG_SCSI_7000FASST - This driver supports the Western Digital 7000 SCSI host adaptor. + This driver supports the Western Digital 7000 SCSI host adapter. Some information is in the source: drivers/scsi/wd7000.c. This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). The @@ -1896,14 +1938,14 @@ enable tagged command queuing CONFIG_SCSI_EATA_TAGGED_QUEUE This is a feature of SCSI-2 which improves performance: the host - adaptor can send several SCSI commands to a device's queue even if + adapter can send several SCSI commands to a device's queue even if previous commands haven't finished yet. Some SCSI devices don't implement this properly, so the save answer is N. enable linked commands CONFIG_SCSI_EATA_LINKED_COMMANDS This is a feature of SCSI-2 which improves performance: the host - adaptor can send a whole list of commands to a device in one + adapter can send a whole list of commands to a device in one batch. Some SCSI devices might not implement this properly, so the save answer is N. @@ -3081,10 +3123,10 @@ by this driver. Read the Ethernet-HOWTO, available via ftp (user: anonymous) in sunsite.unc.edu:/pub/Linux/docs/HOWTO. -Pocket and portable adaptors +Pocket and portable adapters CONFIG_NET_POCKET Cute little network (ethernet) devices which attach to the parallel - port ("pocket adaptors"), commonly used with laptops. If you have + port ("pocket adapters"), commonly used with laptops. If you have one of those, say Y and read the Ethernet-HOWTO, available via ftp (user: anonymous) from sunsite.unc.edu:/pub/Linux/docs/HOWTO. If you want to plug a network card into the PCMCIA slot of your laptop @@ -3098,10 +3140,10 @@ plan to use more than one network device under linux, read the Multiple-Ethernet-mini-HOWTO, available from sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. If you intend to use an - adaptor attaching to the parallel port as well as a parallel + adapter attaching to the parallel port as well as a parallel printer, you should compile both drivers as modules (if possible). -AT-LAN-TEC/RealTek pocket adaptor support +AT-LAN-TEC/RealTek pocket adapter support CONFIG_ATP This is a network (ethernet) device which attaches to your parallel port. Read drivers/net/atp.c as well as the Ethernet-HOWTO, @@ -3113,7 +3155,7 @@ this driver, you should have said N to the Parallel Printer support, because the two drivers don't like each other. -D-Link DE600 pocket adaptor support +D-Link DE600 pocket adapter support CONFIG_DE600 This is a network (ethernet) device which attaches to your parallel port. Read drivers/net/README.DLINK as well as the Ethernet-HOWTO, @@ -3122,13 +3164,13 @@ you want to compile this as a module ( = code which can be inserted in and removed from the running kernel whenever you want), say M here and read Documentation/modules.txt. The module will be called - de600.o. If you intend to use this pocket adaptor as well as a + de600.o. If you intend to use this pocket adapter as well as a parallel printer, you should compile both drivers as modules. If you plan to use more than one network card under linux, read the Multiple-Ethernet-mini-HOWTO, available from sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. -D-Link DE620 pocket adaptor support +D-Link DE620 pocket adapter support CONFIG_DE620 This is a network (ethernet) device which attaches to your parallel port. Read drivers/net/README.DLINK as well as the Ethernet-HOWTO, @@ -3137,7 +3179,7 @@ you want to compile this as a module ( = code which can be inserted in and removed from the running kernel whenever you want), say M here and read Documentation/modules.txt. The module will be called - de620.o. If you intend to use this pocket adaptor as well as a + de620.o. If you intend to use this pocket adapter as well as a parallel printer, you should compile both drivers as modules. If you plan to use more than one network card under linux, read the Multiple-Ethernet-mini-HOWTO, available from @@ -3150,7 +3192,7 @@ ring network and want to use your Token Ring card under Linux, say Y. Most people can say N here. -IBM Tropic chipset based adaptor support +IBM Tropic chipset based adapter support CONFIG_IBMTR This is support for all IBM Token Ring cards that don't use DMA. If you have such a beast, say Y, otherwise N. Warning: this driver will diff -u --recursive --new-file v2.1.27/linux/MAINTAINERS linux/MAINTAINERS --- v2.1.27/linux/MAINTAINERS Thu Feb 27 10:57:29 1997 +++ linux/MAINTAINERS Fri Feb 28 15:15:42 1997 @@ -142,6 +142,7 @@ P: Leonard N. Zubkoff M: Leonard N. Zubkoff L: linux-scsi@vger.rutgers.edu +W: http://www.dandelion.com/Linux/ S: Maintained CYCLADES ASYNC MUX DRIVER @@ -301,6 +302,12 @@ P: Eddie C. Dost M: ecd@skynet.be L: sparclinux@vger.rutgers.edu +S: Maintained + +SCSI SUBSYSTEM +P: Leonard N. Zubkoff +M: Leonard N. Zubkoff +L: linux-scsi@vger.rutgers.edu S: Maintained SVGA HANDLING: diff -u --recursive --new-file v2.1.27/linux/Makefile linux/Makefile --- v2.1.27/linux/Makefile Thu Feb 27 10:57:29 1997 +++ linux/Makefile Thu Feb 27 10:57:04 1997 @@ -1,6 +1,6 @@ VERSION = 2 PATCHLEVEL = 1 -SUBLEVEL = 27 +SUBLEVEL = 28 ARCH = i386 diff -u --recursive --new-file v2.1.27/linux/arch/alpha/kernel/entry.S linux/arch/alpha/kernel/entry.S --- v2.1.27/linux/arch/alpha/kernel/entry.S Thu Feb 27 10:57:29 1997 +++ linux/arch/alpha/kernel/entry.S Fri Feb 28 14:53:24 1997 @@ -125,7 +125,7 @@ lda $0,intr_count ldl $1,0($0) addq $1,1,$1 - stq $1,0($0) + stl $1,0($0) /* set up the arguments to the C interrupt handler */ ldq $8,current_set jsr $26,do_entInt @@ -133,7 +133,7 @@ lda $0,intr_count ldl $1,0($0) subq $1,1,$1 - stq $1,0($0) + stl $1,0($0) br $31,ret_from_sys_call .end entInt @@ -710,7 +710,7 @@ /*0*/ .quad do_entSys, sys_exit, sys_fork, sys_read, sys_write .quad do_entSys, sys_close, sys_wait4, do_entSys, sys_link .quad sys_unlink, do_entSys, sys_chdir, sys_fchdir, sys_mknod - .quad sys_chmod, sys_chown, sys_brk, do_entSys, sys_lseek + .quad sys_chmod, sys_chown, osf_brk, do_entSys, sys_lseek .quad sys_getxpid, osf_mount, osf_umount, sys_setuid, sys_getxuid .quad do_entSys, sys_ptrace, do_entSys, do_entSys, do_entSys .quad do_entSys, do_entSys, do_entSys, sys_access, do_entSys diff -u --recursive --new-file v2.1.27/linux/arch/alpha/kernel/osf_sys.c linux/arch/alpha/kernel/osf_sys.c --- v2.1.27/linux/arch/alpha/kernel/osf_sys.c Sun Jan 26 04:26:39 1997 +++ linux/arch/alpha/kernel/osf_sys.c Thu Feb 27 10:49:38 1997 @@ -48,6 +48,20 @@ extern asmlinkage unsigned long sys_brk(unsigned long); /* + * Brk needs to return an error. Still support Linux's brk(0) query idiom, + * which OSF programs just shouldn't be doing. We're still not quite + * identical to OSF as we don't return 0 on success, but doing otherwise + * would require changes to libc. Hopefully this is good enough. + */ +asmlinkage unsigned long osf_brk(unsigned long brk) +{ + unsigned long retval = sys_brk(brk); + if (brk && brk != retval) + retval = -ENOMEM; + return retval; +} + +/* * This is pure guess-work.. */ asmlinkage int osf_set_program_attributes( diff -u --recursive --new-file v2.1.27/linux/arch/alpha/lib/csum_partial_copy.c linux/arch/alpha/lib/csum_partial_copy.c --- v2.1.27/linux/arch/alpha/lib/csum_partial_copy.c Thu Feb 6 02:44:41 1997 +++ linux/arch/alpha/lib/csum_partial_copy.c Thu Feb 27 14:15:47 1997 @@ -304,20 +304,14 @@ return checksum; } -unsigned int -csum_partial_copy_from_user(int *errp, char *src, char *dst, - int len, unsigned int sum) +static unsigned int +do_csum_partial_copy_from_user(char *src, char *dst, int len, + unsigned int sum, int *errp) { unsigned long checksum = (unsigned) sum; unsigned long soff = 7 & (unsigned long) src; unsigned long doff = 7 & (unsigned long) dst; - if (!access_ok(src, len, VERIFY_READ)) { - *errp = -EFAULT; - memset(dst, 0, len); - return checksum; - } - if (len) { if (!doff) { if (!soff) @@ -358,12 +352,25 @@ } unsigned int +csum_partial_copy_from_user(char *src, char *dst, int len, + unsigned int sum, int *errp) +{ + if (!access_ok(src, len, VERIFY_READ)) { + *errp = -EFAULT; + memset(dst, 0, len); + return sum; + } + + return do_csum_partial_copy_from_user(src, dst, len, sum, errp); +} + +unsigned int csum_partial_copy (const char *src, char *dst, int len, unsigned int sum) { unsigned int ret; int error = 0; - ret = csum_partial_copy_from_user(&error, src, dst, len, sum); + ret = do_csum_partial_copy_from_user(src, dst, len, sum, &error); if (error) printk("csum_partial_copy_old(): tell mingo to convert me!\n"); diff -u --recursive --new-file v2.1.27/linux/arch/i386/defconfig linux/arch/i386/defconfig --- v2.1.27/linux/arch/i386/defconfig Thu Feb 27 10:57:29 1997 +++ linux/arch/i386/defconfig Fri Feb 28 15:39:41 1997 @@ -120,6 +120,7 @@ # CONFIG_SCSI_IN2000 is not set # CONFIG_SCSI_AM53C974 is not set CONFIG_SCSI_BUSLOGIC=y +CONFIG_SCSI_OMIT_FLASHPOINT=y # CONFIG_SCSI_DTC3280 is not set # CONFIG_SCSI_EATA_DMA is not set # CONFIG_SCSI_EATA_PIO is not set @@ -201,11 +202,8 @@ # Character devices # CONFIG_SERIAL=y -# CONFIG_DIGI is not set -# CONFIG_CYCLADES is not set -# CONFIG_STALDRV is not set -# CONFIG_RISCOM8 is not set -# CONFIG_ESPSERIAL is not set +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set # CONFIG_PRINTER is not set CONFIG_MOUSE=y # CONFIG_ATIXL_BUSMOUSE is not set diff -u --recursive --new-file v2.1.27/linux/arch/i386/kernel/irq.c linux/arch/i386/kernel/irq.c --- v2.1.27/linux/arch/i386/kernel/irq.c Sun Jan 26 02:07:04 1997 +++ linux/arch/i386/kernel/irq.c Fri Feb 28 17:57:40 1997 @@ -349,7 +349,7 @@ int do_random = 0; lock_kernel(); - intr_count++; + atomic_inc(&intr_count); #ifdef __SMP__ if(smp_threads_ready && active_kernel_processor!=smp_processor_id()) panic("IRQ %d: active processor set wrongly(%d not %d).\n", irq, active_kernel_processor, smp_processor_id()); @@ -366,7 +366,7 @@ } if (do_random & SA_SAMPLE_RANDOM) add_interrupt_randomness(irq); - intr_count--; + atomic_dec(&intr_count); unlock_kernel(); } diff -u --recursive --new-file v2.1.27/linux/drivers/char/ChangeLog linux/drivers/char/ChangeLog --- v2.1.27/linux/drivers/char/ChangeLog Sun Dec 8 11:21:15 1996 +++ linux/drivers/char/ChangeLog Fri Feb 28 15:00:52 1997 @@ -1,3 +1,52 @@ +Thu Feb 27 01:53:08 1997 Theodore Ts'o + + * serial.c (change_speed): Add support for the termios flag + CMSPAR, which allows the user to select stick parity. + (i.e, if PARODD is set, the the parity bit is always 1; if + PARRODD is not set, then the parity bit is always 0). + +Wed Feb 26 19:03:10 1997 Theodore Ts'o + + * serial.c (cleanup_module): Fix memory leak when using the serial + driver as a module; make sure tmp_buf gets freed! + +Tue Feb 25 11:01:59 1997 Theodore Ts'o + + * serial.c (set_modem_info): Add support for setting and clearing + the OUT1 and OUT2 bits. (For special case UART's, usually + for half-duplex.) + (autoconfig, change_speed): Fix TI 16750 support. + +Sun Feb 16 00:14:43 1997 Theodore Ts'o + + * tty_io.c (release_dev): Add sanity check to make sure there are + no waiters on tty->read_wait or tty->write_wait. + + * serial.c (rs_init): Don't autoconfig a device if the I/O region + is already reserved. + + * serial.c (serial_proc_info): Add support for /proc/serial. + +Thu Feb 13 00:49:10 1997 Theodore Ts'o + + * serial.c (receive_chars): When the UART repotrs an overrun + condition, it does so with a valid character. Changed to + not throw away the valid character, but instead report the + overrun after the valid character. + + * serial.c: Added new #ifdef's for some of the advanced serial + driver features. A minimal driver that only supports COM + 1/2/3/4 without sharing serial interrupts only takes 17k; + the full driver takes 32k. + +Wed Feb 12 14:50:44 1997 Theodore Ts'o + + * vt.c: + * pty.c: + * tty_ioctl.c: + * serial.c: Update routines to use the new 2.1 memory access + routines. + Wed Dec 4 07:51:52 1996 Theodre Ts'o * serial.c (change_speed): Use save_flags(); cli() and diff -u --recursive --new-file v2.1.27/linux/drivers/char/Config.in linux/drivers/char/Config.in --- v2.1.27/linux/drivers/char/Config.in Sun Feb 2 05:51:42 1997 +++ linux/drivers/char/Config.in Fri Feb 28 15:00:53 1997 @@ -4,19 +4,29 @@ mainmenu_option next_comment comment 'Character devices' -tristate 'Standard/generic serial support' CONFIG_SERIAL -bool 'Digiboard PC/Xx Support' CONFIG_DIGI -tristate 'Cyclades async mux support' CONFIG_CYCLADES -bool 'Stallion multiport serial support' CONFIG_STALDRV -if [ "$CONFIG_STALDRV" = "y" ]; then - tristate ' Stallion EasyIO or EC8/32 support' CONFIG_STALLION - tristate ' Stallion EC8/64, ONboard, Brumby support' CONFIG_ISTALLION +tristate 'Standard/generic (dumb) serial support' CONFIG_SERIAL +bool 'Extended dumb serial driver options' CONFIG_SERIAL_EXTENDED +if [ "$CONFIG_SERIAL_EXTENDED" = "y" ]; then + bool ' Support more than 4 serial ports' CONFIG_SERIAL_MANY_PORTS + bool ' Support for sharing serial interrupts' CONFIG_SERIAL_SHARE_IRQ + bool ' Support special multiport boards' CONFIG_SERIAL_MULTIPORT + bool ' Support the Bell Technologies HUB6 card' CONFIG_HUB6 fi -tristate 'SDL RISCom/8 card support' CONFIG_RISCOM8 -tristate 'Hayes ESP serial port support' CONFIG_ESPSERIAL -if [ "$CONFIG_ESPSERIAL" = "y" -o "$CONFIG_ESPSERIAL" = "m" ]; then - int ' DMA channel' CONFIG_ESPSERIAL_DMA_CHANNEL 1 - int ' FIFO trigger level' CONFIG_ESPSERIAL_TRIGGER_LEVEL 768 +bool 'Non-standard serial port support' CONFIG_SERIAL_NONSTANDARD +if [ "$CONFIG_SERIAL_NONSTANDARD" = "y" ]; then + bool 'Digiboard PC/Xx Support' CONFIG_DIGI + tristate 'Cyclades async mux support' CONFIG_CYCLADES + bool 'Stallion multiport serial support' CONFIG_STALDRV + if [ "$CONFIG_STALDRV" = "y" ]; then + tristate ' Stallion EasyIO or EC8/32 support' CONFIG_STALLION + tristate ' Stallion EC8/64, ONboard, Brumby support' CONFIG_ISTALLION + fi + tristate 'SDL RISCom/8 card support' CONFIG_RISCOM8 + tristate 'Hayes ESP serial port support' CONFIG_ESPSERIAL + if [ "$CONFIG_ESPSERIAL" = "y" -o "$CONFIG_ESPSERIAL" = "m" ]; then + int ' DMA channel' CONFIG_ESPSERIAL_DMA_CHANNEL 1 + int ' FIFO trigger level' CONFIG_ESPSERIAL_TRIGGER_LEVEL 768 + fi fi tristate 'Parallel printer support' CONFIG_PRINTER diff -u --recursive --new-file v2.1.27/linux/drivers/char/n_tty.c linux/drivers/char/n_tty.c --- v2.1.27/linux/drivers/char/n_tty.c Sat Jan 25 13:46:13 1997 +++ linux/drivers/char/n_tty.c Fri Feb 28 15:00:53 1997 @@ -1010,6 +1010,7 @@ struct tty_ldisc tty_ldisc_N_TTY = { TTY_LDISC_MAGIC, /* magic */ + "n_tty", /* name */ 0, /* num */ 0, /* flags */ n_tty_open, /* open */ diff -u --recursive --new-file v2.1.27/linux/drivers/char/pty.c linux/drivers/char/pty.c --- v2.1.27/linux/drivers/char/pty.c Mon Oct 28 04:29:21 1996 +++ linux/drivers/char/pty.c Fri Feb 28 15:00:55 1997 @@ -4,14 +4,6 @@ * Copyright (C) 1991, 1992 Linus Torvalds */ -/* - * pty.c - * - * This module exports the following pty function: - * - * int pty_open(struct tty_struct * tty, struct file * filp); - */ - #include #include #include @@ -47,8 +39,8 @@ static unsigned char *tmp_buf; static struct semaphore tmp_buf_sem = MUTEX; -struct tty_driver pty_driver, pty_slave_driver; -struct tty_driver old_pty_driver, old_pty_slave_driver; +static struct tty_driver pty_driver, pty_slave_driver; +static struct tty_driver old_pty_driver, old_pty_slave_driver; static int pty_refcount; static struct tty_struct *pty_table[NR_PTYS]; @@ -74,8 +66,10 @@ } wake_up_interruptible(&tty->read_wait); wake_up_interruptible(&tty->write_wait); + tty->packet = 0; if (!tty->link) return; + tty->link->packet = 0; wake_up_interruptible(&tty->link->read_wait); wake_up_interruptible(&tty->link->write_wait); set_bit(TTY_OTHER_CLOSED, &tty->link->flags); @@ -125,7 +119,12 @@ ((tty->driver.subtype-1) * PTY_BUF_SIZE); while (count > 0) { n = MIN(count, PTY_BUF_SIZE); - copy_from_user(temp_buffer, buf, n); + n -= copy_from_user(temp_buffer, buf, n); + if (!n) { + if (!c) + c = -EFAULT; + break; + } r = to->ldisc.receive_room(to); if (r <= 0) break; @@ -179,7 +178,7 @@ } } -int pty_open(struct tty_struct *tty, struct file * filp) +static int pty_open(struct tty_struct *tty, struct file * filp) { int retval; int line; @@ -230,6 +229,7 @@ memset(&pty_state, 0, sizeof(pty_state)); memset(&pty_driver, 0, sizeof(struct tty_driver)); pty_driver.magic = TTY_DRIVER_MAGIC; + pty_driver.driver_name = "pty_master"; pty_driver.name = "pty"; pty_driver.major = PTY_MASTER_MAJOR; pty_driver.minor_start = 0; @@ -258,6 +258,8 @@ pty_driver.set_termios = pty_set_termios; pty_slave_driver = pty_driver; + pty_slave_driver.driver_name = "pty_slave"; + pty_slave_driver.proc_entry = 0; pty_slave_driver.name = "ttyp"; pty_slave_driver.subtype = PTY_TYPE_SLAVE; pty_slave_driver.major = PTY_SLAVE_MAJOR; @@ -270,12 +272,16 @@ pty_slave_driver.other = &pty_driver; old_pty_driver = pty_driver; + old_pty_driver.driver_name = "compat_pty_master"; + old_pty_driver.proc_entry = 0; old_pty_driver.major = TTY_MAJOR; old_pty_driver.minor_start = 128; old_pty_driver.num = (NR_PTYS > 64) ? 64 : NR_PTYS; old_pty_driver.other = &old_pty_slave_driver; old_pty_slave_driver = pty_slave_driver; + old_pty_slave_driver.driver_name = "compat_pty_slave"; + old_pty_slave_driver.proc_entry = 0; old_pty_slave_driver.major = TTY_MAJOR; old_pty_slave_driver.minor_start = 192; old_pty_slave_driver.num = (NR_PTYS > 64) ? 64 : NR_PTYS; diff -u --recursive --new-file v2.1.27/linux/drivers/char/random.c linux/drivers/char/random.c --- v2.1.27/linux/drivers/char/random.c Sat Jan 25 13:46:13 1997 +++ linux/drivers/char/random.c Fri Feb 28 15:00:52 1997 @@ -1,9 +1,9 @@ /* * random.c -- A strong random number generator * - * Version 1.00, last modified 26-May-96 + * Version 1.01, last modified 13-Feb-97 * - * Copyright Theodore Ts'o, 1994, 1995, 1996. All rights reserved. + * Copyright Theodore Ts'o, 1994, 1995, 1996, 1997. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -269,6 +269,21 @@ #endif /* + * For the purposes of better mixing, we use the CRC-32 polynomial as + * well to make a twisted Generalized Feedback Shift Reigster + * + * (See M. Matsumoto & Y. Kurita, 1992. Twisted GFSR generators. ACM + * Transactions on Modeling and Computer Simulation 2(3):179-194. + * Also see M. Matsumoto & Y. Kurita, 1994. Twisted GFSR generators + * II. ACM Transactions on Mdeling and Computer Simulation 4:254-266) + * + * Thanks to Colin Plumb for suggesting this. (Note that the behavior + * of the 1.0 version of the driver was equivalent to using a second + * element of 0x80000000). + */ +static __u32 twist_table[2] = { 0, 0xEDB88320 }; + +/* * The minimum number of bits to release a "wait on input". Should * probably always be 8, since a /dev/random read can return a single * byte. @@ -287,7 +302,7 @@ unsigned add_ptr; unsigned entropy_count; int input_rotate; - __u32 *pool; + __u32 pool[POOLWORDS]; }; #ifdef RANDOM_BENCHMARK @@ -321,13 +336,13 @@ }; static struct random_bucket random_state; -static __u32 random_pool[POOLWORDS]; static struct timer_rand_state keyboard_timer_state; static struct timer_rand_state mouse_timer_state; static struct timer_rand_state extract_timer_state; static struct timer_rand_state *irq_timer_state[NR_IRQS]; static struct timer_rand_state *blkdev_timer_state[MAX_BLKDEV]; -static struct wait_queue *random_wait; +static struct wait_queue *random_read_wait; +static struct wait_queue *random_write_wait; static long random_read(struct inode * inode, struct file * file, char * buf, unsigned long nbytes); @@ -432,11 +447,7 @@ /* Clear the entropy pool and associated counters. */ static void rand_clear_pool(void) { - random_state.add_ptr = 0; - random_state.entropy_count = 0; - random_state.pool = random_pool; - random_state.input_rotate = 0; - memset(random_pool, 0, sizeof(random_pool)); + memset(&random_state, 0, sizeof(random_state)); init_std_data(&random_state); } @@ -456,7 +467,8 @@ initialize_benchmark(&timer_benchmark, "timer", 0); #endif extract_timer_state.dont_count_entropy = 1; - random_wait = NULL; + random_read_wait = NULL; + random_write_wait = NULL; } void rand_initialize_irq(int irq) @@ -516,8 +528,6 @@ int new_rotate; __u32 w; - w = rotate_left(r->input_rotate, input); - i = r->add_ptr = (r->add_ptr - 1) & (POOLWORDS-1); /* * Normally, we add 7 bits of rotation to the pool. At the * beginning of the pool, add an extra 7 bits rotation, so @@ -525,19 +535,21 @@ * pool evenly. */ new_rotate = r->input_rotate + 14; - if (i) - new_rotate = r->input_rotate + 7; + if ((i = r->add_ptr--)) + new_rotate -= 7; r->input_rotate = new_rotate & 31; + w = rotate_left(r->input_rotate, input); + /* XOR in the various taps */ w ^= r->pool[(i+TAP1)&(POOLWORDS-1)]; w ^= r->pool[(i+TAP2)&(POOLWORDS-1)]; w ^= r->pool[(i+TAP3)&(POOLWORDS-1)]; w ^= r->pool[(i+TAP4)&(POOLWORDS-1)]; w ^= r->pool[(i+TAP5)&(POOLWORDS-1)]; - w ^= r->pool[i]; - /* Rotate w left 1 bit (stolen from SHA) and store */ - r->pool[i] = (w << 1) | (w >> 31); + w ^= r->pool[i&(POOLWORDS-1)]; + /* Use a twisted GFSR for the mixing operation */ + r->pool[i&(POOLWORDS-1)] = (w >> 1) ^ twist_table[w & 1]; } /* @@ -619,7 +631,7 @@ /* Wake up waiting processes, if we have enough entropy. */ if (r->entropy_count >= WAIT_INPUT_BITS) - wake_up_interruptible(&random_wait); + wake_up_interruptible(&random_read_wait); #ifdef RANDOM_BENCHMARK end_benchmark(&timer_benchmark); #endif @@ -662,6 +674,8 @@ #ifdef USE_SHA +#define SMALL_VERSION /* Optimize for space over time */ + #define HASH_BUFFER_SIZE 5 #define HASH_TRANSFORM SHATransform @@ -694,10 +708,14 @@ ( e += ROTL( 5, a ) + f( b, c, d ) + k + data, b = ROTL( 30, b ) ) -void SHATransform(__u32 *digest, __u32 *data) +static void SHATransform(__u32 *digest, __u32 *data) { __u32 A, B, C, D, E; /* Local vars */ __u32 eData[ 16 ]; /* Expanded data */ +#ifdef SMALL_VERSION + int i; + __u32 TEMP; +#endif /* Set up first buffer and local data buffer */ A = digest[ 0 ]; @@ -707,6 +725,25 @@ E = digest[ 4 ]; memcpy( eData, data, 16*sizeof(__u32)); +#ifdef SMALL_VERSION + /* + * Approximately 50% of the speed of the optimized version, but + * takes up 1/16 the space. Saves about 6k on an i386 kernel. + */ + for (i=0; i < 80; i++) { + if (i < 20) + TEMP = f1(B, C, D) + K1; + else if (i < 40) + TEMP = f2(B, C, D) + K2; + else if (i < 60) + TEMP = f3(B, C, D) + K3; + else + TEMP = f4(B, C, D) + K4; + TEMP += ROTL (5, A) + E + + ((i > 15) ? expand(eData, i) : eData[i]); + E = D; D = C; C = ROTL(30, B); B = A; A = TEMP; + } +#else /* Heavy mangling, in 4 sub-rounds of 20 iterations each. */ subRound( A, B, C, D, E, f1, K1, eData[ 0 ] ); subRound( E, A, B, C, D, f1, K1, eData[ 1 ] ); @@ -791,6 +828,7 @@ subRound( D, E, A, B, C, f4, K4, expand( eData, 77 ) ); subRound( C, D, E, A, B, f4, K4, expand( eData, 78 ) ); subRound( B, C, D, E, A, f4, K4, expand( eData, 79 ) ); +#endif /* SMALL_VERSION */ /* Build message digest */ digest[ 0 ] += A; @@ -938,12 +976,6 @@ __u32 tmp[HASH_BUFFER_SIZE]; char *cp,*dp; - if (to_user) { - ret = verify_area(VERIFY_WRITE, (void *) buf, nbytes); - if (ret) - return(ret); - } - add_timer_randomness(r, &extract_timer_state, nbytes); /* Redundant, but just in case... */ @@ -956,6 +988,9 @@ else r->entropy_count = 0; + if (r->entropy_count < WAIT_OUTPUT_BITS) + wake_up_interruptible(&random_write_wait); + while (nbytes) { /* Hash the pool to get the output */ tmp[0] = 0x67452301; @@ -995,9 +1030,13 @@ /* Copy data to destination buffer */ i = MIN(nbytes, HASH_BUFFER_SIZE*sizeof(__u32)/2); - if (to_user) - copy_to_user(buf, (__u8 const *)tmp, i); - else + if (to_user) { + i -= copy_to_user(buf, (__u8 const *)tmp, i); + if (!i) { + ret = -EFAULT; + break; + } + } else memcpy(buf, (__u8 const *)tmp, i); nbytes -= i; buf += i; @@ -1033,7 +1072,7 @@ if (nbytes == 0) return 0; - add_wait_queue(&random_wait, &wait); + add_wait_queue(&random_read_wait, &wait); while (nbytes > 0) { current->state = TASK_INTERRUPTIBLE; @@ -1065,7 +1104,7 @@ /* like a named pipe */ } current->state = TASK_RUNNING; - remove_wait_queue(&random_wait, &wait); + remove_wait_queue(&random_read_wait, &wait); /* * If we gave the user some bytes and we have an inode pointer, @@ -1091,9 +1130,10 @@ { unsigned int mask; - poll_wait(&random_wait, wait); + poll_wait(&random_read_wait, wait); + poll_wait(&random_write_wait, wait); mask = 0; - if (random_state.entropy_count >= 8) + if (random_state.entropy_count >= WAIT_INPUT_BITS) mask |= POLLIN | POLLRDNORM; if (random_state.entropy_count < WAIT_OUTPUT_BITS) mask |= POLLOUT | POLLWRNORM; @@ -1104,25 +1144,33 @@ random_write(struct inode * inode, struct file * file, const char * buffer, unsigned long count) { - int i; - __u32 word, *p; - - for (i = count, p = (__u32 *)buffer; - i >= sizeof(__u32); - i-= sizeof(__u32), p++) { - copy_from_user(&word, p, sizeof(__u32)); - add_entropy_word(&random_state, word); - } - if (i) { - word = 0; - copy_from_user(&word, p, i); - add_entropy_word(&random_state, word); + int i, bytes, ret = 0; + __u32 buf[16]; + const char *p = buffer; + int c = count; + + while (c > 0) { + bytes = MIN(c, sizeof(buf)); + + bytes -= copy_from_user(&buf, p, bytes); + if (!bytes) { + if (!ret) + ret = -EFAULT; + break; + } + c -= bytes; + p += bytes; + ret += bytes; + + i = (c+sizeof(__u32)-1) / sizeof(__u32); + while (i--) + add_entropy_word(&random_state, buf[i]); } - if (inode) { + if ((ret > 0) && inode) { inode->i_mtime = CURRENT_TIME; inode->i_dirt = 1; } - return count; + return ret; } static int @@ -1132,20 +1180,6 @@ int *p, size, ent_count; int retval; - /* - * Translate old 1.3.XX values. - * Remove this code in 2.1.0. - * - */ - switch (cmd) { - case 0x01080000: cmd = RNDGETENTCNT; break; - case 0x01080001: cmd = RNDADDTOENTCNT; break; - case 0x01080002: cmd = RNDGETPOOL; break; - case 0x01080003: cmd = RNDADDENTROPY; break; - case 0x01080004: cmd = RNDZAPENTCNT; break; - case 0x01080006: cmd = RNDCLEARPOOL; break; - } - switch (cmd) { case RNDGETENTCNT: retval = verify_area(VERIFY_WRITE, (void *) arg, sizeof(int)); @@ -1181,7 +1215,7 @@ * entropy. */ if (random_state.entropy_count >= WAIT_INPUT_BITS) - wake_up_interruptible(&random_wait); + wake_up_interruptible(&random_read_wait); return 0; case RNDGETPOOL: if (!suser()) @@ -1201,11 +1235,8 @@ return -EINVAL; if (size > POOLWORDS) size = POOLWORDS; - retval = verify_area(VERIFY_WRITE, (void *) p, - size * sizeof(__u32)); - if (retval) - return retval; - copy_to_user(p, random_state.pool, size*sizeof(__u32)); + if (copy_to_user(p, random_state.pool, size*sizeof(__u32))) + return -EFAULT; return 0; case RNDADDENTROPY: if (!suser()) @@ -1242,7 +1273,7 @@ * entropy. */ if (random_state.entropy_count >= WAIT_INPUT_BITS) - wake_up_interruptible(&random_wait); + wake_up_interruptible(&random_read_wait); return 0; case RNDZAPENTCNT: if (!suser()) diff -u --recursive --new-file v2.1.27/linux/drivers/char/serial.c linux/drivers/char/serial.c --- v2.1.27/linux/drivers/char/serial.c Sun Feb 2 05:21:13 1997 +++ linux/drivers/char/serial.c Fri Feb 28 15:02:02 1997 @@ -18,11 +18,13 @@ * rs_set_termios fixed to look also for changes of the input * flags INPCK, BRKINT, PARMRK, IGNPAR and IGNBRK. * Bernd Anhäupl 05/17/96. + * + * 1/97: Extended dumb serial ports are a config option now. + * Saves 4k. Michael A. Griffith * * This module exports the following rs232 io functions: * * int rs_init(void); - * int rs_open(struct tty_struct * tty, struct file * filp) */ #include @@ -50,17 +52,13 @@ #include static char *serial_name = "Serial driver"; -static char *serial_version = "4.22"; +static char *serial_version = "4.23"; -DECLARE_TASK_QUEUE(tq_serial); +static DECLARE_TASK_QUEUE(tq_serial); -struct tty_driver serial_driver, callout_driver; +static struct tty_driver serial_driver, callout_driver; static int serial_refcount; -/* serial subtype definitions */ -#define SERIAL_TYPE_NORMAL 1 -#define SERIAL_TYPE_CALLOUT 2 - /* number of characters left in xmit buffer before we ask for more */ #define WAKEUP_CHARS 256 @@ -71,6 +69,16 @@ * Enables support for the venerable Bell Technologies * HUB6 card. * + * CONFIG_SERIAL_MANY_PORTS + * Enables support for ports beyond the standard, stupid + * COM 1/2/3/4. + * + * CONFIG_SERIAL_MULTIPORT + * Enables support for special multiport board support. + * + * CONFIG_SERIAL_SHARE_IRQ + * Enables support for multiple serial ports on one IRQ + * * SERIAL_PARANOIA_CHECK * Check the magic number for the async_structure where * ever possible. @@ -80,6 +88,34 @@ #define CONFIG_SERIAL_NOPAUSE_IO #define SERIAL_DO_RESTART +#if 0 +/* Normally these defines are controlled by the autoconf.h */ + +#define CONFIG_SERIAL_MANY_PORTS +#define CONFIG_SERIAL_SHARE_IRQ +#define CONFIG_SERIAL_MULTIPORT +#define CONFIG_HUB6 +#endif + +/* Sanity checks */ + +#ifdef CONFIG_SERIAL_MULTIPORT +#ifndef CONFIG_SERIAL_SHARE_IRQ +#define CONFIG_SERIAL_SHARE_IRQ +#endif +#endif + +#ifdef CONFIG_HUB6 +#ifndef CONFIG_SERIAL_MANY_PORTS +#define CONFIG_SERIAL_MANY_PORTS +#endif +#ifndef CONFIG_SERIAL_SHARE_IRQ +#define CONFIG_SERIAL_SHARE_IRQ +#endif +#endif + +/* Set of debugging defines */ + #undef SERIAL_DEBUG_INTR #undef SERIAL_DEBUG_OPEN #undef SERIAL_DEBUG_FLOW @@ -105,7 +141,9 @@ */ static struct async_struct *IRQ_ports[16]; +#ifdef CONFIG_SERIAL_MULTIPORT static struct rs_multiport_struct rs_multiport[16]; +#endif static int IRQ_timeout[16]; static volatile int rs_irq_triggered; static volatile int rs_triggered; @@ -146,10 +184,13 @@ #define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST ) #define STD_COM4_FLAGS ASYNC_BOOT_AUTOCONF + +#ifdef CONFIG_SERIAL_MANY_PORTS #define FOURPORT_FLAGS ASYNC_FOURPORT #define ACCENT_FLAGS 0 #define BOCA_FLAGS 0 #define HUB6_FLAGS 0 +#endif /* * The following define the access methods for the HUB6 card. All @@ -167,13 +208,13 @@ #define C_P(card,port) (((card)<<6|(port)<<3) + 1) -struct serial_state rs_table[] = { +static struct serial_state rs_table[] = { /* UART CLK PORT IRQ FLAGS */ { 0, BASE_BAUD, 0x3F8, 4, STD_COM_FLAGS }, /* ttyS0 */ { 0, BASE_BAUD, 0x2F8, 3, STD_COM_FLAGS }, /* ttyS1 */ { 0, BASE_BAUD, 0x3E8, 4, STD_COM_FLAGS }, /* ttyS2 */ { 0, BASE_BAUD, 0x2E8, 3, STD_COM4_FLAGS }, /* ttyS3 */ - +#ifdef CONFIG_SERIAL_MANY_PORTS { 0, BASE_BAUD, 0x1A0, 9, FOURPORT_FLAGS }, /* ttyS4 */ { 0, BASE_BAUD, 0x1A8, 9, FOURPORT_FLAGS }, /* ttyS5 */ { 0, BASE_BAUD, 0x1B0, 9, FOURPORT_FLAGS }, /* ttyS6 */ @@ -223,6 +264,7 @@ { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,4) }, /* ttyS42 */ { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,5) }, /* ttyS43 */ #endif +#endif /* CONFIG_SERIAL_MANY_PORTS */ #ifdef CONFIG_MCA { 0, BASE_BAUD, 0x3220, 3, STD_COM_FLAGS }, { 0, BASE_BAUD, 0x3228, 3, STD_COM_FLAGS }, @@ -426,43 +468,79 @@ struct tty_struct *tty = info->tty; unsigned char ch; int ignored = 0; + struct async_icount *icount; + icount = &info->state->icount; do { ch = serial_inp(info, UART_RX); - if (*status & UART_LSR_BI) - *status &= ~(UART_LSR_FE | UART_LSR_PE); - if (*status & info->ignore_status_mask) { - if (++ignored > 100) - break; - goto ignore_char; - } - *status &= info->read_status_mask; if (tty->flip.count >= TTY_FLIPBUF_SIZE) break; - tty->flip.count++; - if (*status & (UART_LSR_BI)) { + *tty->flip.char_buf_ptr = ch; + icount->rx++; + #ifdef SERIAL_DEBUG_INTR - printk("handling break...."); + printk("DR%02x:%02x...", ch, *status); #endif - *tty->flip.flag_buf_ptr++ = TTY_BREAK; - if (info->flags & ASYNC_SAK) - do_SAK(tty); - } else if (*status & UART_LSR_PE) - *tty->flip.flag_buf_ptr++ = TTY_PARITY; - else if (*status & UART_LSR_FE) - *tty->flip.flag_buf_ptr++ = TTY_FRAME; - else if (*status & UART_LSR_OE) - *tty->flip.flag_buf_ptr++ = TTY_OVERRUN; - else - *tty->flip.flag_buf_ptr++ = 0; - *tty->flip.char_buf_ptr++ = ch; + *tty->flip.flag_buf_ptr = 0; + if (*status & (UART_LSR_BI | UART_LSR_PE | + UART_LSR_FE | UART_LSR_OE)) { + /* + * For statistics only + */ + if (*status & UART_LSR_BI) { + *status &= ~(UART_LSR_FE | UART_LSR_PE); + icount->brk++; + } else if (*status & UART_LSR_PE) + icount->parity++; + else if (*status & UART_LSR_FE) + icount->frame++; + if (*status & UART_LSR_OE) + icount->overrun++; + + /* + * Now check to see if character should be + * ignored, and mask off conditions which + * should be ignored. + */ + if (*status & info->ignore_status_mask) { + if (++ignored > 100) + break; + goto ignore_char; + } + *status &= info->read_status_mask; + + if (*status & (UART_LSR_BI)) { +#ifdef SERIAL_DEBUG_INTR + printk("handling break...."); +#endif + *tty->flip.flag_buf_ptr = TTY_BREAK; + if (info->flags & ASYNC_SAK) + do_SAK(tty); + } else if (*status & UART_LSR_PE) + *tty->flip.flag_buf_ptr = TTY_PARITY; + else if (*status & UART_LSR_FE) + *tty->flip.flag_buf_ptr = TTY_FRAME; + if (*status & UART_LSR_OE) { + /* + * Overrun is special, since it's + * reported immediately, and doesn't + * affect the current character + */ + if (tty->flip.count < TTY_FLIPBUF_SIZE) { + tty->flip.count++; + tty->flip.flag_buf_ptr++; + tty->flip.char_buf_ptr++; + *tty->flip.flag_buf_ptr = TTY_OVERRUN; + } + } + } + tty->flip.flag_buf_ptr++; + tty->flip.char_buf_ptr++; + tty->flip.count++; ignore_char: *status = serial_inp(info, UART_LSR); } while (*status & UART_LSR_DR); queue_task_irq_off(&tty->flip.tqueue, &tq_timer); -#ifdef SERIAL_DEBUG_INTR - printk("DR..."); -#endif } static _INLINE_ void transmit_chars(struct async_struct *info, int *intr_done) @@ -471,6 +549,7 @@ if (info->x_char) { serial_outp(info, UART_TX, info->x_char); + info->state->icount.tx++; info->x_char = 0; if (intr_done) *intr_done = 0; @@ -487,6 +566,7 @@ do { serial_out(info, UART_TX, info->xmit_buf[info->xmit_tail++]); info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1); + info->state->icount.tx++; if (--info->xmit_cnt <= 0) break; } while (--count > 0); @@ -574,6 +654,7 @@ } } +#ifdef CONFIG_SERIAL_SHARE_IRQ /* * This is the serial driver's generic interrupt routine */ @@ -583,8 +664,10 @@ struct async_struct * info; int pass_counter = 0; struct async_struct *end_mark = 0; +#ifdef CONFIG_SERIAL_MULTIPORT int first_multi = 0; struct rs_multiport_struct *multi; +#endif #ifdef SERIAL_DEBUG_INTR printk("rs_interrupt(%d)...", irq); @@ -594,9 +677,11 @@ if (!info) return; +#ifdef CONFIG_SERIAL_MULTIPORT multi = &rs_multiport[irq]; if (multi->port_monitor) first_multi = inb(multi->port_monitor); +#endif do { if (!info->tty || @@ -632,14 +717,18 @@ continue; } } while (end_mark != info); +#ifdef CONFIG_SERIAL_MULTIPORT if (multi->port_monitor) printk("rs port monitor (normal) irq %d: 0x%x, 0x%x\n", info->state->irq, first_multi, inb(multi->port_monitor)); +#endif #ifdef SERIAL_DEBUG_INTR printk("end.\n"); #endif } +#endif /* #ifdef CONFIG_SERIAL_SHARE_IRQ */ + /* * This is the serial driver's interrupt routine for a single port @@ -648,9 +737,11 @@ { int status; int pass_counter = 0; - int first_multi = 0; struct async_struct * info; +#ifdef CONFIG_SERIAL_MULTIPORT + int first_multi = 0; struct rs_multiport_struct *multi; +#endif #ifdef SERIAL_DEBUG_INTR printk("rs_interrupt_single(%d)...", irq); @@ -660,9 +751,11 @@ if (!info || !info->tty) return; +#ifdef CONFIG_SERIAL_MULTIPORT multi = &rs_multiport[irq]; if (multi->port_monitor) first_multi = inb(multi->port_monitor); +#endif do { status = serial_inp(info, UART_LSR); @@ -682,15 +775,18 @@ } } while (!(serial_in(info, UART_IIR) & UART_IIR_NO_INT)); info->last_active = jiffies; +#ifdef CONFIG_SERIAL_MULTIPORT if (multi->port_monitor) printk("rs port monitor (single) irq %d: 0x%x, 0x%x\n", info->state->irq, first_multi, inb(multi->port_monitor)); +#endif #ifdef SERIAL_DEBUG_INTR printk("end.\n"); #endif } +#ifdef CONFIG_SERIAL_MULTIPORT /* * This is the serial driver's for multiport boards */ @@ -771,7 +867,7 @@ printk("end.\n"); #endif } - +#endif /* * ------------------------------------------------------------------- @@ -851,6 +947,7 @@ if (!info) continue; cli(); +#ifdef CONFIG_SERIAL_SHARE_IRQ if (info->next_port) { do { serial_out(info, UART_IER, 0); @@ -858,11 +955,14 @@ serial_out(info, UART_IER, info->IER); info = info->next_port; } while (info); +#ifdef CONFIG_SERIAL_MULTIPORT if (rs_multiport[i].port1) rs_interrupt_multi(i, NULL, NULL); else +#endif rs_interrupt(i, NULL, NULL); } else +#endif /* CONFIG_SERIAL_SHARE_IRQ */ rs_interrupt_single(i, NULL, NULL); sti(); } @@ -873,7 +973,11 @@ if (IRQ_ports[0]) { cli(); +#ifdef CONFIG_SERIAL_SHARE_IRQ rs_interrupt(0, NULL, NULL); +#else + rs_interrupt_single(0, NULL, NULL); +#endif sti(); timer_table[RS_TIMER].expires = jiffies + IRQ_timeout[0] - 2; @@ -948,12 +1052,15 @@ static int startup(struct async_struct * info) { - unsigned short ICP; unsigned long flags; int retval; void (*handler)(int, void *, struct pt_regs *); struct serial_state *state= info->state; unsigned long page; +#ifdef CONFIG_SERIAL_MANY_PORTS + unsigned short ICP; +#endif + page = get_free_page(GFP_KERNEL); if (!page) @@ -1026,11 +1133,17 @@ if (state->irq && (!IRQ_ports[state->irq] || !IRQ_ports[state->irq]->next_port)) { if (IRQ_ports[state->irq]) { +#ifdef CONFIG_SERIAL_SHARE_IRQ free_irq(state->irq, NULL); +#ifdef CONFIG_SERIAL_MULTIPORT if (rs_multiport[state->irq].port1) handler = rs_interrupt_multi; else +#endif handler = rs_interrupt; +#else + return -EBUSY; +#endif /* CONFIG_SERIAL_SHARE_IRQ */ } else handler = rs_interrupt_single; @@ -1074,10 +1187,13 @@ info->MCR = 0; if (info->tty->termios->c_cflag & CBAUD) info->MCR = UART_MCR_DTR | UART_MCR_RTS; +#ifdef CONFIG_SERIAL_MANY_PORTS if (info->flags & ASYNC_FOURPORT) { if (state->irq == 0) info->MCR |= UART_MCR_OUT1; - } else { + } else +#endif + { if (state->irq != 0) info->MCR |= UART_MCR_OUT2; } @@ -1095,12 +1211,14 @@ info->IER = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI; serial_outp(info, UART_IER, info->IER); /* enable interrupts */ +#ifdef CONFIG_SERIAL_MANY_PORTS if (info->flags & ASYNC_FOURPORT) { /* Enable interrupts on the AST Fourport board */ ICP = (info->port & 0xFE0) | 0x01F; outb_p(0x80, ICP); (void) inb_p(ICP); } +#endif /* * And clear the interrupt registers again for luck. @@ -1193,11 +1311,13 @@ info->IER = 0; serial_outp(info, UART_IER, 0x00); /* disable all intrs */ +#ifdef CONFIG_SERIAL_MANY_PORTS if (info->flags & ASYNC_FOURPORT) { /* reset interrupts on the AST Fourport board */ (void) inb((info->port & 0xFE0) | 0x01F); info->MCR |= UART_MCR_OUT1; } else +#endif info->MCR &= ~UART_MCR_OUT2; #if defined(__alpha__) && !defined(CONFIG_PCI) /* @@ -1270,6 +1390,10 @@ } if (!(cflag & PARODD)) cval |= UART_LCR_EPAR; +#ifdef CMSPAR + if (cflag & CMSPAR) + cval |= UART_LCR_SPAR; +#endif /* Determine divisor based on baud rate */ i = cflag & CBAUD; @@ -1303,6 +1427,7 @@ if (!quot) quot = baud_base / 9600; } + info->quot = quot; info->timeout = ((info->xmit_fifo_size*HZ*bits*quot) / baud_base); info->timeout += HZ/50; /* Add .02 seconds of slop */ @@ -1376,7 +1501,8 @@ if (info->state->type == PORT_16750) serial_outp(info, UART_FCR, fcr); /* set fcr */ serial_outp(info, UART_LCR, cval); /* reset DLAB */ - serial_outp(info, UART_FCR, fcr); /* set fcr */ + if (info->state->type != PORT_16750) + serial_outp(info, UART_FCR, fcr); /* set fcr */ restore_flags(flags); } @@ -1424,7 +1550,7 @@ static int rs_write(struct tty_struct * tty, int from_user, const unsigned char *buf, int count) { - int c, total = 0; + int c, ret = 0; struct async_struct *info = (struct async_struct *)tty->driver_data; unsigned long flags; @@ -1445,7 +1571,12 @@ break; if (from_user) { - copy_from_user(tmp_buf, buf, c); + c -= copy_from_user(tmp_buf, buf, c); + if (!c) { + if (!ret) + ret = -EFAULT; + break; + } c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, SERIAL_XMIT_SIZE - info->xmit_head)); memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c); @@ -1456,7 +1587,7 @@ restore_flags(flags); buf += c; count -= c; - total += c; + ret += c; } if (from_user) up(&tmp_buf_sem); @@ -1466,7 +1597,7 @@ serial_out(info, UART_IER, info->IER); } restore_flags(flags); - return total; + return ret; } static int rs_write_room(struct tty_struct *tty) @@ -1510,7 +1641,7 @@ * This function is used to send a high-priority XON/XOFF character to * the device */ -void rs_send_xchar(struct tty_struct *tty, char ch) +static void rs_send_xchar(struct tty_struct *tty, char ch) { struct async_struct *info = (struct async_struct *)tty->driver_data; @@ -1609,7 +1740,8 @@ tmp.closing_wait = state->closing_wait; tmp.custom_divisor = state->custom_divisor; tmp.hub6 = state->hub6; - copy_to_user(retinfo,&tmp,sizeof(*retinfo)); + if (copy_to_user(retinfo,&tmp,sizeof(*retinfo))) + return -EFAULT; return 0; } @@ -1621,9 +1753,8 @@ unsigned int i,change_irq,change_port; int retval = 0; - if (!new_info) + if (copy_from_user(&new_serial,new_info,sizeof(new_serial))) return -EFAULT; - copy_from_user(&new_serial,new_info,sizeof(new_serial)); state = info->state; old_state = *state; @@ -1734,8 +1865,7 @@ status = serial_in(info, UART_LSR); sti(); result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0); - put_user(result,value); - return 0; + return put_user(result,value); } @@ -1750,12 +1880,15 @@ sti(); result = ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) | ((control & UART_MCR_DTR) ? TIOCM_DTR : 0) +#ifdef TIOCM_OUT1 + | ((control & UART_MCR_OUT1) ? TIOCM_OUT1 : 0) + | ((control & UART_MCR_OUT2) ? TIOCM_OUT2 : 0) +#endif | ((status & UART_MSR_DCD) ? TIOCM_CAR : 0) | ((status & UART_MSR_RI) ? TIOCM_RNG : 0) | ((status & UART_MSR_DSR) ? TIOCM_DSR : 0) | ((status & UART_MSR_CTS) ? TIOCM_CTS : 0); - put_user(result,value); - return 0; + return put_user(result,value); } static int set_modem_info(struct async_struct * info, unsigned int cmd, @@ -1773,16 +1906,37 @@ info->MCR |= UART_MCR_RTS; if (arg & TIOCM_DTR) info->MCR |= UART_MCR_DTR; +#ifdef TIOCM_OUT1 + if (arg & TIOCM_OUT1) + info->MCR |= UART_MCR_OUT1; + if (arg & TIOCM_OUT2) + info->MCR |= UART_MCR_OUT2; +#endif break; case TIOCMBIC: if (arg & TIOCM_RTS) info->MCR &= ~UART_MCR_RTS; if (arg & TIOCM_DTR) info->MCR &= ~UART_MCR_DTR; +#ifdef TIOCM_OUT1 + if (arg & TIOCM_OUT1) + info->MCR &= ~UART_MCR_OUT1; + if (arg & TIOCM_OUT2) + info->MCR &= ~UART_MCR_OUT2; +#endif break; case TIOCMSET: - info->MCR = ((info->MCR & ~(UART_MCR_RTS | UART_MCR_DTR)) + info->MCR = ((info->MCR & ~(UART_MCR_RTS | +#ifdef TIOCM_OUT1 + UART_MCR_OUT1 | + UART_MCR_OUT2 | +#endif + UART_MCR_DTR)) | ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0) +#ifdef TIOCM_OUT1 + | ((arg & TIOCM_OUT1) ? UART_MCR_OUT1 : 0) + | ((arg & TIOCM_OUT2) ? UART_MCR_OUT2 : 0) +#endif | ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0)); break; default: @@ -1883,6 +2037,7 @@ return wild_interrupts; } +#ifdef CONFIG_SERIAL_MULTIPORT static int get_multiport_struct(struct async_struct * info, struct serial_multiport_struct *retinfo) { @@ -1911,9 +2066,9 @@ ret.irq = info->state->irq; - copy_to_user(retinfo,&ret,sizeof(*retinfo)); + if (copy_to_user(retinfo,&ret,sizeof(*retinfo))) + return -EFAULT; return 0; - } static int set_multiport_struct(struct async_struct * info, @@ -1928,13 +2083,12 @@ if (!suser()) return -EPERM; - if (!in_multi) - return -EFAULT; state = info->state; - copy_from_user(&new_multi, in_multi, - sizeof(struct serial_multiport_struct)); - + if (copy_from_user(&new_multi, in_multi, + sizeof(struct serial_multiport_struct))) + return -EFAULT; + if (new_multi.irq != state->irq || state->irq == 0 || !IRQ_ports[state->irq]) return -EINVAL; @@ -1996,6 +2150,7 @@ return 0; } +#endif static int rs_ioctl(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg) @@ -2053,82 +2208,52 @@ (arg ? CLOCAL : 0)); return 0; case TIOCMGET: - error = verify_area(VERIFY_WRITE, (void *) arg, - sizeof(unsigned int)); - if (error) - return error; return get_modem_info(info, (unsigned int *) arg); case TIOCMBIS: case TIOCMBIC: case TIOCMSET: return set_modem_info(info, cmd, (unsigned int *) arg); case TIOCGSERIAL: - error = verify_area(VERIFY_WRITE, (void *) arg, - sizeof(struct serial_struct)); - if (error) - return error; return get_serial_info(info, (struct serial_struct *) arg); case TIOCSSERIAL: - error = verify_area(VERIFY_READ, (void *) arg, - sizeof(struct serial_struct)); - if (error) - return error; return set_serial_info(info, (struct serial_struct *) arg); case TIOCSERCONFIG: return do_autoconfig(info); case TIOCSERGWILD: - error = verify_area(VERIFY_WRITE, (void *) arg, - sizeof(int)); - if (error) - return error; - put_user(rs_wild_int_mask, (unsigned int *) arg); - return 0; - + return put_user(rs_wild_int_mask, + (unsigned int *) arg); case TIOCSERGETLSR: /* Get line status register */ - error = verify_area(VERIFY_WRITE, (void *) arg, - sizeof(unsigned int)); - if (error) - return error; - else - return get_lsr_info(info, (unsigned int *) arg); + return get_lsr_info(info, (unsigned int *) arg); case TIOCSERSWILD: if (!suser()) return -EPERM; - error = verify_area(VERIFY_READ, (void *) arg,sizeof(long)); + error = get_user(rs_wild_int_mask, + (unsigned int *) arg); if (error) return error; - get_user(rs_wild_int_mask, (unsigned int *) arg); if (rs_wild_int_mask < 0) rs_wild_int_mask = check_wild_interrupts(0); return 0; case TIOCSERGSTRUCT: - error = verify_area(VERIFY_WRITE, (void *) arg, - sizeof(struct async_struct)); - if (error) - return error; - copy_to_user((struct async_struct *) arg, - info, sizeof(struct async_struct)); + if (copy_to_user((struct async_struct *) arg, + info, sizeof(struct async_struct))) + return -EFAULT; return 0; - + +#ifdef CONFIG_SERIAL_MULTIPORT case TIOCSERGETMULTI: - error = verify_area(VERIFY_WRITE, (void *) arg, - sizeof(struct serial_multiport_struct)); - if (error) - return error; return get_multiport_struct(info, (struct serial_multiport_struct *) arg); case TIOCSERSETMULTI: - error = verify_area(VERIFY_READ, (void *) arg, - sizeof(struct serial_multiport_struct)); - if (error) - return error; return set_multiport_struct(info, (struct serial_multiport_struct *) arg); +#endif + /* * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change * - mask passed in arg for lines of interest @@ -2168,18 +2293,18 @@ * RI where only 0->1 is counted. */ case TIOCGICOUNT: - error = verify_area(VERIFY_WRITE, (void *) arg, - sizeof(struct serial_icounter_struct)); - if (error) - return error; cli(); cnow = info->state->icount; sti(); p_cuser = (struct serial_icounter_struct *) arg; - put_user(cnow.cts, &p_cuser->cts); - put_user(cnow.dsr, &p_cuser->dsr); - put_user(cnow.rng, &p_cuser->rng); - put_user(cnow.dcd, &p_cuser->dcd); + error = put_user(cnow.cts, &p_cuser->cts); + if (error) return error; + error = put_user(cnow.dsr, &p_cuser->dsr); + if (error) return error; + error = put_user(cnow.rng, &p_cuser->rng); + if (error) return error; + error = put_user(cnow.dcd, &p_cuser->dcd); + if (error) return error; return 0; default: @@ -2409,7 +2534,7 @@ /* * rs_hangup() --- called by tty_hangup() when a hangup is signaled. */ -void rs_hangup(struct tty_struct *tty) +static void rs_hangup(struct tty_struct *tty) { struct async_struct * info = (struct async_struct *)tty->driver_data; struct serial_state *state = info->state; @@ -2567,7 +2692,7 @@ return 0; } -int get_async_struct(int line, struct async_struct **ret_info) +static int get_async_struct(int line, struct async_struct **ret_info) { struct async_struct *info; struct serial_state *sstate; @@ -2609,7 +2734,7 @@ * the IRQ chain. It also performs the serial-specific * initialization for the tty structure. */ -int rs_open(struct tty_struct *tty, struct file * filp) +static int rs_open(struct tty_struct *tty, struct file * filp) { struct async_struct *info; int retval, line; @@ -2677,6 +2802,106 @@ } /* + * /proc fs routines.... + */ + +static int inline line_info(char *buf, struct serial_state *state) +{ + struct async_struct *info = state->info, scr_info; + char stat_buf[30], control, status; + int ret; + + ret = sprintf(buf, "%d: uart:%s port:%X irq:%d", + state->line, uart_config[state->type].name, + state->port, state->irq); + + if (!state->port || (state->type == PORT_UNKNOWN)) { + ret += sprintf(buf+ret, "\n"); + return ret; + } + + /* + * Figure out the current RS-232 lines + */ + if (!info) { + info = &scr_info; /* This is just for serial_{in,out} */ + + info->magic = SERIAL_MAGIC; + info->port = state->port; + info->flags = state->flags; + info->quot = 0; + info->tty = 0; + } + cli(); + status = serial_in(info, UART_MSR); + control = info ? info->MCR : serial_in(info, UART_MCR); + sti(); + + stat_buf[0] = 0; + stat_buf[1] = 0; + if (control & UART_MCR_RTS) + strcat(stat_buf, "|RTS"); + if (status & UART_MSR_CTS) + strcat(stat_buf, "|CTS"); + if (control & UART_MCR_DTR) + strcat(stat_buf, "|DTR"); + if (status & UART_MSR_DSR) + strcat(stat_buf, "|DSR"); + if (status & UART_MSR_DCD) + strcat(stat_buf, "|CD"); + if (status & UART_MSR_RI) + strcat(stat_buf, "|RI"); + + if (info->quot) { + ret += sprintf(buf+ret, " baud:%d", + state->baud_base / info->quot); + } + + ret += sprintf(buf+ret, " tx:%d rx:%d", + state->icount.tx, state->icount.rx); + + if (state->icount.frame) + ret += sprintf(buf+ret, " fe:%d", state->icount.frame); + + if (state->icount.parity) + ret += sprintf(buf+ret, " pe:%d", state->icount.parity); + + if (state->icount.brk) + ret += sprintf(buf+ret, " brk:%d", state->icount.brk); + + if (state->icount.overrun) + ret += sprintf(buf+ret, " oe:%d", state->icount.overrun); + + /* + * Last thing is the RS-232 status lines + */ + ret += sprintf(buf+ret, " %s\n", stat_buf+1); + return ret; +} + +int rs_read_proc(char *page, char **start, off_t off, int count, void + *data) +{ + int i, len = 0; + off_t begin = 0; + + len += sprintf(page, "serinfo:1.0 driver:%s\n", serial_version); + for (i = 0; i < NR_PORTS && len < 4000; i++) { + len += line_info(page + len, &rs_table[i]); + if (len+begin > off+count) + break; + if (len+begin < off) { + begin += len; + len = 0; + } + } + if (off >= len+begin) + return 0; + *start = page + (begin-off); + return ((count < begin+len-off) ? count : begin+len-off); +} + +/* * --------------------------------------------------------------------- * rs_init() and friends * @@ -2711,9 +2936,14 @@ */ static int get_auto_irq(struct async_struct *info) { - unsigned char save_MCR, save_IER, save_ICP=0; - unsigned short ICP=0, port = info->port; + + unsigned char save_MCR, save_IER; unsigned long timeout; +#ifdef CONFIG_SERIAL_MANY_PORTS + unsigned char save_ICP=0; + unsigned short ICP=0, port = info->port; +#endif + /* * Enable interrupts and see who answers @@ -2722,6 +2952,7 @@ cli(); save_IER = serial_inp(info, UART_IER); save_MCR = serial_inp(info, UART_MCR); +#ifdef CONFIG_SERIAL_MANY_PORTS if (info->flags & ASYNC_FOURPORT) { serial_outp(info, UART_MCR, UART_MCR_DTR | UART_MCR_RTS); serial_outp(info, UART_IER, 0x0f); /* enable all intrs */ @@ -2729,7 +2960,9 @@ save_ICP = inb_p(ICP); outb_p(0x80, ICP); (void) inb_p(ICP); - } else { + } else +#endif + { serial_outp(info, UART_MCR, UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2); serial_outp(info, UART_IER, 0x0f); /* enable all intrs */ @@ -2754,8 +2987,10 @@ cli(); serial_outp(info, UART_IER, save_IER); serial_outp(info, UART_MCR, save_MCR); +#ifdef CONFIG_SERIAL_MANY_PORTS if (info->flags & ASYNC_FOURPORT) outb_p(save_ICP, ICP); +#endif sti(); return(rs_irq_triggered); } @@ -2912,7 +3147,7 @@ serial_outp(info, UART_LCR, 0); serial_outp(info, UART_FCR, UART_FCR_ENABLE_FIFO); scratch = serial_in(info, UART_IIR) >> 5; - if (scratch == 7) + if (scratch == 6) state->type = PORT_16750; } serial_outp(info, UART_FCR, UART_FCR_ENABLE_FIFO); @@ -2981,7 +3216,10 @@ for (i = 0; i < 16; i++) { IRQ_ports[i] = 0; IRQ_timeout[i] = 0; - memset(&rs_multiport[i], 0, sizeof(struct rs_multiport_struct)); +#ifdef CONFIG_SERIAL_MULTIPORT + memset(&rs_multiport[i], 0, + sizeof(struct rs_multiport_struct)); +#endif } show_serial_version(); @@ -2990,6 +3228,7 @@ memset(&serial_driver, 0, sizeof(struct tty_driver)); serial_driver.magic = TTY_DRIVER_MAGIC; + serial_driver.driver_name = "serial"; serial_driver.name = "ttyS"; serial_driver.major = TTY_MAJOR; serial_driver.minor_start = 64; @@ -3022,7 +3261,8 @@ serial_driver.start = rs_start; serial_driver.hangup = rs_hangup; serial_driver.wait_until_sent = rs_wait_until_sent; - + serial_driver.read_proc = rs_read_proc; + /* * The callout device is just like normal device except for * major number and the subtype code. @@ -3031,6 +3271,8 @@ callout_driver.name = "cua"; callout_driver.major = TTYAUX_MAJOR; callout_driver.subtype = SERIAL_TYPE_CALLOUT; + callout_driver.read_proc = 0; + callout_driver.proc_entry = 0; if (tty_register_driver(&serial_driver)) panic("Couldn't register serial driver\n"); @@ -3048,22 +3290,26 @@ state->normal_termios = serial_driver.init_termios; state->icount.cts = state->icount.dsr = state->icount.rng = state->icount.dcd = 0; + state->icount.rx = state->icount.tx = 0; + state->icount.frame = state->icount.parity = 0; + state->icount.overrun = state->icount.brk = 0; if (state->irq == 2) state->irq = 9; if (state->type == PORT_UNKNOWN) { if (!(state->flags & ASYNC_BOOT_AUTOCONF)) continue; + if (check_region(state->port,8)) + continue; autoconfig(state); if (state->type == PORT_UNKNOWN) continue; } - printk(KERN_INFO "tty%02d%s at 0x%04x (irq = %d) is a %s\n", + printk(KERN_INFO "ttyS%02d%s at 0x%04x (irq = %d) is a %s\n", state->line, (state->flags & ASYNC_FOURPORT) ? " FourPort" : "", state->port, state->irq, uart_config[state->type].name); } - return 0; } @@ -3161,5 +3407,10 @@ if (rs_table[i].type != PORT_UNKNOWN) release_region(rs_table[i].port, 8); } + if (tmp_buf) { + free_page((unsigned long) tmp_buf); + tmp_buf = NULL; + } } #endif /* MODULE */ + diff -u --recursive --new-file v2.1.27/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c --- v2.1.27/linux/drivers/char/tty_io.c Sun Jan 26 02:07:17 1997 +++ linux/drivers/char/tty_io.c Fri Feb 28 15:00:53 1997 @@ -63,6 +63,9 @@ #include #include #include +#ifdef CONFIG_PROC_FS +#include +#endif #include #include @@ -1135,6 +1138,25 @@ return; /* + * Sanity check --- if tty->count is zero, there shouldn't be + * any waiters on tty->read_wait or tty->write_wait. But just + * in case.... + */ + while (1) { + if (waitqueue_active(&tty->read_wait)) { + printk("release_dev: %s: read_wait active?!?\n", + tty_name(tty)); + wake_up(&tty->read_wait); + } else if (waitqueue_active(&tty->write_wait)) { + printk("release_dev: %s: write_wait active?!?\n", + tty_name(tty)); + wake_up(&tty->write_wait); + } else + break; + schedule(); + } + + /* * We're committed; at this point, we must not block! */ if (o_tty) { @@ -1232,7 +1254,9 @@ int minor; int noctty, retval; kdev_t device; + unsigned short saved_flags; + saved_flags = filp->f_flags; retry_open: noctty = filp->f_flags & O_NOCTTY; device = inode->i_rdev; @@ -1240,6 +1264,7 @@ if (!current->tty) return -ENXIO; device = current->tty->device; + filp->f_flags |= O_NONBLOCK; /* Don't let /dev/tty block */ /* noctty = 1; */ } if (device == CONSOLE_DEV) { @@ -1263,6 +1288,7 @@ retval = tty->driver.open(tty, filp); else retval = -ENODEV; + filp->f_flags = saved_flags; if (!retval && test_bit(TTY_EXCLUSIVE, &tty->flags) && !suser()) retval = -EBUSY; @@ -1830,6 +1856,10 @@ driver->next = tty_drivers; if (tty_drivers) tty_drivers->prev = driver; tty_drivers = driver; + +#ifdef CONFIG_PROC_FS + proc_tty_register_driver(driver); +#endif return error; } @@ -1871,6 +1901,9 @@ if (driver->next) driver->next->prev = driver->prev; +#ifdef CONFIG_PROC_FS + proc_tty_unregister_driver(driver); +#endif return 0; } @@ -1925,18 +1958,24 @@ */ memset(&dev_tty_driver, 0, sizeof(struct tty_driver)); dev_tty_driver.magic = TTY_DRIVER_MAGIC; - dev_tty_driver.name = "tty"; + dev_tty_driver.driver_name = "/dev/tty"; + dev_tty_driver.name = dev_tty_driver.driver_name + 5; dev_tty_driver.name_base = 0; dev_tty_driver.major = TTY_MAJOR; dev_tty_driver.minor_start = 0; dev_tty_driver.num = 1; + dev_tty_driver.type = TTY_DRIVER_TYPE_SYSTEM; + dev_tty_driver.subtype = SYSTEM_TYPE_TTY; if (tty_register_driver(&dev_tty_driver)) panic("Couldn't register /dev/tty driver\n"); dev_console_driver = dev_tty_driver; - dev_console_driver.name = "console"; + dev_console_driver.driver_name = "/dev/console"; + dev_console_driver.name = dev_console_driver.driver_name + 5; dev_console_driver.major = TTYAUX_MAJOR; + dev_console_driver.type = TTY_DRIVER_TYPE_SYSTEM; + dev_console_driver.subtype = SYSTEM_TYPE_CONSOLE; if (tty_register_driver(&dev_console_driver)) panic("Couldn't register /dev/console driver\n"); diff -u --recursive --new-file v2.1.27/linux/drivers/char/tty_ioctl.c linux/drivers/char/tty_ioctl.c --- v2.1.27/linux/drivers/char/tty_ioctl.c Mon Dec 30 02:44:34 1996 +++ linux/drivers/char/tty_ioctl.c Fri Feb 28 15:00:55 1997 @@ -163,10 +163,10 @@ memcpy(&tmp_termios, tty->termios, sizeof(struct termios)); user_termio_to_kernel_termios(&tmp_termios, (struct termio *) arg); } else { - retval = verify_area(VERIFY_READ, (void *) arg, sizeof(struct termios)); + retval = user_termios_to_kernel_termios + (&tmp_termios, (struct termios *) arg); if (retval) return retval; - user_termios_to_kernel_termios(&tmp_termios, (struct termios *) arg); } if ((opt & TERMIOS_FLUSH) && tty->ldisc.flush_buffer) @@ -240,15 +240,13 @@ int retval; struct sgttyb tmp; - retval = verify_area(VERIFY_WRITE, sgttyb, sizeof(struct sgttyb)); - if (retval) - return retval; tmp.sg_ispeed = 0; tmp.sg_ospeed = 0; tmp.sg_erase = tty->termios->c_cc[VERASE]; tmp.sg_kill = tty->termios->c_cc[VKILL]; tmp.sg_flags = get_sgflags(tty); - copy_to_user(sgttyb, &tmp, sizeof(tmp)); + if (copy_to_user(sgttyb, &tmp, sizeof(tmp))) + return -EFAULT; return 0; } @@ -283,14 +281,12 @@ struct sgttyb tmp; struct termios termios; - retval = verify_area(VERIFY_READ, sgttyb, sizeof(struct sgttyb)); - if (retval) - return retval; retval = tty_check_change(tty); if (retval) return retval; termios = *tty->termios; - copy_from_user(&tmp, sgttyb, sizeof(tmp)); + if (copy_from_user(&tmp, sgttyb, sizeof(tmp))) + return -EFAULT; termios.c_cc[VERASE] = tmp.sg_erase; termios.c_cc[VKILL] = tmp.sg_kill; set_sgflags(&termios, tmp.sg_flags); @@ -305,16 +301,14 @@ int retval; struct tchars tmp; - retval = verify_area(VERIFY_WRITE, tchars, sizeof(struct tchars)); - if (retval) - return retval; tmp.t_intrc = tty->termios->c_cc[VINTR]; tmp.t_quitc = tty->termios->c_cc[VQUIT]; tmp.t_startc = tty->termios->c_cc[VSTART]; tmp.t_stopc = tty->termios->c_cc[VSTOP]; tmp.t_eofc = tty->termios->c_cc[VEOF]; tmp.t_brkc = tty->termios->c_cc[VEOL2]; /* what is brkc anyway? */ - copy_to_user(tchars, &tmp, sizeof(tmp)); + if (copy_to_user(tchars, &tmp, sizeof(tmp))) + return -EFAULT; return 0; } @@ -323,10 +317,8 @@ int retval; struct tchars tmp; - retval = verify_area(VERIFY_READ, tchars, sizeof(struct tchars)); - if (retval) - return retval; - copy_from_user(&tmp, tchars, sizeof(tmp)); + if (copy_from_user(&tmp, tchars, sizeof(tmp))) + return -EFAULT; tty->termios->c_cc[VINTR] = tmp.t_intrc; tty->termios->c_cc[VQUIT] = tmp.t_quitc; tty->termios->c_cc[VSTART] = tmp.t_startc; @@ -343,16 +335,14 @@ int retval; struct ltchars tmp; - retval = verify_area(VERIFY_WRITE, ltchars, sizeof(struct ltchars)); - if (retval) - return retval; tmp.t_suspc = tty->termios->c_cc[VSUSP]; tmp.t_dsuspc = tty->termios->c_cc[VSUSP]; /* what is dsuspc anyway? */ tmp.t_rprntc = tty->termios->c_cc[VREPRINT]; tmp.t_flushc = tty->termios->c_cc[VEOL2]; /* what is flushc anyway? */ tmp.t_werasc = tty->termios->c_cc[VWERASE]; tmp.t_lnextc = tty->termios->c_cc[VLNEXT]; - copy_to_user(ltchars, &tmp, sizeof(tmp)); + if (copy_to_user(ltchars, &tmp, sizeof(tmp))) + return -EFAULT; return 0; } @@ -361,10 +351,9 @@ int retval; struct ltchars tmp; - retval = verify_area(VERIFY_READ, ltchars, sizeof(struct ltchars)); - if (retval) - return retval; - copy_from_user(&tmp, ltchars, sizeof(tmp)); + if (copy_from_user(&tmp, ltchars, sizeof(tmp))) + return -EFAULT; + tty->termios->c_cc[VSUSP] = tmp.t_suspc; tty->termios->c_cc[VEOL2] = tmp.t_dsuspc; /* what is dsuspc anyway? */ tty->termios->c_cc[VREPRINT] = tmp.t_rprntc; @@ -427,13 +416,9 @@ return set_ltchars(real_tty, (struct ltchars *) arg); #endif case TCGETS: - retval = verify_area(VERIFY_WRITE, (void *) arg, - sizeof (struct termios)); - if (retval) - return retval; - kernel_termios_to_user_termios((struct termios *)arg, - real_tty->termios); - return 0; + return kernel_termios_to_user_termios + ((struct termios *)arg, + real_tty->termios); case TCSETSF: opt |= TERMIOS_FLUSH; case TCSETSW: @@ -499,53 +484,31 @@ } return 0; case TIOCOUTQ: - retval = verify_area(VERIFY_WRITE, (void *) arg, - sizeof (int)); - if (retval) - return retval; - if (tty->driver.chars_in_buffer) - put_user(tty->driver.chars_in_buffer(tty), - (int *) arg); - else - put_user(0, (int *) arg); - return 0; + return put_user(tty->driver.chars_in_buffer ? + tty->driver.chars_in_buffer(tty) : 0, + (int *) arg); case TIOCINQ: - retval = verify_area(VERIFY_WRITE, (void *) arg, - sizeof (unsigned int)); - if (retval) - return retval; retval = tty->read_cnt; if (L_ICANON(tty)) retval = inq_canon(tty); - put_user(retval, (unsigned int *) arg); - return 0; + return put_user(retval, (unsigned int *) arg); case TIOCGLCKTRMIOS: - retval = verify_area(VERIFY_WRITE, (void *) arg, - sizeof (struct termios)); - if (retval) - return retval; - kernel_termios_to_user_termios((struct termios *)arg, - real_tty->termios_locked); - return 0; + return kernel_termios_to_user_termios + ((struct termios *)arg, + real_tty->termios_locked); case TIOCSLCKTRMIOS: if (!suser()) return -EPERM; - retval = verify_area(VERIFY_READ, (void *) arg, - sizeof (struct termios)); - if (retval) - return retval; - user_termios_to_kernel_termios(real_tty->termios_locked, - (struct termios *) arg); - return 0; + return user_termios_to_kernel_termios + (real_tty->termios_locked, + (struct termios *) arg); case TIOCPKT: if (tty->driver.type != TTY_DRIVER_TYPE_PTY || tty->driver.subtype != PTY_TYPE_MASTER) return -ENOTTY; - retval = verify_area(VERIFY_READ, (void *) arg, - sizeof (int)); + retval = get_user(retval, (int *) arg); if (retval) return retval; - get_user(retval, (int *) arg); if (retval) { if (!tty->packet) { tty->packet = 1; diff -u --recursive --new-file v2.1.27/linux/drivers/net/ppp.c linux/drivers/net/ppp.c --- v2.1.27/linux/drivers/net/ppp.c Sun Feb 2 05:18:41 1997 +++ linux/drivers/net/ppp.c Fri Feb 28 15:00:55 1997 @@ -358,6 +358,7 @@ */ (void) memset (&ppp_ldisc, 0, sizeof (ppp_ldisc)); ppp_ldisc.magic = TTY_LDISC_MAGIC; + ppp_ldisc.name = "ppp"; ppp_ldisc.open = ppp_tty_open; ppp_ldisc.close = ppp_tty_close; ppp_ldisc.read = ppp_tty_read; diff -u --recursive --new-file v2.1.27/linux/drivers/net/slip.c linux/drivers/net/slip.c --- v2.1.27/linux/drivers/net/slip.c Sun Feb 2 05:18:42 1997 +++ linux/drivers/net/slip.c Fri Feb 28 15:00:55 1997 @@ -1120,6 +1120,7 @@ /* Fill in our line protocol discipline, and register it */ memset(&sl_ldisc, 0, sizeof(sl_ldisc)); sl_ldisc.magic = TTY_LDISC_MAGIC; + sl_ldisc.name = "slip"; sl_ldisc.flags = 0; sl_ldisc.open = slip_open; sl_ldisc.close = slip_close; diff -u --recursive --new-file v2.1.27/linux/drivers/pci/pci.c linux/drivers/pci/pci.c --- v2.1.27/linux/drivers/pci/pci.c Thu Feb 27 10:57:31 1997 +++ linux/drivers/pci/pci.c Fri Feb 28 15:15:42 1997 @@ -917,29 +917,47 @@ pcibios_write_config_word(bus->number, devfn, PCI_STATUS, 0xffff); /* - * Configure the bus numbers for this bridge: + * Read the existing primary/secondary/subordinate bus + * number configuration to determine if the PCI bridge + * has already been configured by the system. If so, + * do not modify the configuration, merely note it. */ 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); + if ((buses & 0xFFFFFF) != 0) + { + child->primary = buses & 0xFF; + child->secondary = (buses >> 8) & 0xFF; + child->subordinate = (buses >> 16) & 0xFF; + child->number = child->secondary; + max = scan_bus(child, mem_startp); + } + else + { + /* + * Configure the bus numbers for this bridge: + */ + 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); } diff -u --recursive --new-file v2.1.27/linux/drivers/scsi/AM53C974.c linux/drivers/scsi/AM53C974.c --- v2.1.27/linux/drivers/scsi/AM53C974.c Tue Oct 1 00:34:00 1996 +++ linux/drivers/scsi/AM53C974.c Thu Feb 27 12:49:29 1997 @@ -684,6 +684,7 @@ AM53C974_write_8(CMDREG, CMDREG_RBUS); /* reset SCSI bus */ udelay(10); AM53C974_config_after_reset(instance); +udelay(500000); return(1); } diff -u --recursive --new-file v2.1.27/linux/drivers/scsi/BusLogic.c linux/drivers/scsi/BusLogic.c --- v2.1.27/linux/drivers/scsi/BusLogic.c Sat Nov 30 23:44:53 1996 +++ linux/drivers/scsi/BusLogic.c Sun Feb 23 16:14:00 1997 @@ -1,6 +1,6 @@ /* - Linux Driver for BusLogic MultiMaster SCSI Host Adapters + Linux Driver for BusLogic MultiMaster and FlashPoint SCSI Host Adapters Copyright 1995 by Leonard N. Zubkoff @@ -17,15 +17,18 @@ The author respectfully requests that any modifications to this software be sent directly to him for evaluation and testing. - Special thanks to Wayne Yen and Alex Win of BusLogic, whose advice has been - invaluable, to David Gentzel, for writing the original Linux BusLogic driver, - and to Paul Gortmaker, for being such a dedicated test site. + Special thanks to Wayne Yen, Jin-Lon Hon, and Alex Win of BusLogic, whose + advice has been invaluable, to David Gentzel, for writing the original Linux + BusLogic driver, and to Paul Gortmaker, for being such a dedicated test site. + + Finally, special thanks to Mylex/BusLogic for making the FlashPoint SCCB + Manager available as freely redistributable source code. */ -#define BusLogic_DriverVersion "2.0.6" -#define BusLogic_DriverDate "1 December 1996" +#define BusLogic_DriverVersion "2.0.7" +#define BusLogic_DriverDate "23 February 1997" #include @@ -69,61 +72,49 @@ /* - BusLogic_ProbeOptions is a bit mask of Probe Options to be applied - across all Host Adapters. + BusLogic_ProbeOptions is a set of Probe Options to be applied across + all BusLogic Host Adapters. */ -static int - BusLogic_ProbeOptions = 0; +static BusLogic_ProbeOptions_T + BusLogic_ProbeOptions = { 0 }; /* - BusLogic_GlobalOptions is a bit mask of Global Options to be applied - across all Host Adapters. + BusLogic_GlobalOptions is a set of Global Options to be applied across + all BusLogic Host Adapters. */ -static int - BusLogic_GlobalOptions = 0; +static BusLogic_GlobalOptions_T + BusLogic_GlobalOptions = { 0 }; /* - BusLogic_RegisteredHostAdapters is a linked list of all the registered - BusLogic Host Adapters. + BusLogic_RegisteredHostAdapters is an array of linked lists of all the + registered BusLogic Host Adapters, indexed by IRQ Channel. */ static BusLogic_HostAdapter_T - *BusLogic_RegisteredHostAdapters = NULL; - - -/* - BusLogic_StandardAddresses is the list of standard ISA I/O Addresses at - which BusLogic Host Adapters may potentially be found. -*/ - -static unsigned int - BusLogic_IO_StandardAddresses[] = - { 0x330, 0x334, 0x230, 0x234, 0x130, 0x134, 0 }; + *BusLogic_RegisteredHostAdapters[NR_IRQS] = { NULL }; /* - 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. + BusLogic_ProbeInfoCount is the numbers of entries in BusLogic_ProbeInfoList. */ -static unsigned int - BusLogic_IO_AddressProbeList[BusLogic_IO_MaxProbeAddresses+1] = { 0 }; +static int + BusLogic_ProbeInfoCount = 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. + BusLogic_ProbeInfoList is the list of I/O Addresses and Bus Probe Information + to be checked 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 int - BusLogic_IRQ_UsageCount[NR_IRQS] = { 0 }; +static BusLogic_ProbeInfo_T + BusLogic_ProbeInfoList[BusLogic_MaxHostAdapters] = { { 0 } }; /* @@ -137,40 +128,49 @@ /* + BusLogic_FirstCompletedCCB and BusLogic_LastCompletedCCB are pointers + to the first and last CCBs that are queued for completion processing. +*/ + +static BusLogic_CCB_T + *BusLogic_FirstCompletedCCB = NULL, + *BusLogic_LastCompletedCCB = NULL; + + +/* BusLogic_ProcDirectoryEntry is the BusLogic /proc/scsi directory entry. */ -static struct proc_dir_entry +PROC_DirectoryEntry_T 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. + Name, Copyright Notice, and Electronic Mail Address. */ -static void BusLogic_AnnounceDriver(void) +static void BusLogic_AnnounceDriver(BusLogic_HostAdapter_T *HostAdapter) { - 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 \n"); - DriverAnnouncementPrinted = true; + BusLogic_Announce("***** BusLogic SCSI Driver Version " + BusLogic_DriverVersion " of " + BusLogic_DriverDate " *****\n", HostAdapter); + BusLogic_Announce("Copyright 1995 by Leonard N. Zubkoff " + "\n", HostAdapter); } /* - BusLogic_DriverInfo returns the Controller Name to identify this SCSI Driver - and Host Adapter. + BusLogic_DriverInfo returns the Host Adapter 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->ControllerName; + return HostAdapter->FullModelName; } @@ -182,15 +182,16 @@ static void BusLogic_RegisterHostAdapter(BusLogic_HostAdapter_T *HostAdapter) { HostAdapter->Next = NULL; - if (BusLogic_RegisteredHostAdapters != NULL) + if (BusLogic_RegisteredHostAdapters[HostAdapter->IRQ_Channel] != NULL) { - BusLogic_HostAdapter_T *LastHostAdapter = BusLogic_RegisteredHostAdapters; + BusLogic_HostAdapter_T *LastHostAdapter = + BusLogic_RegisteredHostAdapters[HostAdapter->IRQ_Channel]; BusLogic_HostAdapter_T *NextHostAdapter; while ((NextHostAdapter = LastHostAdapter->Next) != NULL) LastHostAdapter = NextHostAdapter; LastHostAdapter->Next = HostAdapter; } - else BusLogic_RegisteredHostAdapters = HostAdapter; + else BusLogic_RegisteredHostAdapters[HostAdapter->IRQ_Channel] = HostAdapter; } @@ -201,15 +202,17 @@ static void BusLogic_UnregisterHostAdapter(BusLogic_HostAdapter_T *HostAdapter) { - if (BusLogic_RegisteredHostAdapters != HostAdapter) + if (BusLogic_RegisteredHostAdapters[HostAdapter->IRQ_Channel] != HostAdapter) { - BusLogic_HostAdapter_T *LastHostAdapter = BusLogic_RegisteredHostAdapters; + BusLogic_HostAdapter_T *LastHostAdapter = + BusLogic_RegisteredHostAdapters[HostAdapter->IRQ_Channel]; while (LastHostAdapter != NULL && LastHostAdapter->Next != HostAdapter) LastHostAdapter = LastHostAdapter->Next; if (LastHostAdapter != NULL) LastHostAdapter->Next = HostAdapter->Next; } - else BusLogic_RegisteredHostAdapters = HostAdapter->Next; + else BusLogic_RegisteredHostAdapters[HostAdapter->IRQ_Channel] = + HostAdapter->Next; HostAdapter->Next = NULL; } @@ -221,6 +224,13 @@ static boolean BusLogic_CreateMailboxes(BusLogic_HostAdapter_T *HostAdapter) { + /* + FlashPoint Host Adapters do not use Outgoing and Incoming Mailboxes. + */ + if (BusLogic_FlashPointHostAdapterP(HostAdapter)) return true; + /* + Allocate space for the Outgoing and Incoming Mailboxes. + */ HostAdapter->FirstOutgoingMailbox = (BusLogic_OutgoingMailbox_T *) scsi_init_malloc(HostAdapter->MailboxCount @@ -231,8 +241,8 @@ : GFP_ATOMIC)); if (HostAdapter->FirstOutgoingMailbox == NULL) { - printk("scsi%d: UNABLE TO ALLOCATE MAILBOXES - DETACHING\n", - HostAdapter->HostNumber); + BusLogic_Error("UNABLE TO ALLOCATE MAILBOXES - DETACHING\n", + HostAdapter, HostAdapter->HostNumber); return false; } HostAdapter->LastOutgoingMailbox = @@ -261,34 +271,48 @@ /* - BusLogic_CreateCCBs allocates the initial Command Control Blocks (CCBs) - for Host Adapter. + BusLogic_CreateCCB allocates and initializes a single Command Control + Block (CCB) for Host Adapter, and adds it to Host Adapter's free list. */ -static boolean BusLogic_CreateCCBs(BusLogic_HostAdapter_T *HostAdapter) +static boolean BusLogic_CreateCCB(BusLogic_HostAdapter_T *HostAdapter) { - int i; - for (i = 0; i < HostAdapter->InitialCCBs; i++) + BusLogic_CCB_T *CCB = (BusLogic_CCB_T *) + scsi_init_malloc(sizeof(BusLogic_CCB_T), + (HostAdapter->BounceBuffersRequired + ? GFP_ATOMIC | GFP_DMA + : GFP_ATOMIC)); + if (CCB == NULL) return false; + memset(CCB, 0, sizeof(BusLogic_CCB_T)); + CCB->HostAdapter = HostAdapter; + CCB->Status = BusLogic_CCB_Free; + if (BusLogic_FlashPointHostAdapterP(HostAdapter)) { - BusLogic_CCB_T *CCB = (BusLogic_CCB_T *) - scsi_init_malloc(sizeof(BusLogic_CCB_T), - (HostAdapter->BounceBuffersRequired - ? GFP_ATOMIC | GFP_DMA - : GFP_ATOMIC)); - 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; + CCB->CallbackFunction = BusLogic_QueueCompletedCCB; + CCB->BaseAddress = HostAdapter->IO_Address; } + CCB->Next = HostAdapter->Free_CCBs; + CCB->NextAll = HostAdapter->All_CCBs; + HostAdapter->Free_CCBs = CCB; + HostAdapter->All_CCBs = CCB; + return true; +} + + +/* + BusLogic_CreateCCBs allocates the initial CCBs for Host Adapter. +*/ + +static boolean BusLogic_CreateCCBs(BusLogic_HostAdapter_T *HostAdapter) +{ + int Allocated; + for (Allocated = 0; Allocated < HostAdapter->InitialCCBs; Allocated++) + if (!BusLogic_CreateCCB(HostAdapter)) + { + BusLogic_Error("UNABLE TO ALLOCATE CCB %d - DETACHING\n", + HostAdapter, Allocated); + return false; + } return true; } @@ -311,12 +335,13 @@ /* - BusLogic_AllocateCCB allocates a CCB from the Host Adapter's free list, + BusLogic_AllocateCCB allocates a CCB from Host Adapter's free list, allocating more memory from the Kernel if necessary. The Host Adapter's - Lock should have already been acquired by the caller. + Lock should already have been acquired by the caller. */ -static BusLogic_CCB_T *BusLogic_AllocateCCB(BusLogic_HostAdapter_T *HostAdapter) +static BusLogic_CCB_T *BusLogic_AllocateCCB(BusLogic_HostAdapter_T + *HostAdapter) { static unsigned long SerialNumber = 0; BusLogic_CCB_T *CCB; @@ -330,30 +355,14 @@ return CCB; } for (Allocated = 0; Allocated < HostAdapter->IncrementalCCBs; Allocated++) - { - CCB = (BusLogic_CCB_T *) - scsi_init_malloc(sizeof(BusLogic_CCB_T), - (HostAdapter->BounceBuffersRequired - ? GFP_ATOMIC | GFP_DMA - : GFP_ATOMIC)); - if (CCB == NULL) break; - 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; - } + if (!BusLogic_CreateCCB(HostAdapter)) break; CCB = HostAdapter->Free_CCBs; if (CCB == NULL) { - printk("scsi%d: Failed to allocate additional CCBs\n", - HostAdapter->HostNumber); + BusLogic_Notice("Failed to allocate additional CCBs\n", HostAdapter); return NULL; } - printk("scsi%d: Allocated %d additional CCBs\n", - HostAdapter->HostNumber, Allocated); + BusLogic_Notice("Allocated %d additional CCBs\n", HostAdapter, Allocated); CCB->SerialNumber = ++SerialNumber; HostAdapter->Free_CCBs = CCB->Next; CCB->Next = NULL; @@ -363,7 +372,7 @@ /* BusLogic_DeallocateCCB deallocates a CCB, returning it to the Host Adapter's - free list. The Host Adapter's Lock should have already been acquired by the + free list. The Host Adapter's Lock should already have been acquired by the caller. */ @@ -378,6 +387,47 @@ /* + BusLogic_CreateTargetDeviceStatistics creates the Target Device Statistics + structure for Host Adapter. +*/ + +static boolean BusLogic_CreateTargetDeviceStatistics(BusLogic_HostAdapter_T + *HostAdapter) +{ + HostAdapter->TargetDeviceStatistics = + (BusLogic_TargetDeviceStatistics_T *) + scsi_init_malloc(HostAdapter->MaxTargetDevices + * sizeof(BusLogic_TargetDeviceStatistics_T), + GFP_ATOMIC); + if (HostAdapter->TargetDeviceStatistics == NULL) + { + BusLogic_Error("UNABLE TO ALLOCATE TARGET DEVICE STATISTICS - " + "DETACHING\n", HostAdapter, HostAdapter->HostNumber); + return false; + } + memset(HostAdapter->TargetDeviceStatistics, 0, + HostAdapter->MaxTargetDevices + * sizeof(BusLogic_TargetDeviceStatistics_T)); + return true; +} + + +/* + BusLogic_DestroyTargetDeviceStatistics destroys the Target Device Statistics + structure for Host Adapter. +*/ + +static void BusLogic_DestroyTargetDeviceStatistics(BusLogic_HostAdapter_T + *HostAdapter) +{ + if (HostAdapter->TargetDeviceStatistics == NULL) return; + scsi_init_free((char *) HostAdapter->TargetDeviceStatistics, + HostAdapter->MaxTargetDevices + * sizeof(BusLogic_TargetDeviceStatistics_T)); +} + + +/* 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 @@ -387,12 +437,12 @@ 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 controller detection and initialization, - so performance and latency are not critical, and exclusive access to the Host - Adapter hardware is assumed. Once the controller and driver are initialized, - the only Host Adapter command that is issued is the single byte Execute - Mailbox Command operation code, which does not require waiting for the Host - Adapter Ready bit to be set in the Status Register. + BusLogic_Command is called exclusively during host adapter detection and + initialization, so performance and latency are not critical, and exclusive + access to the Host Adapter hardware is assumed. Once the host adapter and + driver are initialized, the only Host Adapter command that is issued is the + single byte Execute Mailbox Command operation code, 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, @@ -404,27 +454,45 @@ { unsigned char *ParameterPointer = (unsigned char *) ParameterData; unsigned char *ReplyPointer = (unsigned char *) ReplyData; - unsigned char StatusRegister = 0, InterruptRegister; - int ReplyBytes = 0, TimeoutCounter; + BusLogic_StatusRegister_T StatusRegister; + BusLogic_InterruptRegister_T InterruptRegister; + unsigned long ProcessorFlags = 0; + int ReplyBytes = 0, Result; + long TimeoutCounter; /* Clear out the Reply Data if provided. */ if (ReplyLength > 0) memset(ReplyData, 0, ReplyLength); /* + If the IRQ Channel has not yet been acquired, then interrupts must be + disabled while issuing host adapter commands since a Command Complete + interrupt could occur if the IRQ Channel was previously enabled by another + BusLogic Host Adapter or other driver sharing the same IRQ Channel. + */ + if (!HostAdapter->IRQ_ChannelAcquired) + { + save_flags(ProcessorFlags); + cli(); + } + /* 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)) + StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); + if (StatusRegister.Bits.HostAdapterReady && + !StatusRegister.Bits.CommandParameterRegisterBusy) break; } - BusLogic_CommandFailureReason = "Timeout waiting for Host Adapter Ready"; - if (TimeoutCounter < 0) return -2; + if (TimeoutCounter < 0) + { + BusLogic_CommandFailureReason = "Timeout waiting for Host Adapter Ready"; + Result = -2; + goto Done; + } /* Write the OperationCode to the Command/Parameter Register. */ @@ -449,27 +517,40 @@ 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; + InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter); + StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); + if (InterruptRegister.Bits.CommandComplete) break; if (HostAdapter->HostAdapterCommandCompleted) break; - if (StatusRegister & BusLogic_DataInRegisterReady) break; - if (StatusRegister & BusLogic_CommandParameterRegisterBusy) continue; + if (StatusRegister.Bits.DataInRegisterReady) break; + if (StatusRegister.Bits.CommandParameterRegisterBusy) continue; BusLogic_WriteCommandParameterRegister(HostAdapter, *ParameterPointer++); ParameterLength--; } - BusLogic_CommandFailureReason = "Timeout waiting for Parameter Acceptance"; - if (TimeoutCounter < 0) return -2; + if (TimeoutCounter < 0) + { + BusLogic_CommandFailureReason = + "Timeout waiting for Parameter Acceptance"; + Result = -2; + goto Done; + } /* 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; + StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); + if (StatusRegister.Bits.CommandInvalid) + { + BusLogic_CommandFailureReason = "Modify I/O Address Invalid"; + Result = -1; + goto Done; + } + if (BusLogic_GlobalOptions.Bits.TraceConfiguration) + BusLogic_Notice("BusLogic_Command(%02X) Status = %02X: " + "(Modify I/O Address)\n", HostAdapter, + OperationCode, StatusRegister.All); + Result = 0; + goto Done; } /* Select an appropriate timeout value for awaiting command completion. @@ -494,19 +575,23 @@ */ while (--TimeoutCounter >= 0) { - InterruptRegister = BusLogic_ReadInterruptRegister(HostAdapter); - StatusRegister = BusLogic_ReadStatusRegister(HostAdapter); - if (InterruptRegister & BusLogic_CommandComplete) break; + InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter); + StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); + if (InterruptRegister.Bits.CommandComplete) break; if (HostAdapter->HostAdapterCommandCompleted) break; - if (StatusRegister & BusLogic_DataInRegisterReady) + if (StatusRegister.Bits.DataInRegisterReady) if (++ReplyBytes <= ReplyLength) *ReplyPointer++ = BusLogic_ReadDataInRegister(HostAdapter); else BusLogic_ReadDataInRegister(HostAdapter); if (OperationCode == BusLogic_FetchHostAdapterLocalRAM && - (StatusRegister & BusLogic_HostAdapterReady)) break; + StatusRegister.Bits.HostAdapterReady) break; + } + if (TimeoutCounter < 0) + { + BusLogic_CommandFailureReason = "Timeout waiting for Command Complete"; + Result = -2; + goto Done; } - 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 @@ -519,22 +604,27 @@ /* Clear any pending Command Complete Interrupt. */ - BusLogic_WriteControlRegister(HostAdapter, BusLogic_InterruptReset); - if (BusLogic_GlobalOptions & BusLogic_TraceConfiguration) + BusLogic_InterruptReset(HostAdapter); + /* + Provide tracing information if requested. + */ + if (BusLogic_GlobalOptions.Bits.TraceConfiguration) if (OperationCode != BusLogic_TestCommandCompleteInterrupt) { int i; - printk("BusLogic_Command(%02X) Status = %02X: %2d ==> %2d:", - OperationCode, StatusRegister, ReplyLength, ReplyBytes); + BusLogic_Notice("BusLogic_Command(%02X) Status = %02X: %2d ==> %2d:", + HostAdapter, OperationCode, + StatusRegister.All, ReplyLength, ReplyBytes); if (ReplyLength > ReplyBytes) ReplyLength = ReplyBytes; for (i = 0; i < ReplyLength; i++) - printk(" %02X", ((unsigned char *) ReplyData)[i]); - printk("\n"); + BusLogic_Notice(" %02X", HostAdapter, + ((unsigned char *) ReplyData)[i]); + BusLogic_Notice("\n", HostAdapter); } /* Process Command Invalid conditions. */ - if (StatusRegister & BusLogic_CommandInvalid) + if (StatusRegister.Bits.CommandInvalid) { /* Some early BusLogic Host Adapters may not recover properly from @@ -545,154 +635,545 @@ Soft Reset in response to a Command Invalid condition. */ udelay(1000); - StatusRegister = BusLogic_ReadStatusRegister(HostAdapter); - if (StatusRegister != (BusLogic_HostAdapterReady | - BusLogic_InitializationRequired)) + StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); + if (StatusRegister.Bits.CommandInvalid || + StatusRegister.Bits.Reserved || + StatusRegister.Bits.DataInRegisterReady || + StatusRegister.Bits.CommandParameterRegisterBusy || + !StatusRegister.Bits.HostAdapterReady || + !StatusRegister.Bits.InitializationRequired || + StatusRegister.Bits.DiagnosticActive || + StatusRegister.Bits.DiagnosticFailure) { - BusLogic_WriteControlRegister(HostAdapter, BusLogic_SoftReset); + BusLogic_SoftReset(HostAdapter); udelay(1000); } BusLogic_CommandFailureReason = "Command Invalid"; - return -1; + Result = -1; + goto Done; } /* Handle Excess Parameters Supplied conditions. */ - BusLogic_CommandFailureReason = "Excess Parameters Supplied"; - if (ParameterLength > 0) return -1; + if (ParameterLength > 0) + { + BusLogic_CommandFailureReason = "Excess Parameters Supplied"; + Result = -1; + goto Done; + } /* Indicate the command completed successfully. */ BusLogic_CommandFailureReason = NULL; - return ReplyBytes; + Result = ReplyBytes; + /* + Restore the interrupt status if necessary and return. + */ +Done: + if (!HostAdapter->IRQ_ChannelAcquired) + restore_flags(ProcessorFlags); + return Result; } /* - 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. + BusLogic_InitializeProbeInfoListISA initializes the list of I/O Address and + Bus Probe Information to be checked for potential BusLogic SCSI Host Adapters + only from the list of standard BusLogic MultiMaster ISA I/O Addresses. */ -static void BusLogic_InitializeAddressProbeList(void) +static void BusLogic_InitializeProbeInfoListISA(void) { - int ProbeAddressCount = 0, StandardAddressIndex = 0; + int StandardAddressIndex; /* If BusLogic_Setup has provided an I/O Address probe list, do not override the Kernel Command Line specifications. */ - if (BusLogic_IO_AddressProbeList[0] != 0) return; + if (BusLogic_ProbeInfoCount > 0) return; + /* + If a Kernel Command Line specification has requested that ISA Bus Probes + be inhibited, do not proceed further. + */ + if (BusLogic_ProbeOptions.Bits.NoProbeISA) return; + /* + Append the list of standard BusLogic MultiMaster ISA I/O Addresses. + */ + StandardAddressIndex = 0; + while (BusLogic_ProbeInfoCount < BusLogic_MaxHostAdapters && + StandardAddressIndex < BusLogic_ISA_StandardAddressesCount) + { + BusLogic_ProbeInfo_T *ProbeInfo = + &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount++]; + ProbeInfo->IO_Address = + BusLogic_ISA_StandardAddresses[StandardAddressIndex++]; + ProbeInfo->HostAdapterType = BusLogic_MultiMaster; + ProbeInfo->HostAdapterBusType = BusLogic_ISA_Bus; + } +} + + #ifdef CONFIG_PCI + + +/* + BusLogic_SortProbeInfo sorts a section of BusLogic_ProbeInfoList in order + of increasing PCI Bus and Device Number. +*/ + +static void BusLogic_SortProbeInfo(BusLogic_ProbeInfo_T *ProbeInfoList, + int ProbeInfoCount) +{ + int LastInterchange = ProbeInfoCount-1, Bound, j; + while (LastInterchange > 0) + { + Bound = LastInterchange; + LastInterchange = 0; + for (j = 0; j < Bound; j++) + { + BusLogic_ProbeInfo_T *ProbeInfo1 = &ProbeInfoList[j]; + BusLogic_ProbeInfo_T *ProbeInfo2 = &ProbeInfoList[j+1]; + if (ProbeInfo1->Bus > ProbeInfo2->Bus || + (ProbeInfo1->Bus == ProbeInfo2->Bus && + (ProbeInfo1->Device > ProbeInfo2->Device))) + { + BusLogic_ProbeInfo_T TempProbeInfo; + memcpy(&TempProbeInfo, ProbeInfo1, sizeof(BusLogic_ProbeInfo_T)); + memcpy(ProbeInfo1, ProbeInfo2, sizeof(BusLogic_ProbeInfo_T)); + memcpy(ProbeInfo2, &TempProbeInfo, sizeof(BusLogic_ProbeInfo_T)); + LastInterchange = j; + } + } + } +} + + +/* + BusLogic_InitializeMultiMasterProbeInfo initializes the list of I/O Address + and Bus Probe Information to be checked for potential BusLogic MultiMaster + SCSI Host Adapters by interrogating the PCI Configuration Space on PCI + machines as well as from the list of standard BusLogic MultiMaster ISA + I/O Addresses. It returns the number of PCI MultiMaster Host Adapters found. +*/ + +static int BusLogic_InitializeMultiMasterProbeInfo(void) +{ + boolean StandardAddressSeen[BusLogic_ISA_StandardAddressesCount]; + BusLogic_ProbeInfo_T *PrimaryProbeInfo = + &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount]; + int NonPrimaryPCIMultiMasterIndex = BusLogic_ProbeInfoCount; + int NonPrimaryPCIMultiMasterCount = 0, PCIMultiMasterCount = 0; + boolean ForceBusDeviceScanningOrder = false; + boolean ForceBusDeviceScanningOrderChecked = false; + unsigned char Bus, DeviceFunction, IRQ_Channel; + unsigned int BaseAddress0, BaseAddress1; + BusLogic_IO_Address_T IO_Address; + BusLogic_PCI_Address_T PCI_Address; + unsigned short Index = 0; + int StandardAddressIndex, i; + if (BusLogic_ProbeInfoCount >= BusLogic_MaxHostAdapters) + return 0; + BusLogic_ProbeInfoCount++; + for (i = 0; i < BusLogic_ISA_StandardAddressesCount; i++) + StandardAddressSeen[i] = false; + /* + Iterate over the MultiMaster PCI Host Adapters. For each enumerated host + adapter, determine whether its ISA Compatible I/O Port is enabled and if + so, whether it is assigned the Primary I/O Address. A host adapter that is + assigned the Primary I/O Address will always be the preferred boot device. + The MultiMaster BIOS will first recognize a host adapter at the Primary I/O + Address, then any other PCI host adapters, and finally any host adapters + located at the remaining standard ISA I/O Addresses. When a PCI host + adapter is found with its ISA Compatible I/O Port enabled, a command is + issued to disable the ISA Compatible I/O Port, and it is noted that the + particular standard ISA I/O Address need not be probed. + */ + PrimaryProbeInfo->IO_Address = 0; + while (pcibios_find_device(PCI_VENDOR_ID_BUSLOGIC, + PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER, + Index++, &Bus, &DeviceFunction) == 0) + if (pcibios_read_config_dword(Bus, DeviceFunction, + PCI_BASE_ADDRESS_0, &BaseAddress0) == 0 && + pcibios_read_config_dword(Bus, DeviceFunction, + PCI_BASE_ADDRESS_1, &BaseAddress1) == 0 && + pcibios_read_config_byte(Bus, DeviceFunction, + PCI_INTERRUPT_LINE, &IRQ_Channel) == 0) + { + BusLogic_HostAdapter_T HostAdapterPrototype; + BusLogic_HostAdapter_T *HostAdapter = &HostAdapterPrototype; + BusLogic_PCIHostAdapterInformation_T PCIHostAdapterInformation; + BusLogic_ModifyIOAddressRequest_T ModifyIOAddressRequest; + unsigned char Device = DeviceFunction >> 3; + IO_Address = BaseAddress0 & PCI_BASE_ADDRESS_IO_MASK; + PCI_Address = BaseAddress1 & PCI_BASE_ADDRESS_MEM_MASK; + if ((BaseAddress0 & PCI_BASE_ADDRESS_SPACE) + != PCI_BASE_ADDRESS_SPACE_IO) + { + BusLogic_Error("BusLogic: Base Address0 0x%X not I/O for " + "MultiMaster Host Adapter\n", NULL, BaseAddress0); + BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n", + NULL, Bus, Device, IO_Address); + continue; + } + if ((BaseAddress1 & PCI_BASE_ADDRESS_SPACE) + != PCI_BASE_ADDRESS_SPACE_MEMORY) + { + BusLogic_Error("BusLogic: Base Address1 0x%X not Memory for " + "MultiMaster Host Adapter\n", NULL, BaseAddress1); + BusLogic_Error("at PCI Bus %d Device %d PCI Address 0x%X\n", + NULL, Bus, Device, PCI_Address); + continue; + } + if (IRQ_Channel == 0 || IRQ_Channel >= NR_IRQS) + { + BusLogic_Error("BusLogic: IRQ Channel %d illegal for " + "MultiMaster Host Adapter\n", NULL, IRQ_Channel); + BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n", + NULL, Bus, Device, IO_Address); + continue; + } + if (BusLogic_GlobalOptions.Bits.TraceProbe) + { + BusLogic_Notice("BusLogic: PCI MultiMaster Host Adapter " + "detected at\n", NULL); + BusLogic_Notice("BusLogic: PCI Bus %d Device %d I/O Address " + "0x%X PCI Address 0x%X\n", NULL, + Bus, Device, IO_Address, PCI_Address); + } + /* + Issue the Inquire PCI Host Adapter Information command to determine + the ISA Compatible I/O Port. If the ISA Compatible I/O Port is + known and enabled, note that the particular Standard ISA I/O + Address need not be probed. + */ + HostAdapter->IO_Address = IO_Address; + if (BusLogic_Command(HostAdapter, + BusLogic_InquirePCIHostAdapterInformation, + NULL, 0, &PCIHostAdapterInformation, + sizeof(PCIHostAdapterInformation)) + == sizeof(PCIHostAdapterInformation)) + { + if (PCIHostAdapterInformation.ISACompatibleIOPort < + BusLogic_ISA_StandardAddressesCount) + StandardAddressSeen[PCIHostAdapterInformation + .ISACompatibleIOPort] = true; + } + else PCIHostAdapterInformation.ISACompatibleIOPort = + BusLogic_IO_Disable; + /* + Issue the Modify I/O Address command to disable the ISA Compatible + I/O Port. + */ + ModifyIOAddressRequest = BusLogic_IO_Disable; + BusLogic_Command(HostAdapter, BusLogic_ModifyIOAddress, + &ModifyIOAddressRequest, + sizeof(ModifyIOAddressRequest), NULL, 0); + /* + For the first MultiMaster Host Adapter enumerated, issue the Fetch + Host Adapter Local RAM command to read byte 45 of the AutoSCSI area, + for the setting of the "Use Bus And Device # For PCI Scanning Seq." + option. Issue the Inquire Board ID command since this option is + only valid for the BT-948/958/958D. + */ + if (!ForceBusDeviceScanningOrderChecked) + { + BusLogic_FetchHostAdapterLocalRAMRequest_T + FetchHostAdapterLocalRAMRequest; + BusLogic_AutoSCSIByte45_T AutoSCSIByte45; + BusLogic_BoardID_T BoardID; + FetchHostAdapterLocalRAMRequest.ByteOffset = + BusLogic_AutoSCSI_BaseOffset + 45; + FetchHostAdapterLocalRAMRequest.ByteCount = + sizeof(AutoSCSIByte45); + BusLogic_Command(HostAdapter, + BusLogic_FetchHostAdapterLocalRAM, + &FetchHostAdapterLocalRAMRequest, + sizeof(FetchHostAdapterLocalRAMRequest), + &AutoSCSIByte45, sizeof(AutoSCSIByte45)); + BusLogic_Command(HostAdapter, BusLogic_InquireBoardID, + NULL, 0, &BoardID, sizeof(BoardID)); + if (BoardID.FirmwareVersion1stDigit == '5') + ForceBusDeviceScanningOrder = + AutoSCSIByte45.ForceBusDeviceScanningOrder; + ForceBusDeviceScanningOrderChecked = true; + } + /* + Determine whether this MultiMaster Host Adapter has its ISA + Compatible I/O Port enabled and is assigned the Primary I/O Address. + If it does, then it is the Primary MultiMaster Host Adapter and must + be recognized first. If it does not, then it is added to the list + for probing after any Primary MultiMaster Host Adapter is probed. + */ + if (PCIHostAdapterInformation.ISACompatibleIOPort == BusLogic_IO_330) + { + PrimaryProbeInfo->IO_Address = IO_Address; + PrimaryProbeInfo->PCI_Address = PCI_Address; + PrimaryProbeInfo->HostAdapterType = BusLogic_MultiMaster; + PrimaryProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus; + PrimaryProbeInfo->Bus = Bus; + PrimaryProbeInfo->Device = Device; + PrimaryProbeInfo->IRQ_Channel = IRQ_Channel; + PCIMultiMasterCount++; + } + else if (BusLogic_ProbeInfoCount < BusLogic_MaxHostAdapters) + { + BusLogic_ProbeInfo_T *ProbeInfo = + &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount++]; + ProbeInfo->IO_Address = IO_Address; + ProbeInfo->PCI_Address = PCI_Address; + ProbeInfo->HostAdapterType = BusLogic_MultiMaster; + ProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus; + ProbeInfo->Bus = Bus; + ProbeInfo->Device = Device; + ProbeInfo->IRQ_Channel = IRQ_Channel; + NonPrimaryPCIMultiMasterCount++; + PCIMultiMasterCount++; + } + else BusLogic_Warning("BusLogic: Too many Host Adapters " + "detected\n", NULL); + } /* - Interrogate PCI Configuration Space for any BusLogic SCSI Host Adapters. + If the AutoSCSI "Use Bus And Device # For PCI Scanning Seq." option is ON + for the first enumerated MultiMaster Host Adapter, and if that host adapter + is a BT-948/958/958D, then the MultiMaster BIOS will recognize MultiMaster + Host Adapters in the order of increasing PCI Bus and Device Number. In + that case, sort the probe information into the same order the BIOS uses. + If this option is OFF, then the MultiMaster BIOS will recognize MultiMaster + Host Adapters in the order they are enumerated by the PCI BIOS, and hence + no sorting is necessary. + */ + if (ForceBusDeviceScanningOrder) + BusLogic_SortProbeInfo(&BusLogic_ProbeInfoList[ + NonPrimaryPCIMultiMasterIndex], + NonPrimaryPCIMultiMasterCount); + /* + If no PCI MultiMaster Host Adapter is assigned the Primary I/O Address, + then the Primary I/O Address must be probed explicitly before any PCI + host adapters are probed. + */ + if (PrimaryProbeInfo->IO_Address == 0 && + !BusLogic_ProbeOptions.Bits.NoProbeISA) + { + PrimaryProbeInfo->IO_Address = BusLogic_ISA_StandardAddresses[0]; + PrimaryProbeInfo->HostAdapterType = BusLogic_MultiMaster; + PrimaryProbeInfo->HostAdapterBusType = BusLogic_ISA_Bus; + } + /* + Append the list of standard BusLogic MultiMaster ISA I/O Addresses, + omitting the Primary I/O Address which has already been handled. + */ + if (!BusLogic_ProbeOptions.Bits.NoProbeISA) + for (StandardAddressIndex = 1; + StandardAddressIndex < BusLogic_ISA_StandardAddressesCount; + StandardAddressIndex++) + if (!StandardAddressSeen[StandardAddressIndex] && + BusLogic_ProbeInfoCount < BusLogic_MaxHostAdapters) + { + BusLogic_ProbeInfo_T *ProbeInfo = + &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount++]; + ProbeInfo->IO_Address = + BusLogic_ISA_StandardAddresses[StandardAddressIndex]; + ProbeInfo->HostAdapterType = BusLogic_MultiMaster; + ProbeInfo->HostAdapterBusType = BusLogic_ISA_Bus; + } + return PCIMultiMasterCount; +} + + +/* + BusLogic_InitializeFlashPointProbeInfo initializes the list of I/O Address + and Bus Probe Information to be checked for potential BusLogic FlashPoint + Host Adapters by interrogating the PCI Configuration Space. It returns the + number of FlashPoint Host Adapters found. +*/ + +static int BusLogic_InitializeFlashPointProbeInfo(void) +{ + int FlashPointIndex = BusLogic_ProbeInfoCount, FlashPointCount = 0; + unsigned char Bus, DeviceFunction, IRQ_Channel; + unsigned int BaseAddress0, BaseAddress1; + BusLogic_IO_Address_T IO_Address; + BusLogic_PCI_Address_T PCI_Address; + unsigned short Index = 0; + /* + Interrogate PCI Configuration Space for any FlashPoint Host Adapters. + */ + while (pcibios_find_device(PCI_VENDOR_ID_BUSLOGIC, + PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT, + Index++, &Bus, &DeviceFunction) == 0) + if (pcibios_read_config_dword(Bus, DeviceFunction, + PCI_BASE_ADDRESS_0, &BaseAddress0) == 0 && + pcibios_read_config_dword(Bus, DeviceFunction, + PCI_BASE_ADDRESS_1, &BaseAddress1) == 0 && + pcibios_read_config_byte(Bus, DeviceFunction, + PCI_INTERRUPT_LINE, &IRQ_Channel) == 0) + { + unsigned char Device = DeviceFunction >> 3; + IO_Address = BaseAddress0 & PCI_BASE_ADDRESS_IO_MASK; + PCI_Address = BaseAddress1 & PCI_BASE_ADDRESS_MEM_MASK; +#ifndef CONFIG_SCSI_OMIT_FLASHPOINT + if ((BaseAddress0 & PCI_BASE_ADDRESS_SPACE) + != PCI_BASE_ADDRESS_SPACE_IO) + { + BusLogic_Error("BusLogic: Base Address0 0x%X not I/O for " + "FlashPoint Host Adapter\n", NULL, BaseAddress0); + BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n", + NULL, Bus, Device, IO_Address); + continue; + } + if ((BaseAddress1 & PCI_BASE_ADDRESS_SPACE) + != PCI_BASE_ADDRESS_SPACE_MEMORY) + { + BusLogic_Error("BusLogic: Base Address1 0x%X not Memory for " + "FlashPoint Host Adapter\n", NULL, BaseAddress1); + BusLogic_Error("at PCI Bus %d Device %d PCI Address 0x%X\n", + NULL, Bus, Device, PCI_Address); + continue; + } + if (IRQ_Channel == 0 || IRQ_Channel >= NR_IRQS) + { + BusLogic_Error("BusLogic: IRQ Channel %d illegal for " + "FlashPoint Host Adapter\n", NULL, IRQ_Channel); + BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n", + NULL, Bus, Device, IO_Address); + continue; + } + if (BusLogic_GlobalOptions.Bits.TraceProbe) + { + BusLogic_Notice("BusLogic: FlashPoint Host Adapter " + "detected at\n", NULL); + BusLogic_Notice("BusLogic: PCI Bus %d Device %d I/O Address " + "0x%X PCI Address 0x%X\n", NULL, + Bus, Device, IO_Address, PCI_Address); + } + if (BusLogic_ProbeInfoCount < BusLogic_MaxHostAdapters) + { + BusLogic_ProbeInfo_T *ProbeInfo = + &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount++]; + ProbeInfo->IO_Address = IO_Address; + ProbeInfo->PCI_Address = PCI_Address; + ProbeInfo->HostAdapterType = BusLogic_FlashPoint; + ProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus; + ProbeInfo->Bus = Bus; + ProbeInfo->Device = Device; + ProbeInfo->IRQ_Channel = IRQ_Channel; + FlashPointCount++; + } + else BusLogic_Warning("BusLogic: Too many Host Adapters " + "detected\n", NULL); +#else + BusLogic_Error("BusLogic: FlashPoint Host Adapter detected at " + "PCI Bus %d Device %d\n", NULL, Bus, Device); + BusLogic_Error("BusLogic: I/O Address 0x%X PCI Address 0x%X, " + "but FlashPoint\n", NULL, IO_Address, PCI_Address); + BusLogic_Error("BusLogic: support was omitted in this kernel " + "configuration.\n", NULL); +#endif + } + /* + The FlashPoint BIOS will scan for FlashPoint Host Adapters in the order of + increasing PCI Bus and Device Number, so sort the probe information into + the same order the BIOS uses. + */ + BusLogic_SortProbeInfo(&BusLogic_ProbeInfoList[FlashPointIndex], + FlashPointCount); + return FlashPointCount; +} + + +/* + BusLogic_InitializeProbeInfoList initializes the list of I/O Address and Bus + Probe Information to be checked for potential BusLogic SCSI Host Adapters by + interrogating the PCI Configuration Space on PCI machines as well as from the + list of standard BusLogic MultiMaster ISA I/O Addresses. By default, if both + FlashPoint and PCI MultiMaster Host Adapters are present, this driver will + probe for PCI MultiMaster Host Adapters first unless the BIOS primary disk is + not controlled by the first PCI MultiMaster Host Adapter, in which case + FlashPoint Host Adapters will be probed first. The Kernel Command Line + options "MultiMasterFirst" and "FlashPointFirst" can be used to force a + particular probe order. +*/ + +static void BusLogic_InitializeProbeInfoList(void) +{ + /* + If BusLogic_Setup has provided an I/O Address probe list, do not override + the Kernel Command Line specifications. */ - if (pcibios_present()) + if (BusLogic_ProbeInfoCount > 0) return; + /* + If a PCI BIOS is present, interrogate it for MultiMaster and FlashPoint + Host Adapters; otherwise, default to the standard ISA MultiMaster probe. + */ + if (!BusLogic_ProbeOptions.Bits.NoProbePCI && pcibios_present()) { - unsigned int BusDeviceFunction[BusLogic_IO_MaxProbeAddresses]; - unsigned short Index = 0, VendorID, DeviceID; - boolean NonIncreasingScanningOrder = false; - unsigned char Bus, DeviceFunction; - unsigned int BaseAddress0; - while (pcibios_find_class(PCI_CLASS_STORAGE_SCSI<<8, Index++, - &Bus, &DeviceFunction) == 0) - if (pcibios_read_config_word(Bus, DeviceFunction, - PCI_VENDOR_ID, &VendorID) == 0 && - VendorID == PCI_VENDOR_ID_BUSLOGIC && - pcibios_read_config_word(Bus, DeviceFunction, - PCI_DEVICE_ID, &DeviceID) == 0 && - (DeviceID == PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER || - DeviceID == PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC) && - pcibios_read_config_dword(Bus, DeviceFunction, - PCI_BASE_ADDRESS_0, &BaseAddress0) == 0 && - (BaseAddress0 & PCI_BASE_ADDRESS_SPACE) == - PCI_BASE_ADDRESS_SPACE_IO) - { - BusLogic_IO_AddressProbeList[ProbeAddressCount] = - BaseAddress0 & PCI_BASE_ADDRESS_IO_MASK; - BusDeviceFunction[ProbeAddressCount] = (Bus << 8) | DeviceFunction; - if (ProbeAddressCount > 0 && - BusDeviceFunction[ProbeAddressCount] < - BusDeviceFunction[ProbeAddressCount-1]) - NonIncreasingScanningOrder = true; - ProbeAddressCount++; - } - /* - If there are multiple BusLogic PCI SCSI Host Adapters present and if - they are enumerated by the PCI BIOS in an order other than by strictly - increasing Bus Number and Device Number, then interrogate the setting - of the AutoSCSI "Use Bus And Device # For PCI Scanning Seq." option. - If it is ON, and if the first enumeratedBusLogic Host Adapter is a - BT-948/958/958D, then sort the PCI Host Adapter I/O Addresses by - increasing Bus Number and Device Number so that the Host Adapters are - recognized in the same order by the Linux kernel as by the Host - Adapter's BIOS. - */ - if (ProbeAddressCount > 1 && NonIncreasingScanningOrder && - !(BusLogic_ProbeOptions & BusLogic_NoSortPCI)) - { - BusLogic_HostAdapter_T HostAdapterPrototype; - BusLogic_HostAdapter_T *HostAdapter = &HostAdapterPrototype; - BusLogic_FetchHostAdapterLocalRAMRequest_T - FetchHostAdapterLocalRAMRequest; - BusLogic_AutoSCSIByte45_T AutoSCSIByte45; - BusLogic_BoardID_T BoardID; - HostAdapter->IO_Address = BusLogic_IO_AddressProbeList[0]; - FetchHostAdapterLocalRAMRequest.ByteOffset = - BusLogic_AutoSCSI_BaseOffset + 45; - FetchHostAdapterLocalRAMRequest.ByteCount = sizeof(AutoSCSIByte45); - AutoSCSIByte45.ForceBusDeviceScanningOrder = false; - BusLogic_Command(HostAdapter, - BusLogic_FetchHostAdapterLocalRAM, - &FetchHostAdapterLocalRAMRequest, - sizeof(FetchHostAdapterLocalRAMRequest), - &AutoSCSIByte45, sizeof(AutoSCSIByte45)); - BoardID.FirmwareVersion1stDigit = '\0'; - BusLogic_Command(HostAdapter, BusLogic_InquireBoardID, - NULL, 0, &BoardID, sizeof(BoardID)); - if (BoardID.FirmwareVersion1stDigit == '5' && - AutoSCSIByte45.ForceBusDeviceScanningOrder) + if (BusLogic_ProbeOptions.Bits.ProbeMultiMasterFirst) + { + BusLogic_InitializeMultiMasterProbeInfo(); + BusLogic_InitializeFlashPointProbeInfo(); + } + else if (BusLogic_ProbeOptions.Bits.ProbeFlashPointFirst) + { + BusLogic_InitializeFlashPointProbeInfo(); + BusLogic_InitializeMultiMasterProbeInfo(); + } + else + { + int PCIMultiMasterCount = BusLogic_InitializeMultiMasterProbeInfo(); + int FlashPointCount = BusLogic_InitializeFlashPointProbeInfo(); + if (PCIMultiMasterCount > 0 && FlashPointCount > 0) { + BusLogic_ProbeInfo_T *ProbeInfo = &BusLogic_ProbeInfoList[0]; + BusLogic_HostAdapter_T HostAdapterPrototype; + BusLogic_HostAdapter_T *HostAdapter = &HostAdapterPrototype; + BusLogic_FetchHostAdapterLocalRAMRequest_T + FetchHostAdapterLocalRAMRequest; + BusLogic_BIOSDriveMapByte_T Drive0MapByte; + while (ProbeInfo->HostAdapterBusType != BusLogic_PCI_Bus) + ProbeInfo++; + HostAdapter->IO_Address = ProbeInfo->IO_Address; + FetchHostAdapterLocalRAMRequest.ByteOffset = + BusLogic_BIOS_BaseOffset + BusLogic_BIOS_DriveMapOffset + 0; + FetchHostAdapterLocalRAMRequest.ByteCount = + sizeof(Drive0MapByte); + BusLogic_Command(HostAdapter, + BusLogic_FetchHostAdapterLocalRAM, + &FetchHostAdapterLocalRAMRequest, + sizeof(FetchHostAdapterLocalRAMRequest), + &Drive0MapByte, sizeof(Drive0MapByte)); /* - Sort the I/O Addresses such that the corresponding - PCI devices are in ascending order by Bus Number and - Device Number. + If the Map Byte for BIOS Drive 0 indicates that BIOS Drive 0 + is not controlled by this PCI MultiMaster Host Adapter, then + reverse the probe order so that FlashPoint Host Adapters are + probed before MultiMaster Host Adapters. */ - int LastInterchange = ProbeAddressCount-1, Bound, j; - while (LastInterchange > 0) + if (Drive0MapByte.DiskGeometry == + BusLogic_BIOS_Disk_Not_Installed) { - Bound = LastInterchange; - LastInterchange = 0; - for (j = 0; j < Bound; j++) - if (BusDeviceFunction[j] > BusDeviceFunction[j+1]) - { - unsigned int Temp; - Temp = BusDeviceFunction[j]; - BusDeviceFunction[j] = BusDeviceFunction[j+1]; - BusDeviceFunction[j+1] = Temp; - Temp = BusLogic_IO_AddressProbeList[j]; - BusLogic_IO_AddressProbeList[j] = - BusLogic_IO_AddressProbeList[j+1]; - BusLogic_IO_AddressProbeList[j+1] = Temp; - LastInterchange = j; - } + BusLogic_ProbeInfo_T + SavedProbeInfo[BusLogic_MaxHostAdapters]; + int MultiMasterCount = + BusLogic_ProbeInfoCount - FlashPointCount; + memcpy(&SavedProbeInfo[0], + &BusLogic_ProbeInfoList[0], + BusLogic_ProbeInfoCount + * sizeof(BusLogic_ProbeInfo_T)); + memcpy(&BusLogic_ProbeInfoList[0], + &SavedProbeInfo[MultiMasterCount], + FlashPointCount * sizeof(BusLogic_ProbeInfo_T)); + memcpy(&BusLogic_ProbeInfoList[FlashPointCount], + &SavedProbeInfo[0], + MultiMasterCount * sizeof(BusLogic_ProbeInfo_T)); } } } } -#endif - /* - Append the list of standard BusLogic ISA I/O Addresses. - */ - if (!(BusLogic_ProbeOptions & BusLogic_NoProbeISA)) - while (ProbeAddressCount < BusLogic_IO_MaxProbeAddresses && - BusLogic_IO_StandardAddresses[StandardAddressIndex] > 0) - BusLogic_IO_AddressProbeList[ProbeAddressCount++] = - BusLogic_IO_StandardAddresses[StandardAddressIndex++]; - BusLogic_IO_AddressProbeList[ProbeAddressCount] = 0; + else BusLogic_InitializeProbeInfoListISA(); } +#endif /* CONFIG_PCI */ + + /* BusLogic_Failure prints a standardized error message, and then returns false. */ @@ -700,12 +1181,19 @@ 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); + BusLogic_AnnounceDriver(HostAdapter); + if (HostAdapter->HostAdapterBusType == BusLogic_PCI_Bus) + BusLogic_Error("While configuring BusLogic PCI Host Adapter at\n" + "Bus %d Device %d I/O Address 0x%X PCI Address 0x%X:\n", + HostAdapter, HostAdapter->Bus, HostAdapter->Device, + HostAdapter->IO_Address, HostAdapter->PCI_Address); + else BusLogic_Error("While configuring BusLogic Host Adapter at " + "I/O Address 0x%X:\n", HostAdapter, + HostAdapter->IO_Address); + BusLogic_Error("%s FAILED - DETACHING\n", HostAdapter, ErrorMessage); if (BusLogic_CommandFailureReason != NULL) - printk("ADDITIONAL FAILURE INFO - %s\n", BusLogic_CommandFailureReason); + BusLogic_Error("ADDITIONAL FAILURE INFO - %s\n", HostAdapter, + BusLogic_CommandFailureReason); return false; } @@ -716,37 +1204,76 @@ static boolean BusLogic_ProbeHostAdapter(BusLogic_HostAdapter_T *HostAdapter) { - boolean TraceProbe = (BusLogic_GlobalOptions & BusLogic_TraceProbe); - unsigned char StatusRegister, GeometryRegister; + BusLogic_StatusRegister_T StatusRegister; + BusLogic_InterruptRegister_T InterruptRegister; + BusLogic_GeometryRegister_T GeometryRegister; + /* + FlashPoint Host Adapters are Probed by the FlashPoint SCCB Manager. + */ + if (BusLogic_FlashPointHostAdapterP(HostAdapter)) + { + FlashPoint_Info_T *FlashPointInfo = (FlashPoint_Info_T *) + scsi_init_malloc(sizeof(FlashPoint_Info_T), GFP_ATOMIC); + if (FlashPointInfo == NULL) + return BusLogic_Failure(HostAdapter, "ALLOCATING FLASHPOINT INFO"); + FlashPointInfo->BaseAddress = HostAdapter->IO_Address; + FlashPointInfo->IRQ_Channel = HostAdapter->IRQ_Channel; + FlashPointInfo->Present = false; + if (!(FlashPoint_ProbeHostAdapter(FlashPointInfo) == 0 && + FlashPointInfo->Present)) + { + scsi_init_free((char *) FlashPointInfo, sizeof(FlashPoint_Info_T)); + if (BusLogic_GlobalOptions.Bits.TraceProbe) + BusLogic_Notice("BusLogic_Probe(0x%X): FlashPoint Not Found\n", + HostAdapter, HostAdapter->IO_Address); + return false; + } + HostAdapter->FlashPointInfo = FlashPointInfo; + if (BusLogic_GlobalOptions.Bits.TraceProbe) + BusLogic_Notice("BusLogic_Probe(0x%X): FlashPoint Found\n", + HostAdapter, HostAdapter->IO_Address); + /* + Indicate the Host Adapter Probe completed successfully. + */ + return true; + } /* - 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 Status, Interrupt, and Geometry Registers to test if there are I/O + ports that respond, and to check the values to determine if they are from a + BusLogic Host Adapter. A nonexistent I/O port will return 0xFF, in which + case there is definitely no BusLogic Host Adapter at this base I/O Address. + The test here is a subset of that used by the BusLogic Host Adapter BIOS. + */ + StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); + InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter); + GeometryRegister.All = BusLogic_ReadGeometryRegister(HostAdapter); + if (BusLogic_GlobalOptions.Bits.TraceProbe) + BusLogic_Notice("BusLogic_Probe(0x%X): Status 0x%02X, Interrupt 0x%02X, " + "Geometry 0x%02X\n", HostAdapter, + HostAdapter->IO_Address, StatusRegister.All, + InterruptRegister.All, GeometryRegister.All); + if (StatusRegister.All == 0 || + StatusRegister.Bits.DiagnosticActive || + StatusRegister.Bits.CommandParameterRegisterBusy || + StatusRegister.Bits.Reserved || + StatusRegister.Bits.CommandInvalid || + InterruptRegister.Bits.Reserved != 0) + 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 + Check the undocumented Geometry Register to test if there is an I/O port + that responded. 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 - controllers, including the undocumented commands, and is therefore + Host Adapters, 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; + if (GeometryRegister.All == 0xFF) return false; /* Indicate the Host Adapter Probe completed successfully. */ @@ -762,25 +1289,39 @@ static boolean BusLogic_HardResetHostAdapter(BusLogic_HostAdapter_T *HostAdapter) { - boolean TraceHardReset = (BusLogic_GlobalOptions & BusLogic_TraceHardReset); + BusLogic_StatusRegister_T StatusRegister; int TimeoutCounter = loops_per_sec; - unsigned char StatusRegister = 0; + /* + FlashPoint Host Adapters are Hard Reset by the FlashPoint SCCB Manager. + */ + if (BusLogic_FlashPointHostAdapterP(HostAdapter)) + { + HostAdapter->FlashPointInfo->ReportDataUnderrun = true; + HostAdapter->CardHandle = + FlashPoint_HardResetHostAdapter(HostAdapter->FlashPointInfo); + if (HostAdapter->CardHandle == FlashPoint_BadCardHandle) return false; + /* + Indicate the Host Adapter Hard Reset completed successfully. + */ + return true; + } /* 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); + BusLogic_HardReset(HostAdapter); /* Wait until Diagnostic Active is set in the Status Register. */ while (--TimeoutCounter >= 0) { - StatusRegister = BusLogic_ReadStatusRegister(HostAdapter); - if ((StatusRegister & BusLogic_DiagnosticActive)) break; + StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); + if (StatusRegister.Bits.DiagnosticActive) break; } - if (TraceHardReset) - printk("BusLogic_HardReset(0x%X): Diagnostic Active, Status 0x%02X\n", - HostAdapter->IO_Address, StatusRegister); + if (BusLogic_GlobalOptions.Bits.TraceHardReset) + BusLogic_Notice("BusLogic_HardReset(0x%X): Diagnostic Active, " + "Status 0x%02X\n", HostAdapter, + HostAdapter->IO_Address, StatusRegister.All); if (TimeoutCounter < 0) return false; /* Wait 100 microseconds to allow completion of any initial diagnostic @@ -793,12 +1334,13 @@ */ while (--TimeoutCounter >= 0) { - StatusRegister = BusLogic_ReadStatusRegister(HostAdapter); - if (!(StatusRegister & BusLogic_DiagnosticActive)) break; + StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); + if (!StatusRegister.Bits.DiagnosticActive) break; } - if (TraceHardReset) - printk("BusLogic_HardReset(0x%X): Diagnostic Completed, Status 0x%02X\n", - HostAdapter->IO_Address, StatusRegister); + if (BusLogic_GlobalOptions.Bits.TraceHardReset) + BusLogic_Notice("BusLogic_HardReset(0x%X): Diagnostic Completed, " + "Status 0x%02X\n", HostAdapter, + HostAdapter->IO_Address, StatusRegister.All); if (TimeoutCounter < 0) return false; /* Wait until at least one of the Diagnostic Failure, Host Adapter Ready, @@ -806,31 +1348,34 @@ */ while (--TimeoutCounter >= 0) { - StatusRegister = BusLogic_ReadStatusRegister(HostAdapter); - if (StatusRegister & (BusLogic_DiagnosticFailure | - BusLogic_HostAdapterReady | - BusLogic_DataInRegisterReady)) + StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); + if (StatusRegister.Bits.DiagnosticFailure || + StatusRegister.Bits.HostAdapterReady || + StatusRegister.Bits.DataInRegisterReady) break; } - if (TraceHardReset) - printk("BusLogic_HardReset(0x%X): Host Adapter Ready, Status 0x%02X\n", - HostAdapter->IO_Address, StatusRegister); + if (BusLogic_GlobalOptions.Bits.TraceHardReset) + BusLogic_Notice("BusLogic_HardReset(0x%X): Host Adapter Ready, " + "Status 0x%02X\n", HostAdapter, + HostAdapter->IO_Address, StatusRegister.All); 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)) + if (StatusRegister.Bits.DiagnosticFailure || + !StatusRegister.Bits.HostAdapterReady) { BusLogic_CommandFailureReason = NULL; BusLogic_Failure(HostAdapter, "HARD RESET DIAGNOSTICS"); - printk("HOST ADAPTER STATUS REGISTER = %02X\n", StatusRegister); - if (StatusRegister & BusLogic_DataInRegisterReady) + BusLogic_Error("HOST ADAPTER STATUS REGISTER = %02X\n", + HostAdapter, StatusRegister.All); + if (StatusRegister.Bits.DataInRegisterReady) { unsigned char ErrorCode = BusLogic_ReadDataInRegister(HostAdapter); - printk("HOST ADAPTER ERROR CODE = %d\n", ErrorCode); + BusLogic_Error("HOST ADAPTER ERROR CODE = %d\n", + HostAdapter, ErrorCode); } return false; } @@ -843,43 +1388,70 @@ /* BusLogic_CheckHostAdapter checks to be sure this really is a BusLogic - Host Adapter. + Host Adapter. It also determines the IRQ Channel for non-PCI Host Adapters. */ static boolean BusLogic_CheckHostAdapter(BusLogic_HostAdapter_T *HostAdapter) { + BusLogic_Configuration_T Configuration; BusLogic_ExtendedSetupInformation_T ExtendedSetupInformation; BusLogic_RequestedReplyLength_T RequestedReplyLength; - unsigned long ProcessorFlags; - int Result; + boolean Result = true; + /* + FlashPoint Host Adapters do not require this protection. + */ + if (BusLogic_FlashPointHostAdapterP(HostAdapter)) return true; + /* + Issue the Inquire Configuration command if the IRQ Channel is unknown. + */ + if (HostAdapter->IRQ_Channel == 0) + if (BusLogic_Command(HostAdapter, BusLogic_InquireConfiguration, + NULL, 0, &Configuration, sizeof(Configuration)) + == sizeof(Configuration)) + { + 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; + else Result = false; + } + else Result = false; /* 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. + fail this command. */ - 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)); + if (BusLogic_Command(HostAdapter, + BusLogic_InquireExtendedSetupInformation, + &RequestedReplyLength, + sizeof(RequestedReplyLength), + &ExtendedSetupInformation, + sizeof(ExtendedSetupInformation)) + != sizeof(ExtendedSetupInformation)) + Result = false; + /* + Provide tracing information if requested and return. + */ + if (BusLogic_GlobalOptions.Bits.TraceProbe) + BusLogic_Notice("BusLogic_Check(0x%X): MultiMaster %s\n", HostAdapter, + HostAdapter->IO_Address, (Result ? "Found" : "Not Found")); + return Result; } /* BusLogic_ReadHostAdapterConfiguration reads the Configuration Information - from Host Adapter. + from Host Adapter and initializes the Host Adapter structure. */ static boolean BusLogic_ReadHostAdapterConfiguration(BusLogic_HostAdapter_T @@ -889,18 +1461,65 @@ BusLogic_Configuration_T Configuration; BusLogic_SetupInformation_T SetupInformation; BusLogic_ExtendedSetupInformation_T ExtendedSetupInformation; - BusLogic_ControllerModelNumber_T ControllerModelNumber; + BusLogic_HostAdapterModelNumber_T HostAdapterModelNumber; BusLogic_FirmwareVersion3rdDigit_T FirmwareVersion3rdDigit; BusLogic_FirmwareVersionLetter_T FirmwareVersionLetter; - BusLogic_GenericIOPortInformation_T GenericIOPortInformation; + BusLogic_PCIHostAdapterInformation_T PCIHostAdapterInformation; BusLogic_FetchHostAdapterLocalRAMRequest_T FetchHostAdapterLocalRAMRequest; - BusLogic_AutoSCSIByte15_T AutoSCSIByte15; + BusLogic_AutoSCSIData_T AutoSCSIData; + BusLogic_GeometryRegister_T GeometryRegister; BusLogic_RequestedReplyLength_T RequestedReplyLength; - unsigned char GeometryRegister, *TargetPointer, Character; - unsigned short AllTargetsMask, DisconnectPermitted; - unsigned short TaggedQueuingPermitted, TaggedQueuingPermittedDefault; - boolean CommonErrorRecovery; - int TargetID, i; + unsigned char *TargetPointer, Character; + int i; + /* + Configuration Information for FlashPoint Host Adapters is provided in the + FlashPoint_Info structure by the FlashPoint SCCB Manager's Probe Function. + Initialize fields in the Host Adapter structure from the FlashPoint_Info + structure. + */ + if (BusLogic_FlashPointHostAdapterP(HostAdapter)) + { + FlashPoint_Info_T *FlashPointInfo = HostAdapter->FlashPointInfo; + TargetPointer = HostAdapter->ModelName; + *TargetPointer++ = 'B'; + *TargetPointer++ = 'T'; + *TargetPointer++ = '-'; + for (i = 0; i < sizeof(FlashPointInfo->ModelNumber); i++) + *TargetPointer++ = FlashPointInfo->ModelNumber[i]; + *TargetPointer++ = '\0'; + strcpy(HostAdapter->FirmwareVersion, FlashPoint_FirmwareVersion); + HostAdapter->SCSI_ID = FlashPointInfo->SCSI_ID; + HostAdapter->ExtendedTranslationEnabled = + FlashPointInfo->ExtendedTranslationEnabled; + HostAdapter->ParityCheckingEnabled = + FlashPointInfo->ParityCheckingEnabled; + HostAdapter->BusResetEnabled = !FlashPointInfo->HostSoftReset; + HostAdapter->LevelSensitiveInterrupt = true; + HostAdapter->HostWideSCSI = FlashPointInfo->HostWideSCSI; + HostAdapter->HostDifferentialSCSI = false; + HostAdapter->HostSupportsSCAM = true; + HostAdapter->HostUltraSCSI = true; + HostAdapter->ExtendedLUNSupport = true; + HostAdapter->TerminationInfoValid = true; + HostAdapter->LowByteTerminated = FlashPointInfo->LowByteTerminated; + HostAdapter->HighByteTerminated = FlashPointInfo->HighByteTerminated; + HostAdapter->SCAM_Enabled = FlashPointInfo->SCAM_Enabled; + HostAdapter->SCAM_Level2 = FlashPointInfo->SCAM_Level2; + HostAdapter->DriverScatterGatherLimit = BusLogic_ScatterGatherLimit; + HostAdapter->MaxTargetDevices = (HostAdapter->HostWideSCSI ? 16 : 8); + HostAdapter->MaxLogicalUnits = 32; + HostAdapter->InitialCCBs = 64; + HostAdapter->IncrementalCCBs = 32; + HostAdapter->DriverQueueDepth = 255; + HostAdapter->HostAdapterQueueDepth = HostAdapter->DriverQueueDepth; + HostAdapter->SynchronousPermitted = FlashPointInfo->SynchronousPermitted; + HostAdapter->FastPermitted = FlashPointInfo->FastPermitted; + HostAdapter->UltraPermitted = FlashPointInfo->UltraPermitted; + HostAdapter->WidePermitted = FlashPointInfo->WidePermitted; + HostAdapter->DisconnectPermitted = FlashPointInfo->DisconnectPermitted; + HostAdapter->TaggedQueuingPermitted = 0xFFFF; + goto Common; + } /* Issue the Inquire Board ID command. */ @@ -934,39 +1553,47 @@ != sizeof(ExtendedSetupInformation)) return BusLogic_Failure(HostAdapter, "INQUIRE EXTENDED SETUP INFORMATION"); /* - Issue the Inquire Controller Model Number command. + Issue the Inquire Firmware Version 3rd Digit command. + */ + FirmwareVersion3rdDigit = '\0'; + if (BoardID.FirmwareVersion1stDigit > '0') + if (BusLogic_Command(HostAdapter, BusLogic_InquireFirmwareVersion3rdDigit, + NULL, 0, &FirmwareVersion3rdDigit, + sizeof(FirmwareVersion3rdDigit)) + != sizeof(FirmwareVersion3rdDigit)) + return BusLogic_Failure(HostAdapter, "INQUIRE FIRMWARE 3RD DIGIT"); + /* + Issue the Inquire Host Adapter Model Number command. */ if (ExtendedSetupInformation.BusType == 'A' && BoardID.FirmwareVersion1stDigit == '2') /* BusLogic BT-542B ISA 2.xx */ - strcpy(ControllerModelNumber, "542B"); + strcpy(HostAdapterModelNumber, "542B"); + else if (ExtendedSetupInformation.BusType == 'E' && + BoardID.FirmwareVersion1stDigit == '2' && + (BoardID.FirmwareVersion2ndDigit <= '1' || + (BoardID.FirmwareVersion2ndDigit == '2' && + FirmwareVersion3rdDigit == '0'))) + /* BusLogic BT-742A EISA 2.1x or 2.20 */ + strcpy(HostAdapterModelNumber, "742A"); else if (ExtendedSetupInformation.BusType == 'E' && BoardID.FirmwareVersion1stDigit == '0') /* AMI FastDisk EISA Series 441 0.x */ - strcpy(ControllerModelNumber, "747A"); + strcpy(HostAdapterModelNumber, "747A"); else { - RequestedReplyLength = sizeof(ControllerModelNumber); - if (BusLogic_Command(HostAdapter, BusLogic_InquireControllerModelNumber, + RequestedReplyLength = sizeof(HostAdapterModelNumber); + if (BusLogic_Command(HostAdapter, BusLogic_InquireHostAdapterModelNumber, &RequestedReplyLength, sizeof(RequestedReplyLength), - &ControllerModelNumber, - sizeof(ControllerModelNumber)) - != sizeof(ControllerModelNumber)) - return BusLogic_Failure(HostAdapter, "INQUIRE CONTROLLER MODEL NUMBER"); + &HostAdapterModelNumber, + sizeof(HostAdapterModelNumber)) + != sizeof(HostAdapterModelNumber)) + return BusLogic_Failure(HostAdapter, + "INQUIRE HOST ADAPTER MODEL NUMBER"); } /* - Issue the Inquire Firmware Version 3rd Digit command. - */ - FirmwareVersion3rdDigit = '\0'; - if (BoardID.FirmwareVersion1stDigit > '0') - if (BusLogic_Command(HostAdapter, BusLogic_InquireFirmwareVersion3rdDigit, - NULL, 0, &FirmwareVersion3rdDigit, - sizeof(FirmwareVersion3rdDigit)) - != sizeof(FirmwareVersion3rdDigit)) - return BusLogic_Failure(HostAdapter, "INQUIRE FIRMWARE 3RD DIGIT"); - /* - BusLogic Host Adapters can be identified by their model number and - the major version number of their firmware as follows: + BusLogic MultiMaster Host Adapters can be identified by their model number + and the major version number of their firmware as follows: 5.xx BusLogic "W" Series Host Adapters: BT-948/958/958D @@ -980,22 +1607,19 @@ 0.xx AMI FastDisk VLB/EISA BusLogic Clone Host Adapter */ /* - Save the Model Name and Controller Name in the Host Adapter structure. + Save the Model Name and Host Adapter Name in the Host Adapter structure. */ TargetPointer = HostAdapter->ModelName; *TargetPointer++ = 'B'; *TargetPointer++ = 'T'; *TargetPointer++ = '-'; - for (i = 0; i < sizeof(ControllerModelNumber); i++) + for (i = 0; i < sizeof(HostAdapterModelNumber); i++) { - Character = ControllerModelNumber[i]; + Character = HostAdapterModelNumber[i]; if (Character == ' ' || Character == '\0') break; *TargetPointer++ = Character; } *TargetPointer++ = '\0'; - strcpy(HostAdapter->ControllerName, "BusLogic "); - strcat(HostAdapter->ControllerName, HostAdapter->ModelName); - strcpy(HostAdapter->InterruptLabel, HostAdapter->ControllerName); /* Save the Firmware Version in the Host Adapter structure. */ @@ -1015,144 +1639,39 @@ NULL, 0, &FirmwareVersionLetter, sizeof(FirmwareVersionLetter)) != sizeof(FirmwareVersionLetter)) - return BusLogic_Failure(HostAdapter, "INQUIRE FIRMWARE VERSION LETTER"); - if (FirmwareVersionLetter != ' ' && FirmwareVersionLetter != '\0') - *TargetPointer++ = FirmwareVersionLetter; - *TargetPointer = '\0'; - } - /* - Issue the Inquire Generic I/O Port Information command to read the - IRQ Channel from all PCI Host Adapters, and the Termination Information - from "W" Series Host Adapters. - */ - if (HostAdapter->ModelName[3] == '9' && - strcmp(HostAdapter->FirmwareVersion, "4.25") >= 0) - { - if (BusLogic_Command(HostAdapter, - BusLogic_InquireGenericIOPortInformation, - NULL, 0, &GenericIOPortInformation, - sizeof(GenericIOPortInformation)) - != sizeof(GenericIOPortInformation)) return BusLogic_Failure(HostAdapter, - "INQUIRE GENERIC I/O PORT INFORMATION"); - /* - Save the IRQ Channel in the Host Adapter structure. - */ - HostAdapter->IRQ_Channel = GenericIOPortInformation.PCIAssignedIRQChannel; - /* - Save the Termination Information in the Host Adapter structure. - */ - if (HostAdapter->FirmwareVersion[0] == '5' && - GenericIOPortInformation.Valid) - { - HostAdapter->TerminationInfoValid = true; - HostAdapter->LowByteTerminated = - GenericIOPortInformation.LowByteTerminated; - HostAdapter->HighByteTerminated = - GenericIOPortInformation.HighByteTerminated; - } - } - /* - Issue the Fetch Host Adapter Local RAM command to read the Termination - Information from the AutoSCSI area of "C" Series Host Adapters. - */ - if (HostAdapter->FirmwareVersion[0] == '4') - { - FetchHostAdapterLocalRAMRequest.ByteOffset = - BusLogic_AutoSCSI_BaseOffset + 15; - FetchHostAdapterLocalRAMRequest.ByteCount = sizeof(AutoSCSIByte15); - if (BusLogic_Command(HostAdapter, - BusLogic_FetchHostAdapterLocalRAM, - &FetchHostAdapterLocalRAMRequest, - sizeof(FetchHostAdapterLocalRAMRequest), - &AutoSCSIByte15, sizeof(AutoSCSIByte15)) - != sizeof(AutoSCSIByte15)) - return BusLogic_Failure(HostAdapter, "FETCH HOST ADAPTER LOCAL RAM"); - /* - Save the Termination Information in the Host Adapter structure. - */ - HostAdapter->TerminationInfoValid = true; - HostAdapter->LowByteTerminated = AutoSCSIByte15.LowByteTerminated; - HostAdapter->HighByteTerminated = AutoSCSIByte15.HighByteTerminated; - } - /* - Determine the IRQ Channel and save it in the Host Adapter structure. - */ - if (HostAdapter->IRQ_Channel == 0) - { - 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; + "INQUIRE FIRMWARE VERSION LETTER"); + if (FirmwareVersionLetter != ' ' && FirmwareVersionLetter != '\0') + *TargetPointer++ = FirmwareVersionLetter; + *TargetPointer = '\0'; } /* 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, and determine and save the DMA Channel for ISA Host Adapters. */ - switch (HostAdapter->ModelName[3]) - { - case '4': - HostAdapter->BusType = BusLogic_VESA_Bus; - break; - case '5': - HostAdapter->BusType = BusLogic_ISA_Bus; - 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; - break; - case '6': - HostAdapter->BusType = BusLogic_MCA_Bus; - break; - case '7': - HostAdapter->BusType = BusLogic_EISA_Bus; - break; - case '9': - HostAdapter->BusType = BusLogic_PCI_Bus; - break; - } + HostAdapter->HostAdapterBusType = + BusLogic_HostAdapterBusTypes[HostAdapter->ModelName[3] - '4']; + if (HostAdapter->HostAdapterBusType == BusLogic_ISA_Bus) + 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; /* 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 "W" and - "C" Series controllers, but Disconnect/Reconnect is always permitted on "S" - and "A" Series controllers. - */ - if (HostAdapter->FirmwareVersion[0] >= '4') - HostAdapter->DisconnectPermitted = - (SetupInformation.DisconnectPermittedID8to15 << 8) - | SetupInformation.DisconnectPermittedID0to7; - else HostAdapter->DisconnectPermitted = 0xFF; + GeometryRegister.All = BusLogic_ReadGeometryRegister(HostAdapter); + HostAdapter->ExtendedTranslationEnabled = + GeometryRegister.Bits.ExtendedTranslationEnabled; /* - Save the Scatter Gather Limits, Level Sensitive Interrupts flag, Wide - SCSI flag, Differential SCSI flag, Automatic Configuration flag, and + Save the Scatter Gather Limits, Level Sensitive Interrupt flag, Wide + SCSI flag, Differential SCSI flag, SCAM Supported flag, and Ultra SCSI flag in the Host Adapter structure. */ HostAdapter->HostAdapterScatterGatherLimit = @@ -1161,75 +1680,149 @@ HostAdapter->HostAdapterScatterGatherLimit; if (HostAdapter->HostAdapterScatterGatherLimit > BusLogic_ScatterGatherLimit) HostAdapter->DriverScatterGatherLimit = BusLogic_ScatterGatherLimit; - if (ExtendedSetupInformation.Misc.LevelSensitiveInterrupts) - HostAdapter->LevelSensitiveInterrupts = true; + if (ExtendedSetupInformation.Misc.LevelSensitiveInterrupt) + HostAdapter->LevelSensitiveInterrupt = true; HostAdapter->HostWideSCSI = ExtendedSetupInformation.HostWideSCSI; HostAdapter->HostDifferentialSCSI = ExtendedSetupInformation.HostDifferentialSCSI; - HostAdapter->HostAutomaticConfiguration = - ExtendedSetupInformation.HostAutomaticConfiguration; + HostAdapter->HostSupportsSCAM = ExtendedSetupInformation.HostSupportsSCAM; HostAdapter->HostUltraSCSI = ExtendedSetupInformation.HostUltraSCSI; /* - Determine whether 64 LUN Format CCBs are supported and save the information - in the Host Adapter structure. + Determine whether Extended LUN Format CCBs are supported and save the + information in the Host Adapter structure. */ if (HostAdapter->FirmwareVersion[0] == '5' || (HostAdapter->FirmwareVersion[0] == '4' && HostAdapter->HostWideSCSI)) - HostAdapter->Host64LUNSupport = true; + HostAdapter->ExtendedLUNSupport = true; /* - 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. + Issue the Inquire PCI Host Adapter Information command to read the + Termination Information from "W" series MultiMaster Host Adapters. */ - HostAdapter->BIOS_Address = ExtendedSetupInformation.BIOS_Address << 12; + if (HostAdapter->FirmwareVersion[0] == '5') + { + if (BusLogic_Command(HostAdapter, + BusLogic_InquirePCIHostAdapterInformation, + NULL, 0, &PCIHostAdapterInformation, + sizeof(PCIHostAdapterInformation)) + != sizeof(PCIHostAdapterInformation)) + return BusLogic_Failure(HostAdapter, + "INQUIRE PCI HOST ADAPTER INFORMATION"); + /* + Save the Termination Information in the Host Adapter structure. + */ + if (PCIHostAdapterInformation.GenericInfoValid) + { + HostAdapter->TerminationInfoValid = true; + HostAdapter->LowByteTerminated = + PCIHostAdapterInformation.LowByteTerminated; + HostAdapter->HighByteTerminated = + PCIHostAdapterInformation.HighByteTerminated; + } + } /* - ISA Host Adapters require Bounce Buffers if there is more than 16MB memory. + Issue the Fetch Host Adapter Local RAM command to read the AutoSCSI data + from "W" and "C" series MultiMaster Host Adapters. */ - if (HostAdapter->BusType == BusLogic_ISA_Bus && - high_memory > (void *) MAX_DMA_ADDRESS) - HostAdapter->BounceBuffersRequired = true; + if (HostAdapter->FirmwareVersion[0] >= '4') + { + FetchHostAdapterLocalRAMRequest.ByteOffset = + BusLogic_AutoSCSI_BaseOffset; + FetchHostAdapterLocalRAMRequest.ByteCount = sizeof(AutoSCSIData); + if (BusLogic_Command(HostAdapter, + BusLogic_FetchHostAdapterLocalRAM, + &FetchHostAdapterLocalRAMRequest, + sizeof(FetchHostAdapterLocalRAMRequest), + &AutoSCSIData, sizeof(AutoSCSIData)) + != sizeof(AutoSCSIData)) + return BusLogic_Failure(HostAdapter, "FETCH HOST ADAPTER LOCAL RAM"); + /* + Save the Parity Checking Enabled, Bus Reset Enabled, and Termination + Information in the Host Adapter structure. + */ + HostAdapter->ParityCheckingEnabled = AutoSCSIData.ParityCheckingEnabled; + HostAdapter->BusResetEnabled = AutoSCSIData.BusResetEnabled; + if (HostAdapter->FirmwareVersion[0] == '4') + { + HostAdapter->TerminationInfoValid = true; + HostAdapter->LowByteTerminated = AutoSCSIData.LowByteTerminated; + HostAdapter->HighByteTerminated = AutoSCSIData.HighByteTerminated; + } + /* + Save the Wide Permitted, Fast Permitted, Synchronous Permitted, + Disconnect Permitted, Ultra Permitted, and SCAM Information in the + Host Adapter structure. + */ + HostAdapter->WidePermitted = AutoSCSIData.WidePermitted; + HostAdapter->FastPermitted = AutoSCSIData.FastPermitted; + HostAdapter->SynchronousPermitted = + AutoSCSIData.SynchronousPermitted; + HostAdapter->DisconnectPermitted = + AutoSCSIData.DisconnectPermitted; + if (HostAdapter->HostUltraSCSI) + HostAdapter->UltraPermitted = AutoSCSIData.UltraPermitted; + if (HostAdapter->HostSupportsSCAM) + { + HostAdapter->SCAM_Enabled = AutoSCSIData.SCAM_Enabled; + HostAdapter->SCAM_Level2 = AutoSCSIData.SCAM_Level2; + } + } /* - BusLogic BT-445S Host Adapters prior to controller revision E 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 controllers have firmware version 3.37, so we - require that ISA Bounce Buffers be used for the buggy BT-445S models if - there is more than 16MB memory. + Initialize fields in the Host Adapter structure for "S" and "A" series + MultiMaster Host Adapters. */ - if (HostAdapter->BIOS_Address > 0 && - strcmp(HostAdapter->ModelName, "BT-445S") == 0 && - strcmp(HostAdapter->FirmwareVersion, "3.37") < 0 && - high_memory > (void *) MAX_DMA_ADDRESS) - HostAdapter->BounceBuffersRequired = true; + if (HostAdapter->FirmwareVersion[0] < '4') + { + if (SetupInformation.SynchronousInitiationEnabled) + { + HostAdapter->SynchronousPermitted = 0xFF; + if (HostAdapter->HostAdapterBusType == BusLogic_EISA_Bus) + { + if (ExtendedSetupInformation.Misc.FastOnEISA) + HostAdapter->FastPermitted = 0xFF; + if (strcmp(HostAdapter->ModelName, "BT-757") == 0) + HostAdapter->WidePermitted = 0xFF; + } + } + HostAdapter->DisconnectPermitted = 0xFF; + HostAdapter->ParityCheckingEnabled = + SetupInformation.ParityCheckingEnabled; + HostAdapter->BusResetEnabled = true; + } /* Determine the maximum number of Target IDs and Logical Units supported by this driver for Wide and Narrow Host Adapters. */ HostAdapter->MaxTargetDevices = (HostAdapter->HostWideSCSI ? 16 : 8); - HostAdapter->MaxLogicalUnits = (HostAdapter->Host64LUNSupport ? 64 : 8); + HostAdapter->MaxLogicalUnits = (HostAdapter->ExtendedLUNSupport ? 32 : 8); /* - Select appropriate values for the Mailbox Count, Initial CCBs, and - Incremental CCBs variables based on whether or not Strict Round Robin Mode - is supported. If Strict Round Robin Mode is supported, then there is no - performance degradation in using the maximum possible number of Outgoing - and Incoming Mailboxes and allowing the Tagged and Untagged Queue Depths to - determine the actual utilization. If Strict Round Robin Mode is not - supported, then the Host Adapter must scan all the Outgoing Mailboxes - whenever an Outgoing Mailbox entry is made, which can cause a substantial - performance penalty. The Host Adapters actually have room to store the - following number of CCBs internally; that is, they can internally queue and - manage this many active commands on the SCSI bus simultaneously. - Performance measurements demonstrate that the Mailbox Count should be set - to the maximum possible, rather than the internal CCB capacity, as it is - more efficient to have the queued commands waiting in Outgoing Mailboxes if - necessary than to block the process in the higher levels of the SCSI - Subsystem. + Select appropriate values for the Driver Queue Depth, Mailbox Count, + Initial CCBs, and Incremental CCBs variables based on whether or not Strict + Round Robin Mode is supported. If Strict Round Robin Mode is supported, + then there is no performance degradation in using the maximum possible + number of Outgoing and Incoming Mailboxes and allowing the Tagged and + Untagged Queue Depths to determine the actual utilization. If Strict Round + Robin Mode is not supported, then the Host Adapter must scan all the + Outgoing Mailboxes whenever an Outgoing Mailbox entry is made, which can + cause a substantial performance penalty. The host adapters actually have + room to store the following number of CCBs internally; that is, they can + internally queue and manage this many active commands on the SCSI bus + simultaneously. Performance measurements demonstrate that the Driver Queue + Depth should be set to the Mailbox Count, rather than the Host Adapter + Queue Depth (internal CCB capacity), as it is more efficient to have the + queued commands waiting in Outgoing Mailboxes if necessary than to block + the process in the higher levels of the SCSI Subsystem. 192 BT-948/958/958D 100 BT-946C/956C/956CD/747C/757C/757CD/445C 50 BT-545C/540CF 30 BT-747S/747D/757S/757D/445S/545S/542D/542B/742A */ + if (HostAdapter->FirmwareVersion[0] == '5') + HostAdapter->HostAdapterQueueDepth = 192; + else if (HostAdapter->FirmwareVersion[0] == '4') + HostAdapter->HostAdapterQueueDepth = + (HostAdapter->HostAdapterBusType != BusLogic_ISA_Bus ? 100 : 50); + else HostAdapter->HostAdapterQueueDepth = 30; if (strcmp(HostAdapter->FirmwareVersion, "3.31") >= 0) { HostAdapter->StrictRoundRobinModeSupport = true; @@ -1244,30 +1837,85 @@ HostAdapter->InitialCCBs = 32; HostAdapter->IncrementalCCBs = 4; } - if (HostAdapter->FirmwareVersion[0] == '5') - HostAdapter->TotalQueueDepth = 192; - else if (HostAdapter->FirmwareVersion[0] == '4') - HostAdapter->TotalQueueDepth = - (HostAdapter->BusType != BusLogic_ISA_Bus ? 100 : 50); - else HostAdapter->TotalQueueDepth = 30; + HostAdapter->DriverQueueDepth = HostAdapter->MailboxCount; + /* + Tagged Queuing support is available and operates properly on all "W" series + MultiMaster Host Adapters, on "C" series MultiMaster Host Adapters with + firmware version 4.22 and above, and on "S" series MultiMaster Host + Adapters with firmware version 3.35 and above. + */ + HostAdapter->TaggedQueuingPermitted = 0; + switch (HostAdapter->FirmwareVersion[0]) + { + case '5': + HostAdapter->TaggedQueuingPermitted = 0xFFFF; + break; + case '4': + if (strcmp(HostAdapter->FirmwareVersion, "4.22") >= 0) + HostAdapter->TaggedQueuingPermitted = 0xFFFF; + break; + case '3': + if (strcmp(HostAdapter->FirmwareVersion, "3.35") >= 0) + HostAdapter->TaggedQueuingPermitted = 0xFFFF; + break; + } + /* + 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; + /* + ISA Host Adapters require Bounce Buffers if there is more than 16MB memory. + */ + if (HostAdapter->HostAdapterBusType == BusLogic_ISA_Bus && + (void *) high_memory > (void *) MAX_DMA_ADDRESS) + HostAdapter->BounceBuffersRequired = true; + /* + BusLogic BT-445S Host Adapters prior to board revision E 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 Host Adapters have firmware version 3.37, so require + that ISA Bounce Buffers be used for the buggy BT-445S models if there is + more than 16MB memory. + */ + if (HostAdapter->BIOS_Address > 0 && + strcmp(HostAdapter->ModelName, "BT-445S") == 0 && + strcmp(HostAdapter->FirmwareVersion, "3.37") < 0 && + (void *) high_memory > (void *) MAX_DMA_ADDRESS) + HostAdapter->BounceBuffersRequired = true; + /* + Initialize parameters common to MultiMaster and FlashPoint Host Adapters. + */ +Common: + /* + Initialize the Host Adapter Name and Interrupt Label fields from the + Model Name. + */ + strcpy(HostAdapter->FullModelName, "BusLogic "); + strcat(HostAdapter->FullModelName, HostAdapter->ModelName); + strcpy(HostAdapter->InterruptLabel, HostAdapter->FullModelName); /* Select an appropriate value for the Tagged Queue Depth either from a - Command Line Entry, or based on whether this Host Adapter requires that - ISA Bounce Buffers be used. The Tagged Queue Depth is left at 0 for - automatic determination in BusLogic_SelectQueueDepths. Initialize the - Untagged Queue Depth. + Command Line Entry, or based on whether this Host Adapter requires that ISA + Bounce Buffers be used. The Tagged Queue Depth is left at 0 for automatic + determination in BusLogic_SelectQueueDepths. Initialize the Untagged Queue + Depth. Tagged Queuing is disabled by default when the Tagged Queue Depth + is 1 since queuing multiple commands is not possible. */ if (HostAdapter->CommandLineEntry != NULL && HostAdapter->CommandLineEntry->TaggedQueueDepth > 0) HostAdapter->TaggedQueueDepth = HostAdapter->CommandLineEntry->TaggedQueueDepth; else if (HostAdapter->BounceBuffersRequired) - HostAdapter->TaggedQueueDepth = BusLogic_TaggedQueueDepth_BB; - else HostAdapter->TaggedQueueDepth = 0; + HostAdapter->TaggedQueueDepth = BusLogic_TaggedQueueDepthBounceBuffers; + else HostAdapter->TaggedQueueDepth = BusLogic_TaggedQueueDepthAutomatic; HostAdapter->UntaggedQueueDepth = BusLogic_UntaggedQueueDepth; if (HostAdapter->UntaggedQueueDepth > HostAdapter->TaggedQueueDepth && HostAdapter->TaggedQueueDepth > 0) HostAdapter->UntaggedQueueDepth = HostAdapter->TaggedQueueDepth; + if (HostAdapter->TaggedQueueDepth == 1) + HostAdapter->TaggedQueuingPermitted = 0; /* Select an appropriate value for Bus Settle Time either from a Command Line Entry, or from BusLogic_DefaultBusSettleTime. @@ -1293,34 +1941,11 @@ BusLogic_ErrorRecovery_Default, sizeof(HostAdapter->ErrorRecoveryStrategy)); /* - Tagged Queuing support is available and operates properly on all "W" Series - controllers, on "C" Series controllers with firmware version 4.22 and - above, and on "S" Series controllers with firmware version 3.35 and above. - Tagged Queuing is disabled by default when the Tagged Queue Depth is 1 - since queuing multiple commands is not possible. - */ - TaggedQueuingPermittedDefault = 0; - if (HostAdapter->TaggedQueueDepth != 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. + Tagged Queuing is only allowed if Disconnect/Reconnect is permitted. Therefore, mask the Tagged Queuing Permitted Default bits with the Disconnect/Reconnect Permitted bits. */ - TaggedQueuingPermittedDefault &= HostAdapter->DisconnectPermitted; + HostAdapter->TaggedQueuingPermitted &= HostAdapter->DisconnectPermitted; /* Combine the default Tagged Queuing Permitted bits with any Command Line Entry Tagged Queuing specification. @@ -1329,78 +1954,190 @@ HostAdapter->TaggedQueuingPermitted = (HostAdapter->CommandLineEntry->TaggedQueuingPermitted & HostAdapter->CommandLineEntry->TaggedQueuingPermittedMask) | - (TaggedQueuingPermittedDefault & + (HostAdapter->TaggedQueuingPermitted & ~HostAdapter->CommandLineEntry->TaggedQueuingPermittedMask); - else HostAdapter->TaggedQueuingPermitted = TaggedQueuingPermittedDefault; /* - Announce the Host Adapter Configuration. + Indicate reading the Host Adapter Configuration completed successfully. */ - printk("scsi%d: Configuring BusLogic Model %s %s%s%s%s SCSI Host Adapter\n", - HostAdapter->HostNumber, HostAdapter->ModelName, - BusLogic_BusNames[HostAdapter->BusType], - (HostAdapter->HostWideSCSI ? " Wide" : ""), - (HostAdapter->HostDifferentialSCSI ? " Differential" : ""), - (HostAdapter->HostUltraSCSI ? " Ultra" : "")); - 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%X, ", 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 of %d segments, " - "Parity Checking: %s\n", HostAdapter->HostNumber, - HostAdapter->DriverScatterGatherLimit, - HostAdapter->HostAdapterScatterGatherLimit, - (HostAdapter->ParityChecking ? "Enabled" : "Disabled")); - printk("scsi%d: Synchronous Initiation: %s, " - "Extended Disk Translation: %s\n", HostAdapter->HostNumber, - (HostAdapter->SynchronousInitiation ? "Enabled" : "Disabled"), - (HostAdapter->ExtendedTranslation ? "Enabled" : "Disabled")); - AllTargetsMask = (1 << HostAdapter->MaxTargetDevices) - 1; + return true; +} + + +/* + BusLogic_ReportHostAdapterConfiguration reports the configuration of + Host Adapter. +*/ + +static boolean BusLogic_ReportHostAdapterConfiguration(BusLogic_HostAdapter_T + *HostAdapter) +{ + unsigned short AllTargetsMask = (1 << HostAdapter->MaxTargetDevices) - 1; + unsigned short SynchronousPermitted, FastPermitted; + unsigned short UltraPermitted, WidePermitted; + unsigned short DisconnectPermitted, TaggedQueuingPermitted; + boolean CommonSynchronousNegotiation, CommonErrorRecovery; + char SynchronousString[BusLogic_MaxTargetDevices+1]; + char WideString[BusLogic_MaxTargetDevices+1]; + char DisconnectString[BusLogic_MaxTargetDevices+1]; + char TaggedQueuingString[BusLogic_MaxTargetDevices+1]; + char ErrorRecoveryString[BusLogic_MaxTargetDevices+1]; + char *SynchronousMessage = SynchronousString; + char *WideMessage = WideString; + char *DisconnectMessage = DisconnectString; + char *TaggedQueuingMessage = TaggedQueuingString; + char *ErrorRecoveryMessage = ErrorRecoveryString; + int TargetID; + BusLogic_Info("Configuring BusLogic Model %s %s%s%s%s SCSI Host Adapter\n", + HostAdapter, HostAdapter->ModelName, + BusLogic_HostAdapterBusNames[HostAdapter->HostAdapterBusType], + (HostAdapter->HostWideSCSI ? " Wide" : ""), + (HostAdapter->HostDifferentialSCSI ? " Differential" : ""), + (HostAdapter->HostUltraSCSI ? " Ultra" : "")); + BusLogic_Info(" Firmware Version: %s, I/O Address: 0x%X, " + "IRQ Channel: %d/%s\n", HostAdapter, + HostAdapter->FirmwareVersion, + HostAdapter->IO_Address, HostAdapter->IRQ_Channel, + (HostAdapter->LevelSensitiveInterrupt ? "Level" : "Edge")); + if (HostAdapter->HostAdapterBusType != BusLogic_PCI_Bus) + { + BusLogic_Info(" DMA Channel: ", HostAdapter); + if (HostAdapter->DMA_Channel > 0) + BusLogic_Info("%d, ", HostAdapter, HostAdapter->DMA_Channel); + else BusLogic_Info("None, ", HostAdapter); + if (HostAdapter->BIOS_Address > 0) + BusLogic_Info("BIOS Address: 0x%X, ", HostAdapter, + HostAdapter->BIOS_Address); + else BusLogic_Info("BIOS Address: None, ", HostAdapter); + } + else + { + BusLogic_Info(" PCI Bus: %d, Device: %d, Address: ", + HostAdapter, HostAdapter->Bus, HostAdapter->Device); + if (HostAdapter->PCI_Address > 0) + BusLogic_Info("0x%X, ", HostAdapter, HostAdapter->PCI_Address); + else BusLogic_Info("Unassigned, ", HostAdapter); + } + BusLogic_Info("Host Adapter SCSI ID: %d\n", HostAdapter, + HostAdapter->SCSI_ID); + BusLogic_Info(" Parity Checking: %s, Extended Translation: %s\n", + HostAdapter, + (HostAdapter->ParityCheckingEnabled + ? "Enabled" : "Disabled"), + (HostAdapter->ExtendedTranslationEnabled + ? "Enabled" : "Disabled")); + AllTargetsMask &= ~(1 << HostAdapter->SCSI_ID); + SynchronousPermitted = HostAdapter->SynchronousPermitted & AllTargetsMask; + FastPermitted = HostAdapter->FastPermitted & AllTargetsMask; + UltraPermitted = HostAdapter->UltraPermitted & AllTargetsMask; + if ((BusLogic_MultiMasterHostAdapterP(HostAdapter) && + (HostAdapter->FirmwareVersion[0] >= '4' || + HostAdapter->HostAdapterBusType == BusLogic_EISA_Bus)) || + BusLogic_FlashPointHostAdapterP(HostAdapter)) + { + CommonSynchronousNegotiation = false; + if (SynchronousPermitted == 0) + { + SynchronousMessage = "Disabled"; + CommonSynchronousNegotiation = true; + } + else if (SynchronousPermitted == AllTargetsMask) + if (FastPermitted == 0) + { + SynchronousMessage = "Slow"; + CommonSynchronousNegotiation = true; + } + else if (FastPermitted == AllTargetsMask) + if (UltraPermitted == 0) + { + SynchronousMessage = "Fast"; + CommonSynchronousNegotiation = true; + } + else if (UltraPermitted == AllTargetsMask) + { + SynchronousMessage = "Ultra"; + CommonSynchronousNegotiation = true; + } + if (!CommonSynchronousNegotiation) + { + for (TargetID = 0; + TargetID < HostAdapter->MaxTargetDevices; + TargetID++) + SynchronousString[TargetID] = + ((!(SynchronousPermitted & (1 << TargetID))) ? 'N' : + (!(FastPermitted & (1 << TargetID)) ? 'S' : + (!(UltraPermitted & (1 << TargetID)) ? 'F' : 'U'))); + SynchronousString[HostAdapter->SCSI_ID] = '#'; + SynchronousString[HostAdapter->MaxTargetDevices] = '\0'; + } + } + else SynchronousMessage = + (SynchronousPermitted == 0 ? "Disabled" : "Enabled"); + WidePermitted = HostAdapter->WidePermitted & AllTargetsMask; + if (WidePermitted == 0) + WideMessage = "Disabled"; + else if (WidePermitted == AllTargetsMask) + WideMessage = "Enabled"; + else + { + for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) + WideString[TargetID] = + ((WidePermitted & (1 << TargetID)) ? 'Y' : 'N'); + WideString[HostAdapter->SCSI_ID] = '#'; + WideString[HostAdapter->MaxTargetDevices] = '\0'; + } DisconnectPermitted = HostAdapter->DisconnectPermitted & AllTargetsMask; - printk("scsi%d: Disconnect/Reconnect: ", HostAdapter->HostNumber); if (DisconnectPermitted == 0) - printk("Disabled"); + DisconnectMessage = "Disabled"; else if (DisconnectPermitted == AllTargetsMask) - printk("Enabled"); + DisconnectMessage = "Enabled"; else - for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) - printk("%c", (DisconnectPermitted & (1 << TargetID)) ? 'Y' : 'N'); - printk(", Tagged Queuing: "); + { + for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) + DisconnectString[TargetID] = + ((DisconnectPermitted & (1 << TargetID)) ? 'Y' : 'N'); + DisconnectString[HostAdapter->SCSI_ID] = '#'; + DisconnectString[HostAdapter->MaxTargetDevices] = '\0'; + } TaggedQueuingPermitted = HostAdapter->TaggedQueuingPermitted & AllTargetsMask; if (TaggedQueuingPermitted == 0) - printk("Disabled"); + TaggedQueuingMessage = "Disabled"; else if (TaggedQueuingPermitted == AllTargetsMask) - printk("Enabled"); + TaggedQueuingMessage = "Enabled"; else - for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) - printk("%c", (TaggedQueuingPermitted & (1 << TargetID)) ? 'Y' : 'N'); - printk("\n"); - printk("scsi%d: Total Queue Depth: %d, Mailboxes: %d, Initial CCBs: %d\n", - HostAdapter->HostNumber, HostAdapter->TotalQueueDepth, - HostAdapter->MailboxCount, HostAdapter->InitialCCBs); - printk("scsi%d: Tagged Queue Depth: ", HostAdapter->HostNumber); + { + for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) + TaggedQueuingString[TargetID] = + ((TaggedQueuingPermitted & (1 << TargetID)) ? 'Y' : 'N'); + TaggedQueuingString[HostAdapter->SCSI_ID] = '#'; + TaggedQueuingString[HostAdapter->MaxTargetDevices] = '\0'; + } + BusLogic_Info(" Synchronous Negotiation: %s, Wide Negotiation: %s\n", + HostAdapter, SynchronousMessage, WideMessage); + BusLogic_Info(" Disconnect/Reconnect: %s, Tagged Queuing: %s\n", + HostAdapter, DisconnectMessage, TaggedQueuingMessage); + if (BusLogic_MultiMasterHostAdapterP(HostAdapter)) + { + BusLogic_Info(" Scatter/Gather Limit: %d of %d segments, " + "Mailboxes: %d\n", HostAdapter, + HostAdapter->DriverScatterGatherLimit, + HostAdapter->HostAdapterScatterGatherLimit, + HostAdapter->MailboxCount); + BusLogic_Info(" Driver Queue Depth: %d, " + "Host Adapter Queue Depth: %d\n", + HostAdapter, HostAdapter->DriverQueueDepth, + HostAdapter->HostAdapterQueueDepth); + } + else BusLogic_Info(" Driver Queue Depth: %d, " + "Scatter/Gather Limit: %d segments\n", + HostAdapter, HostAdapter->DriverQueueDepth, + HostAdapter->DriverScatterGatherLimit); + BusLogic_Info(" Tagged Queue Depth: ", HostAdapter); if (HostAdapter->TaggedQueueDepth > 0) - printk("%d", HostAdapter->TaggedQueueDepth); - else printk("Automatic"); - printk(", Untagged Queue Depth: %d\n", HostAdapter->UntaggedQueueDepth); - if (HostAdapter->TerminationInfoValid) - if (HostAdapter->HostWideSCSI) - printk("scsi%d: Host Adapter SCSI Bus Termination (Low/High): %s/%s\n", - HostAdapter->HostNumber, - (HostAdapter->LowByteTerminated ? "Enabled" : "Disabled"), - (HostAdapter->HighByteTerminated ? "Enabled" : "Disabled")); - else printk("scsi%d: Host Adapter SCSI Bus Termination: %s\n", - HostAdapter->HostNumber, - (HostAdapter->LowByteTerminated ? "Enabled" : "Disabled")); + BusLogic_Info("%d", HostAdapter, HostAdapter->TaggedQueueDepth); + else BusLogic_Info("Automatic", HostAdapter); + BusLogic_Info(", Untagged Queue Depth: %d\n", HostAdapter, + HostAdapter->UntaggedQueueDepth); CommonErrorRecovery = true; for (TargetID = 1; TargetID < HostAdapter->MaxTargetDevices; TargetID++) if (HostAdapter->ErrorRecoveryStrategy[TargetID] != @@ -1409,17 +2146,44 @@ CommonErrorRecovery = false; break; } - printk("scsi%d: Error Recovery Strategy: ", HostAdapter->HostNumber); if (CommonErrorRecovery) - printk("%s", BusLogic_ErrorRecoveryStrategyNames[ - HostAdapter->ErrorRecoveryStrategy[0]]); + ErrorRecoveryMessage = + BusLogic_ErrorRecoveryStrategyNames[ + HostAdapter->ErrorRecoveryStrategy[0]]; else - for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) - printk("%s", BusLogic_ErrorRecoveryStrategyLetters[ - HostAdapter->ErrorRecoveryStrategy[TargetID]]); - printk("\n"); + { + for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) + ErrorRecoveryString[TargetID] = + BusLogic_ErrorRecoveryStrategyLetters[ + HostAdapter->ErrorRecoveryStrategy[TargetID]]; + ErrorRecoveryString[HostAdapter->SCSI_ID] = '#'; + ErrorRecoveryString[HostAdapter->MaxTargetDevices] = '\0'; + } + BusLogic_Info(" Error Recovery Strategy: %s, SCSI Bus Reset: %s\n", + HostAdapter, ErrorRecoveryMessage, + (HostAdapter->BusResetEnabled ? "Enabled" : "Disabled")); + if (HostAdapter->TerminationInfoValid) + { + if (HostAdapter->HostWideSCSI) + BusLogic_Info(" SCSI Bus Termination: %s", HostAdapter, + (HostAdapter->LowByteTerminated + ? (HostAdapter->HighByteTerminated + ? "Both Enabled" : "Low Enabled") + : (HostAdapter->HighByteTerminated + ? "High Enabled" : "Both Disabled"))); + else BusLogic_Info(" SCSI Bus Termination: %s", HostAdapter, + (HostAdapter->LowByteTerminated ? + "Enabled" : "Disabled")); + if (HostAdapter->HostSupportsSCAM) + BusLogic_Info(", SCAM: %s", HostAdapter, + (HostAdapter->SCAM_Enabled + ? (HostAdapter->SCAM_Level2 + ? "Enabled, Level 2" : "Enabled, Level 1") + : "Disabled")); + BusLogic_Info("\n", HostAdapter); + } /* - Indicate reading the Host Adapter Configuration completed successfully. + Indicate reporting the Host Adapter configuration completed successfully. */ return true; } @@ -1432,47 +2196,33 @@ static boolean BusLogic_AcquireResources(BusLogic_HostAdapter_T *HostAdapter) { + BusLogic_HostAdapter_T *FirstHostAdapter = + BusLogic_RegisteredHostAdapters[HostAdapter->IRQ_Channel]; if (HostAdapter->IRQ_Channel == 0) { - printk("scsi%d: NO INTERRUPT CHANNEL ASSIGNED - DETACHING\n", - HostAdapter->HostNumber); + BusLogic_Error("NO LEGAL INTERRUPT CHANNEL ASSIGNED - DETACHING\n", + HostAdapter); return false; } /* - 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. + Acquire exclusive or shared access to the IRQ Channel if necessary. */ - if (BusLogic_IRQ_UsageCount[HostAdapter->IRQ_Channel]++ == 0) + if (FirstHostAdapter->Next == NULL) { if (request_irq(HostAdapter->IRQ_Channel, BusLogic_InterruptHandler, SA_INTERRUPT | SA_SHIRQ, HostAdapter->InterruptLabel, NULL) < 0) { - BusLogic_IRQ_UsageCount[HostAdapter->IRQ_Channel]--; - printk("scsi%d: UNABLE TO ACQUIRE IRQ CHANNEL %d - DETACHING\n", - HostAdapter->HostNumber, HostAdapter->IRQ_Channel); + BusLogic_Error("UNABLE TO ACQUIRE IRQ CHANNEL %d - DETACHING\n", + HostAdapter, HostAdapter->IRQ_Channel); return false; } } - else + else if (strlen(FirstHostAdapter->InterruptLabel) + 11 + < sizeof(FirstHostAdapter->InterruptLabel)) { - 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; - } + strcat(FirstHostAdapter->InterruptLabel, " + "); + strcat(FirstHostAdapter->InterruptLabel, HostAdapter->ModelName); } HostAdapter->IRQ_ChannelAcquired = true; /* @@ -1481,10 +2231,10 @@ if (HostAdapter->DMA_Channel > 0) { if (request_dma(HostAdapter->DMA_Channel, - HostAdapter->ControllerName) < 0) + HostAdapter->FullModelName) < 0) { - printk("scsi%d: UNABLE TO ACQUIRE DMA CHANNEL %d - DETACHING\n", - HostAdapter->HostNumber, HostAdapter->DMA_Channel); + BusLogic_Error("UNABLE TO ACQUIRE DMA CHANNEL %d - DETACHING\n", + HostAdapter, HostAdapter->DMA_Channel); return false; } set_dma_mode(HostAdapter->DMA_Channel, DMA_MODE_CASCADE); @@ -1505,11 +2255,13 @@ static void BusLogic_ReleaseResources(BusLogic_HostAdapter_T *HostAdapter) { + BusLogic_HostAdapter_T *FirstHostAdapter = + BusLogic_RegisteredHostAdapters[HostAdapter->IRQ_Channel]; /* Release exclusive or shared access to the IRQ Channel. */ if (HostAdapter->IRQ_ChannelAcquired) - if (--BusLogic_IRQ_UsageCount[HostAdapter->IRQ_Channel] == 0) + if (FirstHostAdapter->Next == NULL) free_irq(HostAdapter->IRQ_Channel, NULL); /* Release exclusive access to the DMA Channel. @@ -1532,34 +2284,30 @@ { unsigned int InitialInterruptCount, FinalInterruptCount; int TestCount = 5, i; - InitialInterruptCount = kstat.interrupts[HostAdapter->IRQ_Channel]; + /* + FlashPoint Host Adapters do not provide for an interrupt test. + */ + if (BusLogic_FlashPointHostAdapterP(HostAdapter)) return true; + /* + Inhibit the Interrupt Test if requested. + */ + if (HostAdapter->LocalOptions.Bits.InhibitInterruptTest) return true; /* Issue the Test Command Complete Interrupt commands. */ + InitialInterruptCount = kstat.interrupts[HostAdapter->IRQ_Channel]; for (i = 0; i < TestCount; i++) BusLogic_Command(HostAdapter, BusLogic_TestCommandCompleteInterrupt, NULL, 0, NULL, 0); + FinalInterruptCount = kstat.interrupts[HostAdapter->IRQ_Channel]; /* - 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. + 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, unless one or more + interrupts were lost. */ - 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; - } + return BusLogic_Failure(HostAdapter, "HOST ADAPTER INTERRUPT TEST"); /* Indicate the Host Adapter Interrupt Test completed successfully. */ @@ -1579,11 +2327,10 @@ BusLogic_ExtendedMailboxRequest_T ExtendedMailboxRequest; BusLogic_RoundRobinModeRequest_T RoundRobinModeRequest; BusLogic_SetCCBFormatRequest_T SetCCBFormatRequest; - BusLogic_ModifyIOAddressRequest_T ModifyIOAddressRequest; int TargetID; /* Initialize the Bus Device Reset Pending CCB, Tagged Queuing Active, - Command Successful Flag, Active Command Count, and Total Command Count + Command Successful Flag, Active Commands, and Commands Since Reset for each Target Device. */ for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) @@ -1592,10 +2339,14 @@ sizeof(HostAdapter->TaggedQueuingActive)); memset(HostAdapter->CommandSuccessfulFlag, false, sizeof(HostAdapter->CommandSuccessfulFlag)); - memset(HostAdapter->ActiveCommandCount, 0, - sizeof(HostAdapter->ActiveCommandCount)); - memset(HostAdapter->TotalCommandCount, 0, - sizeof(HostAdapter->TotalCommandCount)); + memset(HostAdapter->ActiveCommands, 0, + sizeof(HostAdapter->ActiveCommands)); + memset(HostAdapter->CommandsSinceReset, 0, + sizeof(HostAdapter->CommandsSinceReset)); + /* + FlashPoint Host Adapters do not use Outgoing and Incoming Mailboxes. + */ + if (BusLogic_FlashPointHostAdapterP(HostAdapter)) goto Done; /* Initialize the Outgoing and Incoming Mailbox structures. */ @@ -1634,42 +2385,27 @@ return BusLogic_Failure(HostAdapter, "ENABLE STRICT ROUND ROBIN MODE"); } /* - For Host Adapters that support 64 LUN Format CCBs, issue the Set CCB Format - command to allow 64 Logical Units per Target Device. + For Host Adapters that support Extended LUN Format CCBs, issue the Set CCB + Format command to allow 32 Logical Units per Target Device. */ - if (HostAdapter->Host64LUNSupport) + if (HostAdapter->ExtendedLUNSupport) { - SetCCBFormatRequest = BusLogic_64LUNFormatCCB; + SetCCBFormatRequest = BusLogic_ExtendedLUNFormatCCB; if (BusLogic_Command(HostAdapter, BusLogic_SetCCBFormat, &SetCCBFormatRequest, sizeof(SetCCBFormatRequest), NULL, 0) < 0) return BusLogic_Failure(HostAdapter, "SET CCB FORMAT"); } /* - 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->ControllerName); +Done: + if (HostAdapter->HostAdapterInitialized) + BusLogic_Warning("*** %s Initialized Successfully ***\n", + HostAdapter, HostAdapter->FullModelName); + else BusLogic_Info("*** %s Initialized Successfully ***\n", + HostAdapter, HostAdapter->FullModelName); + HostAdapter->HostAdapterInitialized = true; /* Indicate the Host Adapter Initialization completed successfully. */ @@ -1698,18 +2434,21 @@ */ BusLogic_Delay(HostAdapter->BusSettleTime); /* + FlashPoint Host Adapters do not provide for Target Device Inquiry. + */ + if (BusLogic_FlashPointHostAdapterP(HostAdapter)) return true; + /* Inhibit the Target Devices Inquiry if requested. */ - if (HostAdapter->LocalOptions & BusLogic_InhibitTargetInquiry) + if (HostAdapter->LocalOptions.Bits.InhibitTargetInquiry) { - printk("scsi%d: Target Device Inquiry Inhibited\n", - HostAdapter->HostNumber); + BusLogic_Info(" Target Device Inquiry Inhibited\n", HostAdapter); return true; } /* - Issue the Inquire Target Devices command for controllers with firmware + Issue the Inquire Target Devices command for host adapters with firmware version 4.25 or later, or the Inquire Installed Devices ID 0 to 7 command - for older controllers. This is necessary to force Synchronous Transfer + for older host adapters. This is necessary to force Synchronous Transfer Negotiation so that the Inquire Setup Information and Inquire Synchronous Period commands will return valid data. The Inquire Target Devices command is preferable to Inquire Installed Devices ID 0 to 7 since it only probes @@ -1789,31 +2528,31 @@ 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); + BusLogic_Info(" Target %d: Synchronous at " + "%d.%02d mega-transfers/second, offset %d\n", + HostAdapter, 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); + BusLogic_Info(" Target %d: Synchronous at " + "%d.%01d mega-transfers/second, offset %d\n", + HostAdapter, TargetID, + RoundedSynchronousTransferRate / 10, + RoundedSynchronousTransferRate % 10, + HostAdapter->SynchronousValues[TargetID].Offset); } - else printk("scsi%d: Target %d: Asynchronous\n", - HostAdapter->HostNumber, TargetID); + else BusLogic_Info(" Target %d: Asynchronous\n", + HostAdapter, TargetID); TargetDevicesFound++; } if (TargetDevicesFound == 0) - printk("scsi%d: No Target Devices Found\n", HostAdapter->HostNumber); + BusLogic_Info(" No Target Devices Found\n", HostAdapter); /* Indicate the Target Device Inquiry completed successfully. */ @@ -1839,7 +2578,7 @@ Host->max_channel = 0; Host->unique_id = HostAdapter->IO_Address; Host->this_id = HostAdapter->SCSI_ID; - Host->can_queue = HostAdapter->MailboxCount; + Host->can_queue = HostAdapter->DriverQueueDepth; Host->sg_tablesize = HostAdapter->DriverScatterGatherLimit; Host->unchecked_isa_dma = HostAdapter->BounceBuffersRequired; Host->cmd_per_lun = HostAdapter->UntaggedQueueDepth; @@ -1872,7 +2611,7 @@ if (TaggedQueueDepth == 0 && TaggedDeviceCount > 0) { TaggedQueueDepth = - 1 + ((HostAdapter->TotalQueueDepth + 1 + ((HostAdapter->HostAdapterQueueDepth - UntaggedDeviceCount * UntaggedQueueDepth) / TaggedDeviceCount); if (TaggedQueueDepth > BusLogic_PreferredTaggedQueueDepth) @@ -1885,9 +2624,7 @@ (HostAdapter->TaggedQueuingPermitted & (1 << Device->id))) Device->queue_depth = TaggedQueueDepth; else Device->queue_depth = UntaggedQueueDepth; - if (BusLogic_GlobalOptions & BusLogic_TraceQueueDepths) - printk("scsi%d: Setting Queue Depth for Target %d to %d\n", - HostAdapter->HostNumber, Device->id, Device->queue_depth); + HostAdapter->QueueDepth[Device->id] = Device->queue_depth; } } @@ -1902,31 +2639,49 @@ int BusLogic_DetectHostAdapter(SCSI_Host_Template_T *HostTemplate) { - int BusLogicHostAdapterCount = 0, CommandLineEntryIndex = 0; - int AddressProbeIndex = 0; - if (BusLogic_ProbeOptions & BusLogic_NoProbe) return 0; - BusLogic_InitializeAddressProbeList(); - while (BusLogic_IO_AddressProbeList[AddressProbeIndex] > 0) + int BusLogicHostAdapterCount = 0, CommandLineEntryIndex = 0, ProbeIndex; + char *MessageBuffer = NULL; + if (BusLogic_ProbeOptions.Bits.NoProbe) return 0; + BusLogic_InitializeProbeInfoList(); + for (ProbeIndex = 0; ProbeIndex < BusLogic_ProbeInfoCount; ProbeIndex++) { + BusLogic_ProbeInfo_T *ProbeInfo = &BusLogic_ProbeInfoList[ProbeIndex]; BusLogic_HostAdapter_T HostAdapterPrototype; BusLogic_HostAdapter_T *HostAdapter = &HostAdapterPrototype; SCSI_Host_T *Host; + if (ProbeInfo->IO_Address == 0) continue; memset(HostAdapter, 0, sizeof(BusLogic_HostAdapter_T)); - HostAdapter->IO_Address = - BusLogic_IO_AddressProbeList[AddressProbeIndex++]; + HostAdapter->IO_Address = ProbeInfo->IO_Address; + HostAdapter->PCI_Address = ProbeInfo->PCI_Address; + HostAdapter->HostAdapterType = ProbeInfo->HostAdapterType; + HostAdapter->HostAdapterBusType = ProbeInfo->HostAdapterBusType; + HostAdapter->Bus = ProbeInfo->Bus; + HostAdapter->Device = ProbeInfo->Device; + HostAdapter->IRQ_Channel = ProbeInfo->IRQ_Channel; + HostAdapter->AddressCount = + BusLogic_HostAdapter_AddressCount[HostAdapter->HostAdapterType]; + if (MessageBuffer == NULL) + MessageBuffer = + scsi_init_malloc(BusLogic_MessageBufferSize, GFP_ATOMIC); + if (MessageBuffer == NULL) + { + BusLogic_Error("BusLogic: Unable to allocate Message Buffer\n", + HostAdapter); + return BusLogicHostAdapterCount; + } + HostAdapter->MessageBuffer = MessageBuffer; /* - Initialize the Command Line Entry field if an explicit I/O Address - was specified. + If an explicit I/O Address was specified, Initialize the Command Line + Entry field and inhibit the check for whether the I/O Address range is + already in use. */ 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) + else if (check_region(HostAdapter->IO_Address, + HostAdapter->AddressCount) < 0) continue; /* Probe the Host Adapter. If unsuccessful, abort further initialization. @@ -1953,7 +2708,7 @@ Announce the Driver Version and Date, Author's Name, Copyright Notice, and Contact Address. */ - BusLogic_AnnounceDriver(); + BusLogic_AnnounceDriver(HostAdapter); /* 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, @@ -1962,12 +2717,11 @@ released, thereby preventing it from being incorrectly identified as any other type of Host Adapter. */ - request_region(HostAdapter->IO_Address, BusLogic_IO_PortCount, + request_region(HostAdapter->IO_Address, HostAdapter->AddressCount, "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, @@ -1979,23 +2733,23 @@ 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. + must be registered. */ 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 Mailboxes and CCBs, - Initialize the Host Adapter, and finally perform Target Device Inquiry. + Read the Host Adapter Configuration, Configure the Host Adapter, + Acquire the System Resources necessary to use the Host Adapter, + then Test Interrupts, Create the Mailboxes, CCBs, and Target + Device Statistics, Initialize the Host Adapter, and finally + perform Target Device Inquiry. */ if (BusLogic_ReadHostAdapterConfiguration(HostAdapter) && + BusLogic_ReportHostAdapterConfiguration(HostAdapter) && BusLogic_AcquireResources(HostAdapter) && BusLogic_TestInterrupts(HostAdapter) && BusLogic_CreateMailboxes(HostAdapter) && BusLogic_CreateCCBs(HostAdapter) && + BusLogic_CreateTargetDeviceStatistics(HostAdapter) && BusLogic_InitializeHostAdapter(HostAdapter) && BusLogic_TargetDeviceInquiry(HostAdapter)) { @@ -2005,9 +2759,12 @@ Name of the Host Adapter will appear, and initialize the SCSI Host structure. */ - release_region(HostAdapter->IO_Address, BusLogic_IO_PortCount); - request_region(HostAdapter->IO_Address, BusLogic_IO_PortCount, - HostAdapter->ControllerName); + MessageBuffer = NULL; + release_region(HostAdapter->IO_Address, + HostAdapter->AddressCount); + request_region(HostAdapter->IO_Address, + HostAdapter->AddressCount, + HostAdapter->FullModelName); BusLogic_InitializeHostStructure(HostAdapter, Host); BusLogicHostAdapterCount++; } @@ -2015,12 +2772,14 @@ { /* 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 and Mailboxes, Release the System Resources, and Unregister - the SCSI Host. + Host Adapter Configuration, 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 Target Device + Statistics, CCBs, and Mailboxes, Release the System Resources, + and Unregister the SCSI Host. */ + BusLogic_DestroyTargetDeviceStatistics(HostAdapter); BusLogic_DestroyCCBs(HostAdapter); BusLogic_DestroyMailboxes(HostAdapter); BusLogic_ReleaseResources(HostAdapter); @@ -2028,6 +2787,8 @@ scsi_unregister(Host); } } + if (MessageBuffer != NULL) + scsi_init_free(MessageBuffer, BusLogic_MessageBufferSize); return BusLogicHostAdapterCount; } @@ -2043,6 +2804,16 @@ BusLogic_HostAdapter_T *HostAdapter = (BusLogic_HostAdapter_T *) Host->hostdata; /* + FlashPoint Host Adapters must also be released by the FlashPoint + SCCB Manager. + */ + if (BusLogic_FlashPointHostAdapterP(HostAdapter)) + { + FlashPoint_ReleaseHostAdapter(HostAdapter->CardHandle); + scsi_init_free((char *) HostAdapter->FlashPointInfo, + sizeof(FlashPoint_Info_T)); + } + /* Destroy the CCBs and Mailboxes, and release any system resources acquired to support Host Adapter. */ @@ -2052,7 +2823,7 @@ /* Release usage of the I/O Address range. */ - release_region(HostAdapter->IO_Address, BusLogic_IO_PortCount); + release_region(HostAdapter->IO_Address, HostAdapter->AddressCount); /* Remove Host Adapter from the list of registered BusLogic Host Adapters. */ @@ -2062,11 +2833,34 @@ /* + BusLogic_QueueCompletedCCB queues CCB for completion processing. +*/ + +static void BusLogic_QueueCompletedCCB(BusLogic_CCB_T *CCB) +{ + CCB->Status = BusLogic_CCB_Completed; + CCB->Next = NULL; + if (BusLogic_FirstCompletedCCB == NULL) + { + BusLogic_FirstCompletedCCB = CCB; + BusLogic_LastCompletedCCB = CCB; + } + else + { + BusLogic_LastCompletedCCB->Next = CCB; + BusLogic_LastCompletedCCB = CCB; + } + CCB->HostAdapter->ActiveCommands[CCB->TargetID]--; +} + + +/* BusLogic_ComputeResultCode computes a SCSI Subsystem Result Code from the Host Adapter Status and Target Device Status. */ -static int BusLogic_ComputeResultCode(BusLogic_HostAdapterStatus_T +static int BusLogic_ComputeResultCode(BusLogic_HostAdapter_T *HostAdapter, + BusLogic_HostAdapterStatus_T HostAdapterStatus, BusLogic_TargetDeviceStatus_T TargetDeviceStatus) @@ -2085,9 +2879,10 @@ case BusLogic_InvalidOutgoingMailboxActionCode: case BusLogic_InvalidCommandOperationCode: case BusLogic_InvalidCommandParameter: - printk("BusLogic: BusLogic Driver Protocol Error 0x%02X\n", - HostAdapterStatus); - case BusLogic_DataOverUnderRun: + BusLogic_Warning("BusLogic Driver Protocol Error 0x%02X\n", + HostAdapter, HostAdapterStatus); + case BusLogic_DataUnderRun: + case BusLogic_DataOverRun: case BusLogic_UnexpectedBusFree: case BusLogic_LinkedCCBhasInvalidLUN: case BusLogic_AutoRequestSenseFailed: @@ -2109,8 +2904,8 @@ HostStatus = DID_RESET; break; default: - printk("BusLogic: Unknown Host Adapter Status 0x%02X\n", - HostAdapterStatus); + BusLogic_Warning("Unknown Host Adapter Status 0x%02X\n", + HostAdapter, HostAdapterStatus); HostStatus = DID_ERROR; break; } @@ -2119,157 +2914,97 @@ /* - 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. + BusLogic_ScanIncomingMailboxes scans the Incoming Mailboxes saving any + Incoming Mailbox entries for completion processing. */ -static void BusLogic_InterruptHandler(int IRQ_Channel, - void *DeviceIdentifier, - Registers_T *InterruptRegisters) +static void BusLogic_ScanIncomingMailboxes(BusLogic_HostAdapter_T *HostAdapter) { - BusLogic_CCB_T *FirstCompletedCCB = NULL, *LastCompletedCCB = NULL; - BusLogic_HostAdapter_T *HostAdapter; - int HostAdapterResetRequestedCount = 0; - BusLogic_Lock_T Lock; /* - Iterate over the installed BusLogic Host Adapters accepting any Incoming - Mailbox entries and saving the completed CCBs for processing. This - interrupt handler is installed as a fast interrupt, so interrupts are - disabled when the interrupt handler is entered. - */ - for (HostAdapter = BusLogic_RegisteredHostAdapters; - HostAdapter != NULL; - HostAdapter = HostAdapter->Next) + 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 CompletionCode; + while ((CompletionCode = NextIncomingMailbox->CompletionCode) != + BusLogic_IncomingMailboxFree) { - unsigned char InterruptRegister; - /* - Acquire exclusive access to Host Adapter. - */ - BusLogic_AcquireHostAdapterLockID(HostAdapter, &Lock); - /* - 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->HostAdapterResetRequested = true; - HostAdapterResetRequestedCount++; - } - 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 = - (BusLogic_CCB_T *) Bus_to_Virtual(NextIncomingMailbox->CCB); - if (MailboxCompletionCode != BusLogic_AbortedCommandNotFound) - if (CCB->Status == BusLogic_CCB_Active || - CCB->Status == BusLogic_CCB_Reset) - { - /* - 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->ActiveCommandCount[CCB->TargetID]--; - } - else - { - /* - If a CCB ever appears in an Incoming Mailbox and - is not marked as status Active or Reset, then there - is most likely a bug in the Host Adapter firmware. - */ - printk("scsi%d: Illegal CCB #%ld status %d in " - "Incoming Mailbox\n", HostAdapter->HostNumber, - CCB->SerialNumber, CCB->Status); - } - else printk("scsi%d: Aborted CCB #%ld 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_ReleaseHostAdapterLockID(HostAdapter, &Lock); + BusLogic_CCB_T *CCB = (BusLogic_CCB_T *) + Bus_to_Virtual(NextIncomingMailbox->CCB); + if (CompletionCode != BusLogic_AbortedCommandNotFound) + if (CCB->Status == BusLogic_CCB_Active || + CCB->Status == BusLogic_CCB_Reset) + { + /* + Save the Completion Code for this CCB and queue the CCB + for completion processing. + */ + CCB->CompletionCode = CompletionCode; + BusLogic_QueueCompletedCCB(CCB); + } + else + { + /* + If a CCB ever appears in an Incoming Mailbox and is not marked as + status Active or Reset, then there is most likely a bug in the + Host Adapter firmware. + */ + BusLogic_Warning("Illegal CCB #%ld status %d in " + "Incoming Mailbox\n", HostAdapter, + CCB->SerialNumber, CCB->Status); + } + else BusLogic_Warning("Aborted CCB #%ld to Target %d Not Found\n", + HostAdapter, CCB->SerialNumber, CCB->TargetID); + NextIncomingMailbox->CompletionCode = BusLogic_IncomingMailboxFree; + if (++NextIncomingMailbox > HostAdapter->LastIncomingMailbox) + NextIncomingMailbox = HostAdapter->FirstIncomingMailbox; } - /* - Iterate over the completed CCBs setting the SCSI Command Result Codes, - deallocating the CCBs, and calling the Completion Routines. - */ - while (FirstCompletedCCB != NULL) + HostAdapter->NextIncomingMailbox = NextIncomingMailbox; +} + + +/* + BusLogic_ProcessCompletedCCBs iterates over the completed CCBs setting + the SCSI Command Result Codes, deallocating the CCBs, and calling the + SCSI Subsystem Completion Routines. Interrupts should already have been + disabled by the caller. +*/ + +static void BusLogic_ProcessCompletedCCBs(void) +{ + static boolean ProcessCompletedCCBsActive = false; + if (ProcessCompletedCCBsActive) return; + ProcessCompletedCCBsActive = true; + while (BusLogic_FirstCompletedCCB != NULL) { - BusLogic_CCB_T *CCB = FirstCompletedCCB; + BusLogic_CCB_T *CCB = BusLogic_FirstCompletedCCB; SCSI_Command_T *Command = CCB->Command; - FirstCompletedCCB = FirstCompletedCCB->Next; - HostAdapter = CCB->HostAdapter; - /* - Acquire exclusive access to Host Adapter. - */ - BusLogic_AcquireHostAdapterLockID(HostAdapter, &Lock); + BusLogic_HostAdapter_T *HostAdapter = CCB->HostAdapter; + BusLogic_FirstCompletedCCB = CCB->Next; + if (BusLogic_FirstCompletedCCB == NULL) + BusLogic_LastCompletedCCB = NULL; /* Process the Completed CCB. */ if (CCB->Opcode == BusLogic_BusDeviceReset) { int TargetID = CCB->TargetID; - printk("scsi%d: Bus Device Reset CCB #%ld to Target %d Completed\n", - HostAdapter->HostNumber, CCB->SerialNumber, TargetID); - HostAdapter->TotalCommandCount[TargetID] = 0; + BusLogic_Warning("Bus Device Reset CCB #%ld to Target " + "%d Completed\n", HostAdapter, + CCB->SerialNumber, TargetID); + BusLogic_IncrementErrorCounter( + &HostAdapter->TargetDeviceStatistics[TargetID] + .BusDeviceResetsCompleted); + HostAdapter->CommandsSinceReset[TargetID] = 0; HostAdapter->TaggedQueuingActive[TargetID] = false; /* Place CCB back on the Host Adapter's free list. @@ -2299,7 +3034,7 @@ { Command = CCB->Command; BusLogic_DeallocateCCB(CCB); - HostAdapter->ActiveCommandCount[TargetID]--; + HostAdapter->ActiveCommands[TargetID]--; Command->result = DID_RESET << 16; Command->scsi_done(Command); } @@ -2308,47 +3043,61 @@ else { /* - Translate the Mailbox Completion Code, Host Adapter Status, and - Target Device Status into a SCSI Subsystem Result Code. + Translate the Completion Code, Host Adapter Status, and Target + Device Status into a SCSI Subsystem Result Code. */ - switch (CCB->MailboxCompletionCode) + switch (CCB->CompletionCode) { case BusLogic_IncomingMailboxFree: case BusLogic_AbortedCommandNotFound: - printk("scsi%d: CCB #%ld to Target %d Impossible State\n", - HostAdapter->HostNumber, CCB->SerialNumber, CCB->TargetID); + case BusLogic_InvalidCCB: + BusLogic_Warning("CCB #%ld to Target %d Impossible State\n", + HostAdapter, CCB->SerialNumber, CCB->TargetID); break; case BusLogic_CommandCompletedWithoutError: + HostAdapter->TargetDeviceStatistics[CCB->TargetID] + .CommandsCompleted++; HostAdapter->CommandSuccessfulFlag[CCB->TargetID] = true; Command->result = DID_OK << 16; break; case BusLogic_CommandAbortedAtHostRequest: - printk("scsi%d: CCB #%ld to Target %d Aborted\n", - HostAdapter->HostNumber, CCB->SerialNumber, CCB->TargetID); + BusLogic_Warning("CCB #%ld to Target %d Aborted\n", + HostAdapter, CCB->SerialNumber, CCB->TargetID); + BusLogic_IncrementErrorCounter( + &HostAdapter->TargetDeviceStatistics[CCB->TargetID] + .CommandAbortsCompleted); Command->result = DID_ABORT << 16; break; case BusLogic_CommandCompletedWithError: Command->result = - BusLogic_ComputeResultCode(CCB->HostAdapterStatus, + BusLogic_ComputeResultCode(HostAdapter, + CCB->HostAdapterStatus, CCB->TargetDeviceStatus); - if (BusLogic_GlobalOptions & BusLogic_TraceErrors) - if (CCB->HostAdapterStatus != BusLogic_SCSISelectionTimeout) - { - int i; - printk("scsi%d: CCB #%ld 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", Command->sense_buffer[i]); - printk("\n"); - } + if (CCB->HostAdapterStatus != BusLogic_SCSISelectionTimeout) + { + HostAdapter->TargetDeviceStatistics[CCB->TargetID] + .CommandsCompleted++; + if (BusLogic_GlobalOptions.Bits.TraceErrors) + { + int i; + BusLogic_Notice("CCB #%ld Target %d: Result %X Host " + "Adapter Status %02X " + "Target Status %02X\n", + HostAdapter, CCB->SerialNumber, + CCB->TargetID, Command->result, + CCB->HostAdapterStatus, + CCB->TargetDeviceStatus); + BusLogic_Notice("CDB ", HostAdapter); + for (i = 0; i < CCB->CDB_Length; i++) + BusLogic_Notice(" %02X", HostAdapter, CCB->CDB[i]); + BusLogic_Notice("\n", HostAdapter); + BusLogic_Notice("Sense ", HostAdapter); + for (i = 0; i < CCB->SenseDataLength; i++) + BusLogic_Notice(" %02X", HostAdapter, + Command->sense_buffer[i]); + BusLogic_Notice("\n", HostAdapter); + } + } break; } /* @@ -2360,31 +3109,117 @@ */ Command->scsi_done(Command); } + } + ProcessCompletedCCBsActive = false; +} + + +/* + BusLogic_InterruptHandler handles hardware interrupts from BusLogic Host + Adapters. +*/ + +static void BusLogic_InterruptHandler(int IRQ_Channel, + void *DeviceIdentifier, + Registers_T *InterruptRegisters) +{ + BusLogic_HostAdapter_T *FirstHostAdapter = + BusLogic_RegisteredHostAdapters[IRQ_Channel]; + boolean HostAdapterResetRequested = false; + BusLogic_HostAdapter_T *HostAdapter; + BusLogic_Lock_T Lock; + /* + Iterate over the installed BusLogic Host Adapters accepting any Incoming + Mailbox entries and saving the completed CCBs for processing. This + interrupt handler is installed as a fast interrupt, so interrupts are + disabled when the interrupt handler is entered. + */ + for (HostAdapter = FirstHostAdapter; + HostAdapter != NULL; + HostAdapter = HostAdapter->Next) + { + /* + Acquire exclusive access to Host Adapter. + */ + BusLogic_AcquireHostAdapterLockID(HostAdapter, &Lock); + /* + Handle Interrupts appropriately for each Host Adapter type. + */ + if (BusLogic_MultiMasterHostAdapterP(HostAdapter)) + { + BusLogic_InterruptRegister_T InterruptRegister; + /* + Read the Host Adapter Interrupt Register. + */ + InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter); + if (InterruptRegister.Bits.InterruptValid) + { + /* + Acknowledge the interrupt and reset the Host Adapter + Interrupt Register. + */ + BusLogic_InterruptReset(HostAdapter); + /* + Process valid External SCSI Bus Reset and Incoming Mailbox + Loaded Interrupts. Command Complete Interrupts are noted, + and Outgoing Mailbox Available Interrupts are ignored, as + they are never enabled. + */ + if (InterruptRegister.Bits.ExternalBusReset) + { + HostAdapter->HostAdapterResetRequested = true; + HostAdapterResetRequested = true; + } + else if (InterruptRegister.Bits.IncomingMailboxLoaded) + BusLogic_ScanIncomingMailboxes(HostAdapter); + else if (InterruptRegister.Bits.CommandComplete) + HostAdapter->HostAdapterCommandCompleted = true; + } + } + else + { + /* + Check if there is a pending interrupt for this Host Adapter. + */ + if (FlashPoint_InterruptPending(HostAdapter->CardHandle)) + if (FlashPoint_HandleInterrupt(HostAdapter->CardHandle) + == FlashPoint_ExternalBusReset) + { + HostAdapter->HostAdapterResetRequested = true; + HostAdapterResetRequested = true; + } + } /* Release exclusive access to Host Adapter. */ BusLogic_ReleaseHostAdapterLockID(HostAdapter, &Lock); } /* - Iterate over the Host Adapters performing any requested Host Adapter Resets. + Process any completed CCBs. */ - if (HostAdapterResetRequestedCount == 0) return; - for (HostAdapter = BusLogic_RegisteredHostAdapters; - HostAdapter != NULL; - HostAdapter = HostAdapter->Next) - if (HostAdapter->HostAdapterResetRequested) - { - BusLogic_ResetHostAdapter(HostAdapter, NULL, 0); - HostAdapter->HostAdapterResetRequested = false; - scsi_mark_host_reset(HostAdapter->SCSI_Host); - } + if (BusLogic_FirstCompletedCCB != NULL) + BusLogic_ProcessCompletedCCBs(); + /* + Iterate over the Host Adapters performing any requested + Host Adapter Resets. + */ + if (HostAdapterResetRequested) + for (HostAdapter = FirstHostAdapter; + HostAdapter != NULL; + HostAdapter = HostAdapter->Next) + if (HostAdapter->HostAdapterResetRequested) + { + BusLogic_ResetHostAdapter(HostAdapter, NULL, 0); + HostAdapter->HostAdapterResetRequested = false; + scsi_mark_host_reset(HostAdapter->SCSI_Host); + } } /* BusLogic_WriteOutgoingMailbox places CCB and Action Code into an Outgoing - Mailbox for execution by Host Adapter. The Host Adapter's Lock should have - already been acquired by the caller. + Mailbox for execution by Host Adapter. The Host Adapter's Lock should + already have been acquired by the caller. */ static boolean BusLogic_WriteOutgoingMailbox(BusLogic_HostAdapter_T @@ -2409,7 +3244,12 @@ NextOutgoingMailbox = HostAdapter->FirstOutgoingMailbox; HostAdapter->NextOutgoingMailbox = NextOutgoingMailbox; if (ActionCode == BusLogic_MailboxStartCommand) - HostAdapter->ActiveCommandCount[CCB->TargetID]++; + { + HostAdapter->ActiveCommands[CCB->TargetID]++; + if (CCB->Opcode != BusLogic_BusDeviceReset) + HostAdapter->TargetDeviceStatistics[CCB->TargetID] + .CommandsAttempted++; + } return true; } return false; @@ -2426,6 +3266,8 @@ { BusLogic_HostAdapter_T *HostAdapter = (BusLogic_HostAdapter_T *) Command->host->hostdata; + BusLogic_TargetDeviceStatistics_T *TargetDeviceStatistics = + HostAdapter->TargetDeviceStatistics; unsigned char *CDB = Command->cmnd; int CDB_Length = Command->cmd_len; int TargetID = Command->target; @@ -2453,8 +3295,8 @@ /* Allocate a CCB from the Host Adapter's free list. In the unlikely event that there are none available and memory allocation fails, wait 1 second - and try again. If that fails, the Host Adapter is probably hung so we - signal an error as a Host Adapter Hard Reset should be initiated soon. + and try again. If that fails, the Host Adapter is probably hung so signal + an error as a Host Adapter Hard Reset should be initiated soon. */ CCB = BusLogic_AllocateCCB(HostAdapter); if (CCB == NULL) @@ -2483,7 +3325,9 @@ int Segment; CCB->Opcode = BusLogic_InitiatorCCB_ScatterGather; CCB->DataLength = SegmentCount * sizeof(BusLogic_ScatterGatherSegment_T); - CCB->DataPointer = Virtual_to_Bus(CCB->ScatterGatherList); + if (BusLogic_MultiMasterHostAdapterP(HostAdapter)) + CCB->DataPointer = Virtual_to_Bus(CCB->ScatterGatherList); + else CCB->DataPointer = (BusLogic_BusAddress_T) CCB->ScatterGatherList; for (Segment = 0; Segment < SegmentCount; Segment++) { CCB->ScatterGatherList[Segment].SegmentByteCount = @@ -2497,10 +3341,22 @@ case READ_6: case READ_10: CCB->DataDirection = BusLogic_DataInLengthChecked; + TargetDeviceStatistics[TargetID].ReadCommands++; + BusLogic_IncrementByteCounter( + &TargetDeviceStatistics[TargetID].TotalBytesRead, BufferLength); + BusLogic_IncrementSizeBucket( + TargetDeviceStatistics[TargetID].ReadCommandSizeBuckets, + BufferLength); break; case WRITE_6: case WRITE_10: CCB->DataDirection = BusLogic_DataOutLengthChecked; + TargetDeviceStatistics[TargetID].WriteCommands++; + BusLogic_IncrementByteCounter( + &TargetDeviceStatistics[TargetID].TotalBytesWritten, BufferLength); + BusLogic_IncrementSizeBucket( + TargetDeviceStatistics[TargetID].WriteCommandSizeBuckets, + BufferLength); break; default: CCB->DataDirection = BusLogic_UncheckedDataTransfer; @@ -2512,17 +3368,8 @@ CCB->TargetDeviceStatus = 0; CCB->TargetID = TargetID; CCB->LogicalUnit = LogicalUnit; - /* - For Host Adapters that support it, 64 LUN Format CCBs are used to allow - 64 Logical Units per Target, and this requires setting the overloaded - TagEnable field to Logical Unit bit 5. - */ - if (HostAdapter->Host64LUNSupport) - { - CCB->TagEnable = LogicalUnit >> 5; - CCB->TagEnable64LUN = false; - } - else CCB->TagEnable = false; + CCB->TagEnable = false; + CCB->LegacyTagEnable = false; /* BusLogic recommends that after a Reset the first couple of commands that are sent to a Target Device be sent in a non Tagged Queue fashion so that @@ -2537,16 +3384,18 @@ necessary to wait until there are no pending commands for a target device before queuing tagged commands. */ - if (HostAdapter->TotalCommandCount[TargetID]++ >= - BusLogic_MaxTaggedQueueDepth && + HostAdapter->TaggedQueuingSupported[TargetID] = + Command->device->tagged_supported; + if (HostAdapter->CommandsSinceReset[TargetID]++ >= + BusLogic_MaxTaggedQueueDepth && !HostAdapter->TaggedQueuingActive[TargetID] && - HostAdapter->ActiveCommandCount[TargetID] == 0 && - (HostAdapter->TaggedQueuingPermitted & (1 << TargetID)) && - Command->device->tagged_supported) + HostAdapter->ActiveCommands[TargetID] == 0 && + HostAdapter->TaggedQueuingSupported[TargetID] && + (HostAdapter->TaggedQueuingPermitted & (1 << TargetID))) { HostAdapter->TaggedQueuingActive[TargetID] = true; - printk("scsi%d: Tagged Queuing now active for Target %d\n", - HostAdapter->HostNumber, TargetID); + BusLogic_Notice("Tagged Queuing now active for Target %d\n", + HostAdapter, TargetID); } if (HostAdapter->TaggedQueuingActive[TargetID]) { @@ -2558,58 +3407,77 @@ 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 5 seconds (one third of the 15 second disk timeout) have + more than 3 seconds (one fifth of the 15 second disk timeout) 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->ActiveCommandCount[TargetID] == 0) + if (HostAdapter->ActiveCommands[TargetID] == 0) HostAdapter->LastSequencePoint[TargetID] = jiffies; - else if (jiffies - HostAdapter->LastSequencePoint[TargetID] > 5*HZ) + else if (jiffies - HostAdapter->LastSequencePoint[TargetID] > 3*HZ) { HostAdapter->LastSequencePoint[TargetID] = jiffies; QueueTag = BusLogic_OrderedQueueTag; } - if (HostAdapter->Host64LUNSupport) + if (HostAdapter->ExtendedLUNSupport) { - CCB->TagEnable64LUN = true; - CCB->QueueTag64LUN = QueueTag; + CCB->TagEnable = true; + CCB->QueueTag = QueueTag; } else { - CCB->TagEnable = true; - CCB->QueueTag = QueueTag; + CCB->LegacyTagEnable = true; + CCB->LegacyQueueTag = QueueTag; } } memcpy(CCB->CDB, CDB, CDB_Length); CCB->SenseDataPointer = Virtual_to_Bus(&Command->sense_buffer); CCB->Command = Command; Command->scsi_done = CompletionRoutine; - /* - Place the CCB in an Outgoing Mailbox. The higher levels of the SCSI - Subsystem should not attempt to queue more commands than can be placed in - Outgoing Mailboxes, so there should always be one free. In the unlikely - event that there are none available, wait 1 second and try again. If - that fails, the Host Adapter is probably hung so we signal an error as - a Host Adapter Hard Reset should be initiated soon. - */ - if (!BusLogic_WriteOutgoingMailbox(HostAdapter, - BusLogic_MailboxStartCommand, CCB)) + if (BusLogic_MultiMasterHostAdapterP(HostAdapter)) { - printk("scsi%d: cannot write Outgoing Mailbox - Pausing for 1 second\n", - HostAdapter->HostNumber); - BusLogic_Delay(1); - if (!BusLogic_WriteOutgoingMailbox(HostAdapter, - BusLogic_MailboxStartCommand, CCB)) + /* + Place the CCB in an Outgoing Mailbox. The higher levels of the SCSI + Subsystem should not attempt to queue more commands than can be placed + in Outgoing Mailboxes, so there should always be one free. In the + unlikely event that there are none available, wait 1 second and try + again. If that fails, the Host Adapter is probably hung so signal an + error as a Host Adapter Hard Reset should be initiated soon. + */ + if (!BusLogic_WriteOutgoingMailbox( + HostAdapter, BusLogic_MailboxStartCommand, CCB)) { - printk("scsi%d: still cannot write Outgoing Mailbox - " - "Host Adapter Dead?\n", HostAdapter->HostNumber); - BusLogic_DeallocateCCB(CCB); - Command->result = DID_ERROR << 16; - Command->scsi_done(Command); + BusLogic_Warning("Unable to write Outgoing Mailbox - " + "Pausing for 1 second\n", HostAdapter); + BusLogic_Delay(1); + if (!BusLogic_WriteOutgoingMailbox( + HostAdapter, BusLogic_MailboxStartCommand, CCB)) + { + BusLogic_Warning("Still unable to write Outgoing Mailbox - " + "Host Adapter Dead?\n", HostAdapter); + BusLogic_DeallocateCCB(CCB); + Command->result = DID_ERROR << 16; + Command->scsi_done(Command); + } } } + else + { + /* + Call the FlashPoint SCCB Manager to start execution of the CCB. + */ + CCB->Status = BusLogic_CCB_Active; + HostAdapter->ActiveCommands[TargetID]++; + TargetDeviceStatistics[TargetID].CommandsAttempted++; + FlashPoint_StartCCB(HostAdapter->CardHandle, CCB); + /* + The Command may have already completed and BusLogic_QueueCompletedCCB + been called, or it may still be pending. + */ + if (CCB->Status == BusLogic_CCB_Completed) + BusLogic_ProcessCompletedCCBs(); + } /* Release exclusive access to Host Adapter. */ @@ -2631,6 +3499,8 @@ BusLogic_Lock_T Lock; BusLogic_CCB_T *CCB; int Result; + BusLogic_IncrementErrorCounter( + &HostAdapter->TargetDeviceStatistics[TargetID].CommandAbortsRequested); /* Acquire exclusive access to Host Adapter. */ @@ -2640,8 +3510,8 @@ */ if (Command->serial_number != Command->serial_number_at_timeout) { - printk("scsi%d: Unable to Abort Command to Target %d - " - "Already Completed\n", HostAdapter->HostNumber, TargetID); + BusLogic_Warning("Unable to Abort Command to Target %d - " + "Already Completed\n", HostAdapter, TargetID); Result = SCSI_ABORT_NOT_RUNNING; goto Done; } @@ -2653,56 +3523,84 @@ if (CCB->Command == Command) break; if (CCB == NULL) { - printk("scsi%d: Unable to Abort Command to Target %d - No CCB Found\n", - HostAdapter->HostNumber, TargetID); + BusLogic_Warning("Unable to Abort Command to Target %d - " + "No CCB Found\n", HostAdapter, TargetID); Result = SCSI_ABORT_NOT_RUNNING; goto Done; } else if (CCB->Status == BusLogic_CCB_Completed) { - printk("scsi%d: Unable to Abort Command to Target %d - CCB Completed\n", - HostAdapter->HostNumber, TargetID); + BusLogic_Warning("Unable to Abort Command to Target %d - " + "CCB Completed\n", HostAdapter, TargetID); Result = SCSI_ABORT_NOT_RUNNING; goto Done; } else if (CCB->Status == BusLogic_CCB_Reset) { - printk("scsi%d: Unable to Abort Command to Target %d - CCB Reset\n", - HostAdapter->HostNumber, TargetID); - Result = SCSI_ABORT_NOT_RUNNING; + BusLogic_Warning("Unable to Abort Command to Target %d - " + "CCB Reset\n", HostAdapter, TargetID); + Result = SCSI_ABORT_PENDING; goto Done; } - /* - Attempt to Abort this CCB. Firmware versions prior to 5.xx do not generate - Abort Tag messages, but only generate the non-tagged Abort message. Since - non-tagged commands are not sent by the Host Adapter until the queue of - outstanding tagged commands has completed, and the Abort message is treated - as a non-tagged command, it is effectively impossible to abort commands - when Tagged Queuing is active. Firmware version 5.xx does generate Abort - Tag messages, so it is possible to abort commands when Tagged Queuing is - active. - */ - if (HostAdapter->TaggedQueuingActive[TargetID] && - HostAdapter->FirmwareVersion[0] < '5') - { - printk("scsi%d: Unable to Abort CCB #%ld to Target %d - " - "Abort Tag Not Supported\n", HostAdapter->HostNumber, - CCB->SerialNumber, TargetID); - Result = SCSI_ABORT_SNOOZE; - } - else if (BusLogic_WriteOutgoingMailbox(HostAdapter, - BusLogic_MailboxAbortCommand, CCB)) + if (BusLogic_MultiMasterHostAdapterP(HostAdapter)) { - printk("scsi%d: Aborting CCB #%ld to Target %d\n", - HostAdapter->HostNumber, CCB->SerialNumber, TargetID); - Result = SCSI_ABORT_PENDING; + /* + Attempt to Abort this CCB. MultiMaster Firmware versions prior to 5.xx + do not generate Abort Tag messages, but only generate the non-tagged + Abort message. Since non-tagged commands are not sent by the Host + Adapter until the queue of outstanding tagged commands has completed, + and the Abort message is treated as a non-tagged command, it is + effectively impossible to abort commands when Tagged Queuing is active. + Firmware version 5.xx does generate Abort Tag messages, so it is + possible to abort commands when Tagged Queuing is active. + */ + if (HostAdapter->TaggedQueuingActive[TargetID] && + HostAdapter->FirmwareVersion[0] < '5') + { + BusLogic_Warning("Unable to Abort CCB #%ld to Target %d - " + "Abort Tag Not Supported\n", + HostAdapter, CCB->SerialNumber, TargetID); + Result = SCSI_ABORT_SNOOZE; + } + else if (BusLogic_WriteOutgoingMailbox( + HostAdapter, BusLogic_MailboxAbortCommand, CCB)) + { + BusLogic_Warning("Aborting CCB #%ld to Target %d\n", + HostAdapter, CCB->SerialNumber, TargetID); + BusLogic_IncrementErrorCounter( + &HostAdapter->TargetDeviceStatistics[TargetID] + .CommandAbortsAttempted); + Result = SCSI_ABORT_PENDING; + } + else + { + BusLogic_Warning("Unable to Abort CCB #%ld to Target %d - " + "No Outgoing Mailboxes\n", + HostAdapter, CCB->SerialNumber, TargetID); + Result = SCSI_ABORT_BUSY; + } } else { - printk("scsi%d: Unable to Abort CCB #%ld to Target %d - " - "No Outgoing Mailboxes\n", HostAdapter->HostNumber, - CCB->SerialNumber, TargetID); - Result = SCSI_ABORT_BUSY; + /* + Call the FlashPoint SCCB Manager to abort execution of the CCB. + */ + BusLogic_Warning("Aborting CCB #%ld to Target %d\n", + HostAdapter, CCB->SerialNumber, TargetID); + BusLogic_IncrementErrorCounter( + &HostAdapter->TargetDeviceStatistics[TargetID].CommandAbortsAttempted); + FlashPoint_AbortCCB(HostAdapter->CardHandle, CCB); + /* + The Abort may have already been completed and + BusLogic_QueueCompletedCCB been called, or it + may still be pending. + */ + Result = SCSI_ABORT_PENDING; + if (CCB->Status == BusLogic_CCB_Completed) + { + BusLogic_ProcessCompletedCCBs(); + Result = SCSI_ABORT_SUCCESS; + } } /* Release exclusive access to Host Adapter. @@ -2725,6 +3623,11 @@ BusLogic_Lock_T Lock; BusLogic_CCB_T *CCB; int TargetID, Result; + if (Command == NULL) + BusLogic_IncrementErrorCounter(&HostAdapter->ExternalHostAdapterResets); + else BusLogic_IncrementErrorCounter( + &HostAdapter->TargetDeviceStatistics[Command->target] + .HostAdapterResetsRequested); /* Acquire exclusive access to Host Adapter. */ @@ -2738,9 +3641,9 @@ TargetID = Command->target; if (Command->serial_number != Command->serial_number_at_timeout) { - printk("scsi%d: Unable to Reset Command to Target %d - " - "Already Completed or Reset\n", - HostAdapter->HostNumber, TargetID); + BusLogic_Warning("Unable to Reset Command to Target %d - " + "Already Completed or Reset\n", + HostAdapter, TargetID); Result = SCSI_RESET_NOT_RUNNING; goto Done; } @@ -2748,44 +3651,53 @@ if (CCB->Command == Command) break; if (CCB == NULL) { - printk("scsi%d: Unable to Reset Command to Target %d - " - "No CCB Found\n", HostAdapter->HostNumber, TargetID); + BusLogic_Warning("Unable to Reset Command to Target %d - " + "No CCB Found\n", HostAdapter, TargetID); Result = SCSI_RESET_NOT_RUNNING; goto Done; } else if (CCB->Status == BusLogic_CCB_Completed) { - printk("scsi%d: Unable to Reset Command to Target %d - " - "CCB Completed\n", HostAdapter->HostNumber, TargetID); + BusLogic_Warning("Unable to Reset Command to Target %d - " + "CCB Completed\n", HostAdapter, TargetID); Result = SCSI_RESET_NOT_RUNNING; goto Done; } else if (CCB->Status == BusLogic_CCB_Reset && HostAdapter->BusDeviceResetPendingCCB[TargetID] == NULL) { - printk("scsi%d: Unable to Reset Command to Target %d - " - "Reset Pending\n", HostAdapter->HostNumber, TargetID); + BusLogic_Warning("Unable to Reset Command to Target %d - " + "Reset Pending\n", HostAdapter, TargetID); Result = SCSI_RESET_PENDING; goto Done; } } if (Command == NULL) - printk("scsi%d: Resetting %s due to SCSI Reset State Interrupt\n", - HostAdapter->HostNumber, HostAdapter->ControllerName); - else printk("scsi%d: Resetting %s due to Target %d\n", - HostAdapter->HostNumber, HostAdapter->ControllerName, - Command->target); + BusLogic_Warning("Resetting %s due to External SCSI Bus Reset\n", + HostAdapter, HostAdapter->FullModelName); + else + { + BusLogic_Warning("Resetting %s due to Target %d\n", HostAdapter, + HostAdapter->FullModelName, Command->target); + BusLogic_IncrementErrorCounter( + &HostAdapter->TargetDeviceStatistics[Command->target] + .HostAdapterResetsAttempted); + } /* Attempt to Reset and Reinitialize the Host Adapter. */ if (!(BusLogic_HardResetHostAdapter(HostAdapter) && BusLogic_InitializeHostAdapter(HostAdapter))) { - printk("scsi%d: Resetting %s Failed\n", - HostAdapter->HostNumber, HostAdapter->ControllerName); + BusLogic_Error("Resetting %s Failed\n", HostAdapter, + HostAdapter->FullModelName); Result = SCSI_RESET_ERROR; goto Done; } + if (Command != NULL) + BusLogic_IncrementErrorCounter( + &HostAdapter->TargetDeviceStatistics[Command->target] + .HostAdapterResetsCompleted); /* Mark all currently executing CCBs as having been Reset. */ @@ -2848,9 +3760,11 @@ unsigned int ResetFlags) { int TargetID = Command->target; + BusLogic_CCB_T *CCB, *XCCB; BusLogic_Lock_T Lock; - BusLogic_CCB_T *CCB; int Result = -1; + BusLogic_IncrementErrorCounter( + &HostAdapter->TargetDeviceStatistics[TargetID].BusDeviceResetsRequested); /* Acquire exclusive access to Host Adapter. */ @@ -2863,8 +3777,8 @@ { if (Command->serial_number != Command->serial_number_at_timeout) { - printk("scsi%d: Unable to Reset Command to Target %d - " - "Already Completed\n", HostAdapter->HostNumber, TargetID); + BusLogic_Warning("Unable to Reset Command to Target %d - " + "Already Completed\n", HostAdapter, TargetID); Result = SCSI_RESET_NOT_RUNNING; goto Done; } @@ -2872,29 +3786,29 @@ if (CCB->Command == Command) break; if (CCB == NULL) { - printk("scsi%d: Unable to Reset Command to Target %d - " - "No CCB Found\n", HostAdapter->HostNumber, TargetID); + BusLogic_Warning("Unable to Reset Command to Target %d - " + "No CCB Found\n", HostAdapter, TargetID); Result = SCSI_RESET_NOT_RUNNING; goto Done; } else if (CCB->Status == BusLogic_CCB_Completed) { - printk("scsi%d: Unable to Reset Command to Target %d - " - "CCB Completed\n", HostAdapter->HostNumber, TargetID); + BusLogic_Warning("Unable to Reset Command to Target %d - " + "CCB Completed\n", HostAdapter, TargetID); Result = SCSI_RESET_NOT_RUNNING; goto Done; } else if (CCB->Status == BusLogic_CCB_Reset) { - printk("scsi%d: Unable to Reset Command to Target %d - " - "Reset Pending\n", HostAdapter->HostNumber, TargetID); + BusLogic_Warning("Unable to Reset Command to Target %d - " + "Reset Pending\n", HostAdapter, TargetID); Result = SCSI_RESET_PENDING; goto Done; } else if (HostAdapter->BusDeviceResetPendingCCB[TargetID] != NULL) { - printk("scsi%d: Bus Device Reset already pending to Target %d\n", - HostAdapter->HostNumber, TargetID); + BusLogic_Warning("Bus Device Reset already pending to Target %d\n", + HostAdapter, TargetID); goto Done; } } @@ -2909,23 +3823,26 @@ { Command->reset_chain = CCB->Command; CCB->Command = Command; - printk("scsi%d: Unable to Reset Command to Target %d - " - "Reset Pending\n", HostAdapter->HostNumber, TargetID); + BusLogic_Warning("Unable to Reset Command to Target %d - " + "Reset Pending\n", HostAdapter, TargetID); Result = SCSI_RESET_PENDING; goto Done; } - /* - Firmware versions prior to 5.xx treat a Bus Device Reset as a non-tagged - command. Since non-tagged commands are not sent by the Host Adapter until - the queue of outstanding tagged commands has completed, it is effectively - impossible to send a Bus Device Reset while there are tagged commands - outstanding. Therefore, in that case a full Host Adapter Hard Reset and - SCSI Bus Reset must be done. - */ - if (HostAdapter->TaggedQueuingActive[TargetID] && - HostAdapter->ActiveCommandCount[TargetID] > 0 && - HostAdapter->FirmwareVersion[0] < '5') - goto Done; + if (BusLogic_MultiMasterHostAdapterP(HostAdapter)) + { + /* + MultiMaster Firmware versions prior to 5.xx treat a Bus Device Reset as + a non-tagged command. Since non-tagged commands are not sent by the + Host Adapter until the queue of outstanding tagged commands has + completed, it is effectively impossible to send a Bus Device Reset + while there are tagged commands outstanding. Therefore, in that case a + full Host Adapter Hard Reset and SCSI Bus Reset must be done. + */ + if (HostAdapter->TaggedQueuingActive[TargetID] && + HostAdapter->ActiveCommands[TargetID] > 0 && + HostAdapter->FirmwareVersion[0] < '5') + goto Done; + } /* Allocate a CCB from the Host Adapter's free list. In the unlikely event that there are none available and memory allocation fails, attempt a full @@ -2933,8 +3850,8 @@ */ CCB = BusLogic_AllocateCCB(HostAdapter); if (CCB == NULL) goto Done; - printk("scsi%d: Sending Bus Device Reset CCB #%ld to Target %d\n", - HostAdapter->HostNumber, CCB->SerialNumber, TargetID); + BusLogic_Warning("Sending Bus Device Reset CCB #%ld to Target %d\n", + HostAdapter, CCB->SerialNumber, TargetID); CCB->Opcode = BusLogic_BusDeviceReset; CCB->TargetID = TargetID; /* @@ -2946,18 +3863,30 @@ Command->reset_chain = NULL; CCB->Command = Command; } - /* - 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); - goto Done; + if (BusLogic_MultiMasterHostAdapterP(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))) + { + BusLogic_Warning("Unable to write Outgoing Mailbox for " + "Bus Device Reset\n", HostAdapter); + BusLogic_DeallocateCCB(CCB); + goto Done; + } + } + else + { + /* + Call the FlashPoint SCCB Manager to start execution of the CCB. + */ + CCB->Status = BusLogic_CCB_Active; + HostAdapter->ActiveCommands[TargetID]++; + FlashPoint_StartCCB(HostAdapter->CardHandle, CCB); } /* If there is a currently executing CCB in the Host Adapter for this Command @@ -2975,12 +3904,25 @@ interrupt handler, any remaining CCBs marked as Reset will have completion processing performed. */ + BusLogic_IncrementErrorCounter( + &HostAdapter->TargetDeviceStatistics[TargetID].BusDeviceResetsAttempted); HostAdapter->BusDeviceResetPendingCCB[TargetID] = CCB; HostAdapter->LastResetTime[TargetID] = jiffies; - for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll) - if (CCB->Status == BusLogic_CCB_Active && CCB->TargetID == TargetID) - CCB->Status = BusLogic_CCB_Reset; + for (XCCB = HostAdapter->All_CCBs; XCCB != NULL; XCCB = XCCB->NextAll) + if (XCCB->Status == BusLogic_CCB_Active && XCCB->TargetID == TargetID) + XCCB->Status = BusLogic_CCB_Reset; + /* + FlashPoint Host Adapters may have already completed the Bus Device + Reset and BusLogic_QueueCompletedCCB been called, or it may still be + pending. + */ Result = SCSI_RESET_PENDING; + if (BusLogic_FlashPointHostAdapterP(HostAdapter)) + if (CCB->Status == BusLogic_CCB_Completed) + { + BusLogic_ProcessCompletedCCBs(); + Result = SCSI_RESET_SUCCESS; + } /* If a Bus Device Reset was not possible for some reason, force a full Host Adapter Hard Reset and SCSI Bus Reset. @@ -3005,7 +3947,8 @@ BusLogic_HostAdapter_T *HostAdapter = (BusLogic_HostAdapter_T *) Command->host->hostdata; int TargetID = Command->target; - int ErrorRecoveryStrategy = HostAdapter->ErrorRecoveryStrategy[TargetID]; + BusLogic_ErrorRecoveryStrategy_T + ErrorRecoveryStrategy = HostAdapter->ErrorRecoveryStrategy[TargetID]; /* Disable Tagged Queuing if it is active for this Target Device and if it has been less than 10 minutes since the last reset occurred, or since @@ -3016,19 +3959,17 @@ { HostAdapter->TaggedQueuingPermitted &= ~(1 << TargetID); HostAdapter->TaggedQueuingActive[TargetID] = false; - printk("scsi%d: Tagged Queuing now disabled for Target %d\n", - HostAdapter->HostNumber, TargetID); + BusLogic_Warning("Tagged Queuing now disabled for Target %d\n", + HostAdapter, TargetID); } - if (ErrorRecoveryStrategy == BusLogic_ErrorRecovery_Default) - if (ResetFlags & SCSI_RESET_SUGGEST_HOST_RESET) - ErrorRecoveryStrategy = BusLogic_ErrorRecovery_HardReset; - else if (ResetFlags & SCSI_RESET_SUGGEST_BUS_RESET) - ErrorRecoveryStrategy = BusLogic_ErrorRecovery_HardReset; - else ErrorRecoveryStrategy = BusLogic_ErrorRecovery_BusDeviceReset; switch (ErrorRecoveryStrategy) { - case BusLogic_ErrorRecovery_HardReset: - return BusLogic_ResetHostAdapter(HostAdapter, Command, ResetFlags); + case BusLogic_ErrorRecovery_Default: + if (ResetFlags & SCSI_RESET_SUGGEST_HOST_RESET) + return BusLogic_ResetHostAdapter(HostAdapter, Command, ResetFlags); + else if (ResetFlags & SCSI_RESET_SUGGEST_BUS_RESET) + return BusLogic_ResetHostAdapter(HostAdapter, Command, ResetFlags); + /* Fall through to Bus Device Reset case. */ case BusLogic_ErrorRecovery_BusDeviceReset: /* The Bus Device Reset Error Recovery Strategy only graduates to a Hard @@ -3044,10 +3985,14 @@ HostAdapter->CommandSuccessfulFlag[TargetID] = false; return BusLogic_SendBusDeviceReset(HostAdapter, Command, ResetFlags); } - else return BusLogic_ResetHostAdapter(HostAdapter, Command, ResetFlags); + /* Fall through to Hard Reset case. */ + case BusLogic_ErrorRecovery_HardReset: + return BusLogic_ResetHostAdapter(HostAdapter, Command, ResetFlags); + case BusLogic_ErrorRecovery_None: + BusLogic_Warning("Error Recovery for Target %d Suppressed\n", + HostAdapter, TargetID); + break; } - printk("scsi%d: Error Recovery for Target %d Suppressed\n", - HostAdapter->HostNumber, TargetID); return SCSI_RESET_PUNT; } @@ -3058,10 +4003,11 @@ 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 "W" and "C" Series controllers or by a dip - switch setting on older controllers. 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 above 2 GB inclusive are given a disk + may be enabled in AutoSCSI on FlashPoint Host Adapters and on "W" and "C" + series MultiMaster Host Adapters, or by a dip switch setting on "S" and "A" + series MultiMaster Host Adapters. 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 above 2 GB inclusive are given a disk geometry of 255 heads and 63 sectors. However, if the BIOS detects that the Extended Translation setting does not match the geometry in the partition table, then the translation inferred from the partition table will be used by @@ -3075,7 +4021,7 @@ (BusLogic_HostAdapter_T *) Disk->device->host->hostdata; BIOS_DiskParameters_T *DiskParameters = (BIOS_DiskParameters_T *) Parameters; struct buffer_head *BufferHead; - if (HostAdapter->ExtendedTranslation && + if (HostAdapter->ExtendedTranslationEnabled && Disk->capacity >= 2*1024*1024 /* 1 GB in 512 byte sectors */) if (Disk->capacity >= 4*1024*1024 /* 2 GB in 512 byte sectors */) { @@ -3134,12 +4080,13 @@ DiskParameters->Cylinders = Disk->capacity / (DiskParameters->Heads * DiskParameters->Sectors); if (SavedCylinders != DiskParameters->Cylinders) - printk("scsi%d: Warning: Extended Translation Setting " - "(> 1GB Switch) does not match\n" - "scsi%d: Partition Table - Adopting %d/%d Geometry " - "from Partition Table\n", - HostAdapter->HostNumber, HostAdapter->HostNumber, - DiskParameters->Heads, DiskParameters->Sectors); + { + BusLogic_Warning("Warning: Extended Translation Setting " + "(> 1GB Switch) does not match\n", HostAdapter); + BusLogic_Warning("Partition Table - Adopting %d/%d Geometry " + "from Partition Table\n", HostAdapter, + DiskParameters->Heads, DiskParameters->Sectors); + } } brelse(BufferHead); return 0; @@ -3147,9 +4094,214 @@ /* + BugLogic_ProcDirectoryInfo implements /proc/scsi/BusLogic/. +*/ + +int BusLogic_ProcDirectoryInfo(char *ProcBuffer, char **StartPointer, + off_t Offset, int BytesAvailable, + int HostNumber, int WriteFlag) +{ + BusLogic_HostAdapter_T *HostAdapter; + BusLogic_TargetDeviceStatistics_T *TargetDeviceStatistics; + int IRQ_Channel, TargetID, Length; + char *Buffer; + if (WriteFlag) return 0; + for (IRQ_Channel = 0; IRQ_Channel < NR_IRQS; IRQ_Channel++) + { + HostAdapter = BusLogic_RegisteredHostAdapters[IRQ_Channel]; + while (HostAdapter != NULL) + { + if (HostAdapter->HostNumber == HostNumber) break; + HostAdapter = HostAdapter->Next; + } + if (HostAdapter != NULL) break; + } + if (HostAdapter == NULL) return -1; + TargetDeviceStatistics = HostAdapter->TargetDeviceStatistics; + Buffer = HostAdapter->MessageBuffer; + Length = HostAdapter->MessageBufferLength; + Length += sprintf(&Buffer[Length], "\n\n\ + DATA TRANSFER STATISTICS\n\ +\n\ +Target Tagged Queuing Queue Depth Commands Attempted Commands Completed\n\ +====== ============== =========== ================== ==================\n"); + for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) + if (TargetDeviceStatistics[TargetID].CommandsCompleted > 0) + { + Length += + sprintf(&Buffer[Length], " %2d %s", TargetID, + (HostAdapter->TaggedQueuingSupported[TargetID] + ? (HostAdapter->TaggedQueuingActive[TargetID] + ? " Active" + : (HostAdapter->TaggedQueuingPermitted & (1 << TargetID) + ? " Permitted" : " Disabled")) + : "Not Supported")); + Length += sprintf(&Buffer[Length], + " %3d %9u %9u\n", + HostAdapter->QueueDepth[TargetID], + TargetDeviceStatistics[TargetID].CommandsAttempted, + TargetDeviceStatistics[TargetID].CommandsCompleted); + } + Length += sprintf(&Buffer[Length], "\n\ +Target Read Commands Write Commands Total Bytes Read Total Bytes Written\n\ +====== ============= ============== =================== ===================\n"); + for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) + if (TargetDeviceStatistics[TargetID].CommandsCompleted > 0) + { + Length += + sprintf(&Buffer[Length], " %2d %9u %9u", TargetID, + TargetDeviceStatistics[TargetID].ReadCommands, + TargetDeviceStatistics[TargetID].WriteCommands); + if (TargetDeviceStatistics[TargetID].TotalBytesRead.Billions > 0) + Length += + sprintf(&Buffer[Length], " %9u%09u", + TargetDeviceStatistics[TargetID].TotalBytesRead.Billions, + TargetDeviceStatistics[TargetID].TotalBytesRead.Units); + else + Length += + sprintf(&Buffer[Length], " %9u", + TargetDeviceStatistics[TargetID].TotalBytesRead.Units); + if (TargetDeviceStatistics[TargetID].TotalBytesWritten.Billions > 0) + Length += + sprintf(&Buffer[Length], " %9u%09u\n", + TargetDeviceStatistics[TargetID].TotalBytesWritten.Billions, + TargetDeviceStatistics[TargetID].TotalBytesWritten.Units); + else + Length += + sprintf(&Buffer[Length], " %9u\n", + TargetDeviceStatistics[TargetID].TotalBytesWritten.Units); + } + Length += sprintf(&Buffer[Length], "\n\ +Target Command 0-1KB 1-2KB 2-4KB 4-8KB 8-16KB\n\ +====== ======= ========= ========= ========= ========= =========\n"); + for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) + if (TargetDeviceStatistics[TargetID].CommandsCompleted > 0) + { + Length += + sprintf(&Buffer[Length], + " %2d Read %9u %9u %9u %9u %9u\n", TargetID, + TargetDeviceStatistics[TargetID].ReadCommandSizeBuckets[0], + TargetDeviceStatistics[TargetID].ReadCommandSizeBuckets[1], + TargetDeviceStatistics[TargetID].ReadCommandSizeBuckets[2], + TargetDeviceStatistics[TargetID].ReadCommandSizeBuckets[3], + TargetDeviceStatistics[TargetID].ReadCommandSizeBuckets[4]); + Length += + sprintf(&Buffer[Length], + " %2d Write %9u %9u %9u %9u %9u\n", TargetID, + TargetDeviceStatistics[TargetID].WriteCommandSizeBuckets[0], + TargetDeviceStatistics[TargetID].WriteCommandSizeBuckets[1], + TargetDeviceStatistics[TargetID].WriteCommandSizeBuckets[2], + TargetDeviceStatistics[TargetID].WriteCommandSizeBuckets[3], + TargetDeviceStatistics[TargetID].WriteCommandSizeBuckets[4]); + } + Length += sprintf(&Buffer[Length], "\n\ +Target Command 16-32KB 32-64KB 64-128KB 128-256KB 256KB+\n\ +====== ======= ========= ========= ========= ========= =========\n"); + for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) + if (TargetDeviceStatistics[TargetID].CommandsCompleted > 0) + { + Length += + sprintf(&Buffer[Length], + " %2d Read %9u %9u %9u %9u %9u\n", TargetID, + TargetDeviceStatistics[TargetID].ReadCommandSizeBuckets[5], + TargetDeviceStatistics[TargetID].ReadCommandSizeBuckets[6], + TargetDeviceStatistics[TargetID].ReadCommandSizeBuckets[7], + TargetDeviceStatistics[TargetID].ReadCommandSizeBuckets[8], + TargetDeviceStatistics[TargetID].ReadCommandSizeBuckets[9]); + Length += + sprintf(&Buffer[Length], + " %2d Write %9u %9u %9u %9u %9u\n", TargetID, + TargetDeviceStatistics[TargetID].WriteCommandSizeBuckets[5], + TargetDeviceStatistics[TargetID].WriteCommandSizeBuckets[6], + TargetDeviceStatistics[TargetID].WriteCommandSizeBuckets[7], + TargetDeviceStatistics[TargetID].WriteCommandSizeBuckets[8], + TargetDeviceStatistics[TargetID].WriteCommandSizeBuckets[9]); + } + Length += sprintf(&Buffer[Length], "\n\n\ + ERROR RECOVERY STATISTICS\n\ +\n\ + Command Aborts Bus Device Resets Host Adapter Resets\n\ +Target Requested Completed Requested Completed Requested Completed\n\ + ID \\\\\\\\ Attempted //// \\\\\\\\ Attempted //// \\\\\\\\ Attempted ////\n\ +====== ===== ===== ===== ===== ===== ===== ===== ===== =====\n"); + for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) + if (TargetDeviceStatistics[TargetID].CommandsCompleted > 0) + Length += + sprintf(&Buffer[Length], "\ + %2d %5d %5d %5d %5d %5d %5d %5d %5d %5d\n", TargetID, + TargetDeviceStatistics[TargetID].CommandAbortsRequested, + TargetDeviceStatistics[TargetID].CommandAbortsAttempted, + TargetDeviceStatistics[TargetID].CommandAbortsCompleted, + TargetDeviceStatistics[TargetID].BusDeviceResetsRequested, + TargetDeviceStatistics[TargetID].BusDeviceResetsAttempted, + TargetDeviceStatistics[TargetID].BusDeviceResetsCompleted, + TargetDeviceStatistics[TargetID].HostAdapterResetsRequested, + TargetDeviceStatistics[TargetID].HostAdapterResetsAttempted, + TargetDeviceStatistics[TargetID].HostAdapterResetsCompleted); + Length += sprintf(&Buffer[Length], "\nExternal Host Adapter Resets: %d\n", + HostAdapter->ExternalHostAdapterResets); + if (Length >= BusLogic_MessageBufferSize) + BusLogic_Error("Message Buffer length %d exceeds size %d\n", + HostAdapter, Length, BusLogic_MessageBufferSize); + if ((Length -= Offset) <= 0) return 0; + if (Length >= BytesAvailable) Length = BytesAvailable; + *StartPointer = &HostAdapter->MessageBuffer[Offset]; + return Length; +} + + +/* + BusLogic_Message prints Driver Messages. +*/ + +static void BusLogic_Message(BusLogic_MessageLevel_T MessageLevel, + char *Format, + BusLogic_HostAdapter_T *HostAdapter, + ...) +{ + static char Buffer[BusLogic_LineBufferSize]; + static boolean BeginningOfLine = true; + va_list Arguments; + int Length = 0; + va_start(Arguments, HostAdapter); + Length = vsprintf(Buffer, Format, Arguments); + va_end(Arguments); + if (MessageLevel == BusLogic_AnnounceLevel) + { + static int AnnouncementLines = 0; + strcpy(&HostAdapter->MessageBuffer[HostAdapter->MessageBufferLength], + Buffer); + HostAdapter->MessageBufferLength += Length; + if (++AnnouncementLines <= 2) + printk("%sscsi: %s", BusLogic_MessageLevelMap[MessageLevel], Buffer); + } + else if (MessageLevel == BusLogic_InfoLevel) + { + strcpy(&HostAdapter->MessageBuffer[HostAdapter->MessageBufferLength], + Buffer); + HostAdapter->MessageBufferLength += Length; + if (BeginningOfLine) + printk("%sscsi%d: %s", BusLogic_MessageLevelMap[MessageLevel], + HostAdapter->HostNumber, Buffer); + else printk("%s", Buffer); + } + else + { + if (BeginningOfLine) + if (HostAdapter != NULL && HostAdapter->HostAdapterInitialized) + printk("%sscsi%d: %s", BusLogic_MessageLevelMap[MessageLevel], + HostAdapter->HostNumber, Buffer); + else printk("%s%s", BusLogic_MessageLevelMap[MessageLevel], Buffer); + else printk("%s", Buffer); + } + BeginningOfLine = (Buffer[Length-1] == '\n'); +} + + +/* BusLogic_Setup handles processing of Kernel Command Line Arguments. - For the BusLogic driver, a Kernel command line entry comprises the driver + 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. @@ -3169,9 +4321,9 @@ automatically based on the Host Adapter's Total Queue Depth and the number, type, speed, and capabilities of the detected Target Devices. For Host Adapters that require ISA Bounce Buffers, the Tagged Queue Depth is - automatically set to BusLogic_TaggedQueueDepth_BB to avoid excessive - preallocation of DMA Bounce Buffer memory. Target Devices that do not - support Tagged Queuing use a Queue Depth of BusLogic_UntaggedQueueDepth. + automatically set to BusLogic_TaggedQueueDepthBounceBuffers to avoid + excessive preallocation of DMA Bounce Buffer memory. Target Devices that do + not support Tagged Queuing use a Queue Depth of BusLogic_UntaggedQueueDepth. 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 @@ -3260,56 +4412,85 @@ no BusLogic Host Adapters will be detected. NoProbeISA No probing of the standard ISA I/O Addresses will - be done, and hence only PCI Host Adapters will be - detected. + be done, and hence only PCI MultiMaster and FlashPoint + Host Adapters will be detected. + + NoProbePCI No interrogation of PCI Configuration Space will be + made, and hence only ISA Multimaster Host Adapters + will be detected, as well as PCI Multimaster Host + Adapters that have their ISA Compatible I/O Port + set to "Primary" or "Alternate". + + NoSortPCI PCI MultiMaster Host Adapters will be enumerated in + the order provided by the PCI BIOS, ignoring any + setting of the AutoSCSI "Use Bus And Device # For PCI + Scanning Seq." option. + + MultiMasterFirst By default, if both FlashPoint and PCI MultiMaster + Host Adapters are present, this driver will probe for + PCI MultiMaster Host Adapters first unless the BIOS + primary disk is not controlled by the first PCI + MultiMaster Host Adapter, in which case FlashPoint + Host Adapters will be probed first. This option + forces MultiMaster Host Adapters to be probed first. + + FlashPointFirst By default, if both FlashPoint and PCI MultiMaster + Host Adapters are present, this driver will probe for + PCI MultiMaster Host Adapters first unless the BIOS + primary disk is not controlled by the first PCI + MultiMaster Host Adapter, in which case FlashPoint + Host Adapters will be probed first. This option + forces FlashPoint Host Adapters to be probed first. + + Debug Sets all the tracing bits in BusLogic_GlobalOptions. - NoSortPCI PCI Host Adapters will be enumerated in the order - provided by the PCI BIOS, ignoring any setting of - the AutoSCSI "Use Bus And Device # For PCI Scanning - Seq." option. */ void BusLogic_Setup(char *Strings, int *Integers) { BusLogic_CommandLineEntry_T *CommandLineEntry = &BusLogic_CommandLineEntries[BusLogic_CommandLineEntryCount++]; - static int ProbeListIndex = 0; int IntegerCount = Integers[0]; int TargetID, i; CommandLineEntry->IO_Address = 0; CommandLineEntry->TaggedQueueDepth = 0; CommandLineEntry->BusSettleTime = 0; - CommandLineEntry->LocalOptions = 0; CommandLineEntry->TaggedQueuingPermitted = 0; CommandLineEntry->TaggedQueuingPermittedMask = 0; + CommandLineEntry->LocalOptions.All = 0; memset(CommandLineEntry->ErrorRecoveryStrategy, BusLogic_ErrorRecovery_Default, sizeof(CommandLineEntry->ErrorRecoveryStrategy)); if (IntegerCount > 5) - printk("BusLogic: Unexpected Command Line Integers ignored\n"); + BusLogic_Error("BusLogic: Unexpected Command Line Integers " + "ignored\n", NULL); if (IntegerCount >= 1) { - unsigned int IO_Address = Integers[1]; + BusLogic_IO_Address_T IO_Address = Integers[1]; if (IO_Address > 0) { + BusLogic_ProbeInfo_T *ProbeInfo; for (i = 0; ; i++) - if (BusLogic_IO_StandardAddresses[i] == 0) + if (BusLogic_ISA_StandardAddresses[i] == 0) { - printk("BusLogic: Invalid Command Line Entry " - "(illegal I/O Address 0x%X)\n", IO_Address); + BusLogic_Error("BusLogic: Invalid Command Line Entry " + "(illegal I/O Address 0x%X)\n", + NULL, IO_Address); return; } - else if (i < ProbeListIndex && - IO_Address == BusLogic_IO_AddressProbeList[i]) + else if (i < BusLogic_ProbeInfoCount && + IO_Address == BusLogic_ProbeInfoList[i].IO_Address) { - printk("BusLogic: Invalid Command Line Entry " - "(duplicate I/O Address 0x%X)\n", IO_Address); + BusLogic_Error("BusLogic: Invalid Command Line Entry " + "(duplicate I/O Address 0x%X)\n", + NULL, IO_Address); return; } else if (IO_Address >= 0x400 || - IO_Address == BusLogic_IO_StandardAddresses[i]) break; - BusLogic_IO_AddressProbeList[ProbeListIndex++] = IO_Address; - BusLogic_IO_AddressProbeList[ProbeListIndex] = 0; + IO_Address == BusLogic_ISA_StandardAddresses[i]) break; + ProbeInfo = &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount++]; + ProbeInfo->HostAdapterType = BusLogic_MultiMaster; + ProbeInfo->HostAdapterBusType = BusLogic_ISA_Bus; } CommandLineEntry->IO_Address = IO_Address; } @@ -3318,8 +4499,9 @@ unsigned short TaggedQueueDepth = Integers[2]; if (TaggedQueueDepth > BusLogic_MaxTaggedQueueDepth) { - printk("BusLogic: Invalid Command Line Entry " - "(illegal Tagged Queue Depth %d)\n", TaggedQueueDepth); + BusLogic_Error("BusLogic: Invalid Command Line Entry " + "(illegal Tagged Queue Depth %d)\n", + NULL, TaggedQueueDepth); return; } CommandLineEntry->TaggedQueueDepth = TaggedQueueDepth; @@ -3327,131 +4509,154 @@ if (IntegerCount >= 3) CommandLineEntry->BusSettleTime = Integers[3]; if (IntegerCount >= 4) - CommandLineEntry->LocalOptions = Integers[4]; + CommandLineEntry->LocalOptions.All = Integers[4]; if (IntegerCount >= 5) - BusLogic_GlobalOptions |= Integers[5]; - if (!(BusLogic_CommandLineEntryCount == 0 || ProbeListIndex == 0 || - BusLogic_CommandLineEntryCount == ProbeListIndex)) + BusLogic_GlobalOptions.All |= Integers[5]; + if (!(BusLogic_CommandLineEntryCount == 0 || + BusLogic_ProbeInfoCount == 0 || + BusLogic_CommandLineEntryCount == BusLogic_ProbeInfoCount)) { - printk("BusLogic: Invalid Command Line Entry " - "(all or no I/O Addresses must be specified)\n"); + BusLogic_Error("BusLogic: Invalid Command Line Entry " + "(all or no I/O Addresses must be specified)\n", NULL); return; } if (Strings == NULL) return; while (*Strings != '\0') - { - 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_MaxTargetDevices; 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_MaxTargetDevices; - break; - } - } - else if (strncmp(Strings, "ER:", 3) == 0) - { - Strings += 3; - if (strncmp(Strings, "Default", 7) == 0) + 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; - else if (strncmp(Strings, "HardReset", 9) == 0) - { - Strings += 9; - memset(CommandLineEntry->ErrorRecoveryStrategy, - BusLogic_ErrorRecovery_HardReset, - sizeof(CommandLineEntry->ErrorRecoveryStrategy)); - } - else if (strncmp(Strings, "BusDeviceReset", 14) == 0) - { - Strings += 14; - memset(CommandLineEntry->ErrorRecoveryStrategy, - BusLogic_ErrorRecovery_BusDeviceReset, - sizeof(CommandLineEntry->ErrorRecoveryStrategy)); - } - else if (strncmp(Strings, "None", 4) == 0) - { - Strings += 4; - memset(CommandLineEntry->ErrorRecoveryStrategy, - BusLogic_ErrorRecovery_None, - sizeof(CommandLineEntry->ErrorRecoveryStrategy)); - } - else - for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; TargetID++) - switch (*Strings++) - { - case 'D': - CommandLineEntry->ErrorRecoveryStrategy[TargetID] = - BusLogic_ErrorRecovery_Default; - break; - case 'H': - CommandLineEntry->ErrorRecoveryStrategy[TargetID] = - BusLogic_ErrorRecovery_HardReset; - break; - case 'B': - CommandLineEntry->ErrorRecoveryStrategy[TargetID] = - BusLogic_ErrorRecovery_BusDeviceReset; - break; - case 'N': - CommandLineEntry->ErrorRecoveryStrategy[TargetID] = - BusLogic_ErrorRecovery_None; - break; - default: - Strings--; - TargetID = BusLogic_MaxTargetDevices; - break; - } - } - else if (strcmp(Strings, "NoProbe") == 0 || - strcmp(Strings, "noprobe") == 0) - { + CommandLineEntry->TaggedQueuingPermitted = 0x0000; + CommandLineEntry->TaggedQueuingPermittedMask = 0xFFFF; + } + else + for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; 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_MaxTargetDevices; + break; + } + } + else if (strncmp(Strings, "ER:", 3) == 0) + { + Strings += 3; + if (strncmp(Strings, "Default", 7) == 0) Strings += 7; - BusLogic_ProbeOptions |= BusLogic_NoProbe; - } - else if (strncmp(Strings, "NoProbeISA", 10) == 0) - { - Strings += 10; - BusLogic_ProbeOptions |= BusLogic_NoProbeISA; - } - else if (strncmp(Strings, "NoSortPCI", 9) == 0) - { - Strings += 9; - BusLogic_ProbeOptions |= BusLogic_NoSortPCI; - } - else - { - printk("BusLogic: Unexpected Command Line String '%s' ignored\n", - Strings); - break; - } - if (*Strings == ',') Strings++; - } + else if (strncmp(Strings, "HardReset", 9) == 0) + { + Strings += 9; + memset(CommandLineEntry->ErrorRecoveryStrategy, + BusLogic_ErrorRecovery_HardReset, + sizeof(CommandLineEntry->ErrorRecoveryStrategy)); + } + else if (strncmp(Strings, "BusDeviceReset", 14) == 0) + { + Strings += 14; + memset(CommandLineEntry->ErrorRecoveryStrategy, + BusLogic_ErrorRecovery_BusDeviceReset, + sizeof(CommandLineEntry->ErrorRecoveryStrategy)); + } + else if (strncmp(Strings, "None", 4) == 0) + { + Strings += 4; + memset(CommandLineEntry->ErrorRecoveryStrategy, + BusLogic_ErrorRecovery_None, + sizeof(CommandLineEntry->ErrorRecoveryStrategy)); + } + else + for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; TargetID++) + switch (*Strings++) + { + case 'D': + CommandLineEntry->ErrorRecoveryStrategy[TargetID] = + BusLogic_ErrorRecovery_Default; + break; + case 'H': + CommandLineEntry->ErrorRecoveryStrategy[TargetID] = + BusLogic_ErrorRecovery_HardReset; + break; + case 'B': + CommandLineEntry->ErrorRecoveryStrategy[TargetID] = + BusLogic_ErrorRecovery_BusDeviceReset; + break; + case 'N': + CommandLineEntry->ErrorRecoveryStrategy[TargetID] = + BusLogic_ErrorRecovery_None; + break; + default: + Strings--; + TargetID = BusLogic_MaxTargetDevices; + break; + } + } + else if (strcmp(Strings, "NoProbe") == 0 || + strcmp(Strings, "noprobe") == 0) + { + Strings += 7; + BusLogic_ProbeOptions.Bits.NoProbe = true; + } + else if (strncmp(Strings, "NoProbeISA", 10) == 0) + { + Strings += 10; + BusLogic_ProbeOptions.Bits.NoProbeISA = true; + } + else if (strncmp(Strings, "NoProbePCI", 10) == 0) + { + Strings += 10; + BusLogic_ProbeOptions.Bits.NoProbePCI = true; + } + else if (strncmp(Strings, "NoSortPCI", 9) == 0) + { + Strings += 9; + BusLogic_ProbeOptions.Bits.NoSortPCI = true; + } + else if (strncmp(Strings, "MultiMasterFirst", 16) == 0) + { + Strings += 16; + BusLogic_ProbeOptions.Bits.ProbeMultiMasterFirst = true; + } + else if (strncmp(Strings, "FlashPointFirst", 15) == 0) + { + Strings += 15; + BusLogic_ProbeOptions.Bits.ProbeFlashPointFirst = true; + } + else if (strncmp(Strings, "Debug", 5) == 0) + { + Strings += 5; + BusLogic_GlobalOptions.Bits.TraceProbe = true; + BusLogic_GlobalOptions.Bits.TraceHardReset = true; + BusLogic_GlobalOptions.Bits.TraceConfiguration = true; + BusLogic_GlobalOptions.Bits.TraceErrors = true; + } + else if (*Strings == ',') + Strings++; + else + { + BusLogic_Error("BusLogic: Unexpected Command Line String '%s' " + "ignored\n", NULL, Strings); + break; + } } diff -u --recursive --new-file v2.1.27/linux/drivers/scsi/BusLogic.h linux/drivers/scsi/BusLogic.h --- v2.1.27/linux/drivers/scsi/BusLogic.h Mon Oct 28 03:39:05 1996 +++ linux/drivers/scsi/BusLogic.h Sun Feb 23 16:14:00 1997 @@ -1,6 +1,6 @@ /* - Linux Driver for BusLogic MultiMaster SCSI Host Adapters + Linux Driver for BusLogic MultiMaster and FlashPoint SCSI Host Adapters Copyright 1995 by Leonard N. Zubkoff @@ -17,9 +17,12 @@ The author respectfully requests that any modifications to this software be sent directly to him for evaluation and testing. - Special thanks to Wayne Yen and Alex Win of BusLogic, whose advice has been - invaluable, to David Gentzel, for writing the original Linux BusLogic driver, - and to Paul Gortmaker, for being such a dedicated test site. + Special thanks to Wayne Yen, Jin-Lon Hon, and Alex Win of BusLogic, whose + advice has been invaluable, to David Gentzel, for writing the original Linux + BusLogic driver, and to Paul Gortmaker, for being such a dedicated test site. + + Finally, special thanks to Mylex/BusLogic for making the FlashPoint SCCB + Manager available as freely redistributable source code. */ @@ -29,6 +32,8 @@ of the Linux Kernel and SCSI Subsystem. */ +typedef kdev_t KernelDevice_T; +typedef struct proc_dir_entry PROC_DirectoryEntry_T; typedef struct pt_regs Registers_T; typedef Scsi_Host_Template SCSI_Host_Template_T; typedef struct Scsi_Host SCSI_Host_T; @@ -36,21 +41,22 @@ 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 *, unsigned int); -int BusLogic_BIOSDiskParameters(SCSI_Disk_T *, KernelDevice_T, int *); +extern PROC_DirectoryEntry_T BusLogic_ProcDirectoryEntry; +extern const char *BusLogic_DriverInfo(SCSI_Host_T *); +extern int BusLogic_DetectHostAdapter(SCSI_Host_Template_T *); +extern int BusLogic_ReleaseHostAdapter(SCSI_Host_T *); +extern int BusLogic_QueueCommand(SCSI_Command_T *, + void (*CompletionRoutine)(SCSI_Command_T *)); +extern int BusLogic_AbortCommand(SCSI_Command_T *); +extern int BusLogic_ResetCommand(SCSI_Command_T *, unsigned int); +extern int BusLogic_BIOSDiskParameters(SCSI_Disk_T *, KernelDevice_T, int *); +extern int BusLogic_ProcDirectoryInfo(char *, char **, off_t, int, int, int); /* @@ -58,26 +64,26 @@ */ #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 */ \ + { NULL, /* Next */ \ + NULL, /* Usage Count Pointer */ \ + &BusLogic_ProcDirectoryEntry, /* /proc Directory Entry */ \ + BusLogic_ProcDirectoryInfo, /* /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, /* BIOS Disk 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 */ @@ -89,17 +95,10 @@ /* - 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 the maximum number of BusLogic Host Adapters supported by this driver. */ -#define BusLogic_IO_MaxProbeAddresses 16 +#define BusLogic_MaxHostAdapters 16 /* @@ -112,7 +111,7 @@ /* Define the maximum number of Scatter/Gather Segments used by this driver. For optimal performance, it is important that this limit be at least as - large as the maximum single request generated by the I/O Subsystem. + large as the largest single request generated by the I/O Subsystem. */ #define BusLogic_ScatterGatherLimit 128 @@ -126,7 +125,8 @@ #define BusLogic_MaxTaggedQueueDepth 63 #define BusLogic_PreferredTaggedQueueDepth 28 -#define BusLogic_TaggedQueueDepth_BB 2 +#define BusLogic_TaggedQueueDepthBounceBuffers 2 +#define BusLogic_TaggedQueueDepthAutomatic 0 #define BusLogic_UntaggedQueueDepth 3 @@ -141,122 +141,334 @@ /* - Define the possible Probe Options. + Define the Host Adapter Line and Message Buffer Sizes. */ -#define BusLogic_NoProbe 1 -#define BusLogic_NoProbeISA 2 -#define BusLogic_NoSortPCI 4 +#define BusLogic_LineBufferSize 100 +#define BusLogic_MessageBufferSize 8900 /* - Define the possible Local Options. + Define the Driver Message Levels. */ -#define BusLogic_InhibitTargetInquiry 1 +typedef enum BusLogic_MessageLevel +{ + BusLogic_AnnounceLevel = 0, + BusLogic_InfoLevel = 1, + BusLogic_NoticeLevel = 2, + BusLogic_WarningLevel = 3, + BusLogic_ErrorLevel = 4 +} +BusLogic_MessageLevel_T; + +static char + *BusLogic_MessageLevelMap[] = + { KERN_INFO, KERN_INFO, KERN_NOTICE, KERN_WARNING, KERN_ERR }; /* - Define the possible Global Options. + Define the types of BusLogic Host Adapters that are supported and the number + of I/O Addresses required by each type. */ -#define BusLogic_TraceProbe 1 -#define BusLogic_TraceHardReset 2 -#define BusLogic_TraceConfiguration 4 -#define BusLogic_TraceErrors 8 -#define BusLogic_TraceQueueDepths 16 +typedef enum +{ + BusLogic_MultiMaster = 1, + BusLogic_FlashPoint = 2 +} +__attribute__ ((packed)) +BusLogic_HostAdapterType_T; + +#define BusLogic_MultiMasterAddressCount 4 +#define BusLogic_FlashPointAddressCount 256 + +static int + BusLogic_HostAdapter_AddressCount[3] = + { 0, BusLogic_MultiMasterAddressCount, BusLogic_FlashPointAddressCount }; /* - Define the possible Error Recovery Strategy Options. + Define the possible Host Adapter Bus Types. */ -#define BusLogic_ErrorRecovery_Default 0 -#define BusLogic_ErrorRecovery_HardReset 1 -#define BusLogic_ErrorRecovery_BusDeviceReset 2 -#define BusLogic_ErrorRecovery_None 3 +typedef enum +{ + BusLogic_Unknown_Bus = 0, + BusLogic_ISA_Bus = 1, + BusLogic_EISA_Bus = 2, + BusLogic_PCI_Bus = 3, + BusLogic_VESA_Bus = 4, + BusLogic_MCA_Bus = 5 +} +BusLogic_HostAdapterBusType_T; static char - *BusLogic_ErrorRecoveryStrategyNames[] = - { "Default", "Hard Reset", "Bus Device Reset", "None" }, - *BusLogic_ErrorRecoveryStrategyLetters[] = - { "D", "H", "B", "N" }; + *BusLogic_HostAdapterBusNames[] = + { "Unknown", "ISA", "EISA", "PCI", "VESA", "MCA" }; + +static BusLogic_HostAdapterBusType_T + BusLogic_HostAdapterBusTypes[] = + { BusLogic_VESA_Bus, /* BT-4xx */ + BusLogic_ISA_Bus, /* BT-5xx */ + BusLogic_MCA_Bus, /* BT-6xx */ + BusLogic_EISA_Bus, /* BT-7xx */ + BusLogic_Unknown_Bus, /* BT-8xx */ + BusLogic_PCI_Bus }; /* BT-9xx */ /* - Define a boolean data type. + Define the possible Host Adapter BIOS Disk Geometry Translations. */ -#define false 0 -#define true 1 -typedef unsigned char boolean; +typedef enum BusLogic_BIOS_DiskGeometryTranslation +{ + BusLogic_BIOS_Disk_Not_Installed = 0, + BusLogic_BIOS_Disk_Installed_64x32 = 1, + BusLogic_BIOS_Disk_Installed_128x32 = 2, + BusLogic_BIOS_Disk_Installed_255x63 = 3 +} +__attribute__ ((packed)) +BusLogic_BIOS_DiskGeometryTranslation_T; /* - Define a 32 bit bus address data type. + Define a Boolean data type. */ -typedef unsigned int bus_address_t; +typedef enum { false, true } __attribute__ ((packed)) boolean; + + +/* + Define a 32 bit I/O Address data type. +*/ + +typedef unsigned int BusLogic_IO_Address_T; + + +/* + Define a 32 bit PCI Bus Address data type. +*/ + +typedef unsigned int BusLogic_PCI_Address_T; + + +/* + Define a 32 bit Bus Address data type. +*/ + +typedef unsigned int BusLogic_BusAddress_T; + + +/* + Define a 32 bit Byte Count data type. +*/ + +typedef unsigned int BusLogic_ByteCount_T; + + +/* + Define a 10^18 Statistics Byte Counter data type. +*/ + +typedef struct BusLogic_ByteCounter +{ + unsigned int Units; + unsigned int Billions; +} +BusLogic_ByteCounter_T; + + +/* + Define the structure for I/O Address and Bus Probing Information. +*/ + +typedef struct BusLogic_ProbeInfo +{ + BusLogic_IO_Address_T IO_Address; + BusLogic_PCI_Address_T PCI_Address; + BusLogic_HostAdapterType_T HostAdapterType:2; + BusLogic_HostAdapterBusType_T HostAdapterBusType:3; + unsigned char :3; + unsigned char Bus; + unsigned char Device; + unsigned char IRQ_Channel; +} +BusLogic_ProbeInfo_T; + + +/* + BusLogic_ISA_StandardAddresses is the list of standard ISA I/O Addresses at + which BusLogic MultiMaster Host Adapters may potentially be found. The first + I/O Address 0x330 is known as the "Primary" I/O Address. A Host Adapter + configured to use the Primary I/O Address will always be the preferred boot + device. +*/ + +#define BusLogic_ISA_StandardAddressesCount 6 + +static BusLogic_IO_Address_T + BusLogic_ISA_StandardAddresses[BusLogic_ISA_StandardAddressesCount] = + { 0x330, 0x334, 0x230, 0x234, 0x130, 0x134 }; + + +/* + Define the Probe Options. +*/ + +typedef union BusLogic_ProbeOptions +{ + unsigned short All; + struct { + boolean NoProbe:1; /* Bit 0 */ + boolean NoProbeISA:1; /* Bit 1 */ + boolean NoProbePCI:1; /* Bit 2 */ + boolean NoSortPCI:1; /* Bit 3 */ + boolean ProbeMultiMasterFirst:1; /* Bit 4 */ + boolean ProbeFlashPointFirst:1; /* Bit 5 */ + } Bits; +} +BusLogic_ProbeOptions_T; + + +/* + Define the Global Options. +*/ + +typedef union BusLogic_GlobalOptions +{ + unsigned short All; + struct { + boolean TraceProbe:1; /* Bit 0 */ + boolean TraceHardReset:1; /* Bit 1 */ + boolean TraceConfiguration:1; /* Bit 2 */ + boolean TraceErrors:1; /* Bit 3 */ + } Bits; +} +BusLogic_GlobalOptions_T; + + +/* + Define the Local Options. +*/ + +typedef union BusLogic_LocalOptions +{ + unsigned short All; + struct { + boolean InhibitTargetInquiry:1; /* Bit 0 */ + boolean InhibitInterruptTest:1; /* Bit 1 */ + } Bits; +} +BusLogic_LocalOptions_T; + + +/* + Define the Error Recovery Strategy Options. +*/ + +typedef enum +{ + BusLogic_ErrorRecovery_Default = 0, + BusLogic_ErrorRecovery_BusDeviceReset = 1, + BusLogic_ErrorRecovery_HardReset = 2, + BusLogic_ErrorRecovery_None = 3 +} +__attribute__ ((packed)) +BusLogic_ErrorRecoveryStrategy_T; + +static char + *BusLogic_ErrorRecoveryStrategyNames[] = + { "Default", "Bus Device Reset", "Hard Reset", "None" }, + BusLogic_ErrorRecoveryStrategyLetters[] = + { 'D', 'B', 'H', 'N' }; /* 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 register */ +#define BusLogic_ControlRegisterOffset 0 /* WO register */ +#define BusLogic_StatusRegisterOffset 0 /* RO register */ +#define BusLogic_CommandParameterRegisterOffset 1 /* WO register */ +#define BusLogic_DataInRegisterOffset 1 /* RO register */ +#define BusLogic_InterruptRegisterOffset 2 /* RO register */ +#define BusLogic_GeometryRegisterOffset 3 /* RO register */ /* - Define the bits in the write-only Control Register. + Define the structure of 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 +typedef union BusLogic_ControlRegister +{ + unsigned char All; + struct { + unsigned char :4; /* Bits 0-3 */ + boolean SCSIBusReset:1; /* Bit 4 */ + boolean InterruptReset:1; /* Bit 5 */ + boolean SoftReset:1; /* Bit 6 */ + boolean HardReset:1; /* Bit 7 */ + } Bits; +} +BusLogic_ControlRegister_T; /* - Define the bits in the read-only Status Register. + Define the structure of 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 +typedef union BusLogic_StatusRegister +{ + unsigned char All; + struct { + boolean CommandInvalid:1; /* Bit 0 */ + boolean Reserved:1; /* Bit 1 */ + boolean DataInRegisterReady:1; /* Bit 2 */ + boolean CommandParameterRegisterBusy:1; /* Bit 3 */ + boolean HostAdapterReady:1; /* Bit 4 */ + boolean InitializationRequired:1; /* Bit 5 */ + boolean DiagnosticFailure:1; /* Bit 6 */ + boolean DiagnosticActive:1; /* Bit 7 */ + } Bits; +} +BusLogic_StatusRegister_T; /* - Define the bits in the read-only Interrupt Register. + Define the structure of 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 +typedef union BusLogic_InterruptRegister +{ + unsigned char All; + struct { + boolean IncomingMailboxLoaded:1; /* Bit 0 */ + boolean OutgoingMailboxAvailable:1; /* Bit 1 */ + boolean CommandComplete:1; /* Bit 2 */ + boolean ExternalBusReset:1; /* Bit 3 */ + unsigned char Reserved:3; /* Bits 4-6 */ + boolean InterruptValid:1; /* Bit 7 */ + } Bits; +} +BusLogic_InterruptRegister_T; /* - Define the bits in the read-only Geometry Register. + Define the structure of the read-only Geometry Register. */ -#define BusLogic_Drive0Geometry 0x03 -#define BusLogic_Drive1Geometry 0x0C -#define BusLogic_ReservedGR 0x70 -#define BusLogic_ExtendedTranslationEnabled 0x80 +typedef union BusLogic_GeometryRegister +{ + unsigned char All; + struct { + BusLogic_BIOS_DiskGeometryTranslation_T Drive0Geometry:2; /* Bits 0-1 */ + BusLogic_BIOS_DiskGeometryTranslation_T Drive1Geometry:2; /* Bits 2-3 */ + unsigned char :3; /* Bits 4-6 */ + boolean ExtendedTranslationEnabled:1; /* Bit 7 */ + } Bits; +} +BusLogic_GeometryRegister_T; /* @@ -293,8 +505,8 @@ BusLogic_ExecuteSCSICommand = 0x83, BusLogic_InquireFirmwareVersion3rdDigit = 0x84, BusLogic_InquireFirmwareVersionLetter = 0x85, - BusLogic_InquireGenericIOPortInformation = 0x86, - BusLogic_InquireControllerModelNumber = 0x8B, + BusLogic_InquirePCIHostAdapterInformation = 0x86, + BusLogic_InquireHostAdapterModelNumber = 0x8B, BusLogic_InquireSynchronousPeriod = 0x8C, BusLogic_InquireExtendedSetupInformation = 0x8D, BusLogic_EnableStrictRoundRobinMode = 0x8F, @@ -341,7 +553,7 @@ Define the Inquire Target Devices reply type. Inquire Target Devices only tests Logical Unit 0 of each Target Device unlike the Inquire Installed Devices commands which test Logical Units 0 - 7. Two bytes are returned, - where bit 0 set indicates that Target Device 0 exists, and so on. + where byte 0 bit 0 set indicates that Target Device 0 exists, and so on. */ typedef unsigned short BusLogic_InstalledDevices_T; @@ -392,7 +604,7 @@ typedef struct BusLogic_SetupInformation { boolean SynchronousInitiationEnabled:1; /* Byte 0 Bit 0 */ - boolean ParityCheckEnabled:1; /* Byte 0 Bit 1 */ + boolean ParityCheckingEnabled:1; /* Byte 0 Bit 1 */ unsigned char :6; /* Byte 0 Bits 2-7 */ unsigned char BusTransferRate; /* Byte 1 */ unsigned char PreemptTimeOnBus; /* Byte 2 */ @@ -419,8 +631,9 @@ typedef struct BusLogic_ExtendedMailboxRequest { unsigned char MailboxCount; /* Byte 0 */ - bus_address_t BaseMailboxAddress __attribute__ ((packed)); /* Bytes 1-4 */ + BusLogic_BusAddress_T BaseMailboxAddress; /* Bytes 1-4 */ } +__attribute__ ((packed)) BusLogic_ExtendedMailboxRequest_T; @@ -439,12 +652,28 @@ /* - Define the Inquire Generic I/O Port Information reply type. + Define the Inquire PCI Host Adapter Information reply type. The ISA + Compatible I/O Port values are defined here and are also used with + the Modify I/O Address command. */ -typedef struct BusLogic_GenericIOPortInformation +typedef enum BusLogic_ISACompatibleIOPort { - unsigned char ISACompatibleIOPort; /* Byte 0 */ + BusLogic_IO_330 = 0, + BusLogic_IO_334 = 1, + BusLogic_IO_230 = 2, + BusLogic_IO_234 = 3, + BusLogic_IO_130 = 4, + BusLogic_IO_134 = 5, + BusLogic_IO_Disable = 6, + BusLogic_IO_Disable2 = 7 +} +__attribute__ ((packed)) +BusLogic_ISACompatibleIOPort_T; + +typedef struct BusLogic_PCIHostAdapterInformation +{ + BusLogic_ISACompatibleIOPort_T ISACompatibleIOPort; /* Byte 0 */ unsigned char PCIAssignedIRQChannel; /* Byte 1 */ boolean LowByteTerminated:1; /* Byte 2 Bit 0 */ boolean HighByteTerminated:1; /* Byte 2 Bit 1 */ @@ -452,17 +681,17 @@ boolean JP1:1; /* Byte 2 Bit 4 */ boolean JP2:1; /* Byte 2 Bit 5 */ boolean JP3:1; /* Byte 2 Bit 6 */ - boolean Valid:1; /* Byte 2 Bit 7 */ + boolean GenericInfoValid:1; /* Byte 2 Bit 7 */ unsigned char :8; /* Byte 3 */ } -BusLogic_GenericIOPortInformation_T; +BusLogic_PCIHostAdapterInformation_T; /* - Define the Inquire Controller Model Number reply type. + Define the Inquire Host Adapter Model Number reply type. */ -typedef unsigned char BusLogic_ControllerModelNumber_T[5]; +typedef unsigned char BusLogic_HostAdapterModelNumber_T[5]; /* @@ -484,18 +713,21 @@ unsigned char BIOS_Address; /* Byte 1 */ unsigned short ScatterGatherLimit; /* Bytes 2-3 */ unsigned char MailboxCount; /* Byte 4 */ - bus_address_t BaseMailboxAddress __attribute__ ((packed)); /* Bytes 5-8 */ - struct { unsigned char :6; /* Byte 9 Bits 0-5 */ - boolean LevelSensitiveInterrupts:1; /* Byte 9 Bit 6 */ + BusLogic_BusAddress_T BaseMailboxAddress; /* Bytes 5-8 */ + struct { unsigned char :2; /* Byte 9 Bits 0-1 */ + boolean FastOnEISA:1; /* Byte 9 Bit 2 */ + unsigned char :3; /* Byte 9 Bits 3-5 */ + boolean LevelSensitiveInterrupt:1; /* Byte 9 Bit 6 */ unsigned char :1; } Misc; /* Byte 9 Bit 7 */ unsigned char FirmwareRevision[3]; /* Bytes 10-12 */ boolean HostWideSCSI:1; /* Byte 13 Bit 0 */ boolean HostDifferentialSCSI:1; /* Byte 13 Bit 1 */ - boolean HostAutomaticConfiguration:1; /* Byte 13 Bit 2 */ + boolean HostSupportsSCAM:1; /* Byte 13 Bit 2 */ boolean HostUltraSCSI:1; /* Byte 13 Bit 3 */ boolean HostSmartTermination:1; /* Byte 13 Bit 4 */ unsigned char :3; /* Byte 13 Bits 5-7 */ } +__attribute__ ((packed)) BusLogic_ExtendedSetupInformation_T; @@ -503,10 +735,13 @@ Define the Enable Strict Round Robin Mode request type. */ -#define BusLogic_AggressiveRoundRobinMode 0x00 -#define BusLogic_StrictRoundRobinMode 0x01 - -typedef unsigned char BusLogic_RoundRobinModeRequest_T; +typedef enum BusLogic_RoundRobinModeRequest +{ + BusLogic_AggressiveRoundRobinMode = 0, + BusLogic_StrictRoundRobinMode = 1 +} +__attribute__ ((packed)) +BusLogic_RoundRobinModeRequest_T; /* @@ -525,21 +760,86 @@ /* - Define the Host Adapter Local RAM Auto SCSI Byte 15 reply structure. + Define the Host Adapter Local RAM AutoSCSI structure. */ -typedef struct BusLogic_AutoSCSIByte15 +typedef struct BusLogic_AutoSCSIData { - unsigned char LowByteTerminated:1; /* Bit 0 */ - unsigned char :1; /* Bit 1 */ - unsigned char HighByteTerminated:1; /* Bit 2 */ - unsigned char :5; /* Bits 3-7 */ + unsigned char InternalFactorySignature[2]; /* Bytes 0-1 */ + unsigned char InformationByteCount; /* Byte 2 */ + unsigned char HostAdapterType[6]; /* Bytes 3-8 */ + unsigned char :8; /* Byte 9 */ + boolean FloppyEnabled:1; /* Byte 10 Bit 0 */ + boolean FloppySecondary:1; /* Byte 10 Bit 1 */ + boolean LevelSensitiveInterrupt:1; /* Byte 10 Bit 2 */ + unsigned char :2; /* Byte 10 Bits 3-4 */ + unsigned char SystemRAMAreaForBIOS:3; /* Byte 10 Bits 5-7 */ + unsigned char DMA_Channel:7; /* Byte 11 Bits 0-6 */ + boolean DMA_AutoConfiguration:1; /* Byte 11 Bit 7 */ + unsigned char IRQ_Channel:7; /* Byte 12 Bits 0-6 */ + boolean IRQ_AutoConfiguration:1; /* Byte 12 Bit 7 */ + unsigned char DMA_TransferRate; /* Byte 13 */ + unsigned char SCSI_ID; /* Byte 14 */ + boolean LowByteTerminated:1; /* Byte 15 Bit 0 */ + boolean ParityCheckingEnabled:1; /* Byte 15 Bit 1 */ + boolean HighByteTerminated:1; /* Byte 15 Bit 2 */ + boolean NoisyCablingEnvironment:1; /* Byte 15 Bit 3 */ + boolean FastSynchronousNegotiation:1; /* Byte 15 Bit 4 */ + boolean BusResetEnabled:1; /* Byte 15 Bit 5 */ + boolean :1; /* Byte 15 Bit 6 */ + boolean ActiveNegationEnabled:1; /* Byte 15 Bit 7 */ + unsigned char BusOnDelay; /* Byte 16 */ + unsigned char BusOffDelay; /* Byte 17 */ + boolean HostAdapterBIOSEnabled:1; /* Byte 18 Bit 0 */ + boolean BIOSRedirectionOfINT19Enabled:1; /* Byte 18 Bit 1 */ + boolean ExtendedTranslationEnabled:1; /* Byte 18 Bit 2 */ + boolean MapRemovableAsFixedEnabled:1; /* Byte 18 Bit 3 */ + boolean :1; /* Byte 18 Bit 4 */ + boolean BIOSSupportsMoreThan2DrivesEnabled:1; /* Byte 18 Bit 5 */ + boolean BIOSInterruptModeEnabled:1; /* Byte 18 Bit 6 */ + boolean FlopticalSupportEnabled:1; /* Byte 19 Bit 7 */ + unsigned short DeviceEnabled; /* Bytes 19-20 */ + unsigned short WidePermitted; /* Bytes 21-22 */ + unsigned short FastPermitted; /* Bytes 23-24 */ + unsigned short SynchronousPermitted; /* Bytes 25-26 */ + unsigned short DisconnectPermitted; /* Bytes 27-28 */ + unsigned short SendStartUnitCommand; /* Bytes 29-30 */ + unsigned short IgnoreInBIOSScan; /* Bytes 31-32 */ + unsigned char PCIInterruptPin:2; /* Byte 33 Bits 0-1 */ + unsigned char HostAdapterIOPortAddress:2; /* Byte 33 Bits 2-3 */ + boolean StrictRoundRobinModeEnabled:1; /* Byte 33 Bit 4 */ + boolean VESABusSpeedGreaterThan33MHz:1; /* Byte 33 Bit 5 */ + boolean VESABurstWriteEnabled:1; /* Byte 33 Bit 6 */ + boolean VESABurstReadEnabled:1; /* Byte 33 Bit 7 */ + unsigned short UltraPermitted; /* Bytes 34-35 */ + unsigned int :32; /* Bytes 36-39 */ + unsigned char :8; /* Byte 40 */ + unsigned char AutoSCSIMaximumLUN; /* Byte 41 */ + boolean :1; /* Byte 42 Bit 0 */ + boolean SCAM_Dominant:1; /* Byte 42 Bit 1 */ + boolean SCAM_Enabled:1; /* Byte 42 Bit 2 */ + boolean SCAM_Level2:1; /* Byte 42 Bit 3 */ + unsigned char :4; /* Byte 42 Bits 4-7 */ + boolean INT13ExtensionEnabled:1; /* Byte 43 Bit 0 */ + boolean :1; /* Byte 43 Bit 1 */ + boolean CDROMBootEnabled:1; /* Byte 43 Bit 2 */ + unsigned char :5; /* Byte 43 Bits 3-7 */ + unsigned char BootTargetID:4; /* Byte 44 Bits 0-3 */ + unsigned char BootChannel:4; /* Byte 44 Bits 4-7 */ + unsigned char ForceBusDeviceScanningOrder:1; /* Byte 45 Bit 0 */ + unsigned char :7; /* Byte 45 Bits 1-7 */ + unsigned short NonTaggedToAlternateLUNPermitted; /* Bytes 46-47 */ + unsigned short RenegotiateSyncAfterCheckCondition; /* Bytes 48-49 */ + unsigned char Reserved[10]; /* Bytes 50-59 */ + unsigned char ManufacturingDiagnostic[2]; /* Bytes 60-61 */ + unsigned short Checksum; /* Bytes 62-63 */ } -BusLogic_AutoSCSIByte15_T; +__attribute__ ((packed)) +BusLogic_AutoSCSIData_T; /* - Define the Host Adapter Local RAM Auto SCSI Byte 45 reply structure. + Define the Host Adapter Local RAM Auto SCSI Byte 45 structure. */ typedef struct BusLogic_AutoSCSIByte45 @@ -551,39 +851,48 @@ /* + Define the Host Adapter Local RAM BIOS Drive Map Byte structure. +*/ + +#define BusLogic_BIOS_DriveMapOffset 17 + +typedef struct BusLogic_BIOSDriveMapByte +{ + unsigned char TargetIDBit3:1; /* Bit 0 */ + unsigned char :2; /* Bits 1-2 */ + BusLogic_BIOS_DiskGeometryTranslation_T DiskGeometry:2; /* Bits 3-4 */ + unsigned char TargetID:3; /* Bits 5-7 */ +} +BusLogic_BIOSDriveMapByte_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; +typedef BusLogic_ISACompatibleIOPort_T BusLogic_ModifyIOAddressRequest_T; /* - Define the Set CCB Format request type. 64 LUN Format CCBs are necessary to - support 64 Logical Units per Target Device. 8 LUN Format CCBs only support 8 - Logical Units per Target Device. + Define the Set CCB Format request type. Extended LUN Format CCBs are + necessary to support more than 8 Logical Units per Target Device. */ -#define BusLogic_8LUNFormatCCB 0x00 -#define BusLogic_64LUNFormatCCB 0x01 - -typedef unsigned char BusLogic_SetCCBFormatRequest_T; +typedef enum BusLogic_SetCCBFormatRequest +{ + BusLogic_LegacyLUNFormatCCB = 0, + BusLogic_ExtendedLUNFormatCCB = 1 +} +__attribute__ ((packed)) +BusLogic_SetCCBFormatRequest_T; /* Define the Requested Reply Length type used by the Inquire Setup Information, - Inquire Controller Model Number, Inquire Synchronous Period, and Inquire + Inquire Host Adapter Model Number, Inquire Synchronous Period, and Inquire Extended Setup Information commands. */ @@ -591,10 +900,10 @@ /* - Define a Lock data structure. Until a true symmetric multiprocessing kernel - with fine grained locking is available, acquiring the lock is implemented as - saving the processor flags and disabling interrupts, and releasing the lock - restores the saved processor flags. + Define the Lock data structure. Until a true symmetric multiprocessing + kernel with fine grained locking is available, acquiring the lock is + implemented as saving the processor flags and disabling interrupts, and + releasing the lock restores the saved processor flags. */ typedef unsigned long BusLogic_Lock_T; @@ -606,25 +915,30 @@ typedef enum { - BusLogic_OutgoingMailboxFree = 0, - BusLogic_MailboxStartCommand = 1, - BusLogic_MailboxAbortCommand = 2 + BusLogic_OutgoingMailboxFree = 0x00, + BusLogic_MailboxStartCommand = 0x01, + BusLogic_MailboxAbortCommand = 0x02 } +__attribute__ ((packed)) BusLogic_ActionCode_T; /* - Define the Incoming Mailbox Completion Codes. + Define the Incoming Mailbox Completion Codes. The MultiMaster Firmware + only uses codes 0 - 4. The FlashPoint SCCB Manager has no mailboxes, so + completion codes are stored in the CCB; it only uses codes 1, 2, 4, and 5. */ typedef enum { - BusLogic_IncomingMailboxFree = 0, - BusLogic_CommandCompletedWithoutError = 1, - BusLogic_CommandAbortedAtHostRequest = 2, - BusLogic_AbortedCommandNotFound = 3, - BusLogic_CommandCompletedWithError = 4 + BusLogic_IncomingMailboxFree = 0x00, + BusLogic_CommandCompletedWithoutError = 0x01, + BusLogic_CommandAbortedAtHostRequest = 0x02, + BusLogic_AbortedCommandNotFound = 0x03, + BusLogic_CommandCompletedWithError = 0x04, + BusLogic_InvalidCCB = 0x05 } +__attribute__ ((packed)) BusLogic_CompletionCode_T; @@ -641,6 +955,7 @@ BusLogic_InitiatorCCB_ScatterGatherResidual = 0x04, BusLogic_BusDeviceReset = 0x81 } +__attribute__ ((packed)) BusLogic_CCB_Opcode_T; @@ -650,16 +965,17 @@ typedef enum { - BusLogic_UncheckedDataTransfer = 0x00, - BusLogic_DataInLengthChecked = 0x01, - BusLogic_DataOutLengthChecked = 0x02, - BusLogic_NoDataTransfer = 0x03 + BusLogic_UncheckedDataTransfer = 0, + BusLogic_DataInLengthChecked = 1, + BusLogic_DataOutLengthChecked = 2, + BusLogic_NoDataTransfer = 3 } BusLogic_DataDirection_T; /* - Define the Host Adapter Status Codes. + Define the Host Adapter Status Codes. The MultiMaster Firmware does not + return status code 0x0C; it uses 0x12 for both overruns and underruns. */ typedef enum @@ -667,8 +983,9 @@ BusLogic_CommandCompletedNormally = 0x00, BusLogic_LinkedCommandCompleted = 0x0A, BusLogic_LinkedCommandCompletedWithFlag = 0x0B, + BusLogic_DataUnderRun = 0x0C, BusLogic_SCSISelectionTimeout = 0x11, - BusLogic_DataOverUnderRun = 0x12, + BusLogic_DataOverRun = 0x12, BusLogic_UnexpectedBusFree = 0x13, BusLogic_InvalidBusPhaseRequested = 0x14, BusLogic_InvalidOutgoingMailboxActionCode = 0x15, @@ -689,6 +1006,7 @@ BusLogic_HostAdapterHardwareTimeoutError = 0x30, BusLogic_SCSIParityErrorDetected = 0x34 } +__attribute__ ((packed)) BusLogic_HostAdapterStatus_T; @@ -702,6 +1020,7 @@ BusLogic_CheckCondition = 0x02, BusLogic_DeviceBusy = 0x08 } +__attribute__ ((packed)) BusLogic_TargetDeviceStatus_T; @@ -711,10 +1030,10 @@ typedef enum { - BusLogic_SimpleQueueTag = 0x00, - BusLogic_HeadOfQueueTag = 0x01, - BusLogic_OrderedQueueTag = 0x02, - BusLogic_ReservedQT = 0x03 + BusLogic_SimpleQueueTag = 0, + BusLogic_HeadOfQueueTag = 1, + BusLogic_OrderedQueueTag = 2, + BusLogic_ReservedQT = 3 } BusLogic_QueueTag_T; @@ -729,59 +1048,75 @@ /* - Define the Scatter/Gather Segment structure required by the Host Adapter - Firmware Interface. + Define the Scatter/Gather Segment structure required by the MultiMaster + Firmware Interface and the FlashPoint SCCB Manager. */ typedef struct BusLogic_ScatterGatherSegment { - unsigned int SegmentByteCount; /* Bytes 0-3 */ - bus_address_t SegmentDataPointer; /* Bytes 4-7 */ + BusLogic_ByteCount_T SegmentByteCount; /* Bytes 0-3 */ + BusLogic_BusAddress_T SegmentDataPointer; /* Bytes 4-7 */ } 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. 64 LUN Format CCBs - differ from standard 8 LUN Format 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 64 LUN Format CCBs. + bytes are defined by and common to both the MultiMaster Firmware and the + FlashPoint SCCB Manager. The next 60 bytes are defined by the FlashPoint + SCCB Manager. The remaining components are defined by the Linux BusLogic + Driver. Extended LUN Format CCBs differ from Legacy LUN Format 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. In theory, + Extended LUN Format CCBs can support up to 64 Logical Units, but in practice + many devices will respond improperly to Logical Units between 32 and 63, and + the SCSI-2 specification defines Bit 5 as LUNTAR. Extended LUN Format CCBs + are used by recent versions of the MultiMaster Firmware, as well as by the + FlashPoint SCCB Manager; the FlashPoint SCCB Manager only supports 32 Logical + Units. Since 64 Logical Units are unlikely to be needed in practice, and + since they are problematic for the above reasons, and since limiting them to + 5 bits simplifies the CCB structure definition, this driver only supports + 32 Logical Units per Target Device. */ typedef struct BusLogic_CCB { /* - BusLogic Host Adapter Firmware Portion. + MultiMaster Firmware and FlashPoint SCCB Manager Common Portion. */ - BusLogic_CCB_Opcode_T Opcode:8; /* Byte 0 */ + BusLogic_CCB_Opcode_T Opcode; /* Byte 0 */ unsigned char :3; /* Byte 1 Bits 0-2 */ BusLogic_DataDirection_T DataDirection:2; /* Byte 1 Bits 3-4 */ - boolean TagEnable64LUN:1; /* Byte 1 Bit 5 */ - BusLogic_QueueTag_T QueueTag64LUN:2; /* Byte 1 Bits 6-7 */ + boolean TagEnable:1; /* Byte 1 Bit 5 */ + BusLogic_QueueTag_T QueueTag:2; /* Byte 1 Bits 6-7 */ unsigned char CDB_Length; /* Byte 2 */ unsigned char SenseDataLength; /* Byte 3 */ - unsigned int DataLength; /* Bytes 4-7 */ - bus_address_t DataPointer; /* Bytes 8-11 */ + BusLogic_ByteCount_T DataLength; /* Bytes 4-7 */ + BusLogic_BusAddress_T 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 */ + BusLogic_HostAdapterStatus_T HostAdapterStatus; /* Byte 14 */ + BusLogic_TargetDeviceStatus_T TargetDeviceStatus; /* 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 */ + boolean LegacyTagEnable:1; /* Byte 17 Bit 5 */ + BusLogic_QueueTag_T LegacyQueueTag:2; /* Byte 17 Bits 6-7 */ SCSI_CDB_T CDB; /* Bytes 18-29 */ unsigned char :8; /* Byte 30 */ unsigned char :8; /* Byte 31 */ unsigned int :32; /* Bytes 32-35 */ - bus_address_t SenseDataPointer; /* Bytes 36-39 */ + BusLogic_BusAddress_T SenseDataPointer; /* Bytes 36-39 */ + /* + FlashPoint SCCB Manager Defined Portion. + */ + void (*CallbackFunction)(struct BusLogic_CCB *); /* Bytes 40-43 */ + BusLogic_IO_Address_T BaseAddress; /* Bytes 44-47 */ + BusLogic_CompletionCode_T CompletionCode; /* Byte 48 */ + unsigned char :8; /* Byte 49 */ + unsigned short OS_Flags; /* Bytes 50-51 */ + unsigned char Private[48]; /* Bytes 52-99 */ /* - BusLogic Linux Driver Portion. + BusLogic Linux Driver Defined Portion. */ struct BusLogic_HostAdapter *HostAdapter; SCSI_Command_T *Command; @@ -789,13 +1124,13 @@ BusLogic_CCB_Active = 1, BusLogic_CCB_Completed = 2, BusLogic_CCB_Reset = 3 } Status; - BusLogic_CompletionCode_T MailboxCompletionCode; unsigned long SerialNumber; struct BusLogic_CCB *Next; struct BusLogic_CCB *NextAll; BusLogic_ScatterGatherSegment_T ScatterGatherList[BusLogic_ScatterGatherLimit]; } +__attribute__ ((packed)) BusLogic_CCB_T; @@ -805,9 +1140,9 @@ typedef struct BusLogic_OutgoingMailbox { - bus_address_t CCB; /* Bytes 0-3 */ - unsigned int :24; /* Byte 4 */ - BusLogic_ActionCode_T ActionCode:8; /* Bytes 5-7 */ + BusLogic_BusAddress_T CCB; /* Bytes 0-3 */ + unsigned int :24; /* Bytes 4-6 */ + BusLogic_ActionCode_T ActionCode; /* Byte 7 */ } BusLogic_OutgoingMailbox_T; @@ -818,85 +1153,155 @@ typedef struct BusLogic_IncomingMailbox { - bus_address_t CCB; /* Bytes 0-3 */ - BusLogic_HostAdapterStatus_T HostAdapterStatus:8; /* Byte 4 */ - BusLogic_TargetDeviceStatus_T TargetDeviceStatus:8; /* Byte 5 */ + BusLogic_BusAddress_T CCB; /* Bytes 0-3 */ + BusLogic_HostAdapterStatus_T HostAdapterStatus; /* Byte 4 */ + BusLogic_TargetDeviceStatus_T TargetDeviceStatus; /* Byte 5 */ unsigned char :8; /* Byte 6 */ - BusLogic_CompletionCode_T CompletionCode:8; /* Byte 7 */ + BusLogic_CompletionCode_T CompletionCode; /* Byte 7 */ } 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 int IO_Address; + BusLogic_IO_Address_T IO_Address; unsigned short TaggedQueueDepth; unsigned short BusSettleTime; - unsigned short LocalOptions; unsigned short TaggedQueuingPermitted; unsigned short TaggedQueuingPermittedMask; - unsigned char ErrorRecoveryStrategy[BusLogic_MaxTargetDevices]; + BusLogic_LocalOptions_T LocalOptions; + BusLogic_ErrorRecoveryStrategy_T + ErrorRecoveryStrategy[BusLogic_MaxTargetDevices]; } BusLogic_CommandLineEntry_T; /* + Define the Host Adapter Target Device Statistics structure. +*/ + +#define BusLogic_SizeBuckets 10 + +typedef unsigned int BusLogic_CommandSizeBuckets_T[BusLogic_SizeBuckets]; + +typedef struct BusLogic_TargetDeviceStatistics +{ + unsigned int CommandsAttempted; + unsigned int CommandsCompleted; + unsigned int ReadCommands; + unsigned int WriteCommands; + BusLogic_ByteCounter_T TotalBytesRead; + BusLogic_ByteCounter_T TotalBytesWritten; + BusLogic_CommandSizeBuckets_T ReadCommandSizeBuckets; + BusLogic_CommandSizeBuckets_T WriteCommandSizeBuckets; + unsigned short CommandAbortsRequested; + unsigned short CommandAbortsAttempted; + unsigned short CommandAbortsCompleted; + unsigned short BusDeviceResetsRequested; + unsigned short BusDeviceResetsAttempted; + unsigned short BusDeviceResetsCompleted; + unsigned short HostAdapterResetsRequested; + unsigned short HostAdapterResetsAttempted; + unsigned short HostAdapterResetsCompleted; +} +BusLogic_TargetDeviceStatistics_T; + + +/* + Define the FlashPoint Card Handle data type. +*/ + +#define FlashPoint_BadCardHandle 0xFFFFFFFF + +typedef unsigned int FlashPoint_CardHandle_T; + + +/* + Define the FlashPoint Information structure. This structure is defined + by the FlashPoint SCCB Manager. +*/ + +typedef struct FlashPoint_Info +{ + BusLogic_IO_Address_T BaseAddress; /* Bytes 0-3 */ + boolean Present; /* Byte 4 */ + unsigned char IRQ_Channel; /* Byte 5 */ + unsigned char SCSI_ID; /* Byte 6 */ + unsigned char SCSI_LUN; /* Byte 7 */ + unsigned short FirmwareRevision; /* Bytes 8-9 */ + unsigned short SynchronousPermitted; /* Bytes 10-11 */ + unsigned short FastPermitted; /* Bytes 12-13 */ + unsigned short UltraPermitted; /* Bytes 14-15 */ + unsigned short DisconnectPermitted; /* Bytes 16-17 */ + unsigned short WidePermitted; /* Bytes 18-19 */ + boolean ParityCheckingEnabled:1; /* Byte 20 Bit 0 */ + boolean HostWideSCSI:1; /* Byte 20 Bit 1 */ + boolean HostSoftReset:1; /* Byte 20 Bit 2 */ + boolean ExtendedTranslationEnabled:1; /* Byte 20 Bit 3 */ + boolean LowByteTerminated:1; /* Byte 20 Bit 4 */ + boolean HighByteTerminated:1; /* Byte 20 Bit 5 */ + boolean ReportDataUnderrun:1; /* Byte 20 Bit 6 */ + boolean SCAM_Enabled:1; /* Byte 20 Bit 7 */ + boolean SCAM_Level2:1; /* Byte 21 Bit 0 */ + unsigned char :7; /* Byte 21 Bits 1-7 */ + unsigned char Family; /* Byte 22 */ + unsigned char BusType; /* Byte 23 */ + unsigned char ModelNumber[3]; /* Bytes 24-26 */ + unsigned char RelativeCardNumber; /* Byte 27 */ + unsigned char Reserved[4]; /* Bytes 28-31 */ + unsigned int OS_Reserved; /* Bytes 32-35 */ + unsigned char TranslationInfo[4]; /* Bytes 36-39 */ + unsigned int Reserved2[5]; /* Bytes 40-59 */ + unsigned int SecondaryRange; /* Bytes 60-63 */ +} +FlashPoint_Info_T; + + +/* Define the Linux BusLogic Driver Host Adapter structure. */ typedef struct BusLogic_HostAdapter { SCSI_Host_T *SCSI_Host; - unsigned int IO_Address; + BusLogic_IO_Address_T IO_Address; + BusLogic_PCI_Address_T PCI_Address; + unsigned short AddressCount; unsigned char HostNumber; unsigned char ModelName[9]; unsigned char FirmwareVersion[6]; - unsigned char ControllerName[18]; - unsigned char InterruptLabel[62]; + unsigned char FullModelName[18]; + unsigned char InterruptLabel[68]; unsigned char IRQ_Channel; unsigned char DMA_Channel; unsigned char SCSI_ID; - BusLogic_BusType_T BusType:3; + unsigned char Bus; + unsigned char Device; + BusLogic_HostAdapterType_T HostAdapterType; + BusLogic_HostAdapterBusType_T HostAdapterBusType:3; boolean IRQ_ChannelAcquired:1; boolean DMA_ChannelAcquired:1; - boolean SynchronousInitiation:1; - boolean ParityChecking:1; - boolean ExtendedTranslation:1; - boolean LevelSensitiveInterrupts:1; + boolean ExtendedTranslationEnabled:1; + boolean ParityCheckingEnabled:1; + boolean BusResetEnabled; + boolean LevelSensitiveInterrupt:1; boolean HostWideSCSI:1; boolean HostDifferentialSCSI:1; - boolean HostAutomaticConfiguration:1; + boolean HostSupportsSCAM:1; boolean HostUltraSCSI:1; + boolean ExtendedLUNSupport:1; boolean TerminationInfoValid:1; boolean LowByteTerminated:1; boolean HighByteTerminated:1; boolean BounceBuffersRequired:1; boolean StrictRoundRobinModeSupport:1; - boolean Host64LUNSupport:1; + boolean SCAM_Enabled:1; + boolean SCAM_Level2:1; + boolean HostAdapterInitialized; boolean HostAdapterResetRequested:1; volatile boolean HostAdapterCommandCompleted:1; unsigned short HostAdapterScatterGatherLimit; @@ -906,27 +1311,40 @@ unsigned short MailboxCount; unsigned short InitialCCBs; unsigned short IncrementalCCBs; - unsigned short TotalQueueDepth; + unsigned short DriverQueueDepth; + unsigned short HostAdapterQueueDepth; unsigned short TaggedQueueDepth; unsigned short UntaggedQueueDepth; unsigned short BusSettleTime; - unsigned short LocalOptions; + unsigned short SynchronousPermitted; + unsigned short FastPermitted; + unsigned short UltraPermitted; + unsigned short WidePermitted; unsigned short DisconnectPermitted; unsigned short TaggedQueuingPermitted; - bus_address_t BIOS_Address; + unsigned short ExternalHostAdapterResets; + BusLogic_LocalOptions_T LocalOptions; + BusLogic_BusAddress_T BIOS_Address; BusLogic_InstalledDevices_T InstalledDevices; BusLogic_SynchronousValues_T SynchronousValues; BusLogic_SynchronousPeriod_T SynchronousPeriod; BusLogic_CommandLineEntry_T *CommandLineEntry; + FlashPoint_Info_T *FlashPointInfo; + FlashPoint_CardHandle_T CardHandle; struct BusLogic_HostAdapter *Next; + char *MessageBuffer; + int MessageBufferLength; BusLogic_CCB_T *All_CCBs; BusLogic_CCB_T *Free_CCBs; BusLogic_CCB_T *BusDeviceResetPendingCCB[BusLogic_MaxTargetDevices]; - unsigned char ErrorRecoveryStrategy[BusLogic_MaxTargetDevices]; - unsigned char TaggedQueuingActive[BusLogic_MaxTargetDevices]; - unsigned char CommandSuccessfulFlag[BusLogic_MaxTargetDevices]; - unsigned char ActiveCommandCount[BusLogic_MaxTargetDevices]; - unsigned long TotalCommandCount[BusLogic_MaxTargetDevices]; + BusLogic_ErrorRecoveryStrategy_T + ErrorRecoveryStrategy[BusLogic_MaxTargetDevices]; + boolean TaggedQueuingSupported[BusLogic_MaxTargetDevices]; + boolean TaggedQueuingActive[BusLogic_MaxTargetDevices]; + boolean CommandSuccessfulFlag[BusLogic_MaxTargetDevices]; + unsigned char QueueDepth[BusLogic_MaxTargetDevices]; + unsigned char ActiveCommands[BusLogic_MaxTargetDevices]; + unsigned int CommandsSinceReset[BusLogic_MaxTargetDevices]; unsigned long LastSequencePoint[BusLogic_MaxTargetDevices]; unsigned long LastResetTime[BusLogic_MaxTargetDevices]; BusLogic_OutgoingMailbox_T *FirstOutgoingMailbox; @@ -935,6 +1353,7 @@ BusLogic_IncomingMailbox_T *FirstIncomingMailbox; BusLogic_IncomingMailbox_T *LastIncomingMailbox; BusLogic_IncomingMailbox_T *NextIncomingMailbox; + BusLogic_TargetDeviceStatistics_T *TargetDeviceStatistics; } BusLogic_HostAdapter_T; @@ -1007,42 +1426,78 @@ */ static inline -void BusLogic_WriteControlRegister(BusLogic_HostAdapter_T *HostAdapter, - unsigned char Value) +void BusLogic_SCSIBusReset(BusLogic_HostAdapter_T *HostAdapter) +{ + BusLogic_ControlRegister_T ControlRegister; + ControlRegister.All = 0; + ControlRegister.Bits.SCSIBusReset = true; + outb(ControlRegister.All, + HostAdapter->IO_Address + BusLogic_ControlRegisterOffset); +} + +static inline +void BusLogic_InterruptReset(BusLogic_HostAdapter_T *HostAdapter) +{ + BusLogic_ControlRegister_T ControlRegister; + ControlRegister.All = 0; + ControlRegister.Bits.InterruptReset = true; + outb(ControlRegister.All, + HostAdapter->IO_Address + BusLogic_ControlRegisterOffset); +} + +static inline +void BusLogic_SoftReset(BusLogic_HostAdapter_T *HostAdapter) +{ + BusLogic_ControlRegister_T ControlRegister; + ControlRegister.All = 0; + ControlRegister.Bits.SoftReset = true; + outb(ControlRegister.All, + HostAdapter->IO_Address + BusLogic_ControlRegisterOffset); +} + +static inline +void BusLogic_HardReset(BusLogic_HostAdapter_T *HostAdapter) { - outb(Value, HostAdapter->IO_Address + BusLogic_ControlRegister); + BusLogic_ControlRegister_T ControlRegister; + ControlRegister.All = 0; + ControlRegister.Bits.HardReset = true; + outb(ControlRegister.All, + HostAdapter->IO_Address + BusLogic_ControlRegisterOffset); } static inline unsigned char BusLogic_ReadStatusRegister(BusLogic_HostAdapter_T *HostAdapter) { - return inb(HostAdapter->IO_Address + BusLogic_StatusRegister); + return inb(HostAdapter->IO_Address + BusLogic_StatusRegisterOffset); } static inline -void BusLogic_WriteCommandParameterRegister(BusLogic_HostAdapter_T *HostAdapter, +void BusLogic_WriteCommandParameterRegister(BusLogic_HostAdapter_T + *HostAdapter, unsigned char Value) { - outb(Value, HostAdapter->IO_Address + BusLogic_CommandParameterRegister); + outb(Value, + HostAdapter->IO_Address + BusLogic_CommandParameterRegisterOffset); } static inline unsigned char BusLogic_ReadDataInRegister(BusLogic_HostAdapter_T *HostAdapter) { - return inb(HostAdapter->IO_Address + BusLogic_DataInRegister); + return inb(HostAdapter->IO_Address + BusLogic_DataInRegisterOffset); } static inline unsigned char BusLogic_ReadInterruptRegister(BusLogic_HostAdapter_T *HostAdapter) { - return inb(HostAdapter->IO_Address + BusLogic_InterruptRegister); + return inb(HostAdapter->IO_Address + BusLogic_InterruptRegisterOffset); } static inline -unsigned char BusLogic_ReadGeometryRegister(BusLogic_HostAdapter_T *HostAdapter) +unsigned char BusLogic_ReadGeometryRegister(BusLogic_HostAdapter_T + *HostAdapter) { - return inb(HostAdapter->IO_Address + BusLogic_GeometryRegister); + return inb(HostAdapter->IO_Address + BusLogic_GeometryRegisterOffset); } @@ -1079,26 +1534,165 @@ and PCI/VLB/EISA/ISA Bus Addresses. */ -static inline bus_address_t Virtual_to_Bus(void *VirtualAddress) +static inline BusLogic_BusAddress_T Virtual_to_Bus(void *VirtualAddress) { - return (bus_address_t) virt_to_bus(VirtualAddress); + return (BusLogic_BusAddress_T) virt_to_bus(VirtualAddress); } -static inline void *Bus_to_Virtual(bus_address_t BusAddress) +static inline void *Bus_to_Virtual(BusLogic_BusAddress_T BusAddress) { return (void *) bus_to_virt(BusAddress); } /* + BusLogic_IncrementErrorCounter increments Error Counter by 1, stopping at + 65535 rather than wrapping around to 0. +*/ + +static inline void BusLogic_IncrementErrorCounter(unsigned short *ErrorCounter) +{ + if (*ErrorCounter < 65535) (*ErrorCounter)++; +} + + +/* + BusLogic_IncrementByteCounter increments Byte Counter by Amount. +*/ + +static inline void BusLogic_IncrementByteCounter(BusLogic_ByteCounter_T + *ByteCounter, + unsigned int Amount) +{ + ByteCounter->Units += Amount; + if (ByteCounter->Units > 999999999) + { + ByteCounter->Units -= 1000000000; + ByteCounter->Billions++; + } +} + + +/* + BusLogic_IncrementSizeBucket increments the Bucket for Amount. +*/ + +static inline void BusLogic_IncrementSizeBucket(BusLogic_CommandSizeBuckets_T + CommandSizeBuckets, + unsigned int Amount) +{ + int Index = 0; + if (Amount < 8*1024) + if (Amount < 2*1024) + Index = (Amount < 1*1024 ? 0 : 1); + else Index = (Amount < 4*1024 ? 2 : 3); + else if (Amount < 128*1024) + if (Amount < 32*1024) + Index = (Amount < 16*1024 ? 4 : 5); + else Index = (Amount < 64*1024 ? 6 : 7); + else Index = (Amount < 256*1024 ? 8 : 9); + CommandSizeBuckets[Index]++; +} + + +/* + If CONFIG_PCI is not set, force CONFIG_SCSI_OMIT_FLASHPOINT, and use the + ISA only probe function as the general one. +*/ + +#ifndef CONFIG_PCI + +#undef CONFIG_SCSI_OMIT_FLASHPOINT +#define CONFIG_SCSI_OMIT_FLASHPOINT +#define BusLogic_InitializeProbeInfoListISA BusLogic_InitializeProbeInfoList + +#endif + + +/* + Define macros for testing the Host Adapter Type. +*/ + +#ifndef CONFIG_SCSI_OMIT_FLASHPOINT + +#define BusLogic_MultiMasterHostAdapterP(HostAdapter) \ + (HostAdapter->HostAdapterType == BusLogic_MultiMaster) + +#define BusLogic_FlashPointHostAdapterP(HostAdapter) \ + (HostAdapter->HostAdapterType == BusLogic_FlashPoint) + +#else + +#define BusLogic_MultiMasterHostAdapterP(HostAdapter) \ + (true) + +#define BusLogic_FlashPointHostAdapterP(HostAdapter) \ + (false) + +#endif + + +/* + Define Driver Message Macros. +*/ + +#define BusLogic_Announce(Format, Arguments...) \ + BusLogic_Message(BusLogic_AnnounceLevel, Format, ##Arguments) + +#define BusLogic_Info(Format, Arguments...) \ + BusLogic_Message(BusLogic_InfoLevel, Format, ##Arguments) + +#define BusLogic_Notice(Format, Arguments...) \ + BusLogic_Message(BusLogic_NoticeLevel, Format, ##Arguments) + +#define BusLogic_Warning(Format, Arguments...) \ + BusLogic_Message(BusLogic_WarningLevel, Format, ##Arguments) + +#define BusLogic_Error(Format, Arguments...) \ + BusLogic_Message(BusLogic_ErrorLevel, Format, ##Arguments) + + +/* + Define the version number of the FlashPoint Firmware (SCCB Manager). +*/ + +#define FlashPoint_FirmwareVersion "5.01" + + +/* + Define the possible return values from FlashPoint_HandleInterrupt. +*/ + +#define FlashPoint_NormalInterrupt 0x00 +#define FlashPoint_ExternalBusReset 0xFF + + +/* + Define prototypes for the FlashPoint SCCB Manager Functions. +*/ + +extern unsigned char FlashPoint_ProbeHostAdapter(FlashPoint_Info_T *); +extern FlashPoint_CardHandle_T + FlashPoint_HardResetHostAdapter(FlashPoint_Info_T *); +extern void FlashPoint_StartCCB(FlashPoint_CardHandle_T, BusLogic_CCB_T *); +extern int FlashPoint_AbortCCB(FlashPoint_CardHandle_T, BusLogic_CCB_T *); +extern boolean FlashPoint_InterruptPending(FlashPoint_CardHandle_T); +extern int FlashPoint_HandleInterrupt(FlashPoint_CardHandle_T); +extern void FlashPoint_ReleaseHostAdapter(FlashPoint_CardHandle_T); + + +/* Define prototypes for the forward referenced BusLogic Driver Internal Functions. */ +static void BusLogic_QueueCompletedCCB(BusLogic_CCB_T *CCB); static void BusLogic_InterruptHandler(int, void *, Registers_T *); static int BusLogic_ResetHostAdapter(BusLogic_HostAdapter_T *, SCSI_Command_T *, unsigned int); +static void BusLogic_Message(BusLogic_MessageLevel_T, char *Format, + BusLogic_HostAdapter_T *, ...); #endif /* BusLogic_DriverVersion */ diff -u --recursive --new-file v2.1.27/linux/drivers/scsi/Config.in linux/drivers/scsi/Config.in --- v2.1.27/linux/drivers/scsi/Config.in Sun Feb 2 05:18:43 1997 +++ linux/drivers/scsi/Config.in Fri Feb 28 15:15:42 1997 @@ -26,6 +26,9 @@ dep_tristate 'Always IN2000 SCSI support' CONFIG_SCSI_IN2000 $CONFIG_SCSI dep_tristate 'AM53/79C974 PCI SCSI support' CONFIG_SCSI_AM53C974 $CONFIG_SCSI dep_tristate 'BusLogic SCSI support' CONFIG_SCSI_BUSLOGIC $CONFIG_SCSI +if [ "$CONFIG_SCSI_BUSLOGIC" != "n" ]; then + bool ' Omit FlashPoint support' CONFIG_SCSI_OMIT_FLASHPOINT +fi dep_tristate 'DTC3180/3280 SCSI support' CONFIG_SCSI_DTC3280 $CONFIG_SCSI dep_tristate 'EATA-DMA (DPT, NEC, AT&T, SNI, AST, Olivetti, Alphatronix) support' CONFIG_SCSI_EATA_DMA $CONFIG_SCSI dep_tristate 'EATA-PIO (old DPT PM2001, PM2012A) support' CONFIG_SCSI_EATA_PIO $CONFIG_SCSI diff -u --recursive --new-file v2.1.27/linux/drivers/scsi/FlashPoint.c linux/drivers/scsi/FlashPoint.c --- v2.1.27/linux/drivers/scsi/FlashPoint.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/scsi/FlashPoint.c Sun Feb 23 16:14:00 1997 @@ -0,0 +1,11776 @@ +/* + + FlashPoint.c -- FlashPoint SCCB Manager for Linux + + This file contains the FlashPoint SCCB Manager from BusLogic's FlashPoint + Driver Developer's Kit, with minor modifications by Leonard N. Zubkoff for + Linux compatibility. It was provided by BusLogic in the form of 16 separate + source files, which would have unnecessarily cluttered the scsi directory, so + the individual files have been combined into this single file. + + Copyright 1995-1996 by Mylex Corporation. All Rights Reserved + + This file is available under both the GNU General Public License + and a BSD-style copyright; see LICENSE.FlashPoint for details. + +*/ + + +#include + + +/* + If CONFIG_PCI is not set, force CONFIG_SCSI_OMIT_FLASHPOINT. +*/ + +#ifndef CONFIG_PCI + +#undef CONFIG_SCSI_OMIT_FLASHPOINT +#define CONFIG_SCSI_OMIT_FLASHPOINT + +#endif + + +#ifndef CONFIG_SCSI_OMIT_FLASHPOINT + + +#define UNIX +#define FW_TYPE _SCCB_MGR_ +#define MAX_CARDS 8 + + +#include + +#define OS_InPortByte(port) inb(port) +#define OS_InPortWord(port) inw(port) +#define OS_InPortLong(port) inl(port) +#define OS_OutPortByte(port, value) outb(value, port) +#define OS_OutPortWord(port, value) outw(value, port) +#define OS_OutPortLong(port, value) outl(value, port) +#define OS_Lock(x) +#define OS_UnLock(x) + + +/* + Define name replacements for compatibility with the Linux BusLogic Driver. +*/ + +#define SccbMgr_sense_adapter FlashPoint_ProbeHostAdapter +#define SccbMgr_config_adapter FlashPoint_HardResetHostAdapter +#define SccbMgr_unload_card FlashPoint_ReleaseHostAdapter +#define SccbMgr_start_sccb FlashPoint_StartCCB +#define SccbMgr_abort_sccb FlashPoint_AbortCCB +#define SccbMgr_my_int FlashPoint_InterruptPending +#define SccbMgr_isr FlashPoint_HandleInterrupt + + +/* + Define name replacements to avoid kernel namespace pollution. +*/ + +#define BL_Card FPT_BL_Card +#define BusMasterInit FPT_BusMasterInit +#define CalcCrc16 FPT_CalcCrc16 +#define CalcLrc FPT_CalcLrc +#define ChkIfChipInitialized FPT_ChkIfChipInitialized +#define DiagBusMaster FPT_DiagBusMaster +#define DiagEEPROM FPT_DiagEEPROM +#define DiagXbow FPT_DiagXbow +#define GetTarLun FPT_GetTarLun +#define RNVRamData FPT_RNVRamData +#define RdStack FPT_RdStack +#define SccbMgrTableInitAll FPT_SccbMgrTableInitAll +#define SccbMgrTableInitCard FPT_SccbMgrTableInitCard +#define SccbMgrTableInitTarget FPT_SccbMgrTableInitTarget +#define SccbMgr_bad_isr FPT_SccbMgr_bad_isr +#define SccbMgr_scsi_reset FPT_SccbMgr_scsi_reset +#define SccbMgr_timer_expired FPT_SccbMgr_timer_expired +#define SendMsg FPT_SendMsg +#define Wait FPT_Wait +#define Wait1Second FPT_Wait1Second +#define WrStack FPT_WrStack +#define XbowInit FPT_XbowInit +#define autoCmdCmplt FPT_autoCmdCmplt +#define autoLoadDefaultMap FPT_autoLoadDefaultMap +#define busMstrDataXferStart FPT_busMstrDataXferStart +#define busMstrSGDataXferStart FPT_busMstrSGDataXferStart +#define busMstrTimeOut FPT_busMstrTimeOut +#define dataXferProcessor FPT_dataXferProcessor +#define default_intena FPT_default_intena +#define hostDataXferAbort FPT_hostDataXferAbort +#define hostDataXferRestart FPT_hostDataXferRestart +#define inisci FPT_inisci +#define mbCards FPT_mbCards +#define nvRamInfo FPT_nvRamInfo +#define phaseBusFree FPT_phaseBusFree +#define phaseChkFifo FPT_phaseChkFifo +#define phaseCommand FPT_phaseCommand +#define phaseDataIn FPT_phaseDataIn +#define phaseDataOut FPT_phaseDataOut +#define phaseDecode FPT_phaseDecode +#define phaseIllegal FPT_phaseIllegal +#define phaseMsgIn FPT_phaseMsgIn +#define phaseMsgOut FPT_phaseMsgOut +#define phaseStatus FPT_phaseStatus +#define queueAddSccb FPT_queueAddSccb +#define queueCmdComplete FPT_queueCmdComplete +#define queueDisconnect FPT_queueDisconnect +#define queueFindSccb FPT_queueFindSccb +#define queueFlushSccb FPT_queueFlushSccb +#define queueFlushTargSccb FPT_queueFlushTargSccb +#define queueSearchSelect FPT_queueSearchSelect +#define queueSelectFail FPT_queueSelectFail +#define s_PhaseTbl FPT_s_PhaseTbl +#define scamHAString FPT_scamHAString +#define scamInfo FPT_scamInfo +#define scarb FPT_scarb +#define scasid FPT_scasid +#define scbusf FPT_scbusf +#define sccbMgrTbl FPT_sccbMgrTbl +#define schkdd FPT_schkdd +#define scini FPT_scini +#define sciso FPT_sciso +#define scmachid FPT_scmachid +#define scsavdi FPT_scsavdi +#define scsel FPT_scsel +#define scsell FPT_scsell +#define scsendi FPT_scsendi +#define scvalq FPT_scvalq +#define scwirod FPT_scwirod +#define scwiros FPT_scwiros +#define scwtsel FPT_scwtsel +#define scxferc FPT_scxferc +#define sdecm FPT_sdecm +#define sfm FPT_sfm +#define shandem FPT_shandem +#define sinits FPT_sinits +#define sisyncn FPT_sisyncn +#define sisyncr FPT_sisyncr +#define siwidn FPT_siwidn +#define siwidr FPT_siwidr +#define sres FPT_sres +#define sresb FPT_sresb +#define ssel FPT_ssel +#define ssenss FPT_ssenss +#define sssyncv FPT_sssyncv +#define stsyncn FPT_stsyncn +#define stwidn FPT_stwidn +#define sxfrp FPT_sxfrp +#define utilEERead FPT_utilEERead +#define utilEESendCmdAddr FPT_utilEESendCmdAddr +#define utilEEWrite FPT_utilEEWrite +#define utilEEWriteOnOff FPT_utilEEWriteOnOff +#define utilUpdateResidual FPT_utilUpdateResidual + + +/*---------------------------------------------------------------------- + * + * + * Copyright 1995-1996 by Mylex Corporation. All Rights Reserved + * + * This file is available under both the GNU General Public License + * and a BSD-style copyright; see LICENSE.FlashPoint for details. + * + * $Workfile: globals.h $ + * + * Description: Common shared global defines. + * + * $Date: 1996/09/04 01:26:13 $ + * + * $Revision: 1.11 $ + * + *----------------------------------------------------------------------*/ +#ifndef __GLOBALS_H__ +#define __GLOBALS_H__ + +#define _UCB_MGR_ 1 +#define _SCCB_MGR_ 2 + +/*#include */ + +#define MAX_CDBLEN 12 + +#define SCAM_LEV_2 1 + +#define CRCMASK 0xA001 + +/* In your osflags.h file, please ENSURE that only ONE OS FLAG + is on at a time !!! Also, please make sure you turn set the + variable FW_TYPE to either _UCB_MGR_ or _SCCB_MGR_ !!! */ + +#if defined(DOS) || defined(WIN95_16) || defined(OS2) || defined(OTHER_16) + #define COMPILER_16_BIT 1 +#elif defined(NETWARE) || defined(NT) || defined(WIN95_32) || defined(UNIX) || defined(OTHER_32) || defined(SOLARIS_REAL_MODE) + #define COMPILER_32_BIT 1 +#endif + + +#define BL_VENDOR_ID 0x104B +#define FP_DEVICE_ID 0x8130 +#define MM_DEVICE_ID 0x1040 + + +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE (!(FALSE)) +#endif + +#ifndef NULL +#define NULL 0 +#endif + +#define FAILURE 0xFFFFFFFFL + + +typedef unsigned char UCHAR; +typedef unsigned short USHORT; +typedef unsigned int UINT; +typedef unsigned long ULONG; +typedef unsigned char * PUCHAR; +typedef unsigned short* PUSHORT; +typedef unsigned long * PULONG; +typedef void * PVOID; + + +#if defined(COMPILER_16_BIT) +typedef unsigned char far * uchar_ptr; +typedef unsigned short far * ushort_ptr; +typedef unsigned long far * ulong_ptr; +#endif /* 16_BIT_COMPILER */ + +#if defined(COMPILER_32_BIT) +typedef unsigned char * uchar_ptr; +typedef unsigned short * ushort_ptr; +typedef unsigned long * ulong_ptr; +#endif /* 32_BIT_COMPILER */ + + +/* NEW TYPE DEFINITIONS (shared with Mylex North) + +** Use following type defines to avoid confusion in 16 and 32-bit +** environments. Avoid using 'int' as it denotes 16 bits in 16-bit +** environment and 32 in 32-bit environments. + +*/ + +#define s08bits char +#define s16bits short +#define s32bits long + +#define u08bits unsigned s08bits +#define u16bits unsigned s16bits +#define u32bits unsigned s32bits + +#if defined(COMPILER_16_BIT) + +typedef u08bits far * pu08bits; +typedef u16bits far * pu16bits; +typedef u32bits far * pu32bits; + +#endif /* COMPILER_16_BIT */ + +#if defined(COMPILER_32_BIT) + +typedef u08bits * pu08bits; +typedef u16bits * pu16bits; +typedef u32bits * pu32bits; + +#endif /* COMPILER_32_BIT */ + + +#define BIT(x) ((UCHAR)(1<<(x))) /* single-bit mask in bit position x */ +#define BITW(x) ((USHORT)(1<<(x))) /* single-bit mask in bit position x */ + + + +#if defined(DOS) +/*#include */ + #undef inportb /* undefine for Borland Lib */ + #undef inport /* they may have define I/O function in LIB */ + #undef outportb + #undef outport + + #define OS_InPortByte(ioport) inportb(ioport) + #define OS_InPortWord(ioport) inport(ioport) + #define OS_InPortLong(ioport) inportq(ioport, val) + #define OS_OutPortByte(ioport, val) outportb(ioport, val) + #define OS_OutPortWord(ioport, val) outport(ioport, val) + #define OS_OutPortLong(ioport) outportq(ioport, val) +#endif /* DOS */ + +#if defined(NETWARE) || defined(OTHER_32) || defined(OTHER_16) + extern u08bits OS_InPortByte(u32bits ioport); + extern u16bits OS_InPortWord(u32bits ioport); + extern u32bits OS_InPortLong(u32bits ioport); + + extern OS_InPortByteBuffer(u32bits ioport, pu08bits buffer, u32bits count); + extern OS_InPortWordBuffer(u32bits ioport, pu16bits buffer, u32bits count); + extern OS_OutPortByte(u32bits ioport, u08bits val); + extern OS_OutPortWord(u32bits ioport, u16bits val); + extern OS_OutPortLong(u32bits ioport, u32bits val); + extern OS_OutPortByteBuffer(u32bits ioport, pu08bits buffer, u32bits count); + extern OS_OutPortWordBuffer(u32bits ioport, pu16bits buffer, u32bits count); +#endif /* NETWARE || OTHER_32 || OTHER_16 */ + +#if defined (NT) || defined(WIN95_32) || defined(WIN95_16) + #if defined(NT) + + extern __declspec(dllimport) u08bits ScsiPortReadPortUchar(pu08bits ioport); + extern __declspec(dllimport) u16bits ScsiPortReadPortUshort(pu16bits ioport); + extern __declspec(dllimport) u32bits ScsiPortReadPortUlong(pu32bits ioport); + extern __declspec(dllimport) void ScsiPortWritePortUchar(pu08bits ioport, u08bits val); + extern __declspec(dllimport) void ScsiPortWritePortUshort(pu16bits port, u16bits val); + extern __declspec(dllimport) void ScsiPortWritePortUlong(pu32bits port, u32bits val); + + #else + + extern u08bits ScsiPortReadPortUchar(pu08bits ioport); + extern u16bits ScsiPortReadPortUshort(pu16bits ioport); + extern u32bits ScsiPortReadPortUlong(pu32bits ioport); + extern void ScsiPortWritePortUchar(pu08bits ioport, u08bits val); + extern void ScsiPortWritePortUshort(pu16bits port, u16bits val); + extern void ScsiPortWritePortUlong(pu32bits port, u32bits val); + #endif + + + #define OS_InPortByte(ioport) ScsiPortReadPortUchar((pu08bits) ioport) + #define OS_InPortWord(ioport) ScsiPortReadPortUshort((pu16bits) ioport) + #define OS_InPortLong(ioport) ScsiPortReadPortUlong((pu32bits) ioport) + + #define OS_OutPortByte(ioport, val) ScsiPortWritePortUchar((pu08bits) ioport, (u08bits) val) + #define OS_OutPortWord(ioport, val) ScsiPortWritePortUshort((pu16bits) ioport, (u16bits) val) + #define OS_OutPortLong(ioport, val) ScsiPortWritePortUlong((pu32bits) ioport, (u32bits) val) + #define OS_OutPortByteBuffer(ioport, buffer, count) \ + ScsiPortWritePortBufferUchar((pu08bits)&port, (pu08bits) buffer, (u32bits) count) + #define OS_OutPortWordBuffer(ioport, buffer, count) \ + ScsiPortWritePortBufferUshort((pu16bits)&port, (pu16bits) buffer, (u32bits) count) + + #define OS_Lock(x) + #define OS_UnLock(x) +#endif /* NT || WIN95_32 || WIN95_16 */ + +#if defined (UNIX) && !defined(OS_InPortByte) + #define OS_InPortByte(ioport) inb((u16bits)ioport) + #define OS_InPortWord(ioport) inw((u16bits)ioport) + #define OS_InPortLong(ioport) inl((u16bits)ioport) + #define OS_OutPortByte(ioport,val) outb((u16bits)ioport, (u08bits)val) + #define OS_OutPortWord(ioport,val) outw((u16bits)ioport, (u16bits)val) + #define OS_OutPortLong(ioport,val) outl((u16bits)ioport, (u32bits)val) + + #define OS_Lock(x) + #define OS_UnLock(x) +#endif /* UNIX */ + + +#if defined(OS2) + extern u08bits inb(u32bits ioport); + extern u16bits inw(u32bits ioport); + extern void outb(u32bits ioport, u08bits val); + extern void outw(u32bits ioport, u16bits val); + + #define OS_InPortByte(ioport) inb(ioport) + #define OS_InPortWord(ioport) inw(ioport) + #define OS_OutPortByte(ioport, val) outb(ioport, val) + #define OS_OutPortWord(ioport, val) outw(ioport, val) + extern u32bits OS_InPortLong(u32bits ioport); + extern void OS_OutPortLong(u32bits ioport, u32bits val); + + #define OS_Lock(x) + #define OS_UnLock(x) +#endif /* OS2 */ + +#if defined(SOLARIS_REAL_MODE) + +extern unsigned char inb(unsigned long ioport); +extern unsigned short inw(unsigned long ioport); + +#define OS_InPortByte(ioport) inb(ioport) +#define OS_InPortWord(ioport) inw(ioport) + +extern void OS_OutPortByte(unsigned long ioport, unsigned char val); +extern void OS_OutPortWord(unsigned long ioport, unsigned short val); +extern unsigned long OS_InPortLong(unsigned long ioport); +extern void OS_OutPortLong(unsigned long ioport, unsigned long val); + +#define OS_Lock(x) +#define OS_UnLock(x) + +#endif /* SOLARIS_REAL_MODE */ + +#endif /* __GLOBALS_H__ */ + +/*---------------------------------------------------------------------- + * + * + * Copyright 1995-1996 by Mylex Corporation. All Rights Reserved + * + * This file is available under both the GNU General Public License + * and a BSD-style copyright; see LICENSE.FlashPoint for details. + * + * $Workfile: sccbmgr.h $ + * + * Description: Common shared SCCB Interface defines and SCCB + * Manager specifics defines. + * + * $Date: 1996/10/24 23:09:33 $ + * + * $Revision: 1.14 $ + * + *----------------------------------------------------------------------*/ + +#ifndef __SCCB_H__ +#define __SCCB_H__ + +/*#include */ +/*#include */ + +#if defined(BUGBUG) +#define debug_size 32 +#endif + +#if defined(DOS) + + typedef struct _SCCB near *PSCCB; + #if (FW_TYPE == _SCCB_MGR_) + typedef void (*CALL_BK_FN)(PSCCB); + #endif + +#elif defined(OS2) + + typedef struct _SCCB far *PSCCB; + #if (FW_TYPE == _SCCB_MGR_) + typedef void (far *CALL_BK_FN)(PSCCB); + #endif + +#else + + typedef struct _SCCB *PSCCB; + #if (FW_TYPE == _SCCB_MGR_) + typedef void (*CALL_BK_FN)(PSCCB); + #endif + +#endif + + +typedef struct SCCBMgr_info { + ULONG si_baseaddr; + UCHAR si_present; + UCHAR si_intvect; + UCHAR si_id; + UCHAR si_lun; + USHORT si_fw_revision; + USHORT si_per_targ_init_sync; + USHORT si_per_targ_fast_nego; + USHORT si_per_targ_ultra_nego; + USHORT si_per_targ_no_disc; + USHORT si_per_targ_wide_nego; + USHORT si_flags; + UCHAR si_card_family; + UCHAR si_bustype; + UCHAR si_card_model[3]; + UCHAR si_relative_cardnum; + UCHAR si_reserved[4]; + ULONG si_OS_reserved; + UCHAR si_XlatInfo[4]; + ULONG si_reserved2[5]; + ULONG si_secondary_range; +} SCCBMGR_INFO; + +#if defined(DOS) + typedef SCCBMGR_INFO * PSCCBMGR_INFO; +#else + #if defined (COMPILER_16_BIT) + typedef SCCBMGR_INFO far * PSCCBMGR_INFO; + #else + typedef SCCBMGR_INFO * PSCCBMGR_INFO; + #endif +#endif // defined(DOS) + + + + +#if (FW_TYPE==_SCCB_MGR_) + #define SCSI_PARITY_ENA 0x0001 + #define LOW_BYTE_TERM 0x0010 + #define HIGH_BYTE_TERM 0x0020 + #define BUSTYPE_PCI 0x3 +#endif + +#define SUPPORT_16TAR_32LUN 0x0002 +#define SOFT_RESET 0x0004 +#define EXTENDED_TRANSLATION 0x0008 +#define POST_ALL_UNDERRRUNS 0x0040 +#define FLAG_SCAM_ENABLED 0x0080 +#define FLAG_SCAM_LEVEL2 0x0100 + + + + +#define HARPOON_FAMILY 0x02 + + +#define ISA_BUS_CARD 0x01 +#define EISA_BUS_CARD 0x02 +#define PCI_BUS_CARD 0x03 +#define VESA_BUS_CARD 0x04 + +/* SCCB struc used for both SCCB and UCB manager compiles! + * The UCB Manager treats the SCCB as it's 'native hardware structure' + */ + + +#pragma pack(1) +typedef struct _SCCB { + UCHAR OperationCode; + UCHAR ControlByte; + UCHAR CdbLength; + UCHAR RequestSenseLength; + ULONG DataLength; + ULONG DataPointer; + UCHAR CcbRes[2]; + UCHAR HostStatus; + UCHAR TargetStatus; + UCHAR TargID; + UCHAR Lun; + UCHAR Cdb[12]; + UCHAR CcbRes1; + UCHAR Reserved1; + ULONG Reserved2; + ULONG SensePointer; + + + CALL_BK_FN SccbCallback; /* VOID (*SccbCallback)(); */ + ULONG SccbIOPort; /* Identifies board base port */ + UCHAR SccbStatus; + UCHAR SCCBRes2; + USHORT SccbOSFlags; + + + ULONG Sccb_XferCnt; /* actual transfer count */ + ULONG Sccb_ATC; + ULONG SccbVirtDataPtr; /* virtual addr for OS/2 */ + ULONG Sccb_res1; + USHORT Sccb_MGRFlags; + USHORT Sccb_sgseg; + UCHAR Sccb_scsimsg; /* identify msg for selection */ + UCHAR Sccb_tag; + UCHAR Sccb_scsistat; + UCHAR Sccb_idmsg; /* image of last msg in */ + PSCCB Sccb_forwardlink; + PSCCB Sccb_backlink; + ULONG Sccb_savedATC; + UCHAR Save_Cdb[6]; + UCHAR Save_CdbLen; + UCHAR Sccb_XferState; + ULONG Sccb_SGoffset; +#if (FW_TYPE == _UCB_MGR_) + PUCB Sccb_ucb_ptr; +#endif + } SCCB; + +#define SCCB_SIZE sizeof(SCCB) + +#pragma pack() + + + +#define SCSI_INITIATOR_COMMAND 0x00 +#define TARGET_MODE_COMMAND 0x01 +#define SCATTER_GATHER_COMMAND 0x02 +#define RESIDUAL_COMMAND 0x03 +#define RESIDUAL_SG_COMMAND 0x04 +#define RESET_COMMAND 0x81 + + +#define F_USE_CMD_Q 0x20 /*Inidcates TAGGED command. */ +#define TAG_TYPE_MASK 0xC0 /*Type of tag msg to send. */ +#define TAG_Q_MASK 0xE0 +#define SCCB_DATA_XFER_OUT 0x10 /* Write */ +#define SCCB_DATA_XFER_IN 0x08 /* Read */ + + +#define FOURTEEN_BYTES 0x00 /* Request Sense Buffer size */ +#define NO_AUTO_REQUEST_SENSE 0x01 /* No Request Sense Buffer */ + + +#define BUS_FREE_ST 0 +#define SELECT_ST 1 +#define SELECT_BDR_ST 2 /* Select w\ Bus Device Reset */ +#define SELECT_SN_ST 3 /* Select w\ Sync Nego */ +#define SELECT_WN_ST 4 /* Select w\ Wide Data Nego */ +#define SELECT_Q_ST 5 /* Select w\ Tagged Q'ing */ +#define COMMAND_ST 6 +#define DATA_OUT_ST 7 +#define DATA_IN_ST 8 +#define DISCONNECT_ST 9 +#define STATUS_ST 10 +#define ABORT_ST 11 +#define MESSAGE_ST 12 + + +#define F_HOST_XFER_DIR 0x01 +#define F_ALL_XFERRED 0x02 +#define F_SG_XFER 0x04 +#define F_AUTO_SENSE 0x08 +#define F_ODD_BALL_CNT 0x10 +#define F_NO_DATA_YET 0x80 + + +#define F_STATUSLOADED 0x01 +#define F_MSGLOADED 0x02 +#define F_DEV_SELECTED 0x04 + + +#define SCCB_COMPLETE 0x00 /* SCCB completed without error */ +#define SCCB_DATA_UNDER_RUN 0x0C +#define SCCB_SELECTION_TIMEOUT 0x11 /* Set SCSI selection timed out */ +#define SCCB_DATA_OVER_RUN 0x12 +#define SCCB_UNEXPECTED_BUS_FREE 0x13 /* Target dropped SCSI BSY */ +#define SCCB_PHASE_SEQUENCE_FAIL 0x14 /* Target bus phase sequence failure */ + +#define SCCB_INVALID_OP_CODE 0x16 /* SCCB invalid operation code */ +#define SCCB_INVALID_SCCB 0x1A /* Invalid SCCB - bad parameter */ +#define SCCB_GROSS_FW_ERR 0x27 /* Major problem! */ +#define SCCB_BM_ERR 0x30 /* BusMaster error. */ +#define SCCB_PARITY_ERR 0x34 /* SCSI parity error */ + + + +#if (FW_TYPE==_UCB_MGR_) + #define HBA_AUTO_SENSE_FAIL 0x1B + #define HBA_TQ_REJECTED 0x1C + #define HBA_UNSUPORTED_MSG 0x1D + #define HBA_HW_ERROR 0x20 + #define HBA_ATN_NOT_RESPONDED 0x21 + #define HBA_SCSI_RESET_BY_ADAPTER 0x22 + #define HBA_SCSI_RESET_BY_TARGET 0x23 + #define HBA_WRONG_CONNECTION 0x24 + #define HBA_BUS_DEVICE_RESET 0x25 + #define HBA_ABORT_QUEUE 0x26 + +#else // these are not defined in BUDI/UCB + + #define SCCB_INVALID_DIRECTION 0x18 /* Invalid target direction */ + #define SCCB_DUPLICATE_SCCB 0x19 /* Duplicate SCCB */ + #define SCCB_SCSI_RST 0x35 /* SCSI RESET detected. */ + +#endif // (FW_TYPE==_UCB_MGR_) + + +#define SCCB_IN_PROCESS 0x00 +#define SCCB_SUCCESS 0x01 +#define SCCB_ABORT 0x02 +#define SCCB_NOT_FOUND 0x03 +#define SCCB_ERROR 0x04 +#define SCCB_INVALID 0x05 + +#define SCCB_SIZE sizeof(SCCB) + + + + +#if (FW_TYPE == _UCB_MGR_) + void SccbMgr_start_sccb(CARD_HANDLE pCurrCard, PUCB p_ucb); + s32bits SccbMgr_abort_sccb(CARD_HANDLE pCurrCard, PUCB p_ucb); + u08bits SccbMgr_my_int(CARD_HANDLE pCurrCard); + s32bits SccbMgr_isr(CARD_HANDLE pCurrCard); + void SccbMgr_scsi_reset(CARD_HANDLE pCurrCard); + void SccbMgr_timer_expired(CARD_HANDLE pCurrCard); + void SccbMgr_unload_card(CARD_HANDLE pCurrCard); + void SccbMgr_restore_foreign_state(CARD_HANDLE pCurrCard); + void SccbMgr_restore_native_state(CARD_HANDLE pCurrCard); + void SccbMgr_save_foreign_state(PADAPTER_INFO pAdapterInfo); + +#endif + + +#if (FW_TYPE == _SCCB_MGR_) + + #if defined (DOS) + int SccbMgr_sense_adapter(PSCCBMGR_INFO pCardInfo); + USHORT SccbMgr_config_adapter(PSCCBMGR_INFO pCardInfo); + void SccbMgr_start_sccb(USHORT pCurrCard, PSCCB p_SCCB); + int SccbMgr_abort_sccb(USHORT pCurrCard, PSCCB p_SCCB); + UCHAR SccbMgr_my_int(USHORT pCurrCard); + int SccbMgr_isr(USHORT pCurrCard); + void SccbMgr_scsi_reset(USHORT pCurrCard); + void SccbMgr_timer_expired(USHORT pCurrCard); + USHORT SccbMgr_status(USHORT pCurrCard); + void SccbMgr_unload_card(USHORT pCurrCard); + + #else //non-DOS + + int SccbMgr_sense_adapter(PSCCBMGR_INFO pCardInfo); + ULONG SccbMgr_config_adapter(PSCCBMGR_INFO pCardInfo); + void SccbMgr_start_sccb(ULONG pCurrCard, PSCCB p_SCCB); + int SccbMgr_abort_sccb(ULONG pCurrCard, PSCCB p_SCCB); + UCHAR SccbMgr_my_int(ULONG pCurrCard); + int SccbMgr_isr(ULONG pCurrCard); + void SccbMgr_scsi_reset(ULONG pCurrCard); + void SccbMgr_enable_int(ULONG pCurrCard); + void SccbMgr_disable_int(ULONG pCurrCard); + void SccbMgr_timer_expired(ULONG pCurrCard); + void SccbMgr_unload_card(ULONG pCurrCard); + + #endif +#endif // (FW_TYPE == _SCCB_MGR_) + +#endif /* __SCCB_H__ */ + +/*---------------------------------------------------------------------- + * + * + * Copyright 1995-1996 by Mylex Corporation. All Rights Reserved + * + * This file is available under both the GNU General Public License + * and a BSD-style copyright; see LICENSE.FlashPoint for details. + * + * $Workfile: blx30.h $ + * + * Description: This module contains SCCB/UCB Manager implementation + * specific stuff. + * + * $Date: 1996/11/13 18:34:22 $ + * + * $Revision: 1.10 $ + * + *----------------------------------------------------------------------*/ + + +#ifndef __blx30_H__ +#define __blx30_H__ + +/*#include */ + +#define ORION_FW_REV 3110 + + + + +#define HARP_REVD 1 + + +#if defined(DOS) +#define QUEUE_DEPTH 8+1 /*1 for Normal disconnect 0 for Q'ing. */ +#else +#define QUEUE_DEPTH 254+1 /*1 for Normal disconnect 32 for Q'ing. */ +#endif // defined(DOS) + +#define MAX_MB_CARDS 4 /* Max. no of cards suppoerted on Mother Board */ + +#define WIDE_SCSI 1 + +#if defined(WIDE_SCSI) + #if defined(DOS) + #define MAX_SCSI_TAR 16 + #define MAX_LUN 8 + #define LUN_MASK 0x07 + #else + #define MAX_SCSI_TAR 16 + #define MAX_LUN 32 + #define LUN_MASK 0x1f + + #endif +#else + #define MAX_SCSI_TAR 8 + #define MAX_LUN 8 + #define LUN_MASK 0x07 +#endif + +#if defined(HARP_REVA) +#define SG_BUF_CNT 15 /*Number of prefetched elements. */ +#else +#define SG_BUF_CNT 16 /*Number of prefetched elements. */ +#endif + +#define SG_ELEMENT_SIZE 8 /*Eight byte per element. */ +#define SG_LOCAL_MASK 0x00000000L +#define SG_ELEMENT_MASK 0xFFFFFFFFL + + +#if (FW_TYPE == _UCB_MGR_) + #define OPC_DECODE_NORMAL 0x0f7f +#endif // _UCB_MGR_ + + + +#if defined(DOS) + +/*#include */ + #define RD_HARPOON(ioport) (OS_InPortByte(ioport)) + #define RDW_HARPOON(ioport) (OS_InPortWord(ioport)) + #define WR_HARPOON(ioport,val) (OS_OutPortByte(ioport,val)) + #define WRW_HARPOON(ioport,val) (OS_OutPortWord(ioport,val)) + + #define RD_HARP32(port,offset,data) asm{db 66h; \ + push ax; \ + mov dx,port; \ + add dx, offset; \ + db 66h; \ + in ax,dx; \ + db 66h; \ + mov word ptr data,ax;\ + db 66h; \ + pop ax} + + #define WR_HARP32(port,offset,data) asm{db 66h; \ + push ax; \ + mov dx,port; \ + add dx, offset; \ + db 66h; \ + mov ax,word ptr data;\ + db 66h; \ + out dx,ax; \ + db 66h; \ + pop ax} +#endif /* DOS */ + +#if defined(NETWARE) || defined(OTHER_32) || defined(OTHER_16) + #define RD_HARPOON(ioport) OS_InPortByte((unsigned long)ioport) + #define RDW_HARPOON(ioport) OS_InPortWord((unsigned long)ioport) + #define RD_HARP32(ioport,offset,data) (data = OS_InPortLong(ioport + offset)) + #define WR_HARPOON(ioport,val) OS_OutPortByte((ULONG)ioport,(UCHAR) val) + #define WRW_HARPOON(ioport,val) OS_OutPortWord((ULONG)ioport,(USHORT)val) + #define WR_HARP32(ioport,offset,data) OS_OutPortLong((ioport + offset), data) +#endif /* NETWARE || OTHER_32 || OTHER_16 */ + +#if defined(NT) || defined(WIN95_32) || defined(WIN95_16) + #define RD_HARPOON(ioport) OS_InPortByte((ULONG)ioport) + #define RDW_HARPOON(ioport) OS_InPortWord((ULONG)ioport) + #define RD_HARP32(ioport,offset,data) (data = OS_InPortLong((ULONG)(ioport + offset))) + #define WR_HARPOON(ioport,val) OS_OutPortByte((ULONG)ioport,(UCHAR) val) + #define WRW_HARPOON(ioport,val) OS_OutPortWord((ULONG)ioport,(USHORT)val) + #define WR_HARP32(ioport,offset,data) OS_OutPortLong((ULONG)(ioport + offset), data) +#endif /* NT || WIN95_32 || WIN95_16 */ + +#if defined (UNIX) + #define RD_HARPOON(ioport) OS_InPortByte((u32bits)ioport) + #define RDW_HARPOON(ioport) OS_InPortWord((u32bits)ioport) + #define RD_HARP32(ioport,offset,data) (data = OS_InPortLong((u32bits)(ioport + offset))) + #define WR_HARPOON(ioport,val) OS_OutPortByte((u32bits)ioport,(u08bits) val) + #define WRW_HARPOON(ioport,val) OS_OutPortWord((u32bits)ioport,(u16bits)val) + #define WR_HARP32(ioport,offset,data) OS_OutPortLong((u32bits)(ioport + offset), data) +#endif /* UNIX */ + +#if defined(OS2) + #define RD_HARPOON(ioport) OS_InPortByte((unsigned long)ioport) + #define RDW_HARPOON(ioport) OS_InPortWord((unsigned long)ioport) + #define RD_HARP32(ioport,offset,data) (data = OS_InPortLong((ULONG)(ioport + offset))) + #define WR_HARPOON(ioport,val) OS_OutPortByte((ULONG)ioport,(UCHAR) val) + #define WRW_HARPOON(ioport,val) OS_OutPortWord((ULONG)ioport,(USHORT)val) + #define WR_HARP32(ioport,offset,data) OS_OutPortLong(((ULONG)(ioport + offset)), data) +#endif /* OS2 */ + +#if defined(SOLARIS_REAL_MODE) + + #define RD_HARPOON(ioport) OS_InPortByte((unsigned long)ioport) + #define RDW_HARPOON(ioport) OS_InPortWord((unsigned long)ioport) + #define RD_HARP32(ioport,offset,data) (data = OS_InPortLong((ULONG)(ioport + offset))) + #define WR_HARPOON(ioport,val) OS_OutPortByte((ULONG)ioport,(UCHAR) val) + #define WRW_HARPOON(ioport,val) OS_OutPortWord((ULONG)ioport,(USHORT)val) + #define WR_HARP32(ioport,offset,data) OS_OutPortLong((ULONG)(ioport + offset), (ULONG)data) + +#endif /* SOLARIS_REAL_MODE */ + +#endif /* __BLX30_H__ */ + + +/*---------------------------------------------------------------------- + * + * + * Copyright 1995-1996 by Mylex Corporation. All Rights Reserved + * + * This file is available under both the GNU General Public License + * and a BSD-style copyright; see LICENSE.FlashPoint for details. + * + * $Workfile: target.h $ + * + * Description: Definitions for Target related structures + * + * $Date: 1996/12/11 22:06:20 $ + * + * $Revision: 1.9 $ + * + *----------------------------------------------------------------------*/ + +#ifndef __TARGET__ +#define __TARGET__ + +/*#include */ +/*#include */ + + +#define TAR_SYNC_MASK (BIT(7)+BIT(6)) +#define SYNC_UNKNOWN 0x00 +#define SYNC_TRYING BIT(6) +#define SYNC_SUPPORTED (BIT(7)+BIT(6)) + +#define TAR_WIDE_MASK (BIT(5)+BIT(4)) +#define WIDE_DISABLED 0x00 +#define WIDE_ENABLED BIT(4) +#define WIDE_NEGOCIATED BIT(5) + +#define TAR_TAG_Q_MASK (BIT(3)+BIT(2)) +#define TAG_Q_UNKNOWN 0x00 +#define TAG_Q_TRYING BIT(2) +#define TAG_Q_REJECT BIT(3) +#define TAG_Q_SUPPORTED (BIT(3)+BIT(2)) + +#define TAR_ALLOW_DISC BIT(0) + + +#define EE_SYNC_MASK (BIT(0)+BIT(1)) +#define EE_SYNC_ASYNC 0x00 +#define EE_SYNC_5MB BIT(0) +#define EE_SYNC_10MB BIT(1) +#define EE_SYNC_20MB (BIT(0)+BIT(1)) + +#define EE_ALLOW_DISC BIT(6) +#define EE_WIDE_SCSI BIT(7) + + +#if defined(DOS) + typedef struct SCCBMgr_tar_info near *PSCCBMgr_tar_info; + +#elif defined(OS2) + typedef struct SCCBMgr_tar_info far *PSCCBMgr_tar_info; + +#else + typedef struct SCCBMgr_tar_info *PSCCBMgr_tar_info; + +#endif + + +typedef struct SCCBMgr_tar_info { + + PSCCB TarSelQ_Head; + PSCCB TarSelQ_Tail; + UCHAR TarLUN_CA; /*Contingent Allgiance */ + UCHAR TarTagQ_Cnt; + UCHAR TarSelQ_Cnt; + UCHAR TarStatus; + UCHAR TarEEValue; + UCHAR TarSyncCtrl; + UCHAR TarReserved[2]; /* for alignment */ + UCHAR LunDiscQ_Idx[MAX_LUN]; + UCHAR TarLUNBusy[MAX_LUN]; +} SCCBMGR_TAR_INFO; + +typedef struct NVRAMInfo { + UCHAR niModel; /* Model No. of card */ + UCHAR niCardNo; /* Card no. */ +#if defined(DOS) + USHORT niBaseAddr; /* Port Address of card */ +#else + ULONG niBaseAddr; /* Port Address of card */ +#endif + UCHAR niSysConf; /* Adapter Configuration byte - Byte 16 of eeprom map */ + UCHAR niScsiConf; /* SCSI Configuration byte - Byte 17 of eeprom map */ + UCHAR niScamConf; /* SCAM Configuration byte - Byte 20 of eeprom map */ + UCHAR niAdapId; /* Host Adapter ID - Byte 24 of eerpom map */ + UCHAR niSyncTbl[MAX_SCSI_TAR / 2]; /* Sync/Wide byte of targets */ + UCHAR niScamTbl[MAX_SCSI_TAR][4]; /* Compressed Scam name string of Targets */ +}NVRAMINFO; + +#if defined(DOS) +typedef NVRAMINFO near *PNVRamInfo; +#elif defined (OS2) +typedef NVRAMINFO far *PNVRamInfo; +#else +typedef NVRAMINFO *PNVRamInfo; +#endif + +#define MODEL_LT 1 +#define MODEL_DL 2 +#define MODEL_LW 3 +#define MODEL_DW 4 + + +typedef struct SCCBcard { + PSCCB currentSCCB; +#if (FW_TYPE==_SCCB_MGR_) + PSCCBMGR_INFO cardInfo; +#else + PADAPTER_INFO cardInfo; +#endif + +#if defined(DOS) + USHORT ioPort; +#else + ULONG ioPort; +#endif + + USHORT cmdCounter; + UCHAR discQCount; + UCHAR tagQ_Lst; + UCHAR cardIndex; + UCHAR scanIndex; + UCHAR globalFlags; + UCHAR ourId; + PNVRamInfo pNvRamInfo; + PSCCB discQ_Tbl[QUEUE_DEPTH]; + +}SCCBCARD; + +#if defined(DOS) +typedef struct SCCBcard near *PSCCBcard; +#elif defined (OS2) +typedef struct SCCBcard far *PSCCBcard; +#else +typedef struct SCCBcard *PSCCBcard; +#endif + + +#define F_TAG_STARTED 0x01 +#define F_CONLUN_IO 0x02 +#define F_DO_RENEGO 0x04 +#define F_NO_FILTER 0x08 +#define F_GREEN_PC 0x10 +#define F_HOST_XFER_ACT 0x20 +#define F_NEW_SCCB_CMD 0x40 +#define F_UPDATE_EEPROM 0x80 + + +#define ID_STRING_LENGTH 32 +#define TYPE_CODE0 0x63 /*Level2 Mstr (bits 7-6), */ + +#define TYPE_CODE1 00 /*No ID yet */ + +#define SLV_TYPE_CODE0 0xA3 /*Priority Bit set (bits 7-6), */ + +#define ASSIGN_ID 0x00 +#define SET_P_FLAG 0x01 +#define CFG_CMPLT 0x03 +#define DOM_MSTR 0x0F +#define SYNC_PTRN 0x1F + +#define ID_0_7 0x18 +#define ID_8_F 0x11 +#define ID_10_17 0x12 +#define ID_18_1F 0x0B +#define MISC_CODE 0x14 +#define CLR_P_FLAG 0x18 +#define LOCATE_ON 0x12 +#define LOCATE_OFF 0x0B + +#define LVL_1_MST 0x00 +#define LVL_2_MST 0x40 +#define DOM_LVL_2 0xC0 + + +#define INIT_SELTD 0x01 +#define LEVEL2_TAR 0x02 + + +enum scam_id_st { ID0,ID1,ID2,ID3,ID4,ID5,ID6,ID7,ID8,ID9,ID10,ID11,ID12, + ID13,ID14,ID15,ID_UNUSED,ID_UNASSIGNED,ID_ASSIGNED,LEGACY, + CLR_PRIORITY,NO_ID_AVAIL }; + +typedef struct SCCBscam_info { + + UCHAR id_string[ID_STRING_LENGTH]; + enum scam_id_st state; + +} SCCBSCAM_INFO, *PSCCBSCAM_INFO; + +#endif +/*---------------------------------------------------------------------- + * + * + * Copyright 1995-1996 by Mylex Corporation. All Rights Reserved + * + * This file is available under both the GNU General Public License + * and a BSD-style copyright; see LICENSE.FlashPoint for details. + * + * $Workfile: scsi2.h $ + * + * Description: Register definitions for HARPOON ASIC. + * + * $Date: 1996/11/13 18:32:57 $ + * + * $Revision: 1.4 $ + * + *----------------------------------------------------------------------*/ + +#ifndef __SCSI_H__ +#define __SCSI_H__ + + + +#define SCSI_TEST_UNIT_READY 0x00 +#define SCSI_REZERO_UNIT 0x01 +#define SCSI_REQUEST_SENSE 0x03 +#define SCSI_FORMAT_UNIT 0x04 +#define SCSI_REASSIGN 0x07 +#define SCSI_READ 0x08 +#define SCSI_WRITE 0x0A +#define SCSI_SEEK 0x0B +#define SCSI_INQUIRY 0x12 +#define SCSI_MODE_SELECT 0x15 +#define SCSI_RESERVE_UNIT 0x16 +#define SCSI_RELEASE_UNIT 0x17 +#define SCSI_MODE_SENSE 0x1A +#define SCSI_START_STOP_UNIT 0x1B +#define SCSI_SEND_DIAGNOSTIC 0x1D +#define SCSI_READ_CAPACITY 0x25 +#define SCSI_READ_EXTENDED 0x28 +#define SCSI_WRITE_EXTENDED 0x2A +#define SCSI_SEEK_EXTENDED 0x2B +#define SCSI_WRITE_AND_VERIFY 0x2E +#define SCSI_VERIFY 0x2F +#define SCSI_READ_DEFECT_DATA 0x37 +#define SCSI_WRITE_BUFFER 0x3B +#define SCSI_READ_BUFFER 0x3C +#define SCSI_RECV_DIAGNOSTIC 0x1C +#define SCSI_READ_LONG 0x3E +#define SCSI_WRITE_LONG 0x3F +#define SCSI_LAST_SCSI_CMND SCSI_WRITE_LONG +#define SCSI_INVALID_CMND 0xFF + + + +#define SSGOOD 0x00 +#define SSCHECK 0x02 +#define SSCOND_MET 0x04 +#define SSBUSY 0x08 +#define SSRESERVATION_CONFLICT 0x18 +#define SSCMD_TERM 0x22 +#define SSQ_FULL 0x28 + + +#define SKNO_SEN 0x00 +#define SKRECOV_ERR 0x01 +#define SKNOT_RDY 0x02 +#define SKMED_ERR 0x03 +#define SKHW_ERR 0x04 +#define SKILL_REQ 0x05 +#define SKUNIT_ATTN 0x06 +#define SKDATA_PROTECT 0x07 +#define SKBLNK_CHK 0x08 +#define SKCPY_ABORT 0x0A +#define SKABORT_CMD 0x0B +#define SKEQUAL 0x0C +#define SKVOL_OVF 0x0D +#define SKMIS_CMP 0x0E + + +#define SMCMD_COMP 0x00 +#define SMEXT 0x01 +#define SMSAVE_DATA_PTR 0x02 +#define SMREST_DATA_PTR 0x03 +#define SMDISC 0x04 +#define SMINIT_DETEC_ERR 0x05 +#define SMABORT 0x06 +#define SMREJECT 0x07 +#define SMNO_OP 0x08 +#define SMPARITY 0x09 +#define SMDEV_RESET 0x0C +#define SMABORT_TAG 0x0D +#define SMINIT_RECOVERY 0x0F +#define SMREL_RECOVERY 0x10 + +#define SMIDENT 0x80 +#define DISC_PRIV 0x40 + + +#define SMSYNC 0x01 +#define SM10MBS 0x19 /* 100ns */ +#define SM5MBS 0x32 /* 200ns */ +#define SMOFFSET 0x0F /* Maxoffset value */ +#define SMWDTR 0x03 +#define SM8BIT 0x00 +#define SM16BIT 0x01 +#define SM32BIT 0x02 +#define SMIGNORWR 0x23 /* Ignore Wide Residue */ + + +#define ARBITRATION_DELAY 0x01 /* 2.4us using a 40Mhz clock */ +#define BUS_SETTLE_DELAY 0x01 /* 400ns */ +#define BUS_CLEAR_DELAY 0x01 /* 800ns */ + + + +#define SPHASE_TO 0x0A /* 10 second timeout waiting for */ +#define SCMD_TO 0x0F /* Overall command timeout */ + + + +#define SIX_BYTE_CMD 0x06 +#define TEN_BYTE_CMD 0x0A +#define TWELVE_BYTE_CMD 0x0C + +#define ASYNC 0x00 +#define PERI25NS 0x06 /* 25/4ns to next clock for xbow. */ +#define SYNC10MBS 0x19 +#define SYNC5MBS 0x32 +#define MAX_OFFSET 0x0F /* Maxbyteoffset for Sync Xfers */ + +#endif +/*---------------------------------------------------------------------- + * + * + * Copyright 1995-1996 by Mylex Corporation. All Rights Reserved + * + * This file is available under both the GNU General Public License + * and a BSD-style copyright; see LICENSE.FlashPoint for details. + * + * $Workfile: eeprom.h $ + * + * Description: Definitions for EEPROM related structures + * + * $Date: 1996/11/13 18:28:39 $ + * + * $Revision: 1.4 $ + * + *----------------------------------------------------------------------*/ + +#ifndef __EEPROM__ +#define __EEPROM__ + +/*#include */ + +#define EEPROM_WD_CNT 256 + +#define EEPROM_CHECK_SUM 0 +#define FW_SIGNATURE 2 +#define MODEL_NUMB_0 4 +#define MODEL_NUMB_1 5 +#define MODEL_NUMB_2 6 +#define MODEL_NUMB_3 7 +#define MODEL_NUMB_4 8 +#define MODEL_NUMB_5 9 +#define IO_BASE_ADDR 10 +#define IRQ_NUMBER 12 +#define PCI_INT_PIN 13 +#define BUS_DELAY 14 /*On time in byte 14 off delay in 15 */ +#define SYSTEM_CONFIG 16 +#define SCSI_CONFIG 17 +#define BIOS_CONFIG 18 +#define SPIN_UP_DELAY 19 +#define SCAM_CONFIG 20 +#define ADAPTER_SCSI_ID 24 + + +#define IGNORE_B_SCAN 32 +#define SEND_START_ENA 34 +#define DEVICE_ENABLE 36 + +#define SYNC_RATE_TBL 38 +#define SYNC_RATE_TBL01 38 +#define SYNC_RATE_TBL23 40 +#define SYNC_RATE_TBL45 42 +#define SYNC_RATE_TBL67 44 +#define SYNC_RATE_TBL89 46 +#define SYNC_RATE_TBLab 48 +#define SYNC_RATE_TBLcd 50 +#define SYNC_RATE_TBLef 52 + + + +#define EE_SCAMBASE 256 + + + + #define DOM_MASTER (BIT(0) + BIT(1)) + #define SCAM_ENABLED BIT(2) + #define SCAM_LEVEL2 BIT(3) + + + #define RENEGO_ENA BITW(10) + #define CONNIO_ENA BITW(11) + #define GREEN_PC_ENA BITW(12) + + + #define AUTO_RATE_00 00 + #define AUTO_RATE_05 01 + #define AUTO_RATE_10 02 + #define AUTO_RATE_20 03 + + #define WIDE_NEGO_BIT BIT(7) + #define DISC_ENABLE_BIT BIT(6) + + +#endif +/*---------------------------------------------------------------------- + * + * + * Copyright 1995-1996 by Mylex Corporation. All Rights Reserved + * + * This file is available under both the GNU General Public License + * and a BSD-style copyright; see LICENSE.FlashPoint for details. + * + * $Workfile: harpoon.h $ + * + * Description: Register definitions for HARPOON ASIC. + * + * $Date: 1997/01/31 02:14:28 $ + * + * $Revision: 1.6 $ + * + *----------------------------------------------------------------------*/ + + +/*#include */ + +#ifndef __HARPOON__ +#define __HARPOON__ + + + #define hp_vendor_id_0 0x00 /* LSB */ + #define ORION_VEND_0 0x4B + + #define hp_vendor_id_1 0x01 /* MSB */ + #define ORION_VEND_1 0x10 + + #define hp_device_id_0 0x02 /* LSB */ + #define ORION_DEV_0 0x30 + + #define hp_device_id_1 0x03 /* MSB */ + #define ORION_DEV_1 0x81 + + /* Sub Vendor ID and Sub Device ID only available in + Harpoon Version 2 and higher */ + + #define hp_sub_vendor_id_0 0x04 /* LSB */ + #define hp_sub_vendor_id_1 0x05 /* MSB */ + #define hp_sub_device_id_0 0x06 /* LSB */ + #define hp_sub_device_id_1 0x07 /* MSB */ + + + #define hp_dual_addr_lo 0x08 + #define hp_dual_addr_lmi 0x09 + #define hp_dual_addr_hmi 0x0A + #define hp_dual_addr_hi 0x0B + + #define hp_semaphore 0x0C + #define SCCB_MGR_ACTIVE BIT(0) + #define TICKLE_ME BIT(1) + #define SCCB_MGR_PRESENT BIT(3) + #define BIOS_IN_USE BIT(4) + + #define hp_user_defined_D 0x0D + + #define hp_reserved_E 0x0E + + #define hp_sys_ctrl 0x0F + + #define STOP_CLK BIT(0) /*Turn off BusMaster Clock */ + #define DRVR_RST BIT(1) /*Firmware Reset to 80C15 chip */ + #define HALT_MACH BIT(3) /*Halt State Machine */ + #define HARD_ABORT BIT(4) /*Hard Abort */ + #define DIAG_MODE BIT(5) /*Diagnostic Mode */ + + #define BM_ABORT_TMOUT 0x50 /*Halt State machine time out */ + + #define hp_sys_cfg 0x10 + + #define DONT_RST_FIFO BIT(7) /*Don't reset FIFO */ + + + #define hp_host_ctrl0 0x11 + + #define DUAL_ADDR_MODE BIT(0) /*Enable 64-bit addresses */ + #define IO_MEM_SPACE BIT(1) /*I/O Memory Space */ + #define RESOURCE_LOCK BIT(2) /*Enable Resource Lock */ + #define IGNOR_ACCESS_ERR BIT(3) /*Ignore Access Error */ + #define HOST_INT_EDGE BIT(4) /*Host interrupt level/edge mode sel */ + #define SIX_CLOCKS BIT(5) /*6 Clocks between Strobe */ + #define DMA_EVEN_PARITY BIT(6) /*Enable DMA Enen Parity */ + +/* + #define BURST_MODE BIT(0) +*/ + + #define hp_reserved_12 0x12 + + #define hp_host_blk_cnt 0x13 + + #define XFER_BLK1 0x00 /* 0 0 0 1 byte per block*/ + #define XFER_BLK2 0x01 /* 0 0 1 2 byte per block*/ + #define XFER_BLK4 0x02 /* 0 1 0 4 byte per block*/ + #define XFER_BLK8 0x03 /* 0 1 1 8 byte per block*/ + #define XFER_BLK16 0x04 /* 1 0 0 16 byte per block*/ + #define XFER_BLK32 0x05 /* 1 0 1 32 byte per block*/ + #define XFER_BLK64 0x06 /* 1 1 0 64 byte per block*/ + + #define BM_THRESHOLD 0x40 /* PCI mode can only xfer 16 bytes*/ + + + #define hp_reserved_14 0x14 + #define hp_reserved_15 0x15 + #define hp_reserved_16 0x16 + + #define hp_int_mask 0x17 + + #define INT_CMD_COMPL BIT(0) /* DMA command complete */ + #define INT_EXT_STATUS BIT(1) /* Extended Status Set */ + #define INT_SCSI BIT(2) /* Scsi block interrupt */ + #define INT_FIFO_RDY BIT(4) /* FIFO data ready */ + + + #define hp_xfer_cnt_lo 0x18 + #define hp_xfer_cnt_mi 0x19 + #define hp_xfer_cnt_hi 0x1A + #define hp_xfer_cmd 0x1B + + #define XFER_HOST_DMA 0x00 /* 0 0 0 Transfer Host -> DMA */ + #define XFER_DMA_HOST 0x01 /* 0 0 1 Transfer DMA -> Host */ + #define XFER_HOST_MPU 0x02 /* 0 1 0 Transfer Host -> MPU */ + #define XFER_MPU_HOST 0x03 /* 0 1 1 Transfer MPU -> Host */ + #define XFER_DMA_MPU 0x04 /* 1 0 0 Transfer DMA -> MPU */ + #define XFER_MPU_DMA 0x05 /* 1 0 1 Transfer MPU -> DMA */ + #define SET_SEMAPHORE 0x06 /* 1 1 0 Set Semaphore */ + #define XFER_NOP 0x07 /* 1 1 1 Transfer NOP */ + #define XFER_MB_MPU 0x06 /* 1 1 0 Transfer MB -> MPU */ + #define XFER_MB_DMA 0x07 /* 1 1 1 Transfer MB -> DMA */ + + + #define XFER_HOST_AUTO 0x00 /* 0 0 Auto Transfer Size */ + #define XFER_HOST_8BIT 0x08 /* 0 1 8 BIT Transfer Size */ + #define XFER_HOST_16BIT 0x10 /* 1 0 16 BIT Transfer Size */ + #define XFER_HOST_32BIT 0x18 /* 1 1 32 BIT Transfer Size */ + + #define XFER_DMA_8BIT 0x20 /* 0 1 8 BIT Transfer Size */ + #define XFER_DMA_16BIT 0x40 /* 1 0 16 BIT Transfer Size */ + + #define DISABLE_INT BIT(7) /*Do not interrupt at end of cmd. */ + + #define HOST_WRT_CMD ((DISABLE_INT + XFER_HOST_DMA + XFER_HOST_AUTO + XFER_DMA_8BIT)) + #define HOST_RD_CMD ((DISABLE_INT + XFER_DMA_HOST + XFER_HOST_AUTO + XFER_DMA_8BIT)) + #define WIDE_HOST_WRT_CMD ((DISABLE_INT + XFER_HOST_DMA + XFER_HOST_AUTO + XFER_DMA_16BIT)) + #define WIDE_HOST_RD_CMD ((DISABLE_INT + XFER_DMA_HOST + XFER_HOST_AUTO + XFER_DMA_16BIT)) + + #define hp_host_addr_lo 0x1C + #define hp_host_addr_lmi 0x1D + #define hp_host_addr_hmi 0x1E + #define hp_host_addr_hi 0x1F + + #define hp_pio_data 0x20 + #define hp_reserved_21 0x21 + #define hp_ee_ctrl 0x22 + + #define EXT_ARB_ACK BIT(7) + #define SCSI_TERM_ENA_H BIT(6) /* SCSI high byte terminator */ + #define SEE_MS BIT(5) + #define SEE_CS BIT(3) + #define SEE_CLK BIT(2) + #define SEE_DO BIT(1) + #define SEE_DI BIT(0) + + #define EE_READ 0x06 + #define EE_WRITE 0x05 + #define EWEN 0x04 + #define EWEN_ADDR 0x03C0 + #define EWDS 0x04 + #define EWDS_ADDR 0x0000 + + #define hp_brdctl 0x23 + + #define DAT_7 BIT(7) + #define DAT_6 BIT(6) + #define DAT_5 BIT(5) + #define BRD_STB BIT(4) + #define BRD_CS BIT(3) + #define BRD_WR BIT(2) + + #define hp_reserved_24 0x24 + #define hp_reserved_25 0x25 + + + + + #define hp_bm_ctrl 0x26 + + #define SCSI_TERM_ENA_L BIT(0) /*Enable/Disable external terminators */ + #define FLUSH_XFER_CNTR BIT(1) /*Flush transfer counter */ + #define BM_XFER_MIN_8 BIT(2) /*Enable bus master transfer of 9 */ + #define BIOS_ENA BIT(3) /*Enable BIOS/FLASH Enable */ + #define FORCE1_XFER BIT(5) /*Always xfer one byte in byte mode */ + #define FAST_SINGLE BIT(6) /*?? */ + + #define BMCTRL_DEFAULT (FORCE1_XFER|FAST_SINGLE|SCSI_TERM_ENA_L) + + #define hp_reserved_27 0x27 + + #define hp_sg_addr 0x28 + #define hp_page_ctrl 0x29 + + #define SCATTER_EN BIT(0) + #define SGRAM_ARAM BIT(1) + #define BIOS_SHADOW BIT(2) + #define G_INT_DISABLE BIT(3) /* Enable/Disable all Interrupts */ + #define NARROW_SCSI_CARD BIT(4) /* NARROW/WIDE SCSI config pin */ + + #define hp_reserved_2A 0x2A + #define hp_pci_cmd_cfg 0x2B + + #define IO_SPACE_ENA BIT(0) /*enable I/O space */ + #define MEM_SPACE_ENA BIT(1) /*enable memory space */ + #define BUS_MSTR_ENA BIT(2) /*enable bus master operation */ + #define MEM_WI_ENA BIT(4) /*enable Write and Invalidate */ + #define PAR_ERR_RESP BIT(6) /*enable parity error responce. */ + + #define hp_reserved_2C 0x2C + + #define hp_pci_stat_cfg 0x2D + + #define DATA_PARITY_ERR BIT(0) + #define REC_TARGET_ABORT BIT(4) /*received Target abort */ + #define REC_MASTER_ABORT BIT(5) /*received Master abort */ + #define SIG_SYSTEM_ERR BIT(6) + #define DETECTED_PAR_ERR BIT(7) + + #define hp_reserved_2E 0x2E + + #define hp_sys_status 0x2F + + #define SLV_DATA_RDY BIT(0) /*Slave data ready */ + #define XFER_CNT_ZERO BIT(1) /*Transfer counter = 0 */ + #define BM_FIFO_EMPTY BIT(2) /*FIFO empty */ + #define BM_FIFO_FULL BIT(3) /*FIFO full */ + #define HOST_OP_DONE BIT(4) /*host operation done */ + #define DMA_OP_DONE BIT(5) /*DMA operation done */ + #define SLV_OP_DONE BIT(6) /*Slave operation done */ + #define PWR_ON_FLAG BIT(7) /*Power on flag */ + + #define hp_reserved_30 0x30 + + #define hp_host_status0 0x31 + + #define HOST_TERM BIT(5) /*Host Terminal Count */ + #define HOST_TRSHLD BIT(6) /*Host Threshold */ + #define CONNECTED_2_HOST BIT(7) /*Connected to Host */ + + #define hp_reserved_32 0x32 + + #define hp_rev_num 0x33 + + #define REV_A_CONST 0x0E + #define REV_B_CONST 0x0E + + #define hp_stack_data 0x34 + #define hp_stack_addr 0x35 + + #define hp_ext_status 0x36 + + #define BM_FORCE_OFF BIT(0) /*Bus Master is forced to get off */ + #define PCI_TGT_ABORT BIT(0) /*PCI bus master transaction aborted */ + #define PCI_DEV_TMOUT BIT(1) /*PCI Device Time out */ + #define FIFO_TC_NOT_ZERO BIT(2) /*FIFO or transfer counter not zero */ + #define CHIP_RST_OCCUR BIT(3) /*Chip reset occurs */ + #define CMD_ABORTED BIT(4) /*Command aborted */ + #define BM_PARITY_ERR BIT(5) /*parity error on data received */ + #define PIO_OVERRUN BIT(6) /*Slave data overrun */ + #define BM_CMD_BUSY BIT(7) /*Bus master transfer command busy */ + #define BAD_EXT_STATUS (BM_FORCE_OFF | PCI_DEV_TMOUT | CMD_ABORTED | \ + BM_PARITY_ERR | PIO_OVERRUN) + + #define hp_int_status 0x37 + + #define BM_CMD_CMPL BIT(0) /*Bus Master command complete */ + #define EXT_STATUS_ON BIT(1) /*Extended status is valid */ + #define SCSI_INTERRUPT BIT(2) /*Global indication of a SCSI int. */ + #define BM_FIFO_RDY BIT(4) + #define INT_ASSERTED BIT(5) /* */ + #define SRAM_BUSY BIT(6) /*Scatter/Gather RAM busy */ + #define CMD_REG_BUSY BIT(7) + + + #define hp_fifo_cnt 0x38 + #define hp_curr_host_cnt 0x39 + #define hp_reserved_3A 0x3A + #define hp_fifo_in_addr 0x3B + + #define hp_fifo_out_addr 0x3C + #define hp_reserved_3D 0x3D + #define hp_reserved_3E 0x3E + #define hp_reserved_3F 0x3F + + + + extern USHORT default_intena; + + #define hp_intena 0x40 + + #define RESET BITW(7) + #define PROG_HLT BITW(6) + #define PARITY BITW(5) + #define FIFO BITW(4) + #define SEL BITW(3) + #define SCAM_SEL BITW(2) + #define RSEL BITW(1) + #define TIMEOUT BITW(0) + #define BUS_FREE BITW(15) + #define XFER_CNT_0 BITW(14) + #define PHASE BITW(13) + #define IUNKWN BITW(12) + #define ICMD_COMP BITW(11) + #define ITICKLE BITW(10) + #define IDO_STRT BITW(9) + #define ITAR_DISC BITW(8) + #define AUTO_INT (BITW(12)+BITW(11)+BITW(10)+BITW(9)+BITW(8)) + #define CLR_ALL_INT 0xFFFF + #define CLR_ALL_INT_1 0xFF00 + + #define hp_intstat 0x42 + + #define hp_scsisig 0x44 + + #define SCSI_SEL BIT(7) + #define SCSI_BSY BIT(6) + #define SCSI_REQ BIT(5) + #define SCSI_ACK BIT(4) + #define SCSI_ATN BIT(3) + #define SCSI_CD BIT(2) + #define SCSI_MSG BIT(1) + #define SCSI_IOBIT BIT(0) + + #define S_SCSI_PHZ (BIT(2)+BIT(1)+BIT(0)) + #define S_CMD_PH (BIT(2) ) + #define S_MSGO_PH (BIT(2)+BIT(1) ) + #define S_STAT_PH (BIT(2) +BIT(0)) + #define S_MSGI_PH (BIT(2)+BIT(1)+BIT(0)) + #define S_DATAI_PH ( BIT(0)) + #define S_DATAO_PH 0x00 + #define S_ILL_PH ( BIT(1) ) + + #define hp_scsictrl_0 0x45 + + #define NO_ARB BIT(7) + #define SEL_TAR BIT(6) + #define ENA_ATN BIT(4) + #define ENA_RESEL BIT(2) + #define SCSI_RST BIT(1) + #define ENA_SCAM_SEL BIT(0) + + + + #define hp_portctrl_0 0x46 + + #define SCSI_PORT BIT(7) + #define SCSI_INBIT BIT(6) + #define DMA_PORT BIT(5) + #define DMA_RD BIT(4) + #define HOST_PORT BIT(3) + #define HOST_WRT BIT(2) + #define SCSI_BUS_EN BIT(1) + #define START_TO BIT(0) + + #define hp_scsireset 0x47 + + #define SCSI_TAR BIT(7) + #define SCSI_INI BIT(6) + #define SCAM_EN BIT(5) + #define ACK_HOLD BIT(4) + #define DMA_RESET BIT(3) + #define HPSCSI_RESET BIT(2) + #define PROG_RESET BIT(1) + #define FIFO_CLR BIT(0) + + #define hp_xfercnt_0 0x48 + #define hp_xfercnt_1 0x49 + #define hp_xfercnt_2 0x4A + #define hp_xfercnt_3 0x4B + + #define hp_fifodata_0 0x4C + #define hp_fifodata_1 0x4D + #define hp_addstat 0x4E + + #define SCAM_TIMER BIT(7) + #define AUTO_RUNNING BIT(6) + #define FAST_SYNC BIT(5) + #define SCSI_MODE8 BIT(3) + #define SCSI_PAR_ERR BIT(0) + + #define hp_prgmcnt_0 0x4F + + #define AUTO_PC_MASK 0x3F + + #define hp_selfid_0 0x50 + #define hp_selfid_1 0x51 + #define hp_arb_id 0x52 + + #define ARB_ID (BIT(3) + BIT(2) + BIT(1) + BIT(0)) + + #define hp_select_id 0x53 + + #define RESEL_ID (BIT(7) + BIT(6) + BIT(5) + BIT(4)) + #define SELECT_ID (BIT(3) + BIT(2) + BIT(1) + BIT(0)) + + #define hp_synctarg_base 0x54 + #define hp_synctarg_12 0x54 + #define hp_synctarg_13 0x55 + #define hp_synctarg_14 0x56 + #define hp_synctarg_15 0x57 + + #define hp_synctarg_8 0x58 + #define hp_synctarg_9 0x59 + #define hp_synctarg_10 0x5A + #define hp_synctarg_11 0x5B + + #define hp_synctarg_4 0x5C + #define hp_synctarg_5 0x5D + #define hp_synctarg_6 0x5E + #define hp_synctarg_7 0x5F + + #define hp_synctarg_0 0x60 + #define hp_synctarg_1 0x61 + #define hp_synctarg_2 0x62 + #define hp_synctarg_3 0x63 + + #define RATE_20MB 0x00 + #define RATE_10MB ( BIT(5)) + #define RATE_6_6MB ( BIT(6) ) + #define RATE_5MB ( BIT(6)+BIT(5)) + #define RATE_4MB (BIT(7) ) + #define RATE_3_33MB (BIT(7) +BIT(5)) + #define RATE_2_85MB (BIT(7)+BIT(6) ) + #define RATE_2_5MB (BIT(7)+BIT(5)+BIT(6)) + #define NEXT_CLK BIT(5) + #define SLOWEST_SYNC (BIT(7)+BIT(6)+BIT(5)) + #define NARROW_SCSI BIT(4) + #define SYNC_OFFSET (BIT(3) + BIT(2) + BIT(1) + BIT(0)) + #define DEFAULT_ASYNC 0x00 + #define DEFAULT_OFFSET 0x0F + + #define hp_autostart_0 0x64 + #define hp_autostart_1 0x65 + #define hp_autostart_2 0x66 + #define hp_autostart_3 0x67 + + + + #define DISABLE 0x00 + #define AUTO_IMMED BIT(5) + #define SELECT BIT(6) + #define RESELECT (BIT(6)+BIT(5)) + #define BUSFREE BIT(7) + #define XFER_0 (BIT(7)+BIT(5)) + #define END_DATA (BIT(7)+BIT(6)) + #define MSG_PHZ (BIT(7)+BIT(6)+BIT(5)) + + #define hp_gp_reg_0 0x68 + #define hp_gp_reg_1 0x69 + #define hp_gp_reg_2 0x6A + #define hp_gp_reg_3 0x6B + + #define hp_seltimeout 0x6C + + + #define TO_2ms 0x54 /* 2.0503ms */ + #define TO_4ms 0x67 /* 3.9959ms */ + + #define TO_5ms 0x03 /* 4.9152ms */ + #define TO_10ms 0x07 /* 11.xxxms */ + #define TO_250ms 0x99 /* 250.68ms */ + #define TO_290ms 0xB1 /* 289.99ms */ + #define TO_350ms 0xD6 /* 350.62ms */ + #define TO_417ms 0xFF /* 417.79ms */ + + #define hp_clkctrl_0 0x6D + + #define PWR_DWN BIT(6) + #define ACTdeassert BIT(4) + #define ATNonErr BIT(3) + #define CLK_30MHZ BIT(1) + #define CLK_40MHZ (BIT(1) + BIT(0)) + #define CLK_50MHZ BIT(2) + + #define CLKCTRL_DEFAULT (ACTdeassert | CLK_40MHZ) + + #define hp_fiforead 0x6E + #define hp_fifowrite 0x6F + + #define hp_offsetctr 0x70 + #define hp_xferstat 0x71 + + #define FIFO_FULL BIT(7) + #define FIFO_EMPTY BIT(6) + #define FIFO_MASK 0x3F /* Mask for the FIFO count value. */ + #define FIFO_LEN 0x20 + + #define hp_portctrl_1 0x72 + + #define EVEN_HOST_P BIT(5) + #define INVT_SCSI BIT(4) + #define CHK_SCSI_P BIT(3) + #define HOST_MODE8 BIT(0) + #define HOST_MODE16 0x00 + + #define hp_xfer_pad 0x73 + + #define ID_UNLOCK BIT(3) + #define XFER_PAD BIT(2) + + #define hp_scsidata_0 0x74 + #define hp_scsidata_1 0x75 + #define hp_timer_0 0x76 + #define hp_timer_1 0x77 + + #define hp_reserved_78 0x78 + #define hp_reserved_79 0x79 + #define hp_reserved_7A 0x7A + #define hp_reserved_7B 0x7B + + #define hp_reserved_7C 0x7C + #define hp_reserved_7D 0x7D + #define hp_reserved_7E 0x7E + #define hp_reserved_7F 0x7F + + #define hp_aramBase 0x80 + #define BIOS_DATA_OFFSET 0x60 + #define BIOS_RELATIVE_CARD 0x64 + + + + + #define AUTO_LEN 0x80 + #define AR0 0x00 + #define AR1 BITW(8) + #define AR2 BITW(9) + #define AR3 (BITW(9) + BITW(8)) + #define SDATA BITW(10) + + #define NOP_OP 0x00 /* Nop command */ + + #define CRD_OP BITW(11) /* Cmp Reg. w/ Data */ + + #define CRR_OP BITW(12) /* Cmp Reg. w. Reg. */ + + #define CBE_OP (BITW(14)+BITW(12)+BITW(11)) /* Cmp SCSI cmd class & Branch EQ */ + + #define CBN_OP (BITW(14)+BITW(13)) /* Cmp SCSI cmd class & Branch NOT EQ */ + + #define CPE_OP (BITW(14)+BITW(11)) /* Cmp SCSI phs & Branch EQ */ + + #define CPN_OP (BITW(14)+BITW(12)) /* Cmp SCSI phs & Branch NOT EQ */ + + + #define ADATA_OUT 0x00 + #define ADATA_IN BITW(8) + #define ACOMMAND BITW(10) + #define ASTATUS (BITW(10)+BITW(8)) + #define AMSG_OUT (BITW(10)+BITW(9)) + #define AMSG_IN (BITW(10)+BITW(9)+BITW(8)) + #define AILLEGAL (BITW(9)+BITW(8)) + + + #define BRH_OP BITW(13) /* Branch */ + + + #define ALWAYS 0x00 + #define EQUAL BITW(8) + #define NOT_EQ BITW(9) + + #define TCB_OP (BITW(13)+BITW(11)) /* Test condition & branch */ + + + #define ATN_SET BITW(8) + #define ATN_RESET BITW(9) + #define XFER_CNT (BITW(9)+BITW(8)) + #define FIFO_0 BITW(10) + #define FIFO_NOT0 (BITW(10)+BITW(8)) + #define T_USE_SYNC0 (BITW(10)+BITW(9)) + + + #define MPM_OP BITW(15) /* Match phase and move data */ + + #define MDR_OP (BITW(12)+BITW(11)) /* Move data to Reg. */ + + #define MRR_OP BITW(14) /* Move DReg. to Reg. */ + + + #define S_IDREG (BIT(2)+BIT(1)+BIT(0)) + + + #define D_AR0 0x00 + #define D_AR1 BIT(0) + #define D_AR2 BIT(1) + #define D_AR3 (BIT(1) + BIT(0)) + #define D_SDATA BIT(2) + #define D_BUCKET (BIT(2) + BIT(1) + BIT(0)) + + + #define ADR_OP (BITW(13)+BITW(12)) /* Logical AND Reg. w. Data */ + + #define ADS_OP (BITW(14)+BITW(13)+BITW(12)) + + #define ODR_OP (BITW(13)+BITW(12)+BITW(11)) + + #define ODS_OP (BITW(14)+BITW(13)+BITW(12)+BITW(11)) + + #define STR_OP (BITW(15)+BITW(14)) /* Store to A_Reg. */ + + #define AINT_ENA1 0x00 + #define AINT_STAT1 BITW(8) + #define ASCSI_SIG BITW(9) + #define ASCSI_CNTL (BITW(9)+BITW(8)) + #define APORT_CNTL BITW(10) + #define ARST_CNTL (BITW(10)+BITW(8)) + #define AXFERCNT0 (BITW(10)+BITW(9)) + #define AXFERCNT1 (BITW(10)+BITW(9)+BITW(8)) + #define AXFERCNT2 BITW(11) + #define AFIFO_DATA (BITW(11)+BITW(8)) + #define ASCSISELID (BITW(11)+BITW(9)) + #define ASCSISYNC0 (BITW(11)+BITW(9)+BITW(8)) + + + #define RAT_OP (BITW(14)+BITW(13)+BITW(11)) + + #define SSI_OP (BITW(15)+BITW(11)) + + + #define SSI_ITAR_DISC (ITAR_DISC >> 8) + #define SSI_IDO_STRT (IDO_STRT >> 8) + #define SSI_IDI_STRT (IDO_STRT >> 8) + + #define SSI_ICMD_COMP (ICMD_COMP >> 8) + #define SSI_ITICKLE (ITICKLE >> 8) + + #define SSI_IUNKWN (IUNKWN >> 8) + #define SSI_INO_CC (IUNKWN >> 8) + #define SSI_IRFAIL (IUNKWN >> 8) + + + #define NP 0x10 /*Next Phase */ + #define NTCMD 0x02 /*Non- Tagged Command start */ + #define CMDPZ 0x04 /*Command phase */ + #define DINT 0x12 /*Data Out/In interrupt */ + #define DI 0x13 /*Data Out */ + #define MI 0x14 /*Message In */ + #define DC 0x19 /*Disconnect Message */ + #define ST 0x1D /*Status Phase */ + #define UNKNWN 0x24 /*Unknown bus action */ + #define CC 0x25 /*Command Completion failure */ + #define TICK 0x26 /*New target reselected us. */ + #define RFAIL 0x27 /*Reselection failed */ + #define SELCHK 0x28 /*Select & Check SCSI ID latch reg */ + + + #define ID_MSG_STRT hp_aramBase + 0x00 + #define NON_TAG_ID_MSG hp_aramBase + 0x06 + #define CMD_STRT hp_aramBase + 0x08 + #define SYNC_MSGS hp_aramBase + 0x08 + + + + + + #define TAG_STRT 0x00 + #define SELECTION_START 0x00 + #define DISCONNECT_START 0x10/2 + #define END_DATA_START 0x14/2 + #define NONTAG_STRT 0x02/2 + #define CMD_ONLY_STRT CMDPZ/2 + #define TICKLE_STRT TICK/2 + #define SELCHK_STRT SELCHK/2 + + + + +#define mEEPROM_CLK_DELAY(port) (RD_HARPOON(port+hp_intstat_1)) + +#define mWAIT_10MS(port) (RD_HARPOON(port+hp_intstat_1)) + + +#define CLR_XFER_CNT(port) (WR_HARPOON(port+hp_xfercnt_0, 0x00)) + +#define SET_XFER_CNT(port, data) (WR_HARP32(port,hp_xfercnt_0,data)) + +#define GET_XFER_CNT(port, xfercnt) {RD_HARP32(port,hp_xfercnt_0,xfercnt); xfercnt &= 0xFFFFFF;} +/* #define GET_XFER_CNT(port, xfercnt) (xfercnt = RD_HARPOON(port+hp_xfercnt_2), \ + xfercnt <<= 16,\ + xfercnt |= RDW_HARPOON((USHORT)(port+hp_xfercnt_0))) + */ +#if defined(DOS) +#define HP_SETUP_ADDR_CNT(port,addr,count) (WRW_HARPOON((USHORT)(port+hp_host_addr_lo), (USHORT)(addr & 0x0000FFFFL)),\ + addr >>= 16,\ + WRW_HARPOON((USHORT)(port+hp_host_addr_hmi), (USHORT)(addr & 0x0000FFFFL)),\ + WR_HARP32(port,hp_xfercnt_0,count),\ + WRW_HARPOON((USHORT)(port+hp_xfer_cnt_lo), (USHORT)(count & 0x0000FFFFL)),\ + count >>= 16,\ + WR_HARPOON(port+hp_xfer_cnt_hi, (count & 0xFF))) +#else +#define HP_SETUP_ADDR_CNT(port,addr,count) (WRW_HARPOON((port+hp_host_addr_lo), (USHORT)(addr & 0x0000FFFFL)),\ + addr >>= 16,\ + WRW_HARPOON((port+hp_host_addr_hmi), (USHORT)(addr & 0x0000FFFFL)),\ + WR_HARP32(port,hp_xfercnt_0,count),\ + WRW_HARPOON((port+hp_xfer_cnt_lo), (USHORT)(count & 0x0000FFFFL)),\ + count >>= 16,\ + WR_HARPOON(port+hp_xfer_cnt_hi, (count & 0xFF))) +#endif + +#define ACCEPT_MSG(port) {while(RD_HARPOON(port+hp_scsisig) & SCSI_REQ){}\ + WR_HARPOON(port+hp_scsisig, S_ILL_PH);} + + +#define ACCEPT_MSG_ATN(port) {while(RD_HARPOON(port+hp_scsisig) & SCSI_REQ){}\ + WR_HARPOON(port+hp_scsisig, (S_ILL_PH|SCSI_ATN));} + +#define ACCEPT_STAT(port) {while(RD_HARPOON(port+hp_scsisig) & SCSI_REQ){}\ + WR_HARPOON(port+hp_scsisig, S_ILL_PH);} + +#define ACCEPT_STAT_ATN(port) {while(RD_HARPOON(port+hp_scsisig) & SCSI_REQ){}\ + WR_HARPOON(port+hp_scsisig, (S_ILL_PH|SCSI_ATN));} + +#define DISABLE_AUTO(port) (WR_HARPOON(port+hp_scsireset, PROG_RESET),\ + WR_HARPOON(port+hp_scsireset, 0x00)) + +#define ARAM_ACCESS(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \ + (RD_HARPOON(p_port+hp_page_ctrl) | SGRAM_ARAM))) + +#define SGRAM_ACCESS(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \ + (RD_HARPOON(p_port+hp_page_ctrl) & ~SGRAM_ARAM))) + +#define MDISABLE_INT(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \ + (RD_HARPOON(p_port+hp_page_ctrl) | G_INT_DISABLE))) + +#define MENABLE_INT(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \ + (RD_HARPOON(p_port+hp_page_ctrl) & ~G_INT_DISABLE))) + + + +#endif + + +#if (FW_TYPE==_UCB_MGR_) +void ReadNVRam(PSCCBcard pCurrCard,PUCB p_ucb); +void WriteNVRam(PSCCBcard pCurrCard,PUCB p_ucb); +void UpdateCheckSum(u32bits baseport); +#endif // (FW_TYPE==_UCB_MGR_) + +#if defined(DOS) +UCHAR sfm(USHORT port, PSCCB pcurrSCCB); +void scsiStartAuto(USHORT port); +UCHAR sisyncn(USHORT port, UCHAR p_card, UCHAR syncFlag); +void ssel(USHORT port, UCHAR p_card); +void sres(USHORT port, UCHAR p_card, PSCCBcard pCurrCard); +void sdecm(UCHAR message, USHORT port, UCHAR p_card); +void shandem(USHORT port, UCHAR p_card,PSCCB pCurrSCCB); +void stsyncn(USHORT port, UCHAR p_card); +void sisyncr(USHORT port,UCHAR sync_pulse, UCHAR offset); +void sssyncv(USHORT p_port, UCHAR p_id, UCHAR p_sync_value, PSCCBMgr_tar_info currTar_Info); +void sresb(USHORT port, UCHAR p_card); +void sxfrp(USHORT p_port, UCHAR p_card); +void schkdd(USHORT port, UCHAR p_card); +UCHAR RdStack(USHORT port, UCHAR index); +void WrStack(USHORT portBase, UCHAR index, UCHAR data); +UCHAR ChkIfChipInitialized(USHORT ioPort); +UCHAR GetTarLun(USHORT port, UCHAR p_card, UCHAR our_target, PSCCBcard pCurrCard, PUCHAR tag, PUCHAR lun); +void SendMsg(USHORT port, UCHAR message); +void queueFlushTargSccb(UCHAR p_card, UCHAR thisTarg, UCHAR error_code); +#else +UCHAR sfm(ULONG port, PSCCB pcurrSCCB); +void scsiStartAuto(ULONG port); +UCHAR sisyncn(ULONG port, UCHAR p_card, UCHAR syncFlag); +void ssel(ULONG port, UCHAR p_card); +void sres(ULONG port, UCHAR p_card, PSCCBcard pCurrCard); +void sdecm(UCHAR message, ULONG port, UCHAR p_card); +void shandem(ULONG port, UCHAR p_card,PSCCB pCurrSCCB); +void stsyncn(ULONG port, UCHAR p_card); +void sisyncr(ULONG port,UCHAR sync_pulse, UCHAR offset); +void sssyncv(ULONG p_port, UCHAR p_id, UCHAR p_sync_value, PSCCBMgr_tar_info currTar_Info); +void sresb(ULONG port, UCHAR p_card); +void sxfrp(ULONG p_port, UCHAR p_card); +void schkdd(ULONG port, UCHAR p_card); +UCHAR RdStack(ULONG port, UCHAR index); +void WrStack(ULONG portBase, UCHAR index, UCHAR data); +UCHAR ChkIfChipInitialized(ULONG ioPort); +UCHAR GetTarLun(ULONG port, UCHAR p_card, UCHAR our_target, PSCCBcard pCurrCard, PUCHAR tar, PUCHAR lun); +void SendMsg(ULONG port, UCHAR message); +void queueFlushTargSccb(UCHAR p_card, UCHAR thisTarg, UCHAR error_code); +#endif + +void ssenss(PSCCBcard pCurrCard); +void sinits(PSCCB p_sccb, UCHAR p_card); +void RNVRamData(PNVRamInfo pNvRamInfo); + +#if defined(WIDE_SCSI) + #if defined(DOS) + UCHAR siwidn(USHORT port, UCHAR p_card); + void stwidn(USHORT port, UCHAR p_card); + void siwidr(USHORT port, UCHAR width); + #else + UCHAR siwidn(ULONG port, UCHAR p_card); + void stwidn(ULONG port, UCHAR p_card); + void siwidr(ULONG port, UCHAR width); + #endif +#endif + + +void queueSelectFail(PSCCBcard pCurrCard, UCHAR p_card); +void queueDisconnect(PSCCB p_SCCB, UCHAR p_card); +void queueCmdComplete(PSCCBcard pCurrCard, PSCCB p_SCCB, UCHAR p_card); +void queueSearchSelect(PSCCBcard pCurrCard, UCHAR p_card); +void queueFlushSccb(UCHAR p_card, UCHAR error_code); +void queueAddSccb(PSCCB p_SCCB, UCHAR card); +UCHAR queueFindSccb(PSCCB p_SCCB, UCHAR p_card); +void utilUpdateResidual(PSCCB p_SCCB); +USHORT CalcCrc16(UCHAR buffer[]); +UCHAR CalcLrc(UCHAR buffer[]); + + +#if defined(DOS) +void Wait1Second(USHORT p_port); +void Wait(USHORT p_port, UCHAR p_delay); +void utilEEWriteOnOff(USHORT p_port,UCHAR p_mode); +void utilEEWrite(USHORT p_port, USHORT ee_data, USHORT ee_addr); +USHORT utilEERead(USHORT p_port, USHORT ee_addr); +void utilEESendCmdAddr(USHORT p_port, UCHAR ee_cmd, USHORT ee_addr); +#else +void Wait1Second(ULONG p_port); +void Wait(ULONG p_port, UCHAR p_delay); +void utilEEWriteOnOff(ULONG p_port,UCHAR p_mode); +void utilEEWrite(ULONG p_port, USHORT ee_data, USHORT ee_addr); +USHORT utilEERead(ULONG p_port, USHORT ee_addr); +void utilEESendCmdAddr(ULONG p_port, UCHAR ee_cmd, USHORT ee_addr); +#endif + + + +#if defined(OS2) + void far phaseDataOut(ULONG port, UCHAR p_card); + void far phaseDataIn(ULONG port, UCHAR p_card); + void far phaseCommand(ULONG port, UCHAR p_card); + void far phaseStatus(ULONG port, UCHAR p_card); + void far phaseMsgOut(ULONG port, UCHAR p_card); + void far phaseMsgIn(ULONG port, UCHAR p_card); + void far phaseIllegal(ULONG port, UCHAR p_card); +#else + #if defined(DOS) + void phaseDataOut(USHORT port, UCHAR p_card); + void phaseDataIn(USHORT port, UCHAR p_card); + void phaseCommand(USHORT port, UCHAR p_card); + void phaseStatus(USHORT port, UCHAR p_card); + void phaseMsgOut(USHORT port, UCHAR p_card); + void phaseMsgIn(USHORT port, UCHAR p_card); + void phaseIllegal(USHORT port, UCHAR p_card); + #else + void phaseDataOut(ULONG port, UCHAR p_card); + void phaseDataIn(ULONG port, UCHAR p_card); + void phaseCommand(ULONG port, UCHAR p_card); + void phaseStatus(ULONG port, UCHAR p_card); + void phaseMsgOut(ULONG port, UCHAR p_card); + void phaseMsgIn(ULONG port, UCHAR p_card); + void phaseIllegal(ULONG port, UCHAR p_card); + #endif +#endif + +#if defined(DOS) +void phaseDecode(USHORT port, UCHAR p_card); +void phaseChkFifo(USHORT port, UCHAR p_card); +void phaseBusFree(USHORT p_port, UCHAR p_card); +#else +void phaseDecode(ULONG port, UCHAR p_card); +void phaseChkFifo(ULONG port, UCHAR p_card); +void phaseBusFree(ULONG p_port, UCHAR p_card); +#endif + + + + +#if defined(DOS) +void XbowInit(USHORT port, UCHAR scamFlg); +void BusMasterInit(USHORT p_port); +int DiagXbow(USHORT port); +int DiagBusMaster(USHORT port); +void DiagEEPROM(USHORT p_port); +#else +void XbowInit(ULONG port, UCHAR scamFlg); +void BusMasterInit(ULONG p_port); +int DiagXbow(ULONG port); +int DiagBusMaster(ULONG port); +void DiagEEPROM(ULONG p_port); +#endif + + + + +#if defined(DOS) +void busMstrAbort(USHORT port); +UCHAR busMstrTimeOut(USHORT port); +void dataXferProcessor(USHORT port, PSCCBcard pCurrCard); +void busMstrSGDataXferStart(USHORT port, PSCCB pCurrSCCB); +void busMstrDataXferStart(USHORT port, PSCCB pCurrSCCB); +void hostDataXferAbort(USHORT port, UCHAR p_card, PSCCB pCurrSCCB); +#else +void busMstrAbort(ULONG port); +UCHAR busMstrTimeOut(ULONG port); +void dataXferProcessor(ULONG port, PSCCBcard pCurrCard); +void busMstrSGDataXferStart(ULONG port, PSCCB pCurrSCCB); +void busMstrDataXferStart(ULONG port, PSCCB pCurrSCCB); +void hostDataXferAbort(ULONG port, UCHAR p_card, PSCCB pCurrSCCB); +#endif +void hostDataXferRestart(PSCCB currSCCB); + + +#if defined (DOS) +UCHAR SccbMgr_bad_isr(USHORT p_port, UCHAR p_card, PSCCBcard pCurrCard, USHORT p_int); +#else +UCHAR SccbMgr_bad_isr(ULONG p_port, UCHAR p_card, PSCCBcard pCurrCard, USHORT p_int); + +#endif + +void SccbMgrTableInitAll(void); +void SccbMgrTableInitCard(PSCCBcard pCurrCard, UCHAR p_card); +void SccbMgrTableInitTarget(UCHAR p_card, UCHAR target); + + + +void scini(UCHAR p_card, UCHAR p_our_id, UCHAR p_power_up); + +#if defined(DOS) +int scarb(USHORT p_port, UCHAR p_sel_type); +void scbusf(USHORT p_port); +void scsel(USHORT p_port); +void scasid(UCHAR p_card, USHORT p_port); +UCHAR scxferc(USHORT p_port, UCHAR p_data); +UCHAR scsendi(USHORT p_port, UCHAR p_id_string[]); +UCHAR sciso(USHORT p_port, UCHAR p_id_string[]); +void scwirod(USHORT p_port, UCHAR p_data_bit); +void scwiros(USHORT p_port, UCHAR p_data_bit); +UCHAR scvalq(UCHAR p_quintet); +UCHAR scsell(USHORT p_port, UCHAR targ_id); +void scwtsel(USHORT p_port); +void inisci(UCHAR p_card, USHORT p_port, UCHAR p_our_id); +void scsavdi(UCHAR p_card, USHORT p_port); +#else +int scarb(ULONG p_port, UCHAR p_sel_type); +void scbusf(ULONG p_port); +void scsel(ULONG p_port); +void scasid(UCHAR p_card, ULONG p_port); +UCHAR scxferc(ULONG p_port, UCHAR p_data); +UCHAR scsendi(ULONG p_port, UCHAR p_id_string[]); +UCHAR sciso(ULONG p_port, UCHAR p_id_string[]); +void scwirod(ULONG p_port, UCHAR p_data_bit); +void scwiros(ULONG p_port, UCHAR p_data_bit); +UCHAR scvalq(UCHAR p_quintet); +UCHAR scsell(ULONG p_port, UCHAR targ_id); +void scwtsel(ULONG p_port); +void inisci(UCHAR p_card, ULONG p_port, UCHAR p_our_id); +void scsavdi(UCHAR p_card, ULONG p_port); +#endif +UCHAR scmachid(UCHAR p_card, UCHAR p_id_string[]); + + +#if defined(DOS) +void autoCmdCmplt(USHORT p_port, UCHAR p_card); +void autoLoadDefaultMap(USHORT p_port); +#else +void autoCmdCmplt(ULONG p_port, UCHAR p_card); +void autoLoadDefaultMap(ULONG p_port); +#endif + + + +#if (FW_TYPE==_SCCB_MGR_) + void OS_start_timer(unsigned long ioport, unsigned long timeout); + void OS_stop_timer(unsigned long ioport, unsigned long timeout); + void OS_disable_int(unsigned char intvec); + void OS_enable_int(unsigned char intvec); + void OS_delay(unsigned long count); + int OS_VirtToPhys(u32bits CardHandle, u32bits *physaddr, u32bits *virtaddr); + #if !(defined(UNIX) || defined(OS2) || defined(SOLARIS_REAL_MODE)) + void OS_Lock(PSCCBMGR_INFO pCardInfo); + void OS_UnLock(PSCCBMGR_INFO pCardInfo); +#endif // if FW_TYPE == ... + +#endif + +extern SCCBCARD BL_Card[MAX_CARDS]; +extern SCCBMGR_TAR_INFO sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR]; + + +#if defined(OS2) + extern void (far *s_PhaseTbl[8]) (ULONG, UCHAR); +#else + #if defined(DOS) + extern void (*s_PhaseTbl[8]) (USHORT, UCHAR); + #else + extern void (*s_PhaseTbl[8]) (ULONG, UCHAR); + #endif +#endif + +extern SCCBSCAM_INFO scamInfo[MAX_SCSI_TAR]; +extern NVRAMINFO nvRamInfo[MAX_MB_CARDS]; +#if defined(DOS) || defined(OS2) +extern UCHAR temp_id_string[ID_STRING_LENGTH]; +#endif +extern UCHAR scamHAString[]; + + +extern UCHAR mbCards; +#if defined(BUGBUG) +extern UCHAR debug_int[MAX_CARDS][debug_size]; +extern UCHAR debug_index[MAX_CARDS]; +void Debug_Load(UCHAR p_card, UCHAR p_bug_data); +#endif + +#if (FW_TYPE==_SCCB_MGR_) +#if defined(DOS) + extern UCHAR first_time; +#endif +#endif /* (FW_TYPE==_SCCB_MGR_) */ + +#if (FW_TYPE==_UCB_MGR_) +#if defined(DOS) + extern u08bits first_time; +#endif +#endif /* (FW_TYPE==_UCB_MGR_) */ + +#if defined(BUGBUG) +void Debug_Load(UCHAR p_card, UCHAR p_bug_data); +#endif + +extern unsigned int SccbGlobalFlags; + + +#ident "$Id: sccb.c 1.17 1997/02/11 21:06:41 mohan Exp $" +/*---------------------------------------------------------------------- + * + * + * Copyright 1995-1996 by Mylex Corporation. All Rights Reserved + * + * This file is available under both the GNU General Public License + * and a BSD-style copyright; see LICENSE.FlashPoint for details. + * + * $Workfile: sccb.c $ + * + * Description: Functions relating to handling of the SCCB interface + * between the device driver and the HARPOON. + * + * $Date: 1997/02/11 21:06:41 $ + * + * $Revision: 1.17 $ + * + *----------------------------------------------------------------------*/ + +/*#include */ + +#if (FW_TYPE==_UCB_MGR_) + /*#include */ + /*#include */ +#endif + +/*#include */ +/*#include */ +/*#include */ +/*#include */ +/*#include */ +/*#include */ + + + +#if (FW_TYPE==_SCCB_MGR_) +#define mOS_Lock(card) OS_Lock((PSCCBMGR_INFO)(((PSCCBcard)card)->cardInfo)) +#define mOS_UnLock(card) OS_UnLock((PSCCBMGR_INFO)(((PSCCBcard)card)->cardInfo)) +#else /* FW_TYPE==_UCB_MGR_ */ +#define mOS_Lock(card) OS_Lock((u32bits)(((PSCCBcard)card)->ioPort)) +#define mOS_UnLock(card) OS_UnLock((u32bits)(((PSCCBcard)card)->ioPort)) +#endif + + +/* +extern SCCBMGR_TAR_INFO sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR]; +extern SCCBCARD BL_Card[MAX_CARDS]; + +extern NVRAMINFO nvRamInfo[MAX_MB_CARDS]; +extern UCHAR mbCards; + +#if defined (OS2) + extern void (far *s_PhaseTbl[8]) (ULONG, UCHAR); +#else + #if defined(DOS) + extern void (*s_PhaseTbl[8]) (USHORT, UCHAR); + #else + extern void (*s_PhaseTbl[8]) (ULONG, UCHAR); + #endif +#endif + + +#if defined(BUGBUG) +extern UCHAR debug_int[MAX_CARDS][debug_size]; +extern UCHAR debug_index[MAX_CARDS]; +void Debug_Load(UCHAR p_card, UCHAR p_bug_data); +#endif +*/ + +#if (FW_TYPE==_SCCB_MGR_) + +/*--------------------------------------------------------------------- + * + * Function: SccbMgr_sense_adapter + * + * Description: Setup and/or Search for cards and return info to caller. + * + *---------------------------------------------------------------------*/ + +int SccbMgr_sense_adapter(PSCCBMGR_INFO pCardInfo) +{ +#if defined(DOS) +#else + static UCHAR first_time = 1; +#endif + + UCHAR i,j,id,ScamFlg; + USHORT temp,temp2,temp3,temp4,temp5,temp6; +#if defined(DOS) + USHORT ioport; +#else + ULONG ioport; +#endif + PNVRamInfo pCurrNvRam; + +#if defined(DOS) + ioport = (USHORT)pCardInfo->si_baseaddr; +#else + ioport = pCardInfo->si_baseaddr; +#endif + + + if (RD_HARPOON(ioport+hp_vendor_id_0) != ORION_VEND_0) + return((int)FAILURE); + + if ((RD_HARPOON(ioport+hp_vendor_id_1) != ORION_VEND_1)) + return((int)FAILURE); + + if ((RD_HARPOON(ioport+hp_device_id_0) != ORION_DEV_0)) + return((int)FAILURE); + + if ((RD_HARPOON(ioport+hp_device_id_1) != ORION_DEV_1)) + return((int)FAILURE); + + + if (RD_HARPOON(ioport+hp_rev_num) != 0x0f){ + +/* For new Harpoon then check for sub_device ID LSB + the bits(0-3) must be all ZERO for compatible with + current version of SCCBMgr, else skip this Harpoon + device. */ + + if (RD_HARPOON(ioport+hp_sub_device_id_0) & 0x0f) + return((int)FAILURE); + } + + if (first_time) + { + SccbMgrTableInitAll(); + first_time = 0; + mbCards = 0; + } + + if(RdStack(ioport, 0) != 0x00) { + if(ChkIfChipInitialized(ioport) == FALSE) + { + pCurrNvRam = NULL; + XbowInit(ioport, 0); /*Must Init the SCSI before attempting */ + DiagEEPROM(ioport); + } + else + { + if(mbCards < MAX_MB_CARDS) { + pCurrNvRam = &nvRamInfo[mbCards]; + mbCards++; + pCurrNvRam->niBaseAddr = ioport; + RNVRamData(pCurrNvRam); + }else + return((int) FAILURE); + } + }else + pCurrNvRam = NULL; +#if defined (NO_BIOS_OPTION) + pCurrNvRam = NULL; + XbowInit(ioport, 0); /*Must Init the SCSI before attempting */ + DiagEEPROM(ioport); +#endif /* No BIOS Option */ + + WR_HARPOON(ioport+hp_clkctrl_0, CLKCTRL_DEFAULT); + WR_HARPOON(ioport+hp_sys_ctrl, 0x00); + + if(pCurrNvRam) + pCardInfo->si_id = pCurrNvRam->niAdapId; + else + pCardInfo->si_id = (UCHAR)(utilEERead(ioport, (ADAPTER_SCSI_ID/2)) & + (UCHAR)0x0FF); + + pCardInfo->si_lun = 0x00; + pCardInfo->si_fw_revision = ORION_FW_REV; + temp2 = 0x0000; + temp3 = 0x0000; + temp4 = 0x0000; + temp5 = 0x0000; + temp6 = 0x0000; + + for (id = 0; id < (16/2); id++) { + + if(pCurrNvRam){ + temp = (USHORT) pCurrNvRam->niSyncTbl[id]; + temp = ((temp & 0x03) + ((temp << 4) & 0xc0)) + + (((temp << 4) & 0x0300) + ((temp << 8) & 0xc000)); + }else + temp = utilEERead(ioport, (USHORT)((SYNC_RATE_TBL/2)+id)); + + for (i = 0; i < 2; temp >>=8,i++) { + + temp2 >>= 1; + temp3 >>= 1; + temp4 >>= 1; + temp5 >>= 1; + temp6 >>= 1; + switch (temp & 0x3) + { + case AUTO_RATE_20: /* Synchronous, 20 mega-transfers/second */ + temp6 |= 0x8000; /* Fall through */ + case AUTO_RATE_10: /* Synchronous, 10 mega-transfers/second */ + temp5 |= 0x8000; /* Fall through */ + case AUTO_RATE_05: /* Synchronous, 5 mega-transfers/second */ + temp2 |= 0x8000; /* Fall through */ + case AUTO_RATE_00: /* Asynchronous */ + break; + } + + if (temp & DISC_ENABLE_BIT) + temp3 |= 0x8000; + + if (temp & WIDE_NEGO_BIT) + temp4 |= 0x8000; + + } + } + + pCardInfo->si_per_targ_init_sync = temp2; + pCardInfo->si_per_targ_no_disc = temp3; + pCardInfo->si_per_targ_wide_nego = temp4; + pCardInfo->si_per_targ_fast_nego = temp5; + pCardInfo->si_per_targ_ultra_nego = temp6; + + if(pCurrNvRam) + i = pCurrNvRam->niSysConf; + else + i = (UCHAR)(utilEERead(ioport, (SYSTEM_CONFIG/2))); + + if(pCurrNvRam) + ScamFlg = pCurrNvRam->niScamConf; + else + ScamFlg = (UCHAR) utilEERead(ioport, SCAM_CONFIG/2); + + pCardInfo->si_flags = 0x0000; + + if (i & 0x01) + pCardInfo->si_flags |= SCSI_PARITY_ENA; + + if (!(i & 0x02)) + pCardInfo->si_flags |= SOFT_RESET; + + if (i & 0x10) + pCardInfo->si_flags |= EXTENDED_TRANSLATION; + + if (ScamFlg & SCAM_ENABLED) + pCardInfo->si_flags |= FLAG_SCAM_ENABLED; + + if (ScamFlg & SCAM_LEVEL2) + pCardInfo->si_flags |= FLAG_SCAM_LEVEL2; + + j = (RD_HARPOON(ioport+hp_bm_ctrl) & ~SCSI_TERM_ENA_L); + if (i & 0x04) { + j |= SCSI_TERM_ENA_L; + } + WR_HARPOON(ioport+hp_bm_ctrl, j ); + + j = (RD_HARPOON(ioport+hp_ee_ctrl) & ~SCSI_TERM_ENA_H); + if (i & 0x08) { + j |= SCSI_TERM_ENA_H; + } + WR_HARPOON(ioport+hp_ee_ctrl, j ); + + if (!(RD_HARPOON(ioport+hp_page_ctrl) & NARROW_SCSI_CARD)) + + pCardInfo->si_flags |= SUPPORT_16TAR_32LUN; + + pCardInfo->si_card_family = HARPOON_FAMILY; + pCardInfo->si_bustype = BUSTYPE_PCI; + + if(pCurrNvRam){ + pCardInfo->si_card_model[0] = '9'; + switch(pCurrNvRam->niModel & 0x0f){ + case MODEL_LT: + pCardInfo->si_card_model[1] = '3'; + pCardInfo->si_card_model[2] = '0'; + break; + case MODEL_LW: + pCardInfo->si_card_model[1] = '5'; + pCardInfo->si_card_model[2] = '0'; + break; + case MODEL_DL: + pCardInfo->si_card_model[1] = '3'; + pCardInfo->si_card_model[2] = '2'; + break; + case MODEL_DW: + pCardInfo->si_card_model[1] = '5'; + pCardInfo->si_card_model[2] = '2'; + break; + } + }else{ + temp = utilEERead(ioport, (MODEL_NUMB_0/2)); + pCardInfo->si_card_model[0] = (UCHAR)(temp >> 8); + temp = utilEERead(ioport, (MODEL_NUMB_2/2)); + + pCardInfo->si_card_model[1] = (UCHAR)(temp & 0x00FF); + pCardInfo->si_card_model[2] = (UCHAR)(temp >> 8); + } + + if (pCardInfo->si_card_model[1] == '3') + { + if (RD_HARPOON(ioport+hp_ee_ctrl) & BIT(7)) + pCardInfo->si_flags |= LOW_BYTE_TERM; + } + else if (pCardInfo->si_card_model[2] == '0') + { + temp = RD_HARPOON(ioport+hp_xfer_pad); + WR_HARPOON(ioport+hp_xfer_pad, (temp & ~BIT(4))); + if (RD_HARPOON(ioport+hp_ee_ctrl) & BIT(7)) + pCardInfo->si_flags |= LOW_BYTE_TERM; + WR_HARPOON(ioport+hp_xfer_pad, (temp | BIT(4))); + if (RD_HARPOON(ioport+hp_ee_ctrl) & BIT(7)) + pCardInfo->si_flags |= HIGH_BYTE_TERM; + WR_HARPOON(ioport+hp_xfer_pad, temp); + } + else + { + temp = RD_HARPOON(ioport+hp_ee_ctrl); + temp2 = RD_HARPOON(ioport+hp_xfer_pad); + WR_HARPOON(ioport+hp_ee_ctrl, (temp | SEE_CS)); + WR_HARPOON(ioport+hp_xfer_pad, (temp2 | BIT(4))); + temp3 = 0; + for (i = 0; i < 8; i++) + { + temp3 <<= 1; + if (!(RD_HARPOON(ioport+hp_ee_ctrl) & BIT(7))) + temp3 |= 1; + WR_HARPOON(ioport+hp_xfer_pad, (temp2 & ~BIT(4))); + WR_HARPOON(ioport+hp_xfer_pad, (temp2 | BIT(4))); + } + WR_HARPOON(ioport+hp_ee_ctrl, temp); + WR_HARPOON(ioport+hp_xfer_pad, temp2); + if (!(temp3 & BIT(7))) + pCardInfo->si_flags |= LOW_BYTE_TERM; + if (!(temp3 & BIT(6))) + pCardInfo->si_flags |= HIGH_BYTE_TERM; + } + + + ARAM_ACCESS(ioport); + + for ( i = 0; i < 4; i++ ) { + + pCardInfo->si_XlatInfo[i] = + RD_HARPOON(ioport+hp_aramBase+BIOS_DATA_OFFSET+i); + } + + /* return with -1 if no sort, else return with + logical card number sorted by BIOS (zero-based) */ + + pCardInfo->si_relative_cardnum = + (UCHAR)(RD_HARPOON(ioport+hp_aramBase+BIOS_RELATIVE_CARD)-1); + + SGRAM_ACCESS(ioport); + + s_PhaseTbl[0] = phaseDataOut; + s_PhaseTbl[1] = phaseDataIn; + s_PhaseTbl[2] = phaseIllegal; + s_PhaseTbl[3] = phaseIllegal; + s_PhaseTbl[4] = phaseCommand; + s_PhaseTbl[5] = phaseStatus; + s_PhaseTbl[6] = phaseMsgOut; + s_PhaseTbl[7] = phaseMsgIn; + + pCardInfo->si_present = 0x01; + +#if defined(BUGBUG) + + + for (i = 0; i < MAX_CARDS; i++) { + + for (id=0; idsi_baseaddr; +#else + ioport = pCardInfo->si_baseaddr; +#endif + + for(thisCard =0; thisCard <= MAX_CARDS; thisCard++) { + + if (thisCard == MAX_CARDS) { + + return(FAILURE); + } + + if (BL_Card[thisCard].ioPort == ioport) { + + CurrCard = &BL_Card[thisCard]; + SccbMgrTableInitCard(CurrCard,thisCard); + break; + } + + else if (BL_Card[thisCard].ioPort == 0x00) { + + BL_Card[thisCard].ioPort = ioport; + CurrCard = &BL_Card[thisCard]; + + if(mbCards) + for(i = 0; i < mbCards; i++){ + if(CurrCard->ioPort == nvRamInfo[i].niBaseAddr) + CurrCard->pNvRamInfo = &nvRamInfo[i]; + } + SccbMgrTableInitCard(CurrCard,thisCard); + CurrCard->cardIndex = thisCard; + CurrCard->cardInfo = pCardInfo; + + break; + } + } + + pCurrNvRam = CurrCard->pNvRamInfo; + + if(pCurrNvRam){ + ScamFlg = pCurrNvRam->niScamConf; + } + else{ + ScamFlg = (UCHAR) utilEERead(ioport, SCAM_CONFIG/2); + } + + + BusMasterInit(ioport); + XbowInit(ioport, ScamFlg); + +#if defined (NO_BIOS_OPTION) + + + if (DiagXbow(ioport)) return(FAILURE); + if (DiagBusMaster(ioport)) return(FAILURE); + +#endif /* No BIOS Option */ + + autoLoadDefaultMap(ioport); + + + for (i = 0,id = 0x01; i != pCardInfo->si_id; i++,id <<= 1){} + + WR_HARPOON(ioport+hp_selfid_0, id); + WR_HARPOON(ioport+hp_selfid_1, 0x00); + WR_HARPOON(ioport+hp_arb_id, pCardInfo->si_id); + CurrCard->ourId = pCardInfo->si_id; + + i = (UCHAR) pCardInfo->si_flags; + if (i & SCSI_PARITY_ENA) + WR_HARPOON(ioport+hp_portctrl_1,(HOST_MODE8 | CHK_SCSI_P)); + + j = (RD_HARPOON(ioport+hp_bm_ctrl) & ~SCSI_TERM_ENA_L); + if (i & LOW_BYTE_TERM) + j |= SCSI_TERM_ENA_L; + WR_HARPOON(ioport+hp_bm_ctrl, j); + + j = (RD_HARPOON(ioport+hp_ee_ctrl) & ~SCSI_TERM_ENA_H); + if (i & HIGH_BYTE_TERM) + j |= SCSI_TERM_ENA_H; + WR_HARPOON(ioport+hp_ee_ctrl, j ); + + + if (!(pCardInfo->si_flags & SOFT_RESET)) { + + sresb(ioport,thisCard); + + scini(thisCard, pCardInfo->si_id, 0); + } + + + + if (pCardInfo->si_flags & POST_ALL_UNDERRRUNS) + CurrCard->globalFlags |= F_NO_FILTER; + + if(pCurrNvRam){ + if(pCurrNvRam->niSysConf & 0x10) + CurrCard->globalFlags |= F_GREEN_PC; + } + else{ + if (utilEERead(ioport, (SYSTEM_CONFIG/2)) & GREEN_PC_ENA) + CurrCard->globalFlags |= F_GREEN_PC; + } + + /* Set global flag to indicate Re-Negotiation to be done on all + ckeck condition */ + if(pCurrNvRam){ + if(pCurrNvRam->niScsiConf & 0x04) + CurrCard->globalFlags |= F_DO_RENEGO; + } + else{ + if (utilEERead(ioport, (SCSI_CONFIG/2)) & RENEGO_ENA) + CurrCard->globalFlags |= F_DO_RENEGO; + } + + if(pCurrNvRam){ + if(pCurrNvRam->niScsiConf & 0x08) + CurrCard->globalFlags |= F_CONLUN_IO; + } + else{ + if (utilEERead(ioport, (SCSI_CONFIG/2)) & CONNIO_ENA) + CurrCard->globalFlags |= F_CONLUN_IO; + } + + + temp = pCardInfo->si_per_targ_no_disc; + + for (i = 0,id = 1; i < MAX_SCSI_TAR; i++, id <<= 1) { + + if (temp & id) + sccbMgrTbl[thisCard][i].TarStatus |= TAR_ALLOW_DISC; + } + + sync_bit_map = 0x0001; + + for (id = 0; id < (MAX_SCSI_TAR/2); id++) { + + if(pCurrNvRam){ + temp = (USHORT) pCurrNvRam->niSyncTbl[id]; + temp = ((temp & 0x03) + ((temp << 4) & 0xc0)) + + (((temp << 4) & 0x0300) + ((temp << 8) & 0xc000)); + }else + temp = utilEERead(ioport, (USHORT)((SYNC_RATE_TBL/2)+id)); + + for (i = 0; i < 2; temp >>=8,i++) { + + if (pCardInfo->si_per_targ_init_sync & sync_bit_map) { + + sccbMgrTbl[thisCard][id*2+i].TarEEValue = (UCHAR)temp; + } + + else { + sccbMgrTbl[thisCard][id*2+i].TarStatus |= SYNC_SUPPORTED; + sccbMgrTbl[thisCard][id*2+i].TarEEValue = + (UCHAR)(temp & ~EE_SYNC_MASK); + } + +#if defined(WIDE_SCSI) +/* if ((pCardInfo->si_per_targ_wide_nego & sync_bit_map) || + (id*2+i >= 8)){ +*/ + if (pCardInfo->si_per_targ_wide_nego & sync_bit_map){ + + sccbMgrTbl[thisCard][id*2+i].TarEEValue |= EE_WIDE_SCSI; + + } + + else { /* NARROW SCSI */ + sccbMgrTbl[thisCard][id*2+i].TarStatus |= WIDE_NEGOCIATED; + } + +#else + sccbMgrTbl[thisCard][id*2+i].TarStatus |= WIDE_NEGOCIATED; +#endif + + + sync_bit_map <<= 1; + + + + } + } + + WR_HARPOON((ioport+hp_semaphore), + (UCHAR)(RD_HARPOON((ioport+hp_semaphore)) | SCCB_MGR_PRESENT)); + +#if defined(DOS) + return((USHORT)CurrCard); +#else + return((ULONG)CurrCard); +#endif +} + +#else /* end (FW_TYPE==_SCCB_MGR_) */ + + + +STATIC s16bits FP_PresenceCheck(PMGR_INFO pMgrInfo) +{ + PMGR_ENTRYPNTS pMgr_EntryPnts = &pMgrInfo->mi_Functions; + + pMgr_EntryPnts->UCBMgr_probe_adapter = probe_adapter; + pMgr_EntryPnts->UCBMgr_init_adapter = init_adapter; + pMgr_EntryPnts->UCBMgr_start_UCB = SccbMgr_start_sccb; + pMgr_EntryPnts->UCBMgr_build_UCB = build_UCB; + pMgr_EntryPnts->UCBMgr_abort_UCB = SccbMgr_abort_sccb; + pMgr_EntryPnts->UCBMgr_my_int = SccbMgr_my_int; + pMgr_EntryPnts->UCBMgr_isr = SccbMgr_isr; + pMgr_EntryPnts->UCBMgr_scsi_reset = SccbMgr_scsi_reset; + pMgr_EntryPnts->UCBMgr_timer_expired = SccbMgr_timer_expired; +#ifndef NO_IOCTLS + pMgr_EntryPnts->UCBMgr_unload_card = SccbMgr_unload_card; + pMgr_EntryPnts->UCBMgr_save_foreign_state = + SccbMgr_save_foreign_state; + pMgr_EntryPnts->UCBMgr_restore_foreign_state = + SccbMgr_restore_foreign_state; + pMgr_EntryPnts->UCBMgr_restore_native_state = + SccbMgr_restore_native_state; +#endif /*NO_IOCTLS*/ + + pMgrInfo->mi_SGListFormat=0x01; + pMgrInfo->mi_DataPtrFormat=0x01; + pMgrInfo->mi_MaxSGElements= (u16bits) 0xffffffff; + pMgrInfo->mi_MgrPrivateLen=sizeof(SCCB); + pMgrInfo->mi_PCIVendorID=BL_VENDOR_ID; + pMgrInfo->mi_PCIDeviceID=FP_DEVICE_ID; + pMgrInfo->mi_MgrAttributes= ATTR_IO_MAPPED + + ATTR_PHYSICAL_ADDRESS + + ATTR_VIRTUAL_ADDRESS + + ATTR_OVERLAPPED_IO_IOCTLS_OK; + pMgrInfo->mi_IoRangeLen = 256; + return(0); +} + + + +/*--------------------------------------------------------------------- + * + * Function: probe_adapter + * + * Description: Setup and/or Search for cards and return info to caller. + * + *---------------------------------------------------------------------*/ +STATIC s32bits probe_adapter(PADAPTER_INFO pAdapterInfo) +{ + u16bits temp,temp2,temp3,temp4; + u08bits i,j,id; + +#if defined(DOS) +#else + static u08bits first_time = 1; +#endif + BASE_PORT ioport; + PNVRamInfo pCurrNvRam; + + ioport = (BASE_PORT)pAdapterInfo->ai_baseaddr; + + + + if (RD_HARPOON(ioport+hp_vendor_id_0) != ORION_VEND_0) + return(1); + + if ((RD_HARPOON(ioport+hp_vendor_id_1) != ORION_VEND_1)) + return(2); + + if ((RD_HARPOON(ioport+hp_device_id_0) != ORION_DEV_0)) + return(3); + + if ((RD_HARPOON(ioport+hp_device_id_1) != ORION_DEV_1)) + return(4); + + + if (RD_HARPOON(ioport+hp_rev_num) != 0x0f){ + + +/* For new Harpoon then check for sub_device ID LSB + the bits(0-3) must be all ZERO for compatible with + current version of SCCBMgr, else skip this Harpoon + device. */ + + if (RD_HARPOON(ioport+hp_sub_device_id_0) & 0x0f) + return(5); + } + + if (first_time) { + + SccbMgrTableInitAll(); + first_time = 0; + mbCards = 0; + } + + if(RdStack(ioport, 0) != 0x00) { + if(ChkIfChipInitialized(ioport) == FALSE) + { + pCurrNvRam = NULL; + XbowInit(ioport, 0); /*Must Init the SCSI before attempting */ + DiagEEPROM(ioport); + } + else + { + if(mbCards < MAX_MB_CARDS) { + pCurrNvRam = &nvRamInfo[mbCards]; + mbCards++; + pCurrNvRam->niBaseAddr = ioport; + RNVRamData(pCurrNvRam); + }else + return((int) FAILURE); + } + }else + pCurrNvRam = NULL; + +#if defined (NO_BIOS_OPTION) + pCurrNvRam = NULL; + XbowInit(ioport, 0); /*Must Init the SCSI before attempting */ + DiagEEPROM(ioport); +#endif /* No BIOS Option */ + + WR_HARPOON(ioport+hp_clkctrl_0, CLKCTRL_DEFAULT); + WR_HARPOON(ioport+hp_sys_ctrl, 0x00); + + if(pCurrNvRam) + pAdapterInfo->ai_id = pCurrNvRam->niAdapId; + else + pAdapterInfo->ai_id = (u08bits)(utilEERead(ioport, (ADAPTER_SCSI_ID/2)) & + (u08bits)0x0FF); + + pAdapterInfo->ai_lun = 0x00; + pAdapterInfo->ai_fw_revision[0] = '3'; + pAdapterInfo->ai_fw_revision[1] = '1'; + pAdapterInfo->ai_fw_revision[2] = '1'; + pAdapterInfo->ai_fw_revision[3] = ' '; + pAdapterInfo->ai_NumChannels = 1; + + temp2 = 0x0000; + temp3 = 0x0000; + temp4 = 0x0000; + + for (id = 0; id < (16/2); id++) { + + if(pCurrNvRam){ + temp = (USHORT) pCurrNvRam->niSyncTbl[id]; + temp = ((temp & 0x03) + ((temp << 4) & 0xc0)) + + (((temp << 4) & 0x0300) + ((temp << 8) & 0xc000)); + }else + temp = utilEERead(ioport, (u16bits)((SYNC_RATE_TBL/2)+id)); + + for (i = 0; i < 2; temp >>=8,i++) { + + if ((temp & 0x03) != AUTO_RATE_00) { + + temp2 >>= 0x01; + temp2 |= 0x8000; + } + + else { + temp2 >>= 0x01; + } + + if (temp & DISC_ENABLE_BIT) { + + temp3 >>= 0x01; + temp3 |= 0x8000; + } + + else { + temp3 >>= 0x01; + } + + if (temp & WIDE_NEGO_BIT) { + + temp4 >>= 0x01; + temp4 |= 0x8000; + } + + else { + temp4 >>= 0x01; + } + + } + } + + pAdapterInfo->ai_per_targ_init_sync = temp2; + pAdapterInfo->ai_per_targ_no_disc = temp3; + pAdapterInfo->ai_per_targ_wide_nego = temp4; + if(pCurrNvRam) + i = pCurrNvRam->niSysConf; + else + i = (u08bits)(utilEERead(ioport, (SYSTEM_CONFIG/2))); + + /* + ** interrupts always level-triggered for FlashPoint + */ + pAdapterInfo->ai_stateinfo |= LEVEL_TRIG; + + if (i & 0x01) + pAdapterInfo->ai_stateinfo |= SCSI_PARITY_ENA; + + if (i & 0x02) /* SCSI Bus reset in AutoSCSI Set ? */ + { + if(pCurrNvRam) + { + j = pCurrNvRam->niScamConf; + } + else + { + j = (u08bits) utilEERead(ioport, SCAM_CONFIG/2); + } + if(j & SCAM_ENABLED) + { + if(j & SCAM_LEVEL2) + { + pAdapterInfo->ai_stateinfo |= SCAM2_ENA; + } + else + { + pAdapterInfo->ai_stateinfo |= SCAM1_ENA; + } + } + } + j = (RD_HARPOON(ioport+hp_bm_ctrl) & ~SCSI_TERM_ENA_L); + if (i & 0x04) { + j |= SCSI_TERM_ENA_L; + pAdapterInfo->ai_stateinfo |= LOW_BYTE_TERM_ENA; + } + WR_HARPOON(ioport+hp_bm_ctrl, j ); + + j = (RD_HARPOON(ioport+hp_ee_ctrl) & ~SCSI_TERM_ENA_H); + if (i & 0x08) { + j |= SCSI_TERM_ENA_H; + pAdapterInfo->ai_stateinfo |= HIGH_BYTE_TERM_ENA; + } + WR_HARPOON(ioport+hp_ee_ctrl, j ); + + if(RD_HARPOON(ioport + hp_page_ctrl) & BIOS_SHADOW) + { + pAdapterInfo->ai_FlashRomSize = 64 * 1024; /* 64k Rom */ + } + else + { + pAdapterInfo->ai_FlashRomSize = 32 * 1024; /* 32k Rom */ + } + + pAdapterInfo->ai_stateinfo |= (FAST20_ENA | TAG_QUEUE_ENA); + if (!(RD_HARPOON(ioport+hp_page_ctrl) & NARROW_SCSI_CARD)) + { + pAdapterInfo->ai_attributes |= (WIDE_CAPABLE | FAST20_CAPABLE + | SCAM2_CAPABLE + | TAG_QUEUE_CAPABLE + | SUPRESS_UNDERRRUNS_CAPABLE + | SCSI_PARITY_CAPABLE); + pAdapterInfo->ai_MaxTarg = 16; + pAdapterInfo->ai_MaxLun = 32; + } + else + { + pAdapterInfo->ai_attributes |= (FAST20_CAPABLE | SCAM2_CAPABLE + | TAG_QUEUE_CAPABLE + | SUPRESS_UNDERRRUNS_CAPABLE + | SCSI_PARITY_CAPABLE); + pAdapterInfo->ai_MaxTarg = 8; + pAdapterInfo->ai_MaxLun = 8; + } + + pAdapterInfo->ai_product_family = HARPOON_FAMILY; + pAdapterInfo->ai_HBAbustype = BUSTYPE_PCI; + + for (i=0;iai_card_model[i]=' '; /* initialize the ai_card_model */ + } + + if(pCurrNvRam){ + pAdapterInfo->ai_card_model[0] = '9'; + switch(pCurrNvRam->niModel & 0x0f){ + case MODEL_LT: + pAdapterInfo->ai_card_model[1] = '3'; + pAdapterInfo->ai_card_model[2] = '0'; + break; + case MODEL_LW: + pAdapterInfo->ai_card_model[1] = '5'; + pAdapterInfo->ai_card_model[2] = '0'; + break; + case MODEL_DL: + pAdapterInfo->ai_card_model[1] = '3'; + pAdapterInfo->ai_card_model[2] = '2'; + break; + case MODEL_DW: + pAdapterInfo->ai_card_model[1] = '5'; + pAdapterInfo->ai_card_model[2] = '2'; + break; + } + }else{ + temp = utilEERead(ioport, (MODEL_NUMB_0/2)); + pAdapterInfo->ai_card_model[0] = (u08bits)(temp >> 8); + temp = utilEERead(ioport, (MODEL_NUMB_2/2)); + + pAdapterInfo->ai_card_model[1] = (u08bits)(temp & 0x00FF); + pAdapterInfo->ai_card_model[2] = (u08bits)(temp >> 8); + } + + + + pAdapterInfo->ai_FiberProductType = 0; + + pAdapterInfo->ai_secondary_range = 0; + + for (i=0;iai_worldwidename[i]='\0'; + } + + for (i=0;iai_vendorstring[i]='\0'; + } + pAdapterInfo->ai_vendorstring[0]='B'; + pAdapterInfo->ai_vendorstring[1]='U'; + pAdapterInfo->ai_vendorstring[2]='S'; + pAdapterInfo->ai_vendorstring[3]='L'; + pAdapterInfo->ai_vendorstring[4]='O'; + pAdapterInfo->ai_vendorstring[5]='G'; + pAdapterInfo->ai_vendorstring[6]='I'; + pAdapterInfo->ai_vendorstring[7]='C'; + + for (i=0;iai_AdapterFamilyString[i]='\0'; + } + pAdapterInfo->ai_AdapterFamilyString[0]='F'; + pAdapterInfo->ai_AdapterFamilyString[1]='L'; + pAdapterInfo->ai_AdapterFamilyString[2]='A'; + pAdapterInfo->ai_AdapterFamilyString[3]='S'; + pAdapterInfo->ai_AdapterFamilyString[4]='H'; + pAdapterInfo->ai_AdapterFamilyString[5]='P'; + pAdapterInfo->ai_AdapterFamilyString[6]='O'; + pAdapterInfo->ai_AdapterFamilyString[7]='I'; + pAdapterInfo->ai_AdapterFamilyString[8]='N'; + pAdapterInfo->ai_AdapterFamilyString[9]='T'; + + ARAM_ACCESS(ioport); + + for ( i = 0; i < 4; i++ ) { + + pAdapterInfo->ai_XlatInfo[i] = + RD_HARPOON(ioport+hp_aramBase+BIOS_DATA_OFFSET+i); + } + + /* return with -1 if no sort, else return with + logical card number sorted by BIOS (zero-based) */ + + + pAdapterInfo->ai_relative_cardnum = + (u08bits)(RD_HARPOON(ioport+hp_aramBase+BIOS_RELATIVE_CARD)-1); + + SGRAM_ACCESS(ioport); + + s_PhaseTbl[0] = phaseDataOut; + s_PhaseTbl[1] = phaseDataIn; + s_PhaseTbl[2] = phaseIllegal; + s_PhaseTbl[3] = phaseIllegal; + s_PhaseTbl[4] = phaseCommand; + s_PhaseTbl[5] = phaseStatus; + s_PhaseTbl[6] = phaseMsgOut; + s_PhaseTbl[7] = phaseMsgIn; + + pAdapterInfo->ai_present = 0x01; + +#if defined(BUGBUG) + + + for (i = 0; i < MAX_CARDS; i++) { + + for (id=0; idai_baseaddr; + + for(thisCard =0; thisCard <= MAX_CARDS; thisCard++) { + + if (thisCard == MAX_CARDS) { + + return(FAILURE); + } + + if (BL_Card[thisCard].ioPort == ioport) { + + CurrCard = &BL_Card[thisCard]; + SccbMgrTableInitCard(CurrCard,thisCard); + break; + } + + else if (BL_Card[thisCard].ioPort == 0x00) { + + BL_Card[thisCard].ioPort = ioport; + CurrCard = &BL_Card[thisCard]; + + if(mbCards) + for(i = 0; i < mbCards; i++){ + if(CurrCard->ioPort == nvRamInfo[i].niBaseAddr) + CurrCard->pNvRamInfo = &nvRamInfo[i]; + } + SccbMgrTableInitCard(CurrCard,thisCard); + CurrCard->cardIndex = thisCard; + CurrCard->cardInfo = pCardInfo; + + break; + } + } + + pCurrNvRam = CurrCard->pNvRamInfo; + + + if(pCurrNvRam){ + ScamFlg = pCurrNvRam->niScamConf; + } + else{ + ScamFlg = (UCHAR) utilEERead(ioport, SCAM_CONFIG/2); + } + + + BusMasterInit(ioport); + XbowInit(ioport, ScamFlg); + +#if defined (NO_BIOS_OPTION) + + + if (DiagXbow(ioport)) return(FAILURE); + if (DiagBusMaster(ioport)) return(FAILURE); + +#endif /* No BIOS Option */ + + autoLoadDefaultMap(ioport); + + + for (i = 0,id = 0x01; i != pCardInfo->ai_id; i++,id <<= 1){} + + WR_HARPOON(ioport+hp_selfid_0, id); + WR_HARPOON(ioport+hp_selfid_1, 0x00); + WR_HARPOON(ioport+hp_arb_id, pCardInfo->ai_id); + CurrCard->ourId = (unsigned char) pCardInfo->ai_id; + + i = (u08bits) pCardInfo->ai_stateinfo; + if (i & SCSI_PARITY_ENA) + WR_HARPOON(ioport+hp_portctrl_1,(HOST_MODE8 | CHK_SCSI_P)); + + j = (RD_HARPOON(ioport+hp_bm_ctrl) & ~SCSI_TERM_ENA_L); + if (i & LOW_BYTE_TERM_ENA) + j |= SCSI_TERM_ENA_L; + WR_HARPOON(ioport+hp_bm_ctrl, j); + + j = (RD_HARPOON(ioport+hp_ee_ctrl) & ~SCSI_TERM_ENA_H); + if (i & HIGH_BYTE_TERM_ENA) + j |= SCSI_TERM_ENA_H; + WR_HARPOON(ioport+hp_ee_ctrl, j ); + + + if (!(pCardInfo->ai_stateinfo & NO_RESET_IN_INIT)) { + + sresb(ioport,thisCard); + + scini(thisCard, (u08bits) pCardInfo->ai_id, 0); + } + + + + if (pCardInfo->ai_stateinfo & SUPRESS_UNDERRRUNS_ENA) + CurrCard->globalFlags |= F_NO_FILTER; + + if(pCurrNvRam){ + if(pCurrNvRam->niSysConf & 0x10) + CurrCard->globalFlags |= F_GREEN_PC; + } + else{ + if (utilEERead(ioport, (SYSTEM_CONFIG/2)) & GREEN_PC_ENA) + CurrCard->globalFlags |= F_GREEN_PC; + } + + /* Set global flag to indicate Re-Negotiation to be done on all + ckeck condition */ + if(pCurrNvRam){ + if(pCurrNvRam->niScsiConf & 0x04) + CurrCard->globalFlags |= F_DO_RENEGO; + } + else{ + if (utilEERead(ioport, (SCSI_CONFIG/2)) & RENEGO_ENA) + CurrCard->globalFlags |= F_DO_RENEGO; + } + + if(pCurrNvRam){ + if(pCurrNvRam->niScsiConf & 0x08) + CurrCard->globalFlags |= F_CONLUN_IO; + } + else{ + if (utilEERead(ioport, (SCSI_CONFIG/2)) & CONNIO_ENA) + CurrCard->globalFlags |= F_CONLUN_IO; + } + + temp = pCardInfo->ai_per_targ_no_disc; + + for (i = 0,id = 1; i < MAX_SCSI_TAR; i++, id <<= 1) { + + if (temp & id) + sccbMgrTbl[thisCard][i].TarStatus |= TAR_ALLOW_DISC; + } + + sync_bit_map = 0x0001; + + for (id = 0; id < (MAX_SCSI_TAR/2); id++){ + + if(pCurrNvRam){ + temp = (USHORT) pCurrNvRam->niSyncTbl[id]; + temp = ((temp & 0x03) + ((temp << 4) & 0xc0)) + + (((temp << 4) & 0x0300) + ((temp << 8) & 0xc000)); + }else + temp = utilEERead(ioport, (u16bits)((SYNC_RATE_TBL/2)+id)); + + for (i = 0; i < 2; temp >>=8,i++){ + + if (pCardInfo->ai_per_targ_init_sync & sync_bit_map){ + + sccbMgrTbl[thisCard][id*2+i].TarEEValue = (u08bits)temp; + } + + else { + sccbMgrTbl[thisCard][id*2+i].TarStatus |= SYNC_SUPPORTED; + sccbMgrTbl[thisCard][id*2+i].TarEEValue = + (u08bits)(temp & ~EE_SYNC_MASK); + } + +#if defined(WIDE_SCSI) +/* if ((pCardInfo->ai_per_targ_wide_nego & sync_bit_map) || + (id*2+i >= 8)){ +*/ + if (pCardInfo->ai_per_targ_wide_nego & sync_bit_map){ + + sccbMgrTbl[thisCard][id*2+i].TarEEValue |= EE_WIDE_SCSI; + + } + + else { /* NARROW SCSI */ + sccbMgrTbl[thisCard][id*2+i].TarStatus |= WIDE_NEGOCIATED; + } + +#else + sccbMgrTbl[thisCard][id*2+i].TarStatus |= WIDE_NEGOCIATED; +#endif + + + sync_bit_map <<= 1; + } + } + + + pCardInfo->ai_SGListFormat=0x01; + pCardInfo->ai_DataPtrFormat=0x01; + pCardInfo->ai_AEN_mask &= SCSI_RESET_COMPLETE; + + WR_HARPOON((ioport+hp_semaphore), + (u08bits)(RD_HARPOON((ioport+hp_semaphore)) | SCCB_MGR_PRESENT)); + + return((u32bits)CurrCard); + +} + + +/*--------------------------------------------------------------------- + * + * Function: build_ucb, exported to BUDI via UCBMgr_build_ucb entry + * + * Description: prepare fw portion of ucb. do not start, resource not guaranteed + * so don't manipulate anything that's derived from states which + * may change + * + *---------------------------------------------------------------------*/ +void build_UCB(CARD_HANDLE pCurrCard, PUCB p_ucb) +{ + + u08bits thisCard; + u08bits i,j; + + PSCCB p_sccb; + + + thisCard = ((PSCCBcard) pCurrCard)->cardIndex; + + + p_sccb=(PSCCB)p_ucb->UCB_MgrPrivatePtr; + + + p_sccb->Sccb_ucb_ptr=p_ucb; + + switch (p_ucb->UCB_opcode & (OPC_DEVICE_RESET+OPC_XFER_SG+OPC_CHK_RESIDUAL)) + { + case OPC_DEVICE_RESET: + p_sccb->OperationCode=RESET_COMMAND; + break; + case OPC_XFER_SG: + p_sccb->OperationCode=SCATTER_GATHER_COMMAND; + break; + case OPC_XFER_SG+OPC_CHK_RESIDUAL: + p_sccb->OperationCode=RESIDUAL_SG_COMMAND; + break; + case OPC_CHK_RESIDUAL: + + p_sccb->OperationCode=RESIDUAL_COMMAND; + break; + default: + p_sccb->OperationCode=SCSI_INITIATOR_COMMAND; + break; + } + + if (p_ucb->UCB_opcode & OPC_TQ_ENABLE) + { + p_sccb->ControlByte = (u08bits)((p_ucb->UCB_opcode & OPC_TQ_MASK)>>2) | F_USE_CMD_Q; + } + else + { + p_sccb->ControlByte = 0; + } + + + p_sccb->CdbLength = (u08bits)p_ucb->UCB_cdblen; + + if (p_ucb->UCB_opcode & OPC_NO_AUTO_SENSE) + { + p_sccb->RequestSenseLength = 0; + } + else + { + p_sccb->RequestSenseLength = (unsigned char) p_ucb->UCB_senselen; + } + + + if (p_ucb->UCB_opcode & OPC_XFER_SG) + { + p_sccb->DataPointer=p_ucb->UCB_virt_dataptr; + p_sccb->DataLength = (((u32bits)p_ucb->UCB_NumSgElements)<<3); + } + else + { + p_sccb->DataPointer=p_ucb->UCB_phys_dataptr; + p_sccb->DataLength=p_ucb->UCB_datalen; + }; + + p_sccb->HostStatus=0; + p_sccb->TargetStatus=0; + p_sccb->TargID=(unsigned char)p_ucb->UCB_targid; + p_sccb->Lun=(unsigned char) p_ucb->UCB_lun; + p_sccb->SccbIOPort=((PSCCBcard)pCurrCard)->ioPort; + + j=p_ucb->UCB_cdblen; + for (i=0;iCdb[i] = p_ucb->UCB_cdb[i]; + } + + p_sccb->SensePointer=p_ucb->UCB_phys_senseptr; + + sinits(p_sccb,thisCard); + +} +#ifndef NO_IOCTLS + +/*--------------------------------------------------------------------- + * + * Function: GetDevSyncRate + * + *---------------------------------------------------------------------*/ +STATIC int GetDevSyncRate(PSCCBcard pCurrCard,PUCB p_ucb) +{ + struct _SYNC_RATE_INFO * pSyncStr; + PSCCBMgr_tar_info currTar_Info; + BASE_PORT ioport; + u08bits scsiID, j; + +#if (FW_TYPE != _SCCB_MGR_) + if( p_ucb->UCB_targid >= pCurrCard->cardInfo->ai_MaxTarg ) + { + return(1); + } +#endif + + ioport = pCurrCard->ioPort; + pSyncStr = (struct _SYNC_RATE_INFO *) p_ucb->UCB_virt_dataptr; + scsiID = (u08bits) p_ucb->UCB_targid; + currTar_Info = &sccbMgrTbl[pCurrCard->cardIndex][scsiID]; + j = currTar_Info->TarSyncCtrl; + + switch (currTar_Info->TarEEValue & EE_SYNC_MASK) + { + case EE_SYNC_ASYNC: + pSyncStr->RequestMegaXferRate = 0x00; + break; + case EE_SYNC_5MB: + pSyncStr->RequestMegaXferRate = (j & NARROW_SCSI) ? 50 : 100; + break; + case EE_SYNC_10MB: + pSyncStr->RequestMegaXferRate = (j & NARROW_SCSI) ? 100 : 200; + break; + case EE_SYNC_20MB: + pSyncStr->RequestMegaXferRate = (j & NARROW_SCSI) ? 200 : 400; + break; + } + + switch ((j >> 5) & 0x07) + { + case 0x00: + if((j & 0x07) == 0x00) + { + pSyncStr->ActualMegaXferRate = 0x00; /* Async Mode */ + } + else + { + pSyncStr->ActualMegaXferRate = (j & NARROW_SCSI) ? 200 : 400; + } + break; + case 0x01: + pSyncStr->ActualMegaXferRate = (j & NARROW_SCSI) ? 100 : 200; + break; + case 0x02: + pSyncStr->ActualMegaXferRate = (j & NARROW_SCSI) ? 66 : 122; + break; + case 0x03: + pSyncStr->ActualMegaXferRate = (j & NARROW_SCSI) ? 50 : 100; + break; + case 0x04: + pSyncStr->ActualMegaXferRate = (j & NARROW_SCSI) ? 40 : 80; + break; + case 0x05: + pSyncStr->ActualMegaXferRate = (j & NARROW_SCSI) ? 33 : 66; + break; + case 0x06: + pSyncStr->ActualMegaXferRate = (j & NARROW_SCSI) ? 28 : 56; + break; + case 0x07: + pSyncStr->ActualMegaXferRate = (j & NARROW_SCSI) ? 25 : 50; + break; + } + pSyncStr->NegotiatedOffset = j & 0x0f; + + return(0); +} + +/*--------------------------------------------------------------------- + * + * Function: SetDevSyncRate + * + *---------------------------------------------------------------------*/ +STATIC int SetDevSyncRate(PSCCBcard pCurrCard, PUCB p_ucb) +{ + struct _SYNC_RATE_INFO * pSyncStr; + PSCCBMgr_tar_info currTar_Info; + BASE_PORT ioPort; + u08bits scsiID, i, j, syncVal; + u16bits syncOffset, actualXferRate; + union { + u08bits tempb[2]; + u16bits tempw; + }temp2; + +#if (FW_TYPE != _SCCB_MGR_) + if( p_ucb->UCB_targid >= pCurrCard->cardInfo->ai_MaxTarg ) + { + return(1); + } +#endif + + ioPort = pCurrCard->ioPort; + pSyncStr = (struct _SYNC_RATE_INFO *) p_ucb->UCB_virt_dataptr; + scsiID = (u08bits) p_ucb->UCB_targid; + currTar_Info = &sccbMgrTbl[pCurrCard->cardIndex][scsiID]; + i = RD_HARPOON(ioPort+hp_xfer_pad); /* Save current value */ + WR_HARPOON(ioPort+hp_xfer_pad, (i | ID_UNLOCK)); + WR_HARPOON(ioPort+hp_select_id, ((scsiID << 4) | scsiID)); + j = RD_HARPOON(ioPort+hp_synctarg_0); + WR_HARPOON(ioPort+hp_xfer_pad, i); /* restore value */ + + actualXferRate = pSyncStr->ActualMegaXferRate; + if(!(j & NARROW_SCSI)) + { + actualXferRate <<= 1; + } + if(actualXferRate == 0x00) + { + syncVal = EE_SYNC_ASYNC; /* Async Mode */ + } + if(actualXferRate == 0x0200) + { + syncVal = EE_SYNC_20MB; /* 20/40 MB Mode */ + } + if(actualXferRate > 0x0050 && actualXferRate < 0x0200 ) + { + syncVal = EE_SYNC_10MB; /* 10/20 MB Mode */ + } + else + { + syncVal = EE_SYNC_5MB; /* 5/10 MB Mode */ + } + if(currTar_Info->TarEEValue && EE_SYNC_MASK == syncVal) + return(0); + currTar_Info->TarEEValue = (currTar_Info->TarEEValue & !EE_SYNC_MASK) + | syncVal; + syncOffset = (SYNC_RATE_TBL + scsiID) / 2; + temp2.tempw = utilEERead(ioPort, syncOffset); + if(scsiID & 0x01) + { + temp2.tempb[0] = (temp2.tempb[0] & !EE_SYNC_MASK) | syncVal; + } + else + { + temp2.tempb[1] = (temp2.tempb[1] & !EE_SYNC_MASK) | syncVal; + } + utilEEWriteOnOff(ioPort, 1); + utilEEWrite(ioPort, temp2.tempw, syncOffset); + utilEEWriteOnOff(ioPort, 0); + UpdateCheckSum(ioPort); + + return(0); +} +/*--------------------------------------------------------------------- + * + * Function: GetDevWideMode + * + *---------------------------------------------------------------------*/ +int GetDevWideMode(PSCCBcard pCurrCard,PUCB p_ucb) +{ + u08bits *pData; + + pData = (u08bits *)p_ucb->UCB_virt_dataptr; + if(sccbMgrTbl[pCurrCard->cardIndex][p_ucb->UCB_targid].TarEEValue + & EE_WIDE_SCSI) + { + *pData = 1; + } + else + { + *pData = 0; + } + + return(0); +} + +/*--------------------------------------------------------------------- + * + * Function: SetDevWideMode + * + *---------------------------------------------------------------------*/ +int SetDevWideMode(PSCCBcard pCurrCard,PUCB p_ucb) +{ + u08bits *pData; + PSCCBMgr_tar_info currTar_Info; + BASE_PORT ioPort; + u08bits scsiID, scsiWideMode; + u16bits syncOffset; + union { + u08bits tempb[2]; + u16bits tempw; + }temp2; + +#if (FW_TYPE != _SCCB_MGR_) + if( !(pCurrCard->cardInfo->ai_attributes & WIDE_CAPABLE) ) + { + return(1); + } + + if( p_ucb->UCB_targid >= pCurrCard->cardInfo->ai_MaxTarg ) + { + return(1); + } +#endif + + ioPort = pCurrCard->ioPort; + pData = (u08bits *)p_ucb->UCB_virt_dataptr; + scsiID = (u08bits) p_ucb->UCB_targid; + currTar_Info = &sccbMgrTbl[pCurrCard->cardIndex][scsiID]; + + if(*pData) + { + if(currTar_Info->TarEEValue & EE_WIDE_SCSI) + { + return(0); + } + else + { + scsiWideMode = EE_WIDE_SCSI; + } + } + else + { + if(!currTar_Info->TarEEValue & EE_WIDE_SCSI) + { + return(0); + } + else + { + scsiWideMode = 0; + } + } + currTar_Info->TarEEValue = (currTar_Info->TarEEValue & !EE_WIDE_SCSI) + | scsiWideMode; + + syncOffset = (SYNC_RATE_TBL + scsiID) / 2; + temp2.tempw = utilEERead(ioPort, syncOffset); + if(scsiID & 0x01) + { + temp2.tempb[0] = (temp2.tempb[0] & !EE_WIDE_SCSI) | scsiWideMode; + } + else + { + temp2.tempb[1] = (temp2.tempb[1] & !EE_WIDE_SCSI) | scsiWideMode; + } + utilEEWriteOnOff(ioPort, 1); + utilEEWrite(ioPort, temp2.tempw, syncOffset); + utilEEWriteOnOff(ioPort, 0); + UpdateCheckSum(ioPort); + + return(0); +} + +/*--------------------------------------------------------------------- + * + * Function: ReadNVRam + * + *---------------------------------------------------------------------*/ +void ReadNVRam(PSCCBcard pCurrCard,PUCB p_ucb) +{ + u08bits *pdata; + u16bits i,numwrds,numbytes,offset,temp; + u08bits OneMore = FALSE; +#if defined(DOS) + u16bits ioport; +#else + u32bits ioport; +#endif + + numbytes = (u16bits) p_ucb->UCB_datalen; + ioport = pCurrCard->ioPort; + pdata = (u08bits *) p_ucb->UCB_virt_dataptr; + offset = (u16bits) (p_ucb->UCB_IOCTLParams[0]); + + + + if (offset & 0x1) + { + *((u16bits*) pdata) = utilEERead(ioport,(u16bits)((offset - 1) / 2)); /* 16 bit read */ + *pdata = *(pdata + 1); + ++offset; + ++pdata; + --numbytes; + } + + numwrds = numbytes / 2; + if (numbytes & 1) + OneMore = TRUE; + + for (i = 0; i < numwrds; i++) + { + *((u16bits*) pdata) = utilEERead(ioport,(u16bits)(offset / 2)); + pdata += 2; + offset += 2; + } + if (OneMore) + { + --pdata; + -- offset; + temp = utilEERead(ioport,(u16bits)(offset / 2)); + *pdata = (u08bits) (temp); + } + +} /* end proc ReadNVRam */ + + +/*--------------------------------------------------------------------- + * + * Function: WriteNVRam + * + *---------------------------------------------------------------------*/ +void WriteNVRam(PSCCBcard pCurrCard,PUCB p_ucb) +{ + u08bits *pdata; + u16bits i,numwrds,numbytes,offset, eeprom_end; + u08bits OneMore = FALSE; + union { + u08bits tempb[2]; + u16bits tempw; + } temp2; + +#if defined(DOS) + u16bits ioport; +#else + u32bits ioport; +#endif + + numbytes = (u16bits) p_ucb->UCB_datalen; + ioport = pCurrCard->ioPort; + pdata = (u08bits *) p_ucb->UCB_virt_dataptr; + offset = (u16bits) (p_ucb->UCB_IOCTLParams[0]); + + if (RD_HARPOON(ioport+hp_page_ctrl) & NARROW_SCSI_CARD) + eeprom_end = 512; + else + eeprom_end = 768; + + if(offset > eeprom_end) + return; + + if((offset + numbytes) > eeprom_end) + numbytes = eeprom_end - offset; + + utilEEWriteOnOff(ioport,1); /* Enable write access to the EEPROM */ + + + + if (offset & 0x1) + { + temp2.tempw = utilEERead(ioport,(u16bits)((offset - 1) / 2)); /* 16 bit read */ + temp2.tempb[1] = *pdata; + utilEEWrite(ioport, temp2.tempw, (u16bits)((offset -1) / 2)); + *pdata = *(pdata + 1); + ++offset; + ++pdata; + --numbytes; + } + + numwrds = numbytes / 2; + if (numbytes & 1) + OneMore = TRUE; + + for (i = 0; i < numwrds; i++) + { + utilEEWrite(ioport, *((pu16bits)pdata),(u16bits)(offset / 2)); + pdata += 2; + offset += 2; + } + if (OneMore) + { + + temp2.tempw = utilEERead(ioport,(u16bits)(offset / 2)); + temp2.tempb[0] = *pdata; + utilEEWrite(ioport, temp2.tempw, (u16bits)(offset / 2)); + } + utilEEWriteOnOff(ioport,0); /* Turn off write access */ + UpdateCheckSum((u32bits)ioport); + +} /* end proc WriteNVRam */ + + + +/*--------------------------------------------------------------------- + * + * Function: UpdateCheckSum + * + * Description: Update Check Sum in EEPROM + * + *---------------------------------------------------------------------*/ + + +void UpdateCheckSum(u32bits baseport) +{ + USHORT i,sum_data, eeprom_end; + + sum_data = 0x0000; + + + if (RD_HARPOON(baseport+hp_page_ctrl) & NARROW_SCSI_CARD) + eeprom_end = 512; + else + eeprom_end = 768; + + for (i = 1; i < eeprom_end/2; i++) + { + sum_data += utilEERead(baseport, i); + } + + utilEEWriteOnOff(baseport,1); /* Enable write access to the EEPROM */ + + utilEEWrite(baseport, sum_data, EEPROM_CHECK_SUM/2); + utilEEWriteOnOff(baseport,0); /* Turn off write access */ +} + +void SccbMgr_save_foreign_state(PADAPTER_INFO pAdapterInfo) +{ +} + + +void SccbMgr_restore_foreign_state(CARD_HANDLE pCurrCard) +{ +} + +void SccbMgr_restore_native_state(CARD_HANDLE pCurrCard) +{ +} + +#endif /* NO_IOCTLS */ + +#endif /* (FW_TYPE==_UCB_MGR_) */ + +#ifndef NO_IOCTLS +#if (FW_TYPE==_UCB_MGR_) +void SccbMgr_unload_card(CARD_HANDLE pCurrCard) +#else +#if defined(DOS) +void SccbMgr_unload_card(USHORT pCurrCard) +#else +void SccbMgr_unload_card(ULONG pCurrCard) +#endif +#endif +{ + UCHAR i; +#if defined(DOS) + USHORT portBase; + USHORT regOffset; +#else + ULONG portBase; + ULONG regOffset; +#endif + ULONG scamData; +#if defined(OS2) + ULONG far *pScamTbl; +#else + ULONG *pScamTbl; +#endif + PNVRamInfo pCurrNvRam; + + pCurrNvRam = ((PSCCBcard)pCurrCard)->pNvRamInfo; + + if(pCurrNvRam){ + WrStack(pCurrNvRam->niBaseAddr, 0, pCurrNvRam->niModel); + WrStack(pCurrNvRam->niBaseAddr, 1, pCurrNvRam->niSysConf); + WrStack(pCurrNvRam->niBaseAddr, 2, pCurrNvRam->niScsiConf); + WrStack(pCurrNvRam->niBaseAddr, 3, pCurrNvRam->niScamConf); + WrStack(pCurrNvRam->niBaseAddr, 4, pCurrNvRam->niAdapId); + + for(i = 0; i < MAX_SCSI_TAR / 2; i++) + WrStack(pCurrNvRam->niBaseAddr, (UCHAR)(i+5), pCurrNvRam->niSyncTbl[i]); + + portBase = pCurrNvRam->niBaseAddr; + + for(i = 0; i < MAX_SCSI_TAR; i++){ + regOffset = hp_aramBase + 64 + i*4; +#if defined(OS2) + pScamTbl = (ULONG far *) &pCurrNvRam->niScamTbl[i]; +#else + pScamTbl = (ULONG *) &pCurrNvRam->niScamTbl[i]; +#endif + scamData = *pScamTbl; + WR_HARP32(portBase, regOffset, scamData); + } + + }else{ + WrStack(((PSCCBcard)pCurrCard)->ioPort, 0, 0); + } +} +#endif /* NO_IOCTLS */ + + +void RNVRamData(PNVRamInfo pNvRamInfo) +{ + UCHAR i; +#if defined(DOS) + USHORT portBase; + USHORT regOffset; +#else + ULONG portBase; + ULONG regOffset; +#endif + ULONG scamData; +#if defined (OS2) + ULONG far *pScamTbl; +#else + ULONG *pScamTbl; +#endif + + pNvRamInfo->niModel = RdStack(pNvRamInfo->niBaseAddr, 0); + pNvRamInfo->niSysConf = RdStack(pNvRamInfo->niBaseAddr, 1); + pNvRamInfo->niScsiConf = RdStack(pNvRamInfo->niBaseAddr, 2); + pNvRamInfo->niScamConf = RdStack(pNvRamInfo->niBaseAddr, 3); + pNvRamInfo->niAdapId = RdStack(pNvRamInfo->niBaseAddr, 4); + + for(i = 0; i < MAX_SCSI_TAR / 2; i++) + pNvRamInfo->niSyncTbl[i] = RdStack(pNvRamInfo->niBaseAddr, (UCHAR)(i+5)); + + portBase = pNvRamInfo->niBaseAddr; + + for(i = 0; i < MAX_SCSI_TAR; i++){ + regOffset = hp_aramBase + 64 + i*4; + RD_HARP32(portBase, regOffset, scamData); +#if defined(OS2) + pScamTbl = (ULONG far *) &pNvRamInfo->niScamTbl[i]; +#else + pScamTbl = (ULONG *) &pNvRamInfo->niScamTbl[i]; +#endif + *pScamTbl = scamData; + } + +} + +#if defined(DOS) +UCHAR RdStack(USHORT portBase, UCHAR index) +#else +UCHAR RdStack(ULONG portBase, UCHAR index) +#endif +{ + WR_HARPOON(portBase + hp_stack_addr, index); + return(RD_HARPOON(portBase + hp_stack_data)); +} + +#if defined(DOS) +void WrStack(USHORT portBase, UCHAR index, UCHAR data) +#else +void WrStack(ULONG portBase, UCHAR index, UCHAR data) +#endif +{ + WR_HARPOON(portBase + hp_stack_addr, index); + WR_HARPOON(portBase + hp_stack_data, data); +} + + +#if (FW_TYPE==_UCB_MGR_) +u08bits ChkIfChipInitialized(BASE_PORT ioPort) +#else +#if defined(DOS) +UCHAR ChkIfChipInitialized(USHORT ioPort) +#else +UCHAR ChkIfChipInitialized(ULONG ioPort) +#endif +#endif +{ + if((RD_HARPOON(ioPort + hp_arb_id) & 0x0f) != RdStack(ioPort, 4)) + return(FALSE); + if((RD_HARPOON(ioPort + hp_clkctrl_0) & CLKCTRL_DEFAULT) + != CLKCTRL_DEFAULT) + return(FALSE); + if((RD_HARPOON(ioPort + hp_seltimeout) == TO_250ms) || + (RD_HARPOON(ioPort + hp_seltimeout) == TO_290ms)) + return(TRUE); + return(FALSE); + +} +/*--------------------------------------------------------------------- + * + * Function: SccbMgr_start_sccb + * + * Description: Start a command pointed to by p_Sccb. When the + * command is completed it will be returned via the + * callback function. + * + *---------------------------------------------------------------------*/ +#if (FW_TYPE==_UCB_MGR_) +void SccbMgr_start_sccb(CARD_HANDLE pCurrCard, PUCB p_ucb) +#else +#if defined(DOS) +void SccbMgr_start_sccb(USHORT pCurrCard, PSCCB p_Sccb) +#else +void SccbMgr_start_sccb(ULONG pCurrCard, PSCCB p_Sccb) +#endif +#endif +{ +#if defined(DOS) + USHORT ioport; +#else + ULONG ioport; +#endif + UCHAR thisCard, lun; + PSCCB pSaveSccb; + CALL_BK_FN callback; + +#if (FW_TYPE==_UCB_MGR_) + PSCCB p_Sccb; +#endif + + mOS_Lock((PSCCBcard)pCurrCard); + thisCard = ((PSCCBcard) pCurrCard)->cardIndex; + ioport = ((PSCCBcard) pCurrCard)->ioPort; + +#if (FW_TYPE==_UCB_MGR_) + p_Sccb = (PSCCB)p_ucb->UCB_MgrPrivatePtr; +#endif + + if((p_Sccb->TargID > MAX_SCSI_TAR) || (p_Sccb->Lun > MAX_LUN)) + { + +#if (FW_TYPE==_UCB_MGR_) + p_ucb->UCB_hbastat = SCCB_COMPLETE; + p_ucb->UCB_status=SCCB_ERROR; + callback = (CALL_BK_FN)p_ucb->UCB_callback; + if (callback) + callback(p_ucb); +#endif + +#if (FW_TYPE==_SCCB_MGR_) + p_Sccb->HostStatus = SCCB_COMPLETE; + p_Sccb->SccbStatus = SCCB_ERROR; + callback = (CALL_BK_FN)p_Sccb->SccbCallback; + if (callback) + callback(p_Sccb); +#endif + + mOS_UnLock((PSCCBcard)pCurrCard); + return; + } + +#if (FW_TYPE==_SCCB_MGR_) + sinits(p_Sccb,thisCard); +#endif + + +#if (FW_TYPE==_UCB_MGR_) +#ifndef NO_IOCTLS + + if (p_ucb->UCB_opcode & OPC_IOCTL) + { + + switch (p_ucb->UCB_IOCTLCommand) + { + case READ_NVRAM: + ReadNVRam((PSCCBcard)pCurrCard,p_ucb); + p_ucb->UCB_status=UCB_SUCCESS; + callback = (CALL_BK_FN)p_ucb->UCB_callback; + if (callback) + callback(p_ucb); + mOS_UnLock((PSCCBcard)pCurrCard); + return; + + case WRITE_NVRAM: + WriteNVRam((PSCCBcard)pCurrCard,p_ucb); + p_ucb->UCB_status=UCB_SUCCESS; + callback = (CALL_BK_FN)p_ucb->UCB_callback; + if (callback) + callback(p_ucb); + mOS_UnLock((PSCCBcard)pCurrCard); + return; + + case SEND_SCSI_PASSTHRU: +#if (FW_TYPE != _SCCB_MGR_) + if( p_ucb->UCB_targid >= + ((PSCCBcard)pCurrCard)->cardInfo->ai_MaxTarg ) + { + p_ucb->UCB_status = UCB_ERROR; + p_ucb->UCB_hbastat = HASTAT_HW_ERROR; + callback = (CALL_BK_FN)p_ucb->UCB_callback; + if (callback) + callback(p_ucb); + mOS_UnLock((PSCCBcard)pCurrCard); + return; + } +#endif + break; + + case HARD_RESET: + p_ucb->UCB_status = UCB_INVALID; + callback = (CALL_BK_FN)p_ucb->UCB_callback; + if (callback) + callback(p_ucb); + mOS_UnLock((PSCCBcard)pCurrCard); + return; + case GET_DEVICE_SYNCRATE: + if( !GetDevSyncRate((PSCCBcard)pCurrCard,p_ucb) ) + { + p_ucb->UCB_status = UCB_SUCCESS; + } + else + { + p_ucb->UCB_status = UCB_ERROR; + p_ucb->UCB_hbastat = HASTAT_HW_ERROR; + } + callback = (CALL_BK_FN)p_ucb->UCB_callback; + if (callback) + callback(p_ucb); + mOS_UnLock((PSCCBcard)pCurrCard); + return; + case SET_DEVICE_SYNCRATE: + if( !SetDevSyncRate((PSCCBcard)pCurrCard,p_ucb) ) + { + p_ucb->UCB_status = UCB_SUCCESS; + } + else + { + p_ucb->UCB_status = UCB_ERROR; + p_ucb->UCB_hbastat = HASTAT_HW_ERROR; + } + callback = (CALL_BK_FN)p_ucb->UCB_callback; + if (callback) + callback(p_ucb); + mOS_UnLock((PSCCBcard)pCurrCard); + return; + case GET_WIDE_MODE: + if( !GetDevWideMode((PSCCBcard)pCurrCard,p_ucb) ) + { + p_ucb->UCB_status = UCB_SUCCESS; + } + else + { + p_ucb->UCB_status = UCB_ERROR; + p_ucb->UCB_hbastat = HASTAT_HW_ERROR; + } + callback = (CALL_BK_FN)p_ucb->UCB_callback; + if (callback) + callback(p_ucb); + mOS_UnLock((PSCCBcard)pCurrCard); + return; + case SET_WIDE_MODE: + if( !SetDevWideMode((PSCCBcard)pCurrCard,p_ucb) ) + { + p_ucb->UCB_status = UCB_SUCCESS; + } + else + { + p_ucb->UCB_status = UCB_ERROR; + p_ucb->UCB_hbastat = HASTAT_HW_ERROR; + } + callback = (CALL_BK_FN)p_ucb->UCB_callback; + if (callback) + callback(p_ucb); + mOS_UnLock((PSCCBcard)pCurrCard); + return; + default: + p_ucb->UCB_status=UCB_INVALID; + callback = (CALL_BK_FN)p_ucb->UCB_callback; + if (callback) + callback(p_ucb); + mOS_UnLock((PSCCBcard)pCurrCard); + return; + } + } +#endif /* NO_IOCTLS */ +#endif /* (FW_TYPE==_UCB_MGR_) */ + + + if (!((PSCCBcard) pCurrCard)->cmdCounter) + { + WR_HARPOON(ioport+hp_semaphore, (RD_HARPOON(ioport+hp_semaphore) + | SCCB_MGR_ACTIVE)); + + if (((PSCCBcard) pCurrCard)->globalFlags & F_GREEN_PC) + { + WR_HARPOON(ioport+hp_clkctrl_0, CLKCTRL_DEFAULT); + WR_HARPOON(ioport+hp_sys_ctrl, 0x00); + } + } + + ((PSCCBcard)pCurrCard)->cmdCounter++; + + if (RD_HARPOON(ioport+hp_semaphore) & BIOS_IN_USE) { + + WR_HARPOON(ioport+hp_semaphore, (RD_HARPOON(ioport+hp_semaphore) + | TICKLE_ME)); + if(p_Sccb->OperationCode == RESET_COMMAND) + { + pSaveSccb = ((PSCCBcard) pCurrCard)->currentSCCB; + ((PSCCBcard) pCurrCard)->currentSCCB = p_Sccb; + queueSelectFail(&BL_Card[thisCard], thisCard); + ((PSCCBcard) pCurrCard)->currentSCCB = pSaveSccb; + } + else + { + queueAddSccb(p_Sccb,thisCard); + } + } + + else if ((RD_HARPOON(ioport+hp_page_ctrl) & G_INT_DISABLE)) { + + if(p_Sccb->OperationCode == RESET_COMMAND) + { + pSaveSccb = ((PSCCBcard) pCurrCard)->currentSCCB; + ((PSCCBcard) pCurrCard)->currentSCCB = p_Sccb; + queueSelectFail(&BL_Card[thisCard], thisCard); + ((PSCCBcard) pCurrCard)->currentSCCB = pSaveSccb; + } + else + { + queueAddSccb(p_Sccb,thisCard); + } + } + + else { + + MDISABLE_INT(ioport); + + if((((PSCCBcard) pCurrCard)->globalFlags & F_CONLUN_IO) && + ((sccbMgrTbl[thisCard][p_Sccb->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)) + lun = p_Sccb->Lun; + else + lun = 0; + if ((((PSCCBcard) pCurrCard)->currentSCCB == NULL) && + (sccbMgrTbl[thisCard][p_Sccb->TargID].TarSelQ_Cnt == 0) && + (sccbMgrTbl[thisCard][p_Sccb->TargID].TarLUNBusy[lun] + == FALSE)) { + + ((PSCCBcard) pCurrCard)->currentSCCB = p_Sccb; + mOS_UnLock((PSCCBcard)pCurrCard); +#if defined(DOS) + ssel((USHORT)p_Sccb->SccbIOPort,thisCard); +#else + ssel(p_Sccb->SccbIOPort,thisCard); +#endif + mOS_Lock((PSCCBcard)pCurrCard); + } + + else { + + if(p_Sccb->OperationCode == RESET_COMMAND) + { + pSaveSccb = ((PSCCBcard) pCurrCard)->currentSCCB; + ((PSCCBcard) pCurrCard)->currentSCCB = p_Sccb; + queueSelectFail(&BL_Card[thisCard], thisCard); + ((PSCCBcard) pCurrCard)->currentSCCB = pSaveSccb; + } + else + { + queueAddSccb(p_Sccb,thisCard); + } + } + + + MENABLE_INT(ioport); + } + + mOS_UnLock((PSCCBcard)pCurrCard); +} + + +/*--------------------------------------------------------------------- + * + * Function: SccbMgr_abort_sccb + * + * Description: Abort the command pointed to by p_Sccb. When the + * command is completed it will be returned via the + * callback function. + * + *---------------------------------------------------------------------*/ +#if (FW_TYPE==_UCB_MGR_) +s32bits SccbMgr_abort_sccb(CARD_HANDLE pCurrCard, PUCB p_ucb) +#else +#if defined(DOS) +int SccbMgr_abort_sccb(USHORT pCurrCard, PSCCB p_Sccb) +#else +int SccbMgr_abort_sccb(ULONG pCurrCard, PSCCB p_Sccb) +#endif +#endif + +{ +#if defined(DOS) + USHORT ioport; +#else + ULONG ioport; +#endif + + UCHAR thisCard; + CALL_BK_FN callback; + UCHAR TID; + PSCCB pSaveSCCB; + PSCCBMgr_tar_info currTar_Info; + + +#if (FW_TYPE==_UCB_MGR_) + PSCCB p_Sccb; + p_Sccb=(PSCCB)p_ucb->UCB_MgrPrivatePtr; +#endif + + ioport = ((PSCCBcard) pCurrCard)->ioPort; + + thisCard = ((PSCCBcard)pCurrCard)->cardIndex; + + mOS_Lock((PSCCBcard)pCurrCard); + + if (RD_HARPOON(ioport+hp_page_ctrl) & G_INT_DISABLE) + { + mOS_UnLock((PSCCBcard)pCurrCard); + } + + else + { + + if (queueFindSccb(p_Sccb,thisCard)) + { + + mOS_UnLock((PSCCBcard)pCurrCard); + + ((PSCCBcard)pCurrCard)->cmdCounter--; + + if (!((PSCCBcard)pCurrCard)->cmdCounter) + WR_HARPOON(ioport+hp_semaphore,(RD_HARPOON(ioport+hp_semaphore) + & (UCHAR)(~(SCCB_MGR_ACTIVE | TICKLE_ME)) )); + +#if (FW_TYPE==_SCCB_MGR_) + p_Sccb->SccbStatus = SCCB_ABORT; + callback = p_Sccb->SccbCallback; + callback(p_Sccb); +#else + p_ucb->UCB_status=SCCB_ABORT; + callback = (CALL_BK_FN)p_ucb->UCB_callback; + callback(p_ucb); +#endif + + return(0); + } + + else + { + mOS_UnLock((PSCCBcard)pCurrCard); + + if (((PSCCBcard)pCurrCard)->currentSCCB == p_Sccb) + { + p_Sccb->SccbStatus = SCCB_ABORT; + return(0); + + } + + else + { + + TID = p_Sccb->TargID; + + + if(p_Sccb->Sccb_tag) + { + MDISABLE_INT(ioport); + if (((PSCCBcard) pCurrCard)->discQ_Tbl[p_Sccb->Sccb_tag]==p_Sccb) + { + p_Sccb->SccbStatus = SCCB_ABORT; + p_Sccb->Sccb_scsistat = ABORT_ST; +#if (FW_TYPE==_UCB_MGR_) + p_ucb->UCB_status=SCCB_ABORT; +#endif + p_Sccb->Sccb_scsimsg = SMABORT_TAG; + + if(((PSCCBcard) pCurrCard)->currentSCCB == NULL) + { + ((PSCCBcard) pCurrCard)->currentSCCB = p_Sccb; + ssel(ioport, thisCard); + } + else + { + pSaveSCCB = ((PSCCBcard) pCurrCard)->currentSCCB; + ((PSCCBcard) pCurrCard)->currentSCCB = p_Sccb; + queueSelectFail((PSCCBcard) pCurrCard, thisCard); + ((PSCCBcard) pCurrCard)->currentSCCB = pSaveSCCB; + } + } + MENABLE_INT(ioport); + return(0); + } + else + { + currTar_Info = &sccbMgrTbl[thisCard][p_Sccb->TargID]; + + if(BL_Card[thisCard].discQ_Tbl[currTar_Info->LunDiscQ_Idx[p_Sccb->Lun]] + == p_Sccb) + { + p_Sccb->SccbStatus = SCCB_ABORT; + return(0); + } + } + } + } + } + return(-1); +} + + +/*--------------------------------------------------------------------- + * + * Function: SccbMgr_my_int + * + * Description: Do a quick check to determine if there is a pending + * interrupt for this card and disable the IRQ Pin if so. + * + *---------------------------------------------------------------------*/ +#if (FW_TYPE==_UCB_MGR_) +u08bits SccbMgr_my_int(CARD_HANDLE pCurrCard) +#else +#if defined(DOS) +UCHAR SccbMgr_my_int(USHORT pCurrCard) +#else +UCHAR SccbMgr_my_int(ULONG pCurrCard) +#endif +#endif +{ +#if defined(DOS) + USHORT ioport; +#else + ULONG ioport; +#endif + + ioport = ((PSCCBcard)pCurrCard)->ioPort; + + if (RD_HARPOON(ioport+hp_int_status) & INT_ASSERTED) + { + +#if defined(DOS) + MDISABLE_INT(ioport); +#endif + + return(TRUE); + } + + else + + return(FALSE); +} + + + +/*--------------------------------------------------------------------- + * + * Function: SccbMgr_isr + * + * Description: This is our entry point when an interrupt is generated + * by the card and the upper level driver passes it on to + * us. + * + *---------------------------------------------------------------------*/ +#if (FW_TYPE==_UCB_MGR_) +s32bits SccbMgr_isr(CARD_HANDLE pCurrCard) +#else +#if defined(DOS) +int SccbMgr_isr(USHORT pCurrCard) +#else +int SccbMgr_isr(ULONG pCurrCard) +#endif +#endif +{ + PSCCB currSCCB; + UCHAR thisCard,result,bm_status, bm_int_st; + USHORT hp_int; + UCHAR i, target; +#if defined(DOS) + USHORT ioport; +#else + ULONG ioport; +#endif + + mOS_Lock((PSCCBcard)pCurrCard); + + thisCard = ((PSCCBcard)pCurrCard)->cardIndex; + ioport = ((PSCCBcard)pCurrCard)->ioPort; + + MDISABLE_INT(ioport); + +#if defined(BUGBUG) + WR_HARPOON(ioport+hp_user_defined_D, RD_HARPOON(ioport+hp_int_status)); +#endif + + if ((bm_int_st=RD_HARPOON(ioport+hp_int_status)) & EXT_STATUS_ON) + bm_status = RD_HARPOON(ioport+hp_ext_status) & (UCHAR)BAD_EXT_STATUS; + else + bm_status = 0; + + WR_HARPOON(ioport+hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT)); + + mOS_UnLock((PSCCBcard)pCurrCard); + + while ((hp_int = RDW_HARPOON((ioport+hp_intstat)) & default_intena) | + bm_status) + { + + currSCCB = ((PSCCBcard)pCurrCard)->currentSCCB; + +#if defined(BUGBUG) + Debug_Load(thisCard,(UCHAR) 0XFF); + Debug_Load(thisCard,bm_int_st); + + Debug_Load(thisCard,hp_int_0); + Debug_Load(thisCard,hp_int_1); +#endif + + + if (hp_int & (FIFO | TIMEOUT | RESET | SCAM_SEL) || bm_status) { + result = SccbMgr_bad_isr(ioport,thisCard,((PSCCBcard)pCurrCard),hp_int); + WRW_HARPOON((ioport+hp_intstat), (FIFO | TIMEOUT | RESET | SCAM_SEL)); + bm_status = 0; + + if (result) { + + mOS_Lock((PSCCBcard)pCurrCard); + MENABLE_INT(ioport); + mOS_UnLock((PSCCBcard)pCurrCard); + return(result); + } + } + + + else if (hp_int & ICMD_COMP) { + + if ( !(hp_int & BUS_FREE) ) { + /* Wait for the BusFree before starting a new command. We + must also check for being reselected since the BusFree + may not show up if another device reselects us in 1.5us or + less. SRR Wednesday, 3/8/1995. + */ + while (!(RDW_HARPOON((ioport+hp_intstat)) & (BUS_FREE | RSEL))) ; + } + + if (((PSCCBcard)pCurrCard)->globalFlags & F_HOST_XFER_ACT) + + phaseChkFifo(ioport, thisCard); + +/* WRW_HARPOON((ioport+hp_intstat), + (BUS_FREE | ICMD_COMP | ITAR_DISC | XFER_CNT_0)); + */ + + WRW_HARPOON((ioport+hp_intstat), CLR_ALL_INT_1); + + autoCmdCmplt(ioport,thisCard); + + } + + + else if (hp_int & ITAR_DISC) + { + + if (((PSCCBcard)pCurrCard)->globalFlags & F_HOST_XFER_ACT) { + + phaseChkFifo(ioport, thisCard); + + } + + if (RD_HARPOON(ioport+hp_gp_reg_1) == SMSAVE_DATA_PTR) { + + WR_HARPOON(ioport+hp_gp_reg_1, 0x00); + currSCCB->Sccb_XferState |= F_NO_DATA_YET; + + currSCCB->Sccb_savedATC = currSCCB->Sccb_ATC; + } + + currSCCB->Sccb_scsistat = DISCONNECT_ST; + queueDisconnect(currSCCB,thisCard); + + /* Wait for the BusFree before starting a new command. We + must also check for being reselected since the BusFree + may not show up if another device reselects us in 1.5us or + less. SRR Wednesday, 3/8/1995. + */ + while (!(RDW_HARPOON((ioport+hp_intstat)) & (BUS_FREE | RSEL))) ; + + WRW_HARPOON((ioport+hp_intstat), (BUS_FREE | ITAR_DISC)); + + + ((PSCCBcard)pCurrCard)->globalFlags |= F_NEW_SCCB_CMD; + + } + + + else if (hp_int & RSEL) { + + WRW_HARPOON((ioport+hp_intstat), (PROG_HLT | RSEL | PHASE | BUS_FREE)); + + if (RDW_HARPOON((ioport+hp_intstat)) & ITAR_DISC) + { + if (((PSCCBcard)pCurrCard)->globalFlags & F_HOST_XFER_ACT) + { + phaseChkFifo(ioport, thisCard); + } + + if (RD_HARPOON(ioport+hp_gp_reg_1) == SMSAVE_DATA_PTR) + { + WR_HARPOON(ioport+hp_gp_reg_1, 0x00); + currSCCB->Sccb_XferState |= F_NO_DATA_YET; + currSCCB->Sccb_savedATC = currSCCB->Sccb_ATC; + } + + WRW_HARPOON((ioport+hp_intstat), (BUS_FREE | ITAR_DISC)); + currSCCB->Sccb_scsistat = DISCONNECT_ST; + queueDisconnect(currSCCB,thisCard); + } + + sres(ioport,thisCard,((PSCCBcard)pCurrCard)); + phaseDecode(ioport,thisCard); + + } + + + else if ((hp_int & IDO_STRT) && (!(hp_int & BUS_FREE))) + { + + WRW_HARPOON((ioport+hp_intstat), (IDO_STRT | XFER_CNT_0)); + phaseDecode(ioport,thisCard); + + } + + + else if ( (hp_int & IUNKWN) || (hp_int & PROG_HLT) ) + { + WRW_HARPOON((ioport+hp_intstat), (PHASE | IUNKWN | PROG_HLT)); + if ((RD_HARPOON(ioport+hp_prgmcnt_0) & (UCHAR)0x3f)< (UCHAR)SELCHK) + { + phaseDecode(ioport,thisCard); + } + else + { + /* Harpoon problem some SCSI target device respond to selection + with short BUSY pulse (<400ns) this will make the Harpoon is not able + to latch the correct Target ID into reg. x53. + The work around require to correct this reg. But when write to this + reg. (0x53) also increment the FIFO write addr reg (0x6f), thus we + need to read this reg first then restore it later. After update to 0x53 */ + + i = (UCHAR)(RD_HARPOON(ioport+hp_fifowrite)); + target = (UCHAR)(RD_HARPOON(ioport+hp_gp_reg_3)); + WR_HARPOON(ioport+hp_xfer_pad, (UCHAR) ID_UNLOCK); + WR_HARPOON(ioport+hp_select_id, (UCHAR)(target | target<<4)); + WR_HARPOON(ioport+hp_xfer_pad, (UCHAR) 0x00); + WR_HARPOON(ioport+hp_fifowrite, i); + WR_HARPOON(ioport+hp_autostart_3, (AUTO_IMMED+TAG_STRT)); + } + } + + else if (hp_int & XFER_CNT_0) { + + WRW_HARPOON((ioport+hp_intstat), XFER_CNT_0); + + schkdd(ioport,thisCard); + + } + + + else if (hp_int & BUS_FREE) { + + WRW_HARPOON((ioport+hp_intstat), BUS_FREE); + + if (((PSCCBcard)pCurrCard)->globalFlags & F_HOST_XFER_ACT) { + + hostDataXferAbort(ioport,thisCard,currSCCB); + } + + phaseBusFree(ioport,thisCard); + } + + + else if (hp_int & ITICKLE) { + + WRW_HARPOON((ioport+hp_intstat), ITICKLE); + ((PSCCBcard)pCurrCard)->globalFlags |= F_NEW_SCCB_CMD; + } + + + + if (((PSCCBcard)pCurrCard)->globalFlags & F_NEW_SCCB_CMD) { + + + ((PSCCBcard)pCurrCard)->globalFlags &= ~F_NEW_SCCB_CMD; + + + if (((PSCCBcard)pCurrCard)->currentSCCB == NULL) { + + queueSearchSelect(((PSCCBcard)pCurrCard),thisCard); + } + + if (((PSCCBcard)pCurrCard)->currentSCCB != NULL) { + ((PSCCBcard)pCurrCard)->globalFlags &= ~F_NEW_SCCB_CMD; + ssel(ioport,thisCard); + } + + break; + + } + + } /*end while */ + + mOS_Lock((PSCCBcard)pCurrCard); + MENABLE_INT(ioport); + mOS_UnLock((PSCCBcard)pCurrCard); + + return(0); +} + +/*--------------------------------------------------------------------- + * + * Function: Sccb_bad_isr + * + * Description: Some type of interrupt has occured which is slightly + * out of the ordinary. We will now decode it fully, in + * this routine. This is broken up in an attempt to save + * processing time. + * + *---------------------------------------------------------------------*/ +#if defined(DOS) +UCHAR SccbMgr_bad_isr(USHORT p_port, UCHAR p_card, PSCCBcard pCurrCard, USHORT p_int) +#else +UCHAR SccbMgr_bad_isr(ULONG p_port, UCHAR p_card, PSCCBcard pCurrCard, USHORT p_int) +#endif +{ +#if defined(HARP_REVX) + ULONG timer; +#endif +UCHAR temp, ScamFlg; +PSCCBMgr_tar_info currTar_Info; +PNVRamInfo pCurrNvRam; + + + if (RD_HARPOON(p_port+hp_ext_status) & + (BM_FORCE_OFF | PCI_DEV_TMOUT | BM_PARITY_ERR | PIO_OVERRUN) ) + { + + if (pCurrCard->globalFlags & F_HOST_XFER_ACT) + { + + hostDataXferAbort(p_port,p_card, pCurrCard->currentSCCB); + } + + if (RD_HARPOON(p_port+hp_pci_stat_cfg) & REC_MASTER_ABORT) + + { + WR_HARPOON(p_port+hp_pci_stat_cfg, + (RD_HARPOON(p_port+hp_pci_stat_cfg) & ~REC_MASTER_ABORT)); + + WR_HARPOON(p_port+hp_host_blk_cnt, 0x00); + + } + + if (pCurrCard->currentSCCB != NULL) + { + + if (!pCurrCard->currentSCCB->HostStatus) + pCurrCard->currentSCCB->HostStatus = SCCB_BM_ERR; + + sxfrp(p_port,p_card); + + temp = (UCHAR)(RD_HARPOON(p_port+hp_ee_ctrl) & + (EXT_ARB_ACK | SCSI_TERM_ENA_H)); + WR_HARPOON(p_port+hp_ee_ctrl, ((UCHAR)temp | SEE_MS | SEE_CS)); + WR_HARPOON(p_port+hp_ee_ctrl, temp); + + if (!(RDW_HARPOON((p_port+hp_intstat)) & (BUS_FREE | RESET))) + { + phaseDecode(p_port,p_card); + } + } + } + + + else if (p_int & RESET) + { + + WR_HARPOON(p_port+hp_clkctrl_0, CLKCTRL_DEFAULT); + WR_HARPOON(p_port+hp_sys_ctrl, 0x00); + if (pCurrCard->currentSCCB != NULL) { + + if (pCurrCard->globalFlags & F_HOST_XFER_ACT) + + hostDataXferAbort(p_port,p_card, pCurrCard->currentSCCB); + } + + + DISABLE_AUTO(p_port); + + sresb(p_port,p_card); + + while(RD_HARPOON(p_port+hp_scsictrl_0) & SCSI_RST) {} + + pCurrNvRam = pCurrCard->pNvRamInfo; + if(pCurrNvRam){ + ScamFlg = pCurrNvRam->niScamConf; + } + else{ + ScamFlg = (UCHAR) utilEERead(p_port, SCAM_CONFIG/2); + } + + XbowInit(p_port, ScamFlg); + + scini(p_card, pCurrCard->ourId, 0); + + return(0xFF); + } + + + else if (p_int & FIFO) { + + WRW_HARPOON((p_port+hp_intstat), FIFO); + +#if defined(HARP_REVX) + + for (timer=0x00FFFFFFL; timer != 0x00000000L; timer--) { + + if (RD_HARPOON(p_port+hp_xferstat) & FIFO_EMPTY) + break; + + if (RDW_HARPOON((p_port+hp_intstat)) & BUS_FREE) + break; + } + + + if ( (RD_HARPOON(p_port+hp_xferstat) & FIFO_EMPTY) && + (RD_HARPOON(p_port+hp_fiforead) != + RD_HARPOON(p_port+hp_fifowrite)) && + (RD_HARPOON(p_port+hp_xfercnt_0)) + ) + + WR_HARPOON((p_port+hp_xferstat), 0x01); + +/* else + */ +/* sxfrp(p_port,p_card); + */ +#else + if (pCurrCard->currentSCCB != NULL) + sxfrp(p_port,p_card); +#endif + } + + else if (p_int & TIMEOUT) + { + + DISABLE_AUTO(p_port); + + WRW_HARPOON((p_port+hp_intstat), + (PROG_HLT | TIMEOUT | SEL |BUS_FREE | PHASE | IUNKWN)); + + pCurrCard->currentSCCB->HostStatus = SCCB_SELECTION_TIMEOUT; + + + currTar_Info = &sccbMgrTbl[p_card][pCurrCard->currentSCCB->TargID]; + if((pCurrCard->globalFlags & F_CONLUN_IO) && + ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)) + currTar_Info->TarLUNBusy[pCurrCard->currentSCCB->Lun] = FALSE; + else + currTar_Info->TarLUNBusy[0] = FALSE; + + + if (currTar_Info->TarEEValue & EE_SYNC_MASK) + { + currTar_Info->TarSyncCtrl = 0; + currTar_Info->TarStatus &= ~TAR_SYNC_MASK; + } + + if (currTar_Info->TarEEValue & EE_WIDE_SCSI) + { + currTar_Info->TarStatus &= ~TAR_WIDE_MASK; + } + + sssyncv(p_port, pCurrCard->currentSCCB->TargID, NARROW_SCSI,currTar_Info); + + queueCmdComplete(pCurrCard, pCurrCard->currentSCCB, p_card); + + } + +#if defined(SCAM_LEV_2) + + else if (p_int & SCAM_SEL) + { + + scarb(p_port,LEVEL2_TAR); + scsel(p_port); + scasid(p_card, p_port); + + scbusf(p_port); + + WRW_HARPOON((p_port+hp_intstat), SCAM_SEL); + } +#endif + + return(0x00); +} + + +/*--------------------------------------------------------------------- + * + * Function: SccbMgr_scsi_reset + * + * Description: A SCSI bus reset will be generated and all outstanding + * Sccbs will be returned via the callback. + * + *---------------------------------------------------------------------*/ +#if (FW_TYPE==_UCB_MGR_) +void SccbMgr_scsi_reset(CARD_HANDLE pCurrCard) +#else +#if defined(DOS) +void SccbMgr_scsi_reset(USHORT pCurrCard) +#else +void SccbMgr_scsi_reset(ULONG pCurrCard) +#endif +#endif +{ + UCHAR thisCard; + + thisCard = ((PSCCBcard)pCurrCard)->cardIndex; + + mOS_Lock((PSCCBcard)pCurrCard); + + if (((PSCCBcard) pCurrCard)->globalFlags & F_GREEN_PC) + { + WR_HARPOON(((PSCCBcard) pCurrCard)->ioPort+hp_clkctrl_0, CLKCTRL_DEFAULT); + WR_HARPOON(((PSCCBcard) pCurrCard)->ioPort+hp_sys_ctrl, 0x00); + } + + sresb(((PSCCBcard)pCurrCard)->ioPort,thisCard); + + if (RD_HARPOON(((PSCCBcard)pCurrCard)->ioPort+hp_ext_status) & BM_CMD_BUSY) + { + WR_HARPOON(((PSCCBcard) pCurrCard)->ioPort+hp_page_ctrl, + (RD_HARPOON(((PSCCBcard) pCurrCard)->ioPort+hp_page_ctrl) + & ~SCATTER_EN)); + + WR_HARPOON(((PSCCBcard) pCurrCard)->ioPort+hp_sg_addr,0x00); + + ((PSCCBcard) pCurrCard)->globalFlags &= ~F_HOST_XFER_ACT; + busMstrTimeOut(((PSCCBcard) pCurrCard)->ioPort); + + WR_HARPOON(((PSCCBcard) pCurrCard)->ioPort+hp_int_mask, + (INT_CMD_COMPL | SCSI_INTERRUPT)); + } + +/* + if (utilEERead(((PSCCBcard)pCurrCard)->ioPort, (SCAM_CONFIG/2)) + & SCAM_ENABLED) +*/ + scini(thisCard, ((PSCCBcard)pCurrCard)->ourId, 0); + +#if (FW_TYPE==_UCB_MGR_) + ((PSCCBcard)pCurrCard)->cardInfo->ai_AEN_routine(0x01,pCurrCard,0,0,0,0); +#endif + + mOS_UnLock((PSCCBcard)pCurrCard); +} + + +/*--------------------------------------------------------------------- + * + * Function: SccbMgr_timer_expired + * + * Description: This function allow me to kill my own job that has not + * yet completed, and has cause a timeout to occur. This + * timeout has caused the upper level driver to call this + * function. + * + *---------------------------------------------------------------------*/ + +#if (FW_TYPE==_UCB_MGR_) +void SccbMgr_timer_expired(CARD_HANDLE pCurrCard) +#else +#if defined(DOS) +void SccbMgr_timer_expired(USHORT pCurrCard) +#else +void SccbMgr_timer_expired(ULONG pCurrCard) +#endif +#endif +{ +} + +#if defined(DOS) +/*--------------------------------------------------------------------- + * + * Function: SccbMgr_status + * + * Description: This function returns the number of outstanding SCCB's. + * This is specific to the DOS enviroment, which needs this + * to help them keep protected and real mode commands staight. + * + *---------------------------------------------------------------------*/ + +USHORT SccbMgr_status(USHORT pCurrCard) +{ + return(BL_Card[pCurrCard].cmdCounter); +} +#endif + +/*--------------------------------------------------------------------- + * + * Function: SccbMgrTableInit + * + * Description: Initialize all Sccb manager data structures. + * + *---------------------------------------------------------------------*/ + +void SccbMgrTableInitAll() +{ + UCHAR thisCard; + + for (thisCard = 0; thisCard < MAX_CARDS; thisCard++) + { + SccbMgrTableInitCard(&BL_Card[thisCard],thisCard); + + BL_Card[thisCard].ioPort = 0x00; + BL_Card[thisCard].cardInfo = NULL; + BL_Card[thisCard].cardIndex = 0xFF; + BL_Card[thisCard].ourId = 0x00; + BL_Card[thisCard].pNvRamInfo = NULL; + } +} + + +/*--------------------------------------------------------------------- + * + * Function: SccbMgrTableInit + * + * Description: Initialize all Sccb manager data structures. + * + *---------------------------------------------------------------------*/ + +void SccbMgrTableInitCard(PSCCBcard pCurrCard, UCHAR p_card) +{ + UCHAR scsiID, qtag; + + for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) + { + BL_Card[p_card].discQ_Tbl[qtag] = NULL; + } + + for (scsiID = 0; scsiID < MAX_SCSI_TAR; scsiID++) + { + sccbMgrTbl[p_card][scsiID].TarStatus = 0; + sccbMgrTbl[p_card][scsiID].TarEEValue = 0; + SccbMgrTableInitTarget(p_card, scsiID); + } + + pCurrCard->scanIndex = 0x00; + pCurrCard->currentSCCB = NULL; + pCurrCard->globalFlags = 0x00; + pCurrCard->cmdCounter = 0x00; + pCurrCard->tagQ_Lst = 0x01; + pCurrCard->discQCount = 0; + + +} + + +/*--------------------------------------------------------------------- + * + * Function: SccbMgrTableInit + * + * Description: Initialize all Sccb manager data structures. + * + *---------------------------------------------------------------------*/ + +void SccbMgrTableInitTarget(UCHAR p_card, UCHAR target) +{ + + UCHAR lun, qtag; + PSCCBMgr_tar_info currTar_Info; + + currTar_Info = &sccbMgrTbl[p_card][target]; + + currTar_Info->TarSelQ_Cnt = 0; + currTar_Info->TarSyncCtrl = 0; + + currTar_Info->TarSelQ_Head = NULL; + currTar_Info->TarSelQ_Tail = NULL; + currTar_Info->TarTagQ_Cnt = 0; + currTar_Info->TarLUN_CA = FALSE; + + + for (lun = 0; lun < MAX_LUN; lun++) + { + currTar_Info->TarLUNBusy[lun] = FALSE; + currTar_Info->LunDiscQ_Idx[lun] = 0; + } + + for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) + { + if(BL_Card[p_card].discQ_Tbl[qtag] != NULL) + { + if(BL_Card[p_card].discQ_Tbl[qtag]->TargID == target) + { + BL_Card[p_card].discQ_Tbl[qtag] = NULL; + BL_Card[p_card].discQCount--; + } + } + } +} + +#if defined(BUGBUG) + +/***************************************************************** + * Save the current byte in the debug array + *****************************************************************/ + + +void Debug_Load(UCHAR p_card, UCHAR p_bug_data) +{ + debug_int[p_card][debug_index[p_card]] = p_bug_data; + debug_index[p_card]++; + + if (debug_index[p_card] == debug_size) + + debug_index[p_card] = 0; +} + +#endif +#ident "$Id: sccb_dat.c 1.9 1997/01/31 02:12:58 mohan Exp $" +/*---------------------------------------------------------------------- + * + * + * Copyright 1995-1996 by Mylex Corporation. All Rights Reserved + * + * This file is available under both the GNU General Public License + * and a BSD-style copyright; see LICENSE.FlashPoint for details. + * + * $Workfile: sccb_dat.c $ + * + * Description: Functions relating to handling of the SCCB interface + * between the device driver and the HARPOON. + * + * $Date: 1997/01/31 02:12:58 $ + * + * $Revision: 1.9 $ + * + *----------------------------------------------------------------------*/ + +/*#include */ + +#if (FW_TYPE==_UCB_MGR_) + /*#include */ +#endif + +/*#include */ +/*#include */ +/*#include */ +/*#include */ + + +#if defined(OS2) || defined (SOLARIS_REAL_MODE) +SCCBMGR_TAR_INFO sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR] = { 0 }; +SCCBCARD BL_Card[MAX_CARDS] = { 0 }; +SCCBSCAM_INFO scamInfo[MAX_SCSI_TAR] = { 0 }; +NVRAMINFO nvRamInfo[MAX_MB_CARDS] = { 0 }; +#else +SCCBMGR_TAR_INFO sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR]; +SCCBCARD BL_Card[MAX_CARDS]; +SCCBSCAM_INFO scamInfo[MAX_SCSI_TAR]; +NVRAMINFO nvRamInfo[MAX_MB_CARDS]; +#endif + + +#if defined(OS2) +void (far *s_PhaseTbl[8]) (ULONG, UCHAR) = { 0 }; +UCHAR temp_id_string[ID_STRING_LENGTH] = { 0 }; +#elif defined(SOLARIS_REAL_MODE) || defined(__STDC__) +void (*s_PhaseTbl[8]) (ULONG, UCHAR) = { 0 }; +#else +void (*s_PhaseTbl[8]) (); +#endif + +#if defined(DOS) +UCHAR first_time; +#endif + +UCHAR mbCards; +UCHAR scamHAString[] = {0x63, 0x07, 'B', 'U', 'S', 'L', 'O', 'G', 'I', 'C', \ + ' ', 'B', 'T', '-', '9', '3', '0', \ + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, \ + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20}; + +USHORT default_intena; + +#if defined(BUGBUG) +UCHAR debug_int[MAX_CARDS][debug_size]; +UCHAR debug_index[MAX_CARDS]; +UCHAR reserved_1[3]; +#endif +#ident "$Id: scsi.c 1.19 1997/01/31 02:08:14 mohan Exp $" +/*---------------------------------------------------------------------- + * + * + * Copyright 1995-1996 by Mylex Corporation. All Rights Reserved + * + * This file is available under both the GNU General Public License + * and a BSD-style copyright; see LICENSE.FlashPoint for details. + * + * $Workfile: scsi.c $ + * + * Description: Functions for handling SCSI bus functions such as + * selection/reselection, sync negotiation, message-in + * decoding. + * + * $Date: 1997/01/31 02:08:14 $ + * + * $Revision: 1.19 $ + * + *----------------------------------------------------------------------*/ + +/*#include */ + +#if (FW_TYPE==_UCB_MGR_) + /*#include */ +#endif + +/*#include */ +/*#include */ +/*#include */ +/*#include */ +/*#include */ +/*#include */ + + +/* +extern SCCBCARD BL_Card[MAX_CARDS]; +extern SCCBMGR_TAR_INFO sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR]; +#if defined(BUGBUG) +void Debug_Load(UCHAR p_card, UCHAR p_bug_data); +#endif +*/ + +/*--------------------------------------------------------------------- + * + * Function: sfetm + * + * Description: Read in a message byte from the SCSI bus, and check + * for a parity error. + * + *---------------------------------------------------------------------*/ + +#if defined(DOS) +UCHAR sfm(USHORT port, PSCCB pCurrSCCB) +#else +UCHAR sfm(ULONG port, PSCCB pCurrSCCB) +#endif +{ + UCHAR message; + USHORT TimeOutLoop; + + TimeOutLoop = 0; + while( (!(RD_HARPOON(port+hp_scsisig) & SCSI_REQ)) && + (TimeOutLoop++ < 20000) ){} + + WR_HARPOON(port+hp_portctrl_0, SCSI_PORT); + + message = RD_HARPOON(port+hp_scsidata_0); + + WR_HARPOON(port+hp_scsisig, (SCSI_ACK + S_ILL_PH)); + + if (TimeOutLoop > 20000) + message = 0x00; /* force message byte = 0 if Time Out on Req */ + + if ((RDW_HARPOON((port+hp_intstat)) & PARITY) && + (RD_HARPOON(port+hp_addstat) & SCSI_PAR_ERR)) + { + if (pCurrSCCB != NULL) + { + pCurrSCCB->Sccb_scsimsg = SMPARITY; + } + message = 0x00; + do + { + ACCEPT_MSG_ATN(port); + while( (!(RD_HARPOON(port+hp_scsisig) & SCSI_REQ)) && + (TimeOutLoop++ < 20000) ){} + if (TimeOutLoop > 20000) + { + WRW_HARPOON((port+hp_intstat), PARITY); + return(message); + } + if ((RD_HARPOON(port+hp_scsisig) & S_SCSI_PHZ) != S_MSGI_PH) + { + WRW_HARPOON((port+hp_intstat), PARITY); + return(message); + } + WR_HARPOON(port+hp_portctrl_0, SCSI_PORT); + + RD_HARPOON(port+hp_scsidata_0); + + WR_HARPOON(port+hp_scsisig, (SCSI_ACK + S_ILL_PH)); + + }while(1); + + } + return(message); +} + + +/*--------------------------------------------------------------------- + * + * Function: ssel + * + * Description: Load up automation and select target device. + * + *---------------------------------------------------------------------*/ + +#if defined(DOS) +void ssel(USHORT port, UCHAR p_card) +#else +void ssel(ULONG port, UCHAR p_card) +#endif +{ + +#if defined(DOS) + UCHAR auto_loaded, i, target, *theCCB; +#elif defined(OS2) + UCHAR auto_loaded, i, target; + UCHAR far *theCCB; +#else + UCHAR auto_loaded, i, target, *theCCB; +#endif + +#if defined(DOS) + USHORT cdb_reg; +#else + ULONG cdb_reg; +#endif + PSCCBcard CurrCard; + PSCCB currSCCB; + PSCCBMgr_tar_info currTar_Info; + UCHAR lastTag, lun; + + CurrCard = &BL_Card[p_card]; + currSCCB = CurrCard->currentSCCB; + target = currSCCB->TargID; + currTar_Info = &sccbMgrTbl[p_card][target]; + lastTag = CurrCard->tagQ_Lst; + + ARAM_ACCESS(port); + + + if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_REJECT) + currSCCB->ControlByte &= ~F_USE_CMD_Q; + + if(((CurrCard->globalFlags & F_CONLUN_IO) && + ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) + + lun = currSCCB->Lun; + else + lun = 0; + + +#if defined(DOS) + currTar_Info->TarLUNBusy[lun] = TRUE; + +#else + + if (CurrCard->globalFlags & F_TAG_STARTED) + { + if (!(currSCCB->ControlByte & F_USE_CMD_Q)) + { + if ((currTar_Info->TarLUN_CA == FALSE) + && ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) + == TAG_Q_TRYING)) + { + + if (currTar_Info->TarTagQ_Cnt !=0) + { + currTar_Info->TarLUNBusy[lun] = TRUE; + queueSelectFail(CurrCard,p_card); + SGRAM_ACCESS(port); + return; + } + + else { + currTar_Info->TarLUNBusy[lun] = TRUE; + } + + } /*End non-tagged */ + + else { + currTar_Info->TarLUNBusy[lun] = TRUE; + } + + } /*!Use cmd Q Tagged */ + + else { + if (currTar_Info->TarLUN_CA == TRUE) + { + queueSelectFail(CurrCard,p_card); + SGRAM_ACCESS(port); + return; + } + + currTar_Info->TarLUNBusy[lun] = TRUE; + + } /*else use cmd Q tagged */ + + } /*if glob tagged started */ + + else { + currTar_Info->TarLUNBusy[lun] = TRUE; + } + +#endif /* DOS */ + + + + if((((CurrCard->globalFlags & F_CONLUN_IO) && + ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)) + || (!(currSCCB->ControlByte & F_USE_CMD_Q)))) + { + if(CurrCard->discQCount >= QUEUE_DEPTH) + { + currTar_Info->TarLUNBusy[lun] = TRUE; + queueSelectFail(CurrCard,p_card); + SGRAM_ACCESS(port); + return; + } + for (i = 1; i < QUEUE_DEPTH; i++) + { + if (++lastTag >= QUEUE_DEPTH) lastTag = 1; + if (CurrCard->discQ_Tbl[lastTag] == NULL) + { + CurrCard->tagQ_Lst = lastTag; + currTar_Info->LunDiscQ_Idx[lun] = lastTag; + CurrCard->discQ_Tbl[lastTag] = currSCCB; + CurrCard->discQCount++; + break; + } + } + if(i == QUEUE_DEPTH) + { + currTar_Info->TarLUNBusy[lun] = TRUE; + queueSelectFail(CurrCard,p_card); + SGRAM_ACCESS(port); + return; + } + } + + + + auto_loaded = FALSE; + + WR_HARPOON(port+hp_select_id, target); + WR_HARPOON(port+hp_gp_reg_3, target); /* Use by new automation logic */ + + if (currSCCB->OperationCode == RESET_COMMAND) { + WRW_HARPOON((port+ID_MSG_STRT), (MPM_OP+AMSG_OUT+ + (currSCCB->Sccb_idmsg & ~DISC_PRIV))); + + WRW_HARPOON((port+ID_MSG_STRT+2),BRH_OP+ALWAYS+NP); + + currSCCB->Sccb_scsimsg = SMDEV_RESET; + + WR_HARPOON(port+hp_autostart_3, (SELECT+SELCHK_STRT)); + auto_loaded = TRUE; + currSCCB->Sccb_scsistat = SELECT_BDR_ST; + + if (currTar_Info->TarEEValue & EE_SYNC_MASK) + { + currTar_Info->TarSyncCtrl = 0; + currTar_Info->TarStatus &= ~TAR_SYNC_MASK; + } + +#if defined(WIDE_SCSI) + + if (currTar_Info->TarEEValue & EE_WIDE_SCSI) + { + currTar_Info->TarStatus &= ~TAR_WIDE_MASK; + } +#endif + + sssyncv(port, target, NARROW_SCSI,currTar_Info); + SccbMgrTableInitTarget(p_card, target); + + } + + else if(currSCCB->Sccb_scsistat == ABORT_ST) + { + WRW_HARPOON((port+ID_MSG_STRT), (MPM_OP+AMSG_OUT+ + (currSCCB->Sccb_idmsg & ~DISC_PRIV))); + + WRW_HARPOON((port+ID_MSG_STRT+2),BRH_OP+ALWAYS+CMDPZ); + + WRW_HARPOON((port+SYNC_MSGS+0), (MPM_OP+AMSG_OUT+ + (((UCHAR)(currSCCB->ControlByte & TAG_TYPE_MASK) + >> 6) | (UCHAR)0x20))); + WRW_HARPOON((port+SYNC_MSGS+2), + (MPM_OP+AMSG_OUT+currSCCB->Sccb_tag)); + WRW_HARPOON((port+SYNC_MSGS+4), (BRH_OP+ALWAYS+NP )); + + WR_HARPOON(port+hp_autostart_3, (SELECT+SELCHK_STRT)); + auto_loaded = TRUE; + + } + +#if defined(WIDE_SCSI) + + + else if (!(currTar_Info->TarStatus & WIDE_NEGOCIATED)) { + auto_loaded = siwidn(port,p_card); + currSCCB->Sccb_scsistat = SELECT_WN_ST; + } + +#endif + + + else if (!((currTar_Info->TarStatus & TAR_SYNC_MASK) + == SYNC_SUPPORTED)) { + auto_loaded = sisyncn(port,p_card, FALSE); + currSCCB->Sccb_scsistat = SELECT_SN_ST; + } + + + if (!auto_loaded) + { + +#if !defined(DOS) + if (currSCCB->ControlByte & F_USE_CMD_Q) + { + + CurrCard->globalFlags |= F_TAG_STARTED; + + if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) + == TAG_Q_REJECT) + { + currSCCB->ControlByte &= ~F_USE_CMD_Q; + + /* Fix up the start instruction with a jump to + Non-Tag-CMD handling */ + WRW_HARPOON((port+ID_MSG_STRT),BRH_OP+ALWAYS+NTCMD); + + WRW_HARPOON((port+NON_TAG_ID_MSG), + (MPM_OP+AMSG_OUT+currSCCB->Sccb_idmsg)); + + WR_HARPOON(port+hp_autostart_3, (SELECT+SELCHK_STRT)); + + /* Setup our STATE so we know what happend when + the wheels fall off. */ + currSCCB->Sccb_scsistat = SELECT_ST; + + currTar_Info->TarLUNBusy[lun] = TRUE; + } + + else + { + WRW_HARPOON((port+ID_MSG_STRT), (MPM_OP+AMSG_OUT+currSCCB->Sccb_idmsg)); + + WRW_HARPOON((port+ID_MSG_STRT+2), (MPM_OP+AMSG_OUT+ + (((UCHAR)(currSCCB->ControlByte & TAG_TYPE_MASK) + >> 6) | (UCHAR)0x20))); + + for (i = 1; i < QUEUE_DEPTH; i++) + { + if (++lastTag >= QUEUE_DEPTH) lastTag = 1; + if (CurrCard->discQ_Tbl[lastTag] == NULL) + { + WRW_HARPOON((port+ID_MSG_STRT+6), + (MPM_OP+AMSG_OUT+lastTag)); + CurrCard->tagQ_Lst = lastTag; + currSCCB->Sccb_tag = lastTag; + CurrCard->discQ_Tbl[lastTag] = currSCCB; + CurrCard->discQCount++; + break; + } + } + + + if ( i == QUEUE_DEPTH ) + { + currTar_Info->TarLUNBusy[lun] = TRUE; + queueSelectFail(CurrCard,p_card); + SGRAM_ACCESS(port); + return; + } + + currSCCB->Sccb_scsistat = SELECT_Q_ST; + + WR_HARPOON(port+hp_autostart_3, (SELECT+SELCHK_STRT)); + } + } + + else + { +#endif /* !DOS */ + + WRW_HARPOON((port+ID_MSG_STRT),BRH_OP+ALWAYS+NTCMD); + + WRW_HARPOON((port+NON_TAG_ID_MSG), + (MPM_OP+AMSG_OUT+currSCCB->Sccb_idmsg)); + + currSCCB->Sccb_scsistat = SELECT_ST; + + WR_HARPOON(port+hp_autostart_3, (SELECT+SELCHK_STRT)); +#if !defined(DOS) + } +#endif + + +#if defined(OS2) + theCCB = (UCHAR far *)&currSCCB->Cdb[0]; +#else + theCCB = (UCHAR *)&currSCCB->Cdb[0]; +#endif + + cdb_reg = port + CMD_STRT; + + for (i=0; i < currSCCB->CdbLength; i++) + { + WRW_HARPOON(cdb_reg, (MPM_OP + ACOMMAND + *theCCB)); + cdb_reg +=2; + theCCB++; + } + + if (currSCCB->CdbLength != TWELVE_BYTE_CMD) + WRW_HARPOON(cdb_reg, (BRH_OP+ALWAYS+ NP)); + + } /* auto_loaded */ + +#if defined(WIDE_SCSI) + WRW_HARPOON((port+hp_fiforead), (USHORT) 0x00); + WR_HARPOON(port+hp_xferstat, 0x00); +#endif + + WRW_HARPOON((port+hp_intstat), (PROG_HLT | TIMEOUT | SEL | BUS_FREE)); + + WR_HARPOON(port+hp_portctrl_0,(SCSI_PORT)); + + + if (!(currSCCB->Sccb_MGRFlags & F_DEV_SELECTED)) + { + WR_HARPOON(port+hp_scsictrl_0, (SEL_TAR | ENA_ATN | ENA_RESEL | ENA_SCAM_SEL)); + } + else + { + +/* auto_loaded = (RD_HARPOON(port+hp_autostart_3) & (UCHAR)0x1F); + auto_loaded |= AUTO_IMMED; */ + auto_loaded = AUTO_IMMED; + + DISABLE_AUTO(port); + + WR_HARPOON(port+hp_autostart_3, auto_loaded); + } + + SGRAM_ACCESS(port); +} + + +/*--------------------------------------------------------------------- + * + * Function: sres + * + * Description: Hookup the correct CCB and handle the incoming messages. + * + *---------------------------------------------------------------------*/ + +#if defined(DOS) +void sres(USHORT port, UCHAR p_card, PSCCBcard pCurrCard) +#else +void sres(ULONG port, UCHAR p_card, PSCCBcard pCurrCard) +#endif +{ +#ifdef DOS + UCHAR our_target,message, msgRetryCount; + extern UCHAR lun, tag; +#else + UCHAR our_target,message,lun,tag, msgRetryCount; +#endif + PSCCBMgr_tar_info currTar_Info; + PSCCB currSCCB; + + + + + if(pCurrCard->currentSCCB != NULL) + { + currTar_Info = &sccbMgrTbl[p_card][pCurrCard->currentSCCB->TargID]; + DISABLE_AUTO(port); + + + WR_HARPOON((port+hp_scsictrl_0),(ENA_RESEL | ENA_SCAM_SEL)); + + + currSCCB = pCurrCard->currentSCCB; + if(currSCCB->Sccb_scsistat == SELECT_WN_ST) + { + currTar_Info->TarStatus &= ~TAR_WIDE_MASK; + currSCCB->Sccb_scsistat = BUS_FREE_ST; + } + if(currSCCB->Sccb_scsistat == SELECT_SN_ST) + { + currTar_Info->TarStatus &= ~TAR_SYNC_MASK; + currSCCB->Sccb_scsistat = BUS_FREE_ST; + } + if(((pCurrCard->globalFlags & F_CONLUN_IO) && + ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) + { + currTar_Info->TarLUNBusy[currSCCB->Lun] = FALSE; + if(currSCCB->Sccb_scsistat != ABORT_ST) + { + pCurrCard->discQCount--; + pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[currSCCB->Lun]] + = NULL; + } + } + else + { + currTar_Info->TarLUNBusy[0] = FALSE; + if(currSCCB->Sccb_tag) + { + if(currSCCB->Sccb_scsistat != ABORT_ST) + { + pCurrCard->discQCount--; + pCurrCard->discQ_Tbl[currSCCB->Sccb_tag] = NULL; + } + }else + { + if(currSCCB->Sccb_scsistat != ABORT_ST) + { + pCurrCard->discQCount--; + pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[0]] = NULL; + } + } + } + + queueSelectFail(&BL_Card[p_card],p_card); + } + +#if defined(WIDE_SCSI) + WRW_HARPOON((port+hp_fiforead), (USHORT) 0x00); +#endif + + + our_target = (UCHAR)(RD_HARPOON(port+hp_select_id) >> 4); + currTar_Info = &sccbMgrTbl[p_card][our_target]; + + + msgRetryCount = 0; + do + { + message = GetTarLun(port, p_card, our_target, pCurrCard, &tag, &lun); + if(message == FALSE) + { + msgRetryCount++; + if(msgRetryCount == 1) + { + SendMsg(port, SMPARITY); + } + else + { + SendMsg(port, SMDEV_RESET); + + sssyncv(port, our_target, NARROW_SCSI,currTar_Info); + + if (sccbMgrTbl[p_card][our_target].TarEEValue & EE_SYNC_MASK) + { + + sccbMgrTbl[p_card][our_target].TarStatus &= ~TAR_SYNC_MASK; + + } + + if (sccbMgrTbl[p_card][our_target].TarEEValue & EE_WIDE_SCSI) + { + + sccbMgrTbl[p_card][our_target].TarStatus &= ~TAR_WIDE_MASK; + } + + + queueFlushTargSccb(p_card, our_target, SCCB_COMPLETE); + SccbMgrTableInitTarget(p_card,our_target); + return; + } + } + }while(message == FALSE); + + + + if(((pCurrCard->globalFlags & F_CONLUN_IO) && + ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) + { + currTar_Info->TarLUNBusy[lun] = TRUE; + pCurrCard->currentSCCB = pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[lun]]; + if(pCurrCard->currentSCCB != NULL) + { + ACCEPT_MSG(port); + } + else + { + ACCEPT_MSG_ATN(port); + } + } + else + { + currTar_Info->TarLUNBusy[0] = TRUE; + + + if (tag) + { + if (pCurrCard->discQ_Tbl[tag] != NULL) + { + pCurrCard->currentSCCB = pCurrCard->discQ_Tbl[tag]; + currTar_Info->TarTagQ_Cnt--; + ACCEPT_MSG(port); + } + else + { + ACCEPT_MSG_ATN(port); + } + }else + { + pCurrCard->currentSCCB = pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[0]]; + if(pCurrCard->currentSCCB != NULL) + { + ACCEPT_MSG(port); + } + else + { + ACCEPT_MSG_ATN(port); + } + } + } + + if(pCurrCard->currentSCCB != NULL) + { + if(pCurrCard->currentSCCB->Sccb_scsistat == ABORT_ST) + { + /* During Abort Tag command, the target could have got re-selected + and completed the command. Check the select Q and remove the CCB + if it is in the Select Q */ + queueFindSccb(pCurrCard->currentSCCB, p_card); + } + } + + + while (!(RDW_HARPOON((port+hp_intstat)) & (PHASE | RESET)) && + !(RD_HARPOON(port+hp_scsisig) & SCSI_REQ) && + (RD_HARPOON(port+hp_scsisig) & SCSI_BSY)) ; +} + +#if defined(DOS) +UCHAR GetTarLun(USHORT port, UCHAR p_card, UCHAR our_target, PSCCBcard pCurrCard, PUCHAR tag, PUCHAR lun) +#else +UCHAR GetTarLun(ULONG port, UCHAR p_card, UCHAR our_target, PSCCBcard pCurrCard, PUCHAR tag, PUCHAR lun) +#endif +{ + UCHAR message; + PSCCBMgr_tar_info currTar_Info; + + + currTar_Info = &sccbMgrTbl[p_card][our_target]; + *tag = 0; + + + while(!(RD_HARPOON(port+hp_scsisig) & SCSI_REQ)) + { + if (! (RD_HARPOON(port+hp_scsisig) & SCSI_BSY)) + { + + WRW_HARPOON((port+hp_intstat), PHASE); + return(TRUE); + } + } + + WRW_HARPOON((port+hp_intstat), PHASE); + if ((RD_HARPOON(port+hp_scsisig) & S_SCSI_PHZ) == S_MSGI_PH) + { + + message = sfm(port,pCurrCard->currentSCCB); + if (message) + { + + if (message <= (0x80 | LUN_MASK)) + { + *lun = message & (UCHAR)LUN_MASK; + +#if !defined(DOS) + if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_TRYING) + { + if (currTar_Info->TarTagQ_Cnt != 0) + { + + if (!(currTar_Info->TarLUN_CA)) + { + ACCEPT_MSG(port); /*Release the ACK for ID msg. */ + + + message = sfm(port,pCurrCard->currentSCCB); + if (message) + { + ACCEPT_MSG(port); + } + + else + return(FALSE); + + *tag = sfm(port,pCurrCard->currentSCCB); + + if (!(*tag)) return(FALSE); + + } /*C.A. exists! */ + + } /*End Q cnt != 0 */ + + } /*End Tag cmds supported! */ +#endif /* !DOS */ + + } /*End valid ID message. */ + + else + { + + ACCEPT_MSG_ATN(port); + } + + } /* End good id message. */ + + else + { + + return(FALSE); + } + } + else + { + ACCEPT_MSG_ATN(port); + return(TRUE); + } + return(TRUE); +} + + +#if defined(DOS) +void SendMsg(USHORT port, UCHAR message) +#else +void SendMsg(ULONG port, UCHAR message) +#endif +{ + while(!(RD_HARPOON(port+hp_scsisig) & SCSI_REQ)) + { + if (! (RD_HARPOON(port+hp_scsisig) & SCSI_BSY)) + { + + WRW_HARPOON((port+hp_intstat), PHASE); + return; + } + } + + WRW_HARPOON((port+hp_intstat), PHASE); + if ((RD_HARPOON(port+hp_scsisig) & S_SCSI_PHZ) == S_MSGO_PH) + { + WRW_HARPOON((port+hp_intstat), (BUS_FREE | PHASE | XFER_CNT_0)); + + + WR_HARPOON(port+hp_portctrl_0, SCSI_BUS_EN); + + WR_HARPOON(port+hp_scsidata_0,message); + + WR_HARPOON(port+hp_scsisig, (SCSI_ACK + S_ILL_PH)); + + ACCEPT_MSG(port); + + WR_HARPOON(port+hp_portctrl_0, 0x00); + + if ((message == SMABORT) || (message == SMDEV_RESET) || + (message == SMABORT_TAG) ) + { + while(!(RDW_HARPOON((port+hp_intstat)) & (BUS_FREE | PHASE))) {} + + if (RDW_HARPOON((port+hp_intstat)) & BUS_FREE) + { + WRW_HARPOON((port+hp_intstat), BUS_FREE); + } + } + } +} + +/*--------------------------------------------------------------------- + * + * Function: sdecm + * + * Description: Determine the proper responce to the message from the + * target device. + * + *---------------------------------------------------------------------*/ +#if defined(DOS) +void sdecm(UCHAR message, USHORT port, UCHAR p_card) +#else +void sdecm(UCHAR message, ULONG port, UCHAR p_card) +#endif +{ + PSCCB currSCCB; + PSCCBcard CurrCard; + PSCCBMgr_tar_info currTar_Info; + + CurrCard = &BL_Card[p_card]; + currSCCB = CurrCard->currentSCCB; + + currTar_Info = &sccbMgrTbl[p_card][currSCCB->TargID]; + + if (message == SMREST_DATA_PTR) + { + if (!(currSCCB->Sccb_XferState & F_NO_DATA_YET)) + { + currSCCB->Sccb_ATC = currSCCB->Sccb_savedATC; + + hostDataXferRestart(currSCCB); + } + + ACCEPT_MSG(port); + WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START)); + } + + else if (message == SMCMD_COMP) + { + + + if (currSCCB->Sccb_scsistat == SELECT_Q_ST) + { + currTar_Info->TarStatus &= ~(UCHAR)TAR_TAG_Q_MASK; + currTar_Info->TarStatus |= (UCHAR)TAG_Q_REJECT; + } + + ACCEPT_MSG(port); + + } + + else if ((message == SMNO_OP) || (message >= SMIDENT) + || (message == SMINIT_RECOVERY) || (message == SMREL_RECOVERY)) + { + + ACCEPT_MSG(port); + WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START)); + } + + else if (message == SMREJECT) + { + + if ((currSCCB->Sccb_scsistat == SELECT_SN_ST) || + (currSCCB->Sccb_scsistat == SELECT_WN_ST) || + ((currTar_Info->TarStatus & TAR_SYNC_MASK) == SYNC_TRYING ) || + ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_TRYING ) ) + + { + WRW_HARPOON((port+hp_intstat), BUS_FREE); + + ACCEPT_MSG(port); + + + while ((!(RD_HARPOON(port+hp_scsisig) & SCSI_REQ)) && + (!(RDW_HARPOON((port+hp_intstat)) & BUS_FREE))) {} + + if(currSCCB->Lun == 0x00) + { + if ((currSCCB->Sccb_scsistat == SELECT_SN_ST)) + { + + currTar_Info->TarStatus |= (UCHAR)SYNC_SUPPORTED; + + currTar_Info->TarEEValue &= ~EE_SYNC_MASK; + } + +#if defined(WIDE_SCSI) + else if ((currSCCB->Sccb_scsistat == SELECT_WN_ST)) + { + + + currTar_Info->TarStatus = (currTar_Info->TarStatus & + ~WIDE_ENABLED) | WIDE_NEGOCIATED; + + currTar_Info->TarEEValue &= ~EE_WIDE_SCSI; + + } +#endif + + else if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_TRYING ) + { + currTar_Info->TarStatus = (currTar_Info->TarStatus & + ~(UCHAR)TAR_TAG_Q_MASK) | TAG_Q_REJECT; + + + currSCCB->ControlByte &= ~F_USE_CMD_Q; + CurrCard->discQCount--; + CurrCard->discQ_Tbl[currSCCB->Sccb_tag] = NULL; + currSCCB->Sccb_tag = 0x00; + + } + } + + if (RDW_HARPOON((port+hp_intstat)) & BUS_FREE) + { + + + if(currSCCB->Lun == 0x00) + { + WRW_HARPOON((port+hp_intstat), BUS_FREE); + CurrCard->globalFlags |= F_NEW_SCCB_CMD; + } + } + + else + { + + if((CurrCard->globalFlags & F_CONLUN_IO) && + ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)) + currTar_Info->TarLUNBusy[currSCCB->Lun] = TRUE; + else + currTar_Info->TarLUNBusy[0] = TRUE; + + + currSCCB->ControlByte &= ~(UCHAR)F_USE_CMD_Q; + + WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START)); + + } + } + + else + { + ACCEPT_MSG(port); + + while ((!(RD_HARPOON(port+hp_scsisig) & SCSI_REQ)) && + (!(RDW_HARPOON((port+hp_intstat)) & BUS_FREE))) {} + + if (!(RDW_HARPOON((port+hp_intstat)) & BUS_FREE)) + { + WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START)); + } + } + } + + else if (message == SMEXT) + { + + ACCEPT_MSG(port); + shandem(port,p_card,currSCCB); + } + + else if (message == SMIGNORWR) + { + + ACCEPT_MSG(port); /* ACK the RESIDUE MSG */ + + message = sfm(port,currSCCB); + + if(currSCCB->Sccb_scsimsg != SMPARITY) + ACCEPT_MSG(port); + WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START)); + } + + + else + { + + currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL; + currSCCB->Sccb_scsimsg = SMREJECT; + + ACCEPT_MSG_ATN(port); + WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START)); + } +} + + +/*--------------------------------------------------------------------- + * + * Function: shandem + * + * Description: Decide what to do with the extended message. + * + *---------------------------------------------------------------------*/ +#if defined(DOS) +void shandem(USHORT port, UCHAR p_card, PSCCB pCurrSCCB) +#else +void shandem(ULONG port, UCHAR p_card, PSCCB pCurrSCCB) +#endif +{ + UCHAR length,message; + + length = sfm(port,pCurrSCCB); + if (length) + { + + ACCEPT_MSG(port); + message = sfm(port,pCurrSCCB); + if (message) + { + + if (message == SMSYNC) + { + + if (length == 0x03) + { + + ACCEPT_MSG(port); + stsyncn(port,p_card); + } + else + { + + pCurrSCCB->Sccb_scsimsg = SMREJECT; + ACCEPT_MSG_ATN(port); + } + } +#if defined(WIDE_SCSI) + else if (message == SMWDTR) + { + + if (length == 0x02) + { + + ACCEPT_MSG(port); + stwidn(port,p_card); + } + else + { + + pCurrSCCB->Sccb_scsimsg = SMREJECT; + ACCEPT_MSG_ATN(port); + + WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START)); + } + } +#endif + else + { + + pCurrSCCB->Sccb_scsimsg = SMREJECT; + ACCEPT_MSG_ATN(port); + + WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START)); + } + } + else + { + if(pCurrSCCB->Sccb_scsimsg != SMPARITY) + ACCEPT_MSG(port); + WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START)); + } + } +} + + +/*--------------------------------------------------------------------- + * + * Function: sisyncn + * + * Description: Read in a message byte from the SCSI bus, and check + * for a parity error. + * + *---------------------------------------------------------------------*/ + +#if defined(DOS) +UCHAR sisyncn(USHORT port, UCHAR p_card, UCHAR syncFlag) +#else +UCHAR sisyncn(ULONG port, UCHAR p_card, UCHAR syncFlag) +#endif +{ + PSCCB currSCCB; + PSCCBMgr_tar_info currTar_Info; + + currSCCB = BL_Card[p_card].currentSCCB; + currTar_Info = &sccbMgrTbl[p_card][currSCCB->TargID]; + + if (!((currTar_Info->TarStatus & TAR_SYNC_MASK) == SYNC_TRYING)) { + + + WRW_HARPOON((port+ID_MSG_STRT), + (MPM_OP+AMSG_OUT+(currSCCB->Sccb_idmsg & ~(UCHAR)DISC_PRIV))); + + WRW_HARPOON((port+ID_MSG_STRT+2),BRH_OP+ALWAYS+CMDPZ); + + WRW_HARPOON((port+SYNC_MSGS+0), (MPM_OP+AMSG_OUT+SMEXT )); + WRW_HARPOON((port+SYNC_MSGS+2), (MPM_OP+AMSG_OUT+0x03 )); + WRW_HARPOON((port+SYNC_MSGS+4), (MPM_OP+AMSG_OUT+SMSYNC)); + + + if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_20MB) + + WRW_HARPOON((port+SYNC_MSGS+6), (MPM_OP+AMSG_OUT+ 12)); + + else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_10MB) + + WRW_HARPOON((port+SYNC_MSGS+6), (MPM_OP+AMSG_OUT+ 25)); + + else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_5MB) + + WRW_HARPOON((port+SYNC_MSGS+6), (MPM_OP+AMSG_OUT+ 50)); + + else + WRW_HARPOON((port+SYNC_MSGS+6), (MPM_OP+AMSG_OUT+ 00)); + + + WRW_HARPOON((port+SYNC_MSGS+8), (RAT_OP )); + WRW_HARPOON((port+SYNC_MSGS+10),(MPM_OP+AMSG_OUT+DEFAULT_OFFSET)); + WRW_HARPOON((port+SYNC_MSGS+12),(BRH_OP+ALWAYS+NP )); + + + if(syncFlag == FALSE) + { + WR_HARPOON(port+hp_autostart_3, (SELECT+SELCHK_STRT)); + currTar_Info->TarStatus = ((currTar_Info->TarStatus & + ~(UCHAR)TAR_SYNC_MASK) | (UCHAR)SYNC_TRYING); + } + else + { + WR_HARPOON(port+hp_autostart_3, (AUTO_IMMED + CMD_ONLY_STRT)); + } + + + return(TRUE); + } + + else { + + currTar_Info->TarStatus |= (UCHAR)SYNC_SUPPORTED; + currTar_Info->TarEEValue &= ~EE_SYNC_MASK; + return(FALSE); + } +} + + + +/*--------------------------------------------------------------------- + * + * Function: stsyncn + * + * Description: The has sent us a Sync Nego message so handle it as + * necessary. + * + *---------------------------------------------------------------------*/ +#if defined(DOS) +void stsyncn(USHORT port, UCHAR p_card) +#else +void stsyncn(ULONG port, UCHAR p_card) +#endif +{ + UCHAR sync_msg,offset,sync_reg,our_sync_msg; + PSCCB currSCCB; + PSCCBMgr_tar_info currTar_Info; + + currSCCB = BL_Card[p_card].currentSCCB; + currTar_Info = &sccbMgrTbl[p_card][currSCCB->TargID]; + + sync_msg = sfm(port,currSCCB); + + if((sync_msg == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY)) + { + WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START)); + return; + } + + ACCEPT_MSG(port); + + + offset = sfm(port,currSCCB); + + if((offset == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY)) + { + WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START)); + return; + } + + if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_20MB) + + our_sync_msg = 12; /* Setup our Message to 20mb/s */ + + else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_10MB) + + our_sync_msg = 25; /* Setup our Message to 10mb/s */ + + else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_5MB) + + our_sync_msg = 50; /* Setup our Message to 5mb/s */ + else + + our_sync_msg = 0; /* Message = Async */ + + if (sync_msg < our_sync_msg) { + sync_msg = our_sync_msg; /*if faster, then set to max. */ + } + + if (offset == ASYNC) + sync_msg = ASYNC; + + if (offset > MAX_OFFSET) + offset = MAX_OFFSET; + + sync_reg = 0x00; + + if (sync_msg > 12) + + sync_reg = 0x20; /* Use 10MB/s */ + + if (sync_msg > 25) + + sync_reg = 0x40; /* Use 6.6MB/s */ + + if (sync_msg > 38) + + sync_reg = 0x60; /* Use 5MB/s */ + + if (sync_msg > 50) + + sync_reg = 0x80; /* Use 4MB/s */ + + if (sync_msg > 62) + + sync_reg = 0xA0; /* Use 3.33MB/s */ + + if (sync_msg > 75) + + sync_reg = 0xC0; /* Use 2.85MB/s */ + + if (sync_msg > 87) + + sync_reg = 0xE0; /* Use 2.5MB/s */ + + if (sync_msg > 100) { + + sync_reg = 0x00; /* Use ASYNC */ + offset = 0x00; + } + + +#if defined(WIDE_SCSI) + if (currTar_Info->TarStatus & WIDE_ENABLED) + + sync_reg |= offset; + + else + + sync_reg |= (offset | NARROW_SCSI); + +#else + sync_reg |= (offset | NARROW_SCSI); +#endif + + sssyncv(port,currSCCB->TargID,sync_reg,currTar_Info); + + + if (currSCCB->Sccb_scsistat == SELECT_SN_ST) { + + + ACCEPT_MSG(port); + + currTar_Info->TarStatus = ((currTar_Info->TarStatus & + ~(UCHAR)TAR_SYNC_MASK) | (UCHAR)SYNC_SUPPORTED); + + WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START)); + } + + else { + + + ACCEPT_MSG_ATN(port); + + sisyncr(port,sync_msg,offset); + + currTar_Info->TarStatus = ((currTar_Info->TarStatus & + ~(UCHAR)TAR_SYNC_MASK) | (UCHAR)SYNC_SUPPORTED); + } +} + + +/*--------------------------------------------------------------------- + * + * Function: sisyncr + * + * Description: Answer the targets sync message. + * + *---------------------------------------------------------------------*/ +#if defined(DOS) +void sisyncr(USHORT port,UCHAR sync_pulse, UCHAR offset) +#else +void sisyncr(ULONG port,UCHAR sync_pulse, UCHAR offset) +#endif +{ + ARAM_ACCESS(port); + WRW_HARPOON((port+SYNC_MSGS+0), (MPM_OP+AMSG_OUT+SMEXT )); + WRW_HARPOON((port+SYNC_MSGS+2), (MPM_OP+AMSG_OUT+0x03 )); + WRW_HARPOON((port+SYNC_MSGS+4), (MPM_OP+AMSG_OUT+SMSYNC)); + WRW_HARPOON((port+SYNC_MSGS+6), (MPM_OP+AMSG_OUT+sync_pulse)); + WRW_HARPOON((port+SYNC_MSGS+8), (RAT_OP )); + WRW_HARPOON((port+SYNC_MSGS+10),(MPM_OP+AMSG_OUT+offset)); + WRW_HARPOON((port+SYNC_MSGS+12),(BRH_OP+ALWAYS+NP )); + SGRAM_ACCESS(port); + + WR_HARPOON(port+hp_portctrl_0, SCSI_PORT); + WRW_HARPOON((port+hp_intstat), CLR_ALL_INT_1); + + WR_HARPOON(port+hp_autostart_3, (AUTO_IMMED+CMD_ONLY_STRT)); + + while (!(RDW_HARPOON((port+hp_intstat)) & (BUS_FREE | AUTO_INT))) {} +} + + + +#if defined(WIDE_SCSI) + +/*--------------------------------------------------------------------- + * + * Function: siwidn + * + * Description: Read in a message byte from the SCSI bus, and check + * for a parity error. + * + *---------------------------------------------------------------------*/ + +#if defined(DOS) +UCHAR siwidn(USHORT port, UCHAR p_card) +#else +UCHAR siwidn(ULONG port, UCHAR p_card) +#endif +{ + PSCCB currSCCB; + PSCCBMgr_tar_info currTar_Info; + + currSCCB = BL_Card[p_card].currentSCCB; + currTar_Info = &sccbMgrTbl[p_card][currSCCB->TargID]; + + if (!((currTar_Info->TarStatus & TAR_WIDE_MASK) == WIDE_NEGOCIATED)) { + + + WRW_HARPOON((port+ID_MSG_STRT), + (MPM_OP+AMSG_OUT+(currSCCB->Sccb_idmsg & ~(UCHAR)DISC_PRIV))); + + WRW_HARPOON((port+ID_MSG_STRT+2),BRH_OP+ALWAYS+CMDPZ); + + WRW_HARPOON((port+SYNC_MSGS+0), (MPM_OP+AMSG_OUT+SMEXT )); + WRW_HARPOON((port+SYNC_MSGS+2), (MPM_OP+AMSG_OUT+0x02 )); + WRW_HARPOON((port+SYNC_MSGS+4), (MPM_OP+AMSG_OUT+SMWDTR)); + WRW_HARPOON((port+SYNC_MSGS+6), (RAT_OP )); + WRW_HARPOON((port+SYNC_MSGS+8), (MPM_OP+AMSG_OUT+ SM16BIT)); + WRW_HARPOON((port+SYNC_MSGS+10),(BRH_OP+ALWAYS+NP )); + + WR_HARPOON(port+hp_autostart_3, (SELECT+SELCHK_STRT)); + + + currTar_Info->TarStatus = ((currTar_Info->TarStatus & + ~(UCHAR)TAR_WIDE_MASK) | (UCHAR)WIDE_ENABLED); + + return(TRUE); + } + + else { + + currTar_Info->TarStatus = ((currTar_Info->TarStatus & + ~(UCHAR)TAR_WIDE_MASK) | WIDE_NEGOCIATED); + + currTar_Info->TarEEValue &= ~EE_WIDE_SCSI; + return(FALSE); + } +} + + + +/*--------------------------------------------------------------------- + * + * Function: stwidn + * + * Description: The has sent us a Wide Nego message so handle it as + * necessary. + * + *---------------------------------------------------------------------*/ +#if defined(DOS) +void stwidn(USHORT port, UCHAR p_card) +#else +void stwidn(ULONG port, UCHAR p_card) +#endif +{ + UCHAR width; + PSCCB currSCCB; + PSCCBMgr_tar_info currTar_Info; + + currSCCB = BL_Card[p_card].currentSCCB; + currTar_Info = &sccbMgrTbl[p_card][currSCCB->TargID]; + + width = sfm(port,currSCCB); + + if((width == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY)) + { + WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START)); + return; + } + + + if (!(currTar_Info->TarEEValue & EE_WIDE_SCSI)) + width = 0; + + if (width) { + currTar_Info->TarStatus |= WIDE_ENABLED; + width = 0; + } + else { + width = NARROW_SCSI; + currTar_Info->TarStatus &= ~WIDE_ENABLED; + } + + + sssyncv(port,currSCCB->TargID,width,currTar_Info); + + + if (currSCCB->Sccb_scsistat == SELECT_WN_ST) + { + + + + currTar_Info->TarStatus |= WIDE_NEGOCIATED; + + if (!((currTar_Info->TarStatus & TAR_SYNC_MASK) == SYNC_SUPPORTED)) + { + ACCEPT_MSG_ATN(port); + ARAM_ACCESS(port); + sisyncn(port,p_card, TRUE); + currSCCB->Sccb_scsistat = SELECT_SN_ST; + SGRAM_ACCESS(port); + } + else + { + ACCEPT_MSG(port); + WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START)); + } + } + + else { + + + ACCEPT_MSG_ATN(port); + + if (currTar_Info->TarEEValue & EE_WIDE_SCSI) + width = SM16BIT; + else + width = SM8BIT; + + siwidr(port,width); + + currTar_Info->TarStatus |= (WIDE_NEGOCIATED | WIDE_ENABLED); + } +} + + +/*--------------------------------------------------------------------- + * + * Function: siwidr + * + * Description: Answer the targets Wide nego message. + * + *---------------------------------------------------------------------*/ +#if defined(DOS) +void siwidr(USHORT port, UCHAR width) +#else +void siwidr(ULONG port, UCHAR width) +#endif +{ + ARAM_ACCESS(port); + WRW_HARPOON((port+SYNC_MSGS+0), (MPM_OP+AMSG_OUT+SMEXT )); + WRW_HARPOON((port+SYNC_MSGS+2), (MPM_OP+AMSG_OUT+0x02 )); + WRW_HARPOON((port+SYNC_MSGS+4), (MPM_OP+AMSG_OUT+SMWDTR)); + WRW_HARPOON((port+SYNC_MSGS+6), (RAT_OP )); + WRW_HARPOON((port+SYNC_MSGS+8),(MPM_OP+AMSG_OUT+width)); + WRW_HARPOON((port+SYNC_MSGS+10),(BRH_OP+ALWAYS+NP )); + SGRAM_ACCESS(port); + + WR_HARPOON(port+hp_portctrl_0, SCSI_PORT); + WRW_HARPOON((port+hp_intstat), CLR_ALL_INT_1); + + WR_HARPOON(port+hp_autostart_3, (AUTO_IMMED+CMD_ONLY_STRT)); + + while (!(RDW_HARPOON((port+hp_intstat)) & (BUS_FREE | AUTO_INT))) {} +} + +#endif + + + +/*--------------------------------------------------------------------- + * + * Function: sssyncv + * + * Description: Write the desired value to the Sync Regisiter for the + * ID specified. + * + *---------------------------------------------------------------------*/ +#if defined(DOS) +void sssyncv(USHORT p_port, UCHAR p_id, UCHAR p_sync_value,PSCCBMgr_tar_info currTar_Info) +#else +void sssyncv(ULONG p_port, UCHAR p_id, UCHAR p_sync_value,PSCCBMgr_tar_info currTar_Info) +#endif +{ + UCHAR index; + + index = p_id; + + switch (index) { + + case 0: + index = 12; /* hp_synctarg_0 */ + break; + case 1: + index = 13; /* hp_synctarg_1 */ + break; + case 2: + index = 14; /* hp_synctarg_2 */ + break; + case 3: + index = 15; /* hp_synctarg_3 */ + break; + case 4: + index = 8; /* hp_synctarg_4 */ + break; + case 5: + index = 9; /* hp_synctarg_5 */ + break; + case 6: + index = 10; /* hp_synctarg_6 */ + break; + case 7: + index = 11; /* hp_synctarg_7 */ + break; + case 8: + index = 4; /* hp_synctarg_8 */ + break; + case 9: + index = 5; /* hp_synctarg_9 */ + break; + case 10: + index = 6; /* hp_synctarg_10 */ + break; + case 11: + index = 7; /* hp_synctarg_11 */ + break; + case 12: + index = 0; /* hp_synctarg_12 */ + break; + case 13: + index = 1; /* hp_synctarg_13 */ + break; + case 14: + index = 2; /* hp_synctarg_14 */ + break; + case 15: + index = 3; /* hp_synctarg_15 */ + + } + + WR_HARPOON(p_port+hp_synctarg_base+index, p_sync_value); + + currTar_Info->TarSyncCtrl = p_sync_value; +} + + +/*--------------------------------------------------------------------- + * + * Function: sresb + * + * Description: Reset the desired card's SCSI bus. + * + *---------------------------------------------------------------------*/ +#if defined(DOS) +void sresb(USHORT port, UCHAR p_card) +#else +void sresb(ULONG port, UCHAR p_card) +#endif +{ + UCHAR scsiID, i; + + PSCCBMgr_tar_info currTar_Info; + + WR_HARPOON(port+hp_page_ctrl, + (RD_HARPOON(port+hp_page_ctrl) | G_INT_DISABLE)); + WRW_HARPOON((port+hp_intstat), CLR_ALL_INT); + + WR_HARPOON(port+hp_scsictrl_0, SCSI_RST); + + scsiID = RD_HARPOON(port+hp_seltimeout); + WR_HARPOON(port+hp_seltimeout,TO_5ms); + WRW_HARPOON((port+hp_intstat), TIMEOUT); + + WR_HARPOON(port+hp_portctrl_0,(SCSI_PORT | START_TO)); + + while (!(RDW_HARPOON((port+hp_intstat)) & TIMEOUT)) {} + + WR_HARPOON(port+hp_seltimeout,scsiID); + + WR_HARPOON(port+hp_scsictrl_0, ENA_SCAM_SEL); + + Wait(port, TO_5ms); + + WRW_HARPOON((port+hp_intstat), CLR_ALL_INT); + + WR_HARPOON(port+hp_int_mask, (RD_HARPOON(port+hp_int_mask) | 0x00)); + + for (scsiID = 0; scsiID < MAX_SCSI_TAR; scsiID++) + { + currTar_Info = &sccbMgrTbl[p_card][scsiID]; + + if (currTar_Info->TarEEValue & EE_SYNC_MASK) + { + currTar_Info->TarSyncCtrl = 0; + currTar_Info->TarStatus &= ~TAR_SYNC_MASK; + } + + if (currTar_Info->TarEEValue & EE_WIDE_SCSI) + { + currTar_Info->TarStatus &= ~TAR_WIDE_MASK; + } + + sssyncv(port, scsiID, NARROW_SCSI,currTar_Info); + + SccbMgrTableInitTarget(p_card, scsiID); + } + + BL_Card[p_card].scanIndex = 0x00; + BL_Card[p_card].currentSCCB = NULL; + BL_Card[p_card].globalFlags &= ~(F_TAG_STARTED | F_HOST_XFER_ACT + | F_NEW_SCCB_CMD); + BL_Card[p_card].cmdCounter = 0x00; + BL_Card[p_card].discQCount = 0x00; + BL_Card[p_card].tagQ_Lst = 0x01; + + for(i = 0; i < QUEUE_DEPTH; i++) + BL_Card[p_card].discQ_Tbl[i] = NULL; + + WR_HARPOON(port+hp_page_ctrl, + (RD_HARPOON(port+hp_page_ctrl) & ~G_INT_DISABLE)); + +} + +/*--------------------------------------------------------------------- + * + * Function: ssenss + * + * Description: Setup for the Auto Sense command. + * + *---------------------------------------------------------------------*/ +void ssenss(PSCCBcard pCurrCard) +{ + UCHAR i; + PSCCB currSCCB; + + currSCCB = pCurrCard->currentSCCB; + + + currSCCB->Save_CdbLen = currSCCB->CdbLength; + + for (i = 0; i < 6; i++) { + + currSCCB->Save_Cdb[i] = currSCCB->Cdb[i]; + } + + currSCCB->CdbLength = SIX_BYTE_CMD; + currSCCB->Cdb[0] = SCSI_REQUEST_SENSE; + currSCCB->Cdb[1] = currSCCB->Cdb[1] & (UCHAR)0xE0; /*Keep LUN. */ + currSCCB->Cdb[2] = 0x00; + currSCCB->Cdb[3] = 0x00; + currSCCB->Cdb[4] = currSCCB->RequestSenseLength; + currSCCB->Cdb[5] = 0x00; + + currSCCB->Sccb_XferCnt = (unsigned long)currSCCB->RequestSenseLength; + + currSCCB->Sccb_ATC = 0x00; + + currSCCB->Sccb_XferState |= F_AUTO_SENSE; + + currSCCB->Sccb_XferState &= ~F_SG_XFER; + + currSCCB->Sccb_idmsg = currSCCB->Sccb_idmsg & ~(UCHAR)DISC_PRIV; + + currSCCB->ControlByte = 0x00; + + currSCCB->Sccb_MGRFlags &= F_STATUSLOADED; +} + + + +/*--------------------------------------------------------------------- + * + * Function: sxfrp + * + * Description: Transfer data into the bit bucket until the device + * decides to switch phase. + * + *---------------------------------------------------------------------*/ + +#if defined(DOS) +void sxfrp(USHORT p_port, UCHAR p_card) +#else +void sxfrp(ULONG p_port, UCHAR p_card) +#endif +{ + UCHAR curr_phz; + + + DISABLE_AUTO(p_port); + + if (BL_Card[p_card].globalFlags & F_HOST_XFER_ACT) { + + hostDataXferAbort(p_port,p_card,BL_Card[p_card].currentSCCB); + + } + + /* If the Automation handled the end of the transfer then do not + match the phase or we will get out of sync with the ISR. */ + + if (RDW_HARPOON((p_port+hp_intstat)) & (BUS_FREE | XFER_CNT_0 | AUTO_INT)) + return; + + WR_HARPOON(p_port+hp_xfercnt_0, 0x00); + + curr_phz = RD_HARPOON(p_port+hp_scsisig) & (UCHAR)S_SCSI_PHZ; + + WRW_HARPOON((p_port+hp_intstat), XFER_CNT_0); + + + WR_HARPOON(p_port+hp_scsisig, curr_phz); + + while ( !(RDW_HARPOON((p_port+hp_intstat)) & (BUS_FREE | RESET)) && + (curr_phz == (RD_HARPOON(p_port+hp_scsisig) & (UCHAR)S_SCSI_PHZ)) ) + { + if (curr_phz & (UCHAR)SCSI_IOBIT) + { + WR_HARPOON(p_port+hp_portctrl_0, (SCSI_PORT | HOST_PORT | SCSI_INBIT)); + + if (!(RD_HARPOON(p_port+hp_xferstat) & FIFO_EMPTY)) + { + RD_HARPOON(p_port+hp_fifodata_0); + } + } + else + { + WR_HARPOON(p_port+hp_portctrl_0, (SCSI_PORT | HOST_PORT | HOST_WRT)); + if (RD_HARPOON(p_port+hp_xferstat) & FIFO_EMPTY) + { + WR_HARPOON(p_port+hp_fifodata_0,0xFA); + } + } + } /* End of While loop for padding data I/O phase */ + + while ( !(RDW_HARPOON((p_port+hp_intstat)) & (BUS_FREE | RESET))) + { + if (RD_HARPOON(p_port+hp_scsisig) & SCSI_REQ) + break; + } + + WR_HARPOON(p_port+hp_portctrl_0, (SCSI_PORT | HOST_PORT | SCSI_INBIT)); + while (!(RD_HARPOON(p_port+hp_xferstat) & FIFO_EMPTY)) + { + RD_HARPOON(p_port+hp_fifodata_0); + } + + if ( !(RDW_HARPOON((p_port+hp_intstat)) & (BUS_FREE | RESET))) + { + WR_HARPOON(p_port+hp_autostart_0, (AUTO_IMMED+DISCONNECT_START)); + while (!(RDW_HARPOON((p_port+hp_intstat)) & AUTO_INT)) {} + + if (RDW_HARPOON((p_port+hp_intstat)) & (ICMD_COMP | ITAR_DISC)) + while (!(RDW_HARPOON((p_port+hp_intstat)) & (BUS_FREE | RSEL))) ; + } +} + + +/*--------------------------------------------------------------------- + * + * Function: schkdd + * + * Description: Make sure data has been flushed from both FIFOs and abort + * the operations if necessary. + * + *---------------------------------------------------------------------*/ + +#if defined(DOS) +void schkdd(USHORT port, UCHAR p_card) +#else +void schkdd(ULONG port, UCHAR p_card) +#endif +{ + USHORT TimeOutLoop; + UCHAR sPhase; + + PSCCB currSCCB; + + currSCCB = BL_Card[p_card].currentSCCB; + + + if ((currSCCB->Sccb_scsistat != DATA_OUT_ST) && + (currSCCB->Sccb_scsistat != DATA_IN_ST)) { + return; + } + + + + if (currSCCB->Sccb_XferState & F_ODD_BALL_CNT) + { + + currSCCB->Sccb_ATC += (currSCCB->Sccb_XferCnt-1); + + currSCCB->Sccb_XferCnt = 1; + + currSCCB->Sccb_XferState &= ~F_ODD_BALL_CNT; + WRW_HARPOON((port+hp_fiforead), (USHORT) 0x00); + WR_HARPOON(port+hp_xferstat, 0x00); + } + + else + { + + currSCCB->Sccb_ATC += currSCCB->Sccb_XferCnt; + + currSCCB->Sccb_XferCnt = 0; + } + + if ((RDW_HARPOON((port+hp_intstat)) & PARITY) && + (currSCCB->HostStatus == SCCB_COMPLETE)) { + + currSCCB->HostStatus = SCCB_PARITY_ERR; + WRW_HARPOON((port+hp_intstat), PARITY); + } + + + hostDataXferAbort(port,p_card,currSCCB); + + + while (RD_HARPOON(port+hp_scsisig) & SCSI_ACK) {} + + TimeOutLoop = 0; + + while(RD_HARPOON(port+hp_xferstat) & FIFO_EMPTY) + { + if (RDW_HARPOON((port+hp_intstat)) & BUS_FREE) { + return; + } + if (RD_HARPOON(port+hp_offsetctr) & (UCHAR)0x1F) { + break; + } + if (RDW_HARPOON((port+hp_intstat)) & RESET) { + return; + } + if ((RD_HARPOON(port+hp_scsisig) & SCSI_REQ) || (TimeOutLoop++>0x3000) ) + break; + } + + sPhase = RD_HARPOON(port+hp_scsisig) & (SCSI_BSY | S_SCSI_PHZ); + if ((!(RD_HARPOON(port+hp_xferstat) & FIFO_EMPTY)) || + (RD_HARPOON(port+hp_offsetctr) & (UCHAR)0x1F) || + (sPhase == (SCSI_BSY | S_DATAO_PH)) || + (sPhase == (SCSI_BSY | S_DATAI_PH))) + { + + WR_HARPOON(port+hp_portctrl_0, SCSI_PORT); + + if (!(currSCCB->Sccb_XferState & F_ALL_XFERRED)) + { + if (currSCCB->Sccb_XferState & F_HOST_XFER_DIR) { + phaseDataIn(port,p_card); + } + + else { + phaseDataOut(port,p_card); + } + } + else + { + sxfrp(port,p_card); + if (!(RDW_HARPOON((port+hp_intstat)) & + (BUS_FREE | ICMD_COMP | ITAR_DISC | RESET))) + { + WRW_HARPOON((port+hp_intstat), AUTO_INT); + phaseDecode(port,p_card); + } + } + + } + + else { + WR_HARPOON(port+hp_portctrl_0, 0x00); + } +} + + +/*--------------------------------------------------------------------- + * + * Function: sinits + * + * Description: Setup SCCB manager fields in this SCCB. + * + *---------------------------------------------------------------------*/ + +void sinits(PSCCB p_sccb, UCHAR p_card) +{ + PSCCBMgr_tar_info currTar_Info; + + if((p_sccb->TargID > MAX_SCSI_TAR) || (p_sccb->Lun > MAX_LUN)) + { + return; + } + currTar_Info = &sccbMgrTbl[p_card][p_sccb->TargID]; + + p_sccb->Sccb_XferState = 0x00; + p_sccb->Sccb_XferCnt = p_sccb->DataLength; + + if ((p_sccb->OperationCode == SCATTER_GATHER_COMMAND) || + (p_sccb->OperationCode == RESIDUAL_SG_COMMAND)) { + + p_sccb->Sccb_SGoffset = 0; + p_sccb->Sccb_XferState = F_SG_XFER; + p_sccb->Sccb_XferCnt = 0x00; + } + + if (p_sccb->DataLength == 0x00) + + p_sccb->Sccb_XferState |= F_ALL_XFERRED; + + if (p_sccb->ControlByte & F_USE_CMD_Q) + { + if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_REJECT) + p_sccb->ControlByte &= ~F_USE_CMD_Q; + + else + currTar_Info->TarStatus |= TAG_Q_TRYING; + } + +/* For !single SCSI device in system & device allow Disconnect + or command is tag_q type then send Cmd with Disconnect Enable + else send Cmd with Disconnect Disable */ + +/* + if (((!(BL_Card[p_card].globalFlags & F_SINGLE_DEVICE)) && + (currTar_Info->TarStatus & TAR_ALLOW_DISC)) || + (currTar_Info->TarStatus & TAG_Q_TRYING)) { +*/ + if ((currTar_Info->TarStatus & TAR_ALLOW_DISC) || + (currTar_Info->TarStatus & TAG_Q_TRYING)) { + p_sccb->Sccb_idmsg = (UCHAR)(SMIDENT | DISC_PRIV) | p_sccb->Lun; + } + + else { + + p_sccb->Sccb_idmsg = (UCHAR)SMIDENT | p_sccb->Lun; + } + + p_sccb->HostStatus = 0x00; + p_sccb->TargetStatus = 0x00; + p_sccb->Sccb_tag = 0x00; + p_sccb->Sccb_MGRFlags = 0x00; + p_sccb->Sccb_sgseg = 0x00; + p_sccb->Sccb_ATC = 0x00; + p_sccb->Sccb_savedATC = 0x00; +/* + p_sccb->SccbVirtDataPtr = 0x00; + p_sccb->Sccb_forwardlink = NULL; + p_sccb->Sccb_backlink = NULL; + */ + p_sccb->Sccb_scsistat = BUS_FREE_ST; + p_sccb->SccbStatus = SCCB_IN_PROCESS; + p_sccb->Sccb_scsimsg = SMNO_OP; +} + + +#ident "$Id: phase.c 1.11 1997/01/31 02:08:49 mohan Exp $" +/*---------------------------------------------------------------------- + * + * + * Copyright 1995-1996 by Mylex Corporation. All Rights Reserved + * + * This file is available under both the GNU General Public License + * and a BSD-style copyright; see LICENSE.FlashPoint for details. + * + * $Workfile: phase.c $ + * + * Description: Functions to intially handle the SCSI bus phase when + * the target asserts request (and the automation is not + * enabled to handle the situation). + * + * $Date: 1997/01/31 02:08:49 $ + * + * $Revision: 1.11 $ + * + *----------------------------------------------------------------------*/ + +/*#include */ + +#if (FW_TYPE==_UCB_MGR_) + /*#include */ +#endif + +/*#include */ +/*#include */ +/*#include */ +/*#include */ +/*#include */ + + +/* +extern SCCBCARD BL_Card[MAX_CARDS]; +extern SCCBMGR_TAR_INFO sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR]; + +#if defined(OS2) + extern void (far *s_PhaseTbl[8]) (ULONG, UCHAR); +#else + #if defined(DOS) + extern void (*s_PhaseTbl[8]) (USHORT, UCHAR); + #else + extern void (*s_PhaseTbl[8]) (ULONG, UCHAR); + #endif +#endif +*/ + +/*--------------------------------------------------------------------- + * + * Function: Phase Decode + * + * Description: Determine the phase and call the appropriate function. + * + *---------------------------------------------------------------------*/ + +#if defined(DOS) +void phaseDecode(USHORT p_port, UCHAR p_card) +#else +void phaseDecode(ULONG p_port, UCHAR p_card) +#endif +{ + unsigned char phase_ref; +#if defined(OS2) + void (far *phase) (ULONG, UCHAR); +#else + #if defined(DOS) + void (*phase) (USHORT, UCHAR); + #else + void (*phase) (ULONG, UCHAR); + #endif +#endif + + + DISABLE_AUTO(p_port); + + phase_ref = (UCHAR) (RD_HARPOON(p_port+hp_scsisig) & S_SCSI_PHZ); + + phase = s_PhaseTbl[phase_ref]; + + (*phase)(p_port, p_card); /* Call the correct phase func */ +} + + + +/*--------------------------------------------------------------------- + * + * Function: Data Out Phase + * + * Description: Start up both the BusMaster and Xbow. + * + *---------------------------------------------------------------------*/ + +#if defined(OS2) +void far phaseDataOut(ULONG port, UCHAR p_card) +#else +#if defined(DOS) +void phaseDataOut(USHORT port, UCHAR p_card) +#else +void phaseDataOut(ULONG port, UCHAR p_card) +#endif +#endif +{ + + PSCCB currSCCB; + + currSCCB = BL_Card[p_card].currentSCCB; + if (currSCCB == NULL) + { + return; /* Exit if No SCCB record */ + } + + currSCCB->Sccb_scsistat = DATA_OUT_ST; + currSCCB->Sccb_XferState &= ~(F_HOST_XFER_DIR | F_NO_DATA_YET); + + WR_HARPOON(port+hp_portctrl_0, SCSI_PORT); + + WRW_HARPOON((port+hp_intstat), XFER_CNT_0); + + WR_HARPOON(port+hp_autostart_0, (END_DATA+END_DATA_START)); + + dataXferProcessor(port, &BL_Card[p_card]); + +#if defined(NOBUGBUG) + if (RDW_HARPOON((port+hp_intstat)) & XFER_CNT_0) + WRW_HARPOON((port+hp_intstat), XFER_CNT_0); + +#endif + + + if (currSCCB->Sccb_XferCnt == 0) { + + + if ((currSCCB->ControlByte & SCCB_DATA_XFER_OUT) && + (currSCCB->HostStatus == SCCB_COMPLETE)) + currSCCB->HostStatus = SCCB_DATA_OVER_RUN; + + sxfrp(port,p_card); + if (!(RDW_HARPOON((port+hp_intstat)) & (BUS_FREE | RESET))) + phaseDecode(port,p_card); + } +} + + +/*--------------------------------------------------------------------- + * + * Function: Data In Phase + * + * Description: Startup the BusMaster and the XBOW. + * + *---------------------------------------------------------------------*/ + +#if defined(OS2) +void far phaseDataIn(ULONG port, UCHAR p_card) +#else +#if defined(DOS) +void phaseDataIn(USHORT port, UCHAR p_card) +#else +void phaseDataIn(ULONG port, UCHAR p_card) +#endif +#endif +{ + + PSCCB currSCCB; + + currSCCB = BL_Card[p_card].currentSCCB; + + if (currSCCB == NULL) + { + return; /* Exit if No SCCB record */ + } + + + currSCCB->Sccb_scsistat = DATA_IN_ST; + currSCCB->Sccb_XferState |= F_HOST_XFER_DIR; + currSCCB->Sccb_XferState &= ~F_NO_DATA_YET; + + WR_HARPOON(port+hp_portctrl_0, SCSI_PORT); + + WRW_HARPOON((port+hp_intstat), XFER_CNT_0); + + WR_HARPOON(port+hp_autostart_0, (END_DATA+END_DATA_START)); + + dataXferProcessor(port, &BL_Card[p_card]); + + if (currSCCB->Sccb_XferCnt == 0) { + + + if ((currSCCB->ControlByte & SCCB_DATA_XFER_IN) && + (currSCCB->HostStatus == SCCB_COMPLETE)) + currSCCB->HostStatus = SCCB_DATA_OVER_RUN; + + sxfrp(port,p_card); + if (!(RDW_HARPOON((port+hp_intstat)) & (BUS_FREE | RESET))) + phaseDecode(port,p_card); + + } +} + +/*--------------------------------------------------------------------- + * + * Function: Command Phase + * + * Description: Load the CDB into the automation and start it up. + * + *---------------------------------------------------------------------*/ + +#if defined(OS2) +void far phaseCommand(ULONG p_port, UCHAR p_card) +#else +#if defined(DOS) +void phaseCommand(USHORT p_port, UCHAR p_card) +#else +void phaseCommand(ULONG p_port, UCHAR p_card) +#endif +#endif +{ + PSCCB currSCCB; +#if defined(DOS) + USHORT cdb_reg; +#else + ULONG cdb_reg; +#endif + UCHAR i; + + currSCCB = BL_Card[p_card].currentSCCB; + + if (currSCCB->OperationCode == RESET_COMMAND) { + + currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL; + currSCCB->CdbLength = SIX_BYTE_CMD; + } + + WR_HARPOON(p_port+hp_scsisig, 0x00); + + ARAM_ACCESS(p_port); + + + cdb_reg = p_port + CMD_STRT; + + for (i=0; i < currSCCB->CdbLength; i++) { + + if (currSCCB->OperationCode == RESET_COMMAND) + + WRW_HARPOON(cdb_reg, (MPM_OP + ACOMMAND + 0x00)); + + else + WRW_HARPOON(cdb_reg, (MPM_OP + ACOMMAND + currSCCB->Cdb[i])); + cdb_reg +=2; + } + + if (currSCCB->CdbLength != TWELVE_BYTE_CMD) + WRW_HARPOON(cdb_reg, (BRH_OP+ALWAYS+ NP)); + + WR_HARPOON(p_port+hp_portctrl_0,(SCSI_PORT)); + + currSCCB->Sccb_scsistat = COMMAND_ST; + + WR_HARPOON(p_port+hp_autostart_3, (AUTO_IMMED | CMD_ONLY_STRT)); + SGRAM_ACCESS(p_port); +} + + +/*--------------------------------------------------------------------- + * + * Function: Status phase + * + * Description: Bring in the status and command complete message bytes + * + *---------------------------------------------------------------------*/ + +#if defined(OS2) +void far phaseStatus(ULONG port, UCHAR p_card) +#else +#if defined(DOS) +void phaseStatus(USHORT port, UCHAR p_card) +#else +void phaseStatus(ULONG port, UCHAR p_card) +#endif +#endif +{ + /* Start-up the automation to finish off this command and let the + isr handle the interrupt for command complete when it comes in. + We could wait here for the interrupt to be generated? + */ + + WR_HARPOON(port+hp_scsisig, 0x00); + + WR_HARPOON(port+hp_autostart_0, (AUTO_IMMED+END_DATA_START)); +} + + +/*--------------------------------------------------------------------- + * + * Function: Phase Message Out + * + * Description: Send out our message (if we have one) and handle whatever + * else is involed. + * + *---------------------------------------------------------------------*/ + +#if defined(OS2) +void far phaseMsgOut(ULONG port, UCHAR p_card) +#else +#if defined(DOS) +void phaseMsgOut(USHORT port, UCHAR p_card) +#else +void phaseMsgOut(ULONG port, UCHAR p_card) +#endif +#endif +{ + UCHAR message,scsiID; + PSCCB currSCCB; + PSCCBMgr_tar_info currTar_Info; + + currSCCB = BL_Card[p_card].currentSCCB; + + if (currSCCB != NULL) { + + message = currSCCB->Sccb_scsimsg; + scsiID = currSCCB->TargID; + + if (message == SMDEV_RESET) + { + + + currTar_Info = &sccbMgrTbl[p_card][scsiID]; + currTar_Info->TarSyncCtrl = 0; + sssyncv(port, scsiID, NARROW_SCSI,currTar_Info); + + if (sccbMgrTbl[p_card][scsiID].TarEEValue & EE_SYNC_MASK) + { + + sccbMgrTbl[p_card][scsiID].TarStatus &= ~TAR_SYNC_MASK; + + } + + if (sccbMgrTbl[p_card][scsiID].TarEEValue & EE_WIDE_SCSI) + { + + sccbMgrTbl[p_card][scsiID].TarStatus &= ~TAR_WIDE_MASK; + } + + + queueFlushSccb(p_card,SCCB_COMPLETE); + SccbMgrTableInitTarget(p_card,scsiID); + } + else if (currSCCB->Sccb_scsistat == ABORT_ST) + { + currSCCB->HostStatus = SCCB_COMPLETE; + if(BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] != NULL) + { + BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] = NULL; + sccbMgrTbl[p_card][scsiID].TarTagQ_Cnt--; + } + + } + + else if (currSCCB->Sccb_scsistat < COMMAND_ST) + { + + + if(message == SMNO_OP) + { + currSCCB->Sccb_MGRFlags |= F_DEV_SELECTED; + + ssel(port,p_card); + return; + } + } + else + { + + + if (message == SMABORT) + + queueFlushSccb(p_card,SCCB_COMPLETE); + } + + } + else + { + message = SMABORT; + } + + WRW_HARPOON((port+hp_intstat), (BUS_FREE | PHASE | XFER_CNT_0)); + + + WR_HARPOON(port+hp_portctrl_0, SCSI_BUS_EN); + + WR_HARPOON(port+hp_scsidata_0,message); + + WR_HARPOON(port+hp_scsisig, (SCSI_ACK + S_ILL_PH)); + + ACCEPT_MSG(port); + + WR_HARPOON(port+hp_portctrl_0, 0x00); + + if ((message == SMABORT) || (message == SMDEV_RESET) || + (message == SMABORT_TAG) ) + { + + while(!(RDW_HARPOON((port+hp_intstat)) & (BUS_FREE | PHASE))) {} + + if (RDW_HARPOON((port+hp_intstat)) & BUS_FREE) + { + WRW_HARPOON((port+hp_intstat), BUS_FREE); + + if (currSCCB != NULL) + { + + if((BL_Card[p_card].globalFlags & F_CONLUN_IO) && + ((sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)) + sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = FALSE; + else + sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = FALSE; + + queueCmdComplete(&BL_Card[p_card],currSCCB, p_card); + } + + else + { + BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD; + } + } + + else + { + + sxfrp(port,p_card); + } + } + + else + { + + if(message == SMPARITY) + { + currSCCB->Sccb_scsimsg = SMNO_OP; + WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START)); + } + else + { + sxfrp(port,p_card); + } + } +} + + +/*--------------------------------------------------------------------- + * + * Function: Message In phase + * + * Description: Bring in the message and determine what to do with it. + * + *---------------------------------------------------------------------*/ + +#if defined(OS2) +void far phaseMsgIn(ULONG port, UCHAR p_card) +#else +#if defined(DOS) +void phaseMsgIn(USHORT port, UCHAR p_card) +#else +void phaseMsgIn(ULONG port, UCHAR p_card) +#endif +#endif +{ + UCHAR message; + PSCCB currSCCB; + + currSCCB = BL_Card[p_card].currentSCCB; + + if (BL_Card[p_card].globalFlags & F_HOST_XFER_ACT) + { + + phaseChkFifo(port, p_card); + } + + message = RD_HARPOON(port+hp_scsidata_0); + if ((message == SMDISC) || (message == SMSAVE_DATA_PTR)) + { + + WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+END_DATA_START)); + + } + + else + { + + message = sfm(port,currSCCB); + if (message) + { + + + sdecm(message,port,p_card); + + } + else + { + if(currSCCB->Sccb_scsimsg != SMPARITY) + ACCEPT_MSG(port); + WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START)); + } + } + +} + + +/*--------------------------------------------------------------------- + * + * Function: Illegal phase + * + * Description: Target switched to some illegal phase, so all we can do + * is report an error back to the host (if that is possible) + * and send an ABORT message to the misbehaving target. + * + *---------------------------------------------------------------------*/ + +#if defined(OS2) +void far phaseIllegal(ULONG port, UCHAR p_card) +#else +#if defined(DOS) +void phaseIllegal(USHORT port, UCHAR p_card) +#else +void phaseIllegal(ULONG port, UCHAR p_card) +#endif +#endif +{ + PSCCB currSCCB; + + currSCCB = BL_Card[p_card].currentSCCB; + + WR_HARPOON(port+hp_scsisig, RD_HARPOON(port+hp_scsisig)); + if (currSCCB != NULL) { + + currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL; + currSCCB->Sccb_scsistat = ABORT_ST; + currSCCB->Sccb_scsimsg = SMABORT; + } + + ACCEPT_MSG_ATN(port); +} + + + +/*--------------------------------------------------------------------- + * + * Function: Phase Check FIFO + * + * Description: Make sure data has been flushed from both FIFOs and abort + * the operations if necessary. + * + *---------------------------------------------------------------------*/ + +#if defined(DOS) +void phaseChkFifo(USHORT port, UCHAR p_card) +#else +void phaseChkFifo(ULONG port, UCHAR p_card) +#endif +{ + ULONG xfercnt; + PSCCB currSCCB; + + currSCCB = BL_Card[p_card].currentSCCB; + + if (currSCCB->Sccb_scsistat == DATA_IN_ST) + { + + while((!(RD_HARPOON(port+hp_xferstat) & FIFO_EMPTY)) && + (RD_HARPOON(port+hp_ext_status) & BM_CMD_BUSY)) {} + + + if (!(RD_HARPOON(port+hp_xferstat) & FIFO_EMPTY)) + { + currSCCB->Sccb_ATC += currSCCB->Sccb_XferCnt; + + currSCCB->Sccb_XferCnt = 0; + + if ((RDW_HARPOON((port+hp_intstat)) & PARITY) && + (currSCCB->HostStatus == SCCB_COMPLETE)) + { + currSCCB->HostStatus = SCCB_PARITY_ERR; + WRW_HARPOON((port+hp_intstat), PARITY); + } + + hostDataXferAbort(port,p_card,currSCCB); + + dataXferProcessor(port, &BL_Card[p_card]); + + while((!(RD_HARPOON(port+hp_xferstat) & FIFO_EMPTY)) && + (RD_HARPOON(port+hp_ext_status) & BM_CMD_BUSY)) {} + + } + } /*End Data In specific code. */ + + + +#if defined(DOS) + asm { mov dx,port; + add dx,hp_xfercnt_2; + in al,dx; + dec dx; + xor ah,ah; + mov word ptr xfercnt+2,ax; + in al,dx; + dec dx; + mov ah,al; + in al,dx; + mov word ptr xfercnt,ax; + } +#else + GET_XFER_CNT(port,xfercnt); +#endif + + + WR_HARPOON(port+hp_xfercnt_0, 0x00); + + + WR_HARPOON(port+hp_portctrl_0, 0x00); + + currSCCB->Sccb_ATC += (currSCCB->Sccb_XferCnt - xfercnt); + + currSCCB->Sccb_XferCnt = xfercnt; + + if ((RDW_HARPOON((port+hp_intstat)) & PARITY) && + (currSCCB->HostStatus == SCCB_COMPLETE)) { + + currSCCB->HostStatus = SCCB_PARITY_ERR; + WRW_HARPOON((port+hp_intstat), PARITY); + } + + + hostDataXferAbort(port,p_card,currSCCB); + + + WR_HARPOON(port+hp_fifowrite, 0x00); + WR_HARPOON(port+hp_fiforead, 0x00); + WR_HARPOON(port+hp_xferstat, 0x00); + + WRW_HARPOON((port+hp_intstat), XFER_CNT_0); +} + + +/*--------------------------------------------------------------------- + * + * Function: Phase Bus Free + * + * Description: We just went bus free so figure out if it was + * because of command complete or from a disconnect. + * + *---------------------------------------------------------------------*/ +#if defined(DOS) +void phaseBusFree(USHORT port, UCHAR p_card) +#else +void phaseBusFree(ULONG port, UCHAR p_card) +#endif +{ + PSCCB currSCCB; + + currSCCB = BL_Card[p_card].currentSCCB; + + if (currSCCB != NULL) + { + + DISABLE_AUTO(port); + + + if (currSCCB->OperationCode == RESET_COMMAND) + { + + if((BL_Card[p_card].globalFlags & F_CONLUN_IO) && + ((sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)) + sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = FALSE; + else + sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = FALSE; + + queueCmdComplete(&BL_Card[p_card], currSCCB, p_card); + + queueSearchSelect(&BL_Card[p_card],p_card); + + } + + else if(currSCCB->Sccb_scsistat == SELECT_SN_ST) + { + sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |= + (UCHAR)SYNC_SUPPORTED; + sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &= ~EE_SYNC_MASK; + } + + else if(currSCCB->Sccb_scsistat == SELECT_WN_ST) + { + sccbMgrTbl[p_card][currSCCB->TargID].TarStatus = + (sccbMgrTbl[p_card][currSCCB->TargID]. + TarStatus & ~WIDE_ENABLED) | WIDE_NEGOCIATED; + + sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &= ~EE_WIDE_SCSI; + } + +#if !defined(DOS) + else if(currSCCB->Sccb_scsistat == SELECT_Q_ST) + { + /* Make sure this is not a phony BUS_FREE. If we were + reselected or if BUSY is NOT on then this is a + valid BUS FREE. SRR Wednesday, 5/10/1995. */ + + if ((!(RD_HARPOON(port+hp_scsisig) & SCSI_BSY)) || + (RDW_HARPOON((port+hp_intstat)) & RSEL)) + { + sccbMgrTbl[p_card][currSCCB->TargID].TarStatus &= ~TAR_TAG_Q_MASK; + sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |= TAG_Q_REJECT; + } + + else + { + return; + } + } +#endif + + else + { + + currSCCB->Sccb_scsistat = BUS_FREE_ST; + + if (!currSCCB->HostStatus) + { + currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL; + } + + if((BL_Card[p_card].globalFlags & F_CONLUN_IO) && + ((sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)) + sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = FALSE; + else + sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = FALSE; + + queueCmdComplete(&BL_Card[p_card], currSCCB, p_card); + return; + } + + + BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD; + + } /*end if !=null */ +} + + + + +#ident "$Id: automate.c 1.14 1997/01/31 02:11:46 mohan Exp $" +/*---------------------------------------------------------------------- + * + * + * Copyright 1995-1996 by Mylex Corporation. All Rights Reserved + * + * This file is available under both the GNU General Public License + * and a BSD-style copyright; see LICENSE.FlashPoint for details. + * + * $Workfile: automate.c $ + * + * Description: Functions relating to programming the automation of + * the HARPOON. + * + * $Date: 1997/01/31 02:11:46 $ + * + * $Revision: 1.14 $ + * + *----------------------------------------------------------------------*/ + +/*#include */ + +#if (FW_TYPE==_UCB_MGR_) + /*#include */ +#endif + +/*#include */ +/*#include */ +/*#include */ +/*#include */ +/*#include */ + +/* +extern SCCBCARD BL_Card[MAX_CARDS]; +extern SCCBMGR_TAR_INFO sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR]; +extern SCCBCARD BL_Card[MAX_CARDS]; +*/ + +/*--------------------------------------------------------------------- + * + * Function: Auto Load Default Map + * + * Description: Load the Automation RAM with the defualt map values. + * + *---------------------------------------------------------------------*/ +#if defined(DOS) +void autoLoadDefaultMap(USHORT p_port) +#else +void autoLoadDefaultMap(ULONG p_port) +#endif +{ +#if defined(DOS) + USHORT map_addr; +#else + ULONG map_addr; +#endif + + ARAM_ACCESS(p_port); + map_addr = p_port + hp_aramBase; + + WRW_HARPOON(map_addr, (MPM_OP+AMSG_OUT+ 0xC0)); /*ID MESSAGE */ + map_addr +=2; + WRW_HARPOON(map_addr, (MPM_OP+AMSG_OUT+ 0x20)); /*SIMPLE TAG QUEUEING MSG */ + map_addr +=2; + WRW_HARPOON(map_addr, RAT_OP); /*RESET ATTENTION */ + map_addr +=2; + WRW_HARPOON(map_addr, (MPM_OP+AMSG_OUT+ 0x00)); /*TAG ID MSG */ + map_addr +=2; + WRW_HARPOON(map_addr, (MPM_OP+ACOMMAND+ 0x00)); /*CDB BYTE 0 */ + map_addr +=2; + WRW_HARPOON(map_addr, (MPM_OP+ACOMMAND+ 0x00)); /*CDB BYTE 1 */ + map_addr +=2; + WRW_HARPOON(map_addr, (MPM_OP+ACOMMAND+ 0x00)); /*CDB BYTE 2 */ + map_addr +=2; + WRW_HARPOON(map_addr, (MPM_OP+ACOMMAND+ 0x00)); /*CDB BYTE 3 */ + map_addr +=2; + WRW_HARPOON(map_addr, (MPM_OP+ACOMMAND+ 0x00)); /*CDB BYTE 4 */ + map_addr +=2; + WRW_HARPOON(map_addr, (MPM_OP+ACOMMAND+ 0x00)); /*CDB BYTE 5 */ + map_addr +=2; + WRW_HARPOON(map_addr, (MPM_OP+ACOMMAND+ 0x00)); /*CDB BYTE 6 */ + map_addr +=2; + WRW_HARPOON(map_addr, (MPM_OP+ACOMMAND+ 0x00)); /*CDB BYTE 7 */ + map_addr +=2; + WRW_HARPOON(map_addr, (MPM_OP+ACOMMAND+ 0x00)); /*CDB BYTE 8 */ + map_addr +=2; + WRW_HARPOON(map_addr, (MPM_OP+ACOMMAND+ 0x00)); /*CDB BYTE 9 */ + map_addr +=2; + WRW_HARPOON(map_addr, (MPM_OP+ACOMMAND+ 0x00)); /*CDB BYTE 10 */ + map_addr +=2; + WRW_HARPOON(map_addr, (MPM_OP+ACOMMAND+ 0x00)); /*CDB BYTE 11 */ + map_addr +=2; + WRW_HARPOON(map_addr, (CPE_OP+ADATA_OUT+ DINT)); /*JUMP IF DATA OUT */ + map_addr +=2; + WRW_HARPOON(map_addr, (TCB_OP+FIFO_0+ DI)); /*JUMP IF NO DATA IN FIFO */ + map_addr +=2; /*This means AYNC DATA IN */ + WRW_HARPOON(map_addr, (SSI_OP+ SSI_IDO_STRT)); /*STOP AND INTERRUPT */ + map_addr +=2; + WRW_HARPOON(map_addr, (CPE_OP+ADATA_IN+DINT)); /*JUMP IF NOT DATA IN PHZ */ + map_addr +=2; + WRW_HARPOON(map_addr, (CPN_OP+AMSG_IN+ ST)); /*IF NOT MSG IN CHECK 4 DATA IN */ + map_addr +=2; + WRW_HARPOON(map_addr, (CRD_OP+SDATA+ 0x02)); /*SAVE DATA PTR MSG? */ + map_addr +=2; + WRW_HARPOON(map_addr, (BRH_OP+NOT_EQ+ DC)); /*GO CHECK FOR DISCONNECT MSG */ + map_addr +=2; + WRW_HARPOON(map_addr, (MRR_OP+SDATA+ D_AR1)); /*SAVE DATA PTRS MSG */ + map_addr +=2; + WRW_HARPOON(map_addr, (CPN_OP+AMSG_IN+ ST)); /*IF NOT MSG IN CHECK DATA IN */ + map_addr +=2; + WRW_HARPOON(map_addr, (CRD_OP+SDATA+ 0x04)); /*DISCONNECT MSG? */ + map_addr +=2; + WRW_HARPOON(map_addr, (BRH_OP+NOT_EQ+ UNKNWN));/*UKNKNOWN MSG */ + map_addr +=2; + WRW_HARPOON(map_addr, (MRR_OP+SDATA+ D_BUCKET));/*XFER DISCONNECT MSG */ + map_addr +=2; + WRW_HARPOON(map_addr, (SSI_OP+ SSI_ITAR_DISC));/*STOP AND INTERRUPT */ + map_addr +=2; + WRW_HARPOON(map_addr, (CPN_OP+ASTATUS+ UNKNWN));/*JUMP IF NOT STATUS PHZ. */ + map_addr +=2; + WRW_HARPOON(map_addr, (MRR_OP+SDATA+ D_AR0)); /*GET STATUS BYTE */ + map_addr +=2; + WRW_HARPOON(map_addr, (CPN_OP+AMSG_IN+ CC)); /*ERROR IF NOT MSG IN PHZ */ + map_addr +=2; + WRW_HARPOON(map_addr, (CRD_OP+SDATA+ 0x00)); /*CHECK FOR CMD COMPLETE MSG. */ + map_addr +=2; + WRW_HARPOON(map_addr, (BRH_OP+NOT_EQ+ CC)); /*ERROR IF NOT CMD COMPLETE MSG. */ + map_addr +=2; + WRW_HARPOON(map_addr, (MRR_OP+SDATA+ D_BUCKET));/*GET CMD COMPLETE MSG */ + map_addr +=2; + WRW_HARPOON(map_addr, (SSI_OP+ SSI_ICMD_COMP));/*END OF COMMAND */ + map_addr +=2; + + WRW_HARPOON(map_addr, (SSI_OP+ SSI_IUNKWN)); /*RECEIVED UNKNOWN MSG BYTE */ + map_addr +=2; + WRW_HARPOON(map_addr, (SSI_OP+ SSI_INO_CC)); /*NO COMMAND COMPLETE AFTER STATUS */ + map_addr +=2; + WRW_HARPOON(map_addr, (SSI_OP+ SSI_ITICKLE)); /*BIOS Tickled the Mgr */ + map_addr +=2; + WRW_HARPOON(map_addr, (SSI_OP+ SSI_IRFAIL)); /*EXPECTED ID/TAG MESSAGES AND */ + map_addr +=2; /* DIDN'T GET ONE */ + WRW_HARPOON(map_addr, (CRR_OP+AR3+ S_IDREG)); /* comp SCSI SEL ID & AR3*/ + map_addr +=2; + WRW_HARPOON(map_addr, (BRH_OP+EQUAL+ 0x00)); /*SEL ID OK then Conti. */ + map_addr +=2; + WRW_HARPOON(map_addr, (SSI_OP+ SSI_INO_CC)); /*NO COMMAND COMPLETE AFTER STATUS */ + + + + SGRAM_ACCESS(p_port); +} + +/*--------------------------------------------------------------------- + * + * Function: Auto Command Complete + * + * Description: Post command back to host and find another command + * to execute. + * + *---------------------------------------------------------------------*/ + +#if defined(DOS) +void autoCmdCmplt(USHORT p_port, UCHAR p_card) +#else +void autoCmdCmplt(ULONG p_port, UCHAR p_card) +#endif +{ + PSCCB currSCCB; + UCHAR status_byte; + + currSCCB = BL_Card[p_card].currentSCCB; + + status_byte = RD_HARPOON(p_port+hp_gp_reg_0); + + sccbMgrTbl[p_card][currSCCB->TargID].TarLUN_CA = FALSE; + + if (status_byte != SSGOOD) { + + if (status_byte == SSQ_FULL) { + + + if(((BL_Card[p_card].globalFlags & F_CONLUN_IO) && + ((sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) + { + sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = TRUE; + if(BL_Card[p_card].discQCount != 0) + BL_Card[p_card].discQCount--; + BL_Card[p_card].discQ_Tbl[sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[currSCCB->Lun]] = NULL; + } + else + { + sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = TRUE; + if(currSCCB->Sccb_tag) + { + if(BL_Card[p_card].discQCount != 0) + BL_Card[p_card].discQCount--; + BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] = NULL; + }else + { + if(BL_Card[p_card].discQCount != 0) + BL_Card[p_card].discQCount--; + BL_Card[p_card].discQ_Tbl[sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[0]] = NULL; + } + } + + currSCCB->Sccb_MGRFlags |= F_STATUSLOADED; + + queueSelectFail(&BL_Card[p_card],p_card); + + return; + } + + if(currSCCB->Sccb_scsistat == SELECT_SN_ST) + { + sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |= + (UCHAR)SYNC_SUPPORTED; + + sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &= ~EE_SYNC_MASK; + BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD; + + if(((BL_Card[p_card].globalFlags & F_CONLUN_IO) && + ((sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) + { + sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = TRUE; + if(BL_Card[p_card].discQCount != 0) + BL_Card[p_card].discQCount--; + BL_Card[p_card].discQ_Tbl[sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[currSCCB->Lun]] = NULL; + } + else + { + sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = TRUE; + if(currSCCB->Sccb_tag) + { + if(BL_Card[p_card].discQCount != 0) + BL_Card[p_card].discQCount--; + BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] = NULL; + }else + { + if(BL_Card[p_card].discQCount != 0) + BL_Card[p_card].discQCount--; + BL_Card[p_card].discQ_Tbl[sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[0]] = NULL; + } + } + return; + + } + + if(currSCCB->Sccb_scsistat == SELECT_WN_ST) + { + + sccbMgrTbl[p_card][currSCCB->TargID].TarStatus = + (sccbMgrTbl[p_card][currSCCB->TargID]. + TarStatus & ~WIDE_ENABLED) | WIDE_NEGOCIATED; + + sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &= ~EE_WIDE_SCSI; + BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD; + + if(((BL_Card[p_card].globalFlags & F_CONLUN_IO) && + ((sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) + { + sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = TRUE; + if(BL_Card[p_card].discQCount != 0) + BL_Card[p_card].discQCount--; + BL_Card[p_card].discQ_Tbl[sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[currSCCB->Lun]] = NULL; + } + else + { + sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = TRUE; + if(currSCCB->Sccb_tag) + { + if(BL_Card[p_card].discQCount != 0) + BL_Card[p_card].discQCount--; + BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] = NULL; + }else + { + if(BL_Card[p_card].discQCount != 0) + BL_Card[p_card].discQCount--; + BL_Card[p_card].discQ_Tbl[sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[0]] = NULL; + } + } + return; + + } + + if (status_byte == SSCHECK) + { + if(BL_Card[p_card].globalFlags & F_DO_RENEGO) + { + if (sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue & EE_SYNC_MASK) + { + sccbMgrTbl[p_card][currSCCB->TargID].TarStatus &= ~TAR_SYNC_MASK; + } + if (sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue & EE_WIDE_SCSI) + { + sccbMgrTbl[p_card][currSCCB->TargID].TarStatus &= ~TAR_WIDE_MASK; + } + } + } + + if (!(currSCCB->Sccb_XferState & F_AUTO_SENSE)) { + + currSCCB->SccbStatus = SCCB_ERROR; + currSCCB->TargetStatus = status_byte; + + if (status_byte == SSCHECK) { + + sccbMgrTbl[p_card][currSCCB->TargID].TarLUN_CA + = TRUE; + + +#if (FW_TYPE==_SCCB_MGR_) + if (currSCCB->RequestSenseLength != NO_AUTO_REQUEST_SENSE) { + + if (currSCCB->RequestSenseLength == 0) + currSCCB->RequestSenseLength = 14; + + ssenss(&BL_Card[p_card]); + BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD; + + if(((BL_Card[p_card].globalFlags & F_CONLUN_IO) && + ((sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) + { + sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = TRUE; + if(BL_Card[p_card].discQCount != 0) + BL_Card[p_card].discQCount--; + BL_Card[p_card].discQ_Tbl[sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[currSCCB->Lun]] = NULL; + } + else + { + sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = TRUE; + if(currSCCB->Sccb_tag) + { + if(BL_Card[p_card].discQCount != 0) + BL_Card[p_card].discQCount--; + BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] = NULL; + }else + { + if(BL_Card[p_card].discQCount != 0) + BL_Card[p_card].discQCount--; + BL_Card[p_card].discQ_Tbl[sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[0]] = NULL; + } + } + return; + } +#else + if ((!(currSCCB->Sccb_ucb_ptr->UCB_opcode & OPC_NO_AUTO_SENSE)) && + (currSCCB->RequestSenseLength)) + { + ssenss(&BL_Card[p_card]); + BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD; + + if(((BL_Card[p_card].globalFlags & F_CONLUN_IO) && + ((sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) + { + sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = TRUE; + if(BL_Card[p_card].discQCount != 0) + BL_Card[p_card].discQCount--; + BL_Card[p_card].discQ_Tbl[sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[currSCCB->Lun]] = NULL; + } + else + { + sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = TRUE; + if(currSCCB->Sccb_tag) + { + if(BL_Card[p_card].discQCount != 0) + BL_Card[p_card].discQCount--; + BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] = NULL; + }else + { + if(BL_Card[p_card].discQCount != 0) + BL_Card[p_card].discQCount--; + BL_Card[p_card].discQ_Tbl[sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[0]] = NULL; + } + } + return; + } + +#endif + } + } + } + + + if((BL_Card[p_card].globalFlags & F_CONLUN_IO) && + ((sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)) + sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = FALSE; + else + sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = FALSE; + + + queueCmdComplete(&BL_Card[p_card], currSCCB, p_card); +} +#ident "$Id: busmstr.c 1.8 1997/01/31 02:10:27 mohan Exp $" +/*---------------------------------------------------------------------- + * + * + * Copyright 1995-1996 by Mylex Corporation. All Rights Reserved + * + * This file is available under both the GNU General Public License + * and a BSD-style copyright; see LICENSE.FlashPoint for details. + * + * $Workfile: busmstr.c $ + * + * Description: Functions to start, stop, and abort BusMaster operations. + * + * $Date: 1997/01/31 02:10:27 $ + * + * $Revision: 1.8 $ + * + *----------------------------------------------------------------------*/ + +/*#include */ + +#if (FW_TYPE==_UCB_MGR_) + /*#include */ +#endif + +/*#include */ +/*#include */ +/*#include */ +/*#include */ +/*#include */ + + +/* +extern SCCBCARD BL_Card[MAX_CARDS]; +extern SCCBMGR_TAR_INFO sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR]; +*/ + +#define SHORT_WAIT 0x0000000F +#define LONG_WAIT 0x0000FFFFL + +#if defined(BUGBUG) +void Debug_Load(UCHAR p_card, UCHAR p_bug_data); +#endif + +/*--------------------------------------------------------------------- + * + * Function: Data Transfer Processor + * + * Description: This routine performs two tasks. + * (1) Start data transfer by calling HOST_DATA_XFER_START + * function. Once data transfer is started, (2) Depends + * on the type of data transfer mode Scatter/Gather mode + * or NON Scatter/Gather mode. In NON Scatter/Gather mode, + * this routine checks Sccb_MGRFlag (F_HOST_XFER_ACT bit) for + * data transfer done. In Scatter/Gather mode, this routine + * checks bus master command complete and dual rank busy + * bit to keep chaining SC transfer command. Similarly, + * in Scatter/Gather mode, it checks Sccb_MGRFlag + * (F_HOST_XFER_ACT bit) for data transfer done. + * + *---------------------------------------------------------------------*/ + +#if defined(DOS) +void dataXferProcessor(USHORT port, PSCCBcard pCurrCard) +#else +void dataXferProcessor(ULONG port, PSCCBcard pCurrCard) +#endif +{ + PSCCB currSCCB; + + currSCCB = pCurrCard->currentSCCB; + + if (currSCCB->Sccb_XferState & F_SG_XFER) + { + if (pCurrCard->globalFlags & F_HOST_XFER_ACT) + + { + currSCCB->Sccb_sgseg += (UCHAR)SG_BUF_CNT; + currSCCB->Sccb_SGoffset = 0x00; + } + pCurrCard->globalFlags |= F_HOST_XFER_ACT; + + busMstrSGDataXferStart(port, currSCCB); + } + + else + { + if (!(pCurrCard->globalFlags & F_HOST_XFER_ACT)) + { + pCurrCard->globalFlags |= F_HOST_XFER_ACT; + + busMstrDataXferStart(port, currSCCB); + } + } +} + + +/*--------------------------------------------------------------------- + * + * Function: BusMaster Scatter Gather Data Transfer Start + * + * Description: + * + *---------------------------------------------------------------------*/ +#if defined(DOS) +void busMstrSGDataXferStart(USHORT p_port, PSCCB pcurrSCCB) +#else +void busMstrSGDataXferStart(ULONG p_port, PSCCB pcurrSCCB) +#endif +{ + ULONG count,addr,tmpSGCnt; + UINT sg_index; + UCHAR sg_count, i; +#if defined(DOS) + USHORT reg_offset; +#else + ULONG reg_offset; +#endif + + + if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) { + + count = ((ULONG) HOST_RD_CMD)<<24; + } + + else { + count = ((ULONG) HOST_WRT_CMD)<<24; + } + + sg_count = 0; + tmpSGCnt = 0; + sg_index = pcurrSCCB->Sccb_sgseg; + reg_offset = hp_aramBase; + + + i = (UCHAR) (RD_HARPOON(p_port+hp_page_ctrl) & ~(SGRAM_ARAM|SCATTER_EN)); + + + WR_HARPOON(p_port+hp_page_ctrl, i); + + while ((sg_count < (UCHAR)SG_BUF_CNT) && + ((ULONG)(sg_index * (UINT)SG_ELEMENT_SIZE) < pcurrSCCB->DataLength) ) { + +#if defined(COMPILER_16_BIT) && !defined(DOS) + tmpSGCnt += *(((ULONG far *)pcurrSCCB->DataPointer)+ + (sg_index * 2)); + + count |= *(((ULONG far *)pcurrSCCB->DataPointer)+ + (sg_index * 2)); + + addr = *(((ULONG far *)pcurrSCCB->DataPointer)+ + ((sg_index * 2) + 1)); + +#else + tmpSGCnt += *(((ULONG *)pcurrSCCB->DataPointer)+ + (sg_index * 2)); + + count |= *(((ULONG *)pcurrSCCB->DataPointer)+ + (sg_index * 2)); + + addr = *(((ULONG *)pcurrSCCB->DataPointer)+ + ((sg_index * 2) + 1)); +#endif + + + if ((!sg_count) && (pcurrSCCB->Sccb_SGoffset)) { + + addr += ((count & 0x00FFFFFFL) - pcurrSCCB->Sccb_SGoffset); + count = (count & 0xFF000000L) | pcurrSCCB->Sccb_SGoffset; + + tmpSGCnt = count & 0x00FFFFFFL; + } + + WR_HARP32(p_port,reg_offset,addr); + reg_offset +=4; + + WR_HARP32(p_port,reg_offset,count); + reg_offset +=4; + + count &= 0xFF000000L; + sg_index++; + sg_count++; + + } /*End While */ + + pcurrSCCB->Sccb_XferCnt = tmpSGCnt; + + WR_HARPOON(p_port+hp_sg_addr,(sg_count<<4)); + + if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) { + + WR_HARP32(p_port,hp_xfercnt_0,tmpSGCnt); + + + WR_HARPOON(p_port+hp_portctrl_0,(DMA_PORT | SCSI_PORT | SCSI_INBIT)); + WR_HARPOON(p_port+hp_scsisig, S_DATAI_PH); + } + + else { + + + if ((!(RD_HARPOON(p_port+hp_synctarg_0) & NARROW_SCSI)) && + (tmpSGCnt & 0x000000001)) + { + + pcurrSCCB->Sccb_XferState |= F_ODD_BALL_CNT; + tmpSGCnt--; + } + + + WR_HARP32(p_port,hp_xfercnt_0,tmpSGCnt); + + WR_HARPOON(p_port+hp_portctrl_0,(SCSI_PORT | DMA_PORT | DMA_RD)); + WR_HARPOON(p_port+hp_scsisig, S_DATAO_PH); + } + + + WR_HARPOON(p_port+hp_page_ctrl, (UCHAR) (i | SCATTER_EN)); + +} + + +/*--------------------------------------------------------------------- + * + * Function: BusMaster Data Transfer Start + * + * Description: + * + *---------------------------------------------------------------------*/ +#if defined(DOS) +void busMstrDataXferStart(USHORT p_port, PSCCB pcurrSCCB) +#else +void busMstrDataXferStart(ULONG p_port, PSCCB pcurrSCCB) +#endif +{ + ULONG addr,count; + + if (!(pcurrSCCB->Sccb_XferState & F_AUTO_SENSE)) { + + count = pcurrSCCB->Sccb_XferCnt; + + addr = (ULONG) pcurrSCCB->DataPointer + pcurrSCCB->Sccb_ATC; + } + + else { + addr = pcurrSCCB->SensePointer; + count = pcurrSCCB->RequestSenseLength; + + } + +#if defined(DOS) + asm { mov dx,p_port; + mov ax,word ptr count; + add dx,hp_xfer_cnt_lo; + out dx,al; + inc dx; + xchg ah,al + out dx,al; + inc dx; + mov ax,word ptr count+2; + out dx,al; + inc dx; + inc dx; + mov ax,word ptr addr; + out dx,al; + inc dx; + xchg ah,al + out dx,al; + inc dx; + mov ax,word ptr addr+2; + out dx,al; + inc dx; + xchg ah,al + out dx,al; + } + + WR_HARP32(p_port,hp_xfercnt_0,count); + +#else + HP_SETUP_ADDR_CNT(p_port,addr,count); +#endif + + + if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) { + + WR_HARPOON(p_port+hp_portctrl_0,(DMA_PORT | SCSI_PORT | SCSI_INBIT)); + WR_HARPOON(p_port+hp_scsisig, S_DATAI_PH); + + WR_HARPOON(p_port+hp_xfer_cmd, + (XFER_DMA_HOST | XFER_HOST_AUTO | XFER_DMA_8BIT)); + } + + else { + + WR_HARPOON(p_port+hp_portctrl_0,(SCSI_PORT | DMA_PORT | DMA_RD)); + WR_HARPOON(p_port+hp_scsisig, S_DATAO_PH); + + WR_HARPOON(p_port+hp_xfer_cmd, + (XFER_HOST_DMA | XFER_HOST_AUTO | XFER_DMA_8BIT)); + + } +} + + +/*--------------------------------------------------------------------- + * + * Function: BusMaster Timeout Handler + * + * Description: This function is called after a bus master command busy time + * out is detected. This routines issue halt state machine + * with a software time out for command busy. If command busy + * is still asserted at the end of the time out, it issues + * hard abort with another software time out. It hard abort + * command busy is also time out, it'll just give up. + * + *---------------------------------------------------------------------*/ +#if defined(DOS) +UCHAR busMstrTimeOut(USHORT p_port) +#else +UCHAR busMstrTimeOut(ULONG p_port) +#endif +{ + ULONG timeout; + + timeout = LONG_WAIT; + + WR_HARPOON(p_port+hp_sys_ctrl, HALT_MACH); + + while ((!(RD_HARPOON(p_port+hp_ext_status) & CMD_ABORTED)) && timeout--) {} + + + + if (RD_HARPOON(p_port+hp_ext_status) & BM_CMD_BUSY) { + WR_HARPOON(p_port+hp_sys_ctrl, HARD_ABORT); + + timeout = LONG_WAIT; + while ((RD_HARPOON(p_port+hp_ext_status) & BM_CMD_BUSY) && timeout--) {} + } + + RD_HARPOON(p_port+hp_int_status); /*Clear command complete */ + + if (RD_HARPOON(p_port+hp_ext_status) & BM_CMD_BUSY) { + return(TRUE); + } + + else { + return(FALSE); + } +} + + +/*--------------------------------------------------------------------- + * + * Function: Host Data Transfer Abort + * + * Description: Abort any in progress transfer. + * + *---------------------------------------------------------------------*/ +#if defined(DOS) +void hostDataXferAbort(USHORT port, UCHAR p_card, PSCCB pCurrSCCB) +#else +void hostDataXferAbort(ULONG port, UCHAR p_card, PSCCB pCurrSCCB) +#endif +{ + + ULONG timeout; + ULONG remain_cnt; + UINT sg_ptr; + + BL_Card[p_card].globalFlags &= ~F_HOST_XFER_ACT; + + if (pCurrSCCB->Sccb_XferState & F_AUTO_SENSE) { + + + if (!(RD_HARPOON(port+hp_int_status) & INT_CMD_COMPL)) { + + WR_HARPOON(port+hp_bm_ctrl, (RD_HARPOON(port+hp_bm_ctrl) | FLUSH_XFER_CNTR)); + timeout = LONG_WAIT; + + while ((RD_HARPOON(port+hp_ext_status) & BM_CMD_BUSY) && timeout--) {} + + WR_HARPOON(port+hp_bm_ctrl, (RD_HARPOON(port+hp_bm_ctrl) & ~FLUSH_XFER_CNTR)); + + if (RD_HARPOON(port+hp_ext_status) & BM_CMD_BUSY) { + + if (busMstrTimeOut(port)) { + + if (pCurrSCCB->HostStatus == 0x00) + + pCurrSCCB->HostStatus = SCCB_BM_ERR; + + } + + if (RD_HARPOON(port+hp_int_status) & INT_EXT_STATUS) + + if (RD_HARPOON(port+hp_ext_status) & BAD_EXT_STATUS) + + if (pCurrSCCB->HostStatus == 0x00) + + { + pCurrSCCB->HostStatus = SCCB_BM_ERR; +#if defined(BUGBUG) + WR_HARPOON(port+hp_dual_addr_lo, + RD_HARPOON(port+hp_ext_status)); +#endif + } + } + } + } + + else if (pCurrSCCB->Sccb_XferCnt) { + + if (pCurrSCCB->Sccb_XferState & F_SG_XFER) { + + + WR_HARPOON(port+hp_page_ctrl, (RD_HARPOON(port+hp_page_ctrl) & + ~SCATTER_EN)); + + WR_HARPOON(port+hp_sg_addr,0x00); + + sg_ptr = pCurrSCCB->Sccb_sgseg + SG_BUF_CNT; + + if (sg_ptr > (UINT)(pCurrSCCB->DataLength / SG_ELEMENT_SIZE)) { + + sg_ptr = (UINT)(pCurrSCCB->DataLength / SG_ELEMENT_SIZE); + } + + remain_cnt = pCurrSCCB->Sccb_XferCnt; + + while (remain_cnt < 0x01000000L) { + + sg_ptr--; + +#if defined(COMPILER_16_BIT) && !defined(DOS) + if (remain_cnt > (ULONG)(*(((ULONG far *)pCurrSCCB-> + DataPointer) + (sg_ptr * 2)))) { + + remain_cnt -= (ULONG)(*(((ULONG far *)pCurrSCCB-> + DataPointer) + (sg_ptr * 2))); + } + +#else + if (remain_cnt > (ULONG)(*(((ULONG *)pCurrSCCB-> + DataPointer) + (sg_ptr * 2)))) { + + remain_cnt -= (ULONG)(*(((ULONG *)pCurrSCCB-> + DataPointer) + (sg_ptr * 2))); + } +#endif + + else { + + break; + } + } + + + + if (remain_cnt < 0x01000000L) { + + + pCurrSCCB->Sccb_SGoffset = remain_cnt; + + pCurrSCCB->Sccb_sgseg = (USHORT)sg_ptr; + + + if ((ULONG)(sg_ptr * SG_ELEMENT_SIZE) == pCurrSCCB->DataLength + && (remain_cnt == 0)) + + pCurrSCCB->Sccb_XferState |= F_ALL_XFERRED; + } + + else { + + + if (pCurrSCCB->HostStatus == 0x00) { + + pCurrSCCB->HostStatus = SCCB_GROSS_FW_ERR; + } + } + } + + + if (!(pCurrSCCB->Sccb_XferState & F_HOST_XFER_DIR)) { + + + if (RD_HARPOON(port+hp_ext_status) & BM_CMD_BUSY) { + + busMstrTimeOut(port); + } + + else { + + if (RD_HARPOON(port+hp_int_status) & INT_EXT_STATUS) { + + if (RD_HARPOON(port+hp_ext_status) & BAD_EXT_STATUS) { + + if (pCurrSCCB->HostStatus == 0x00) { + + pCurrSCCB->HostStatus = SCCB_BM_ERR; +#if defined(BUGBUG) + WR_HARPOON(port+hp_dual_addr_lo, + RD_HARPOON(port+hp_ext_status)); +#endif + } + } + } + + } + } + + else { + + + if ((RD_HARPOON(port+hp_fifo_cnt)) >= BM_THRESHOLD) { + + timeout = SHORT_WAIT; + + while ((RD_HARPOON(port+hp_ext_status) & BM_CMD_BUSY) && + ((RD_HARPOON(port+hp_fifo_cnt)) >= BM_THRESHOLD) && + timeout--) {} + } + + if (RD_HARPOON(port+hp_ext_status) & BM_CMD_BUSY) { + + WR_HARPOON(port+hp_bm_ctrl, (RD_HARPOON(port+hp_bm_ctrl) | + FLUSH_XFER_CNTR)); + + timeout = LONG_WAIT; + + while ((RD_HARPOON(port+hp_ext_status) & BM_CMD_BUSY) && + timeout--) {} + + WR_HARPOON(port+hp_bm_ctrl, (RD_HARPOON(port+hp_bm_ctrl) & + ~FLUSH_XFER_CNTR)); + + + if (RD_HARPOON(port+hp_ext_status) & BM_CMD_BUSY) { + + if (pCurrSCCB->HostStatus == 0x00) { + + pCurrSCCB->HostStatus = SCCB_BM_ERR; + } + + busMstrTimeOut(port); + } + } + + if (RD_HARPOON(port+hp_int_status) & INT_EXT_STATUS) { + + if (RD_HARPOON(port+hp_ext_status) & BAD_EXT_STATUS) { + + if (pCurrSCCB->HostStatus == 0x00) { + + pCurrSCCB->HostStatus = SCCB_BM_ERR; +#if defined(BUGBUG) + WR_HARPOON(port+hp_dual_addr_lo, + RD_HARPOON(port+hp_ext_status)); +#endif + } + } + } + } + + } + + else { + + + if (RD_HARPOON(port+hp_ext_status) & BM_CMD_BUSY) { + + timeout = LONG_WAIT; + + while ((RD_HARPOON(port+hp_ext_status) & BM_CMD_BUSY) && timeout--) {} + + if (RD_HARPOON(port+hp_ext_status) & BM_CMD_BUSY) { + + if (pCurrSCCB->HostStatus == 0x00) { + + pCurrSCCB->HostStatus = SCCB_BM_ERR; + } + + busMstrTimeOut(port); + } + } + + + if (RD_HARPOON(port+hp_int_status) & INT_EXT_STATUS) { + + if (RD_HARPOON(port+hp_ext_status) & BAD_EXT_STATUS) { + + if (pCurrSCCB->HostStatus == 0x00) { + + pCurrSCCB->HostStatus = SCCB_BM_ERR; +#if defined(BUGBUG) + WR_HARPOON(port+hp_dual_addr_lo, + RD_HARPOON(port+hp_ext_status)); +#endif + } + } + + } + + if (pCurrSCCB->Sccb_XferState & F_SG_XFER) { + + WR_HARPOON(port+hp_page_ctrl, (RD_HARPOON(port+hp_page_ctrl) & + ~SCATTER_EN)); + + WR_HARPOON(port+hp_sg_addr,0x00); + + pCurrSCCB->Sccb_sgseg += SG_BUF_CNT; + + pCurrSCCB->Sccb_SGoffset = 0x00; + + + if ((ULONG)(pCurrSCCB->Sccb_sgseg * SG_ELEMENT_SIZE) >= + pCurrSCCB->DataLength) { + + pCurrSCCB->Sccb_XferState |= F_ALL_XFERRED; + + pCurrSCCB->Sccb_sgseg = (USHORT)(pCurrSCCB->DataLength / SG_ELEMENT_SIZE); + + } + } + + else { + + if (!(pCurrSCCB->Sccb_XferState & F_AUTO_SENSE)) + + pCurrSCCB->Sccb_XferState |= F_ALL_XFERRED; + } + } + + WR_HARPOON(port+hp_int_mask,(INT_CMD_COMPL | SCSI_INTERRUPT)); +} + + + +/*--------------------------------------------------------------------- + * + * Function: Host Data Transfer Restart + * + * Description: Reset the available count due to a restore data + * pointers message. + * + *---------------------------------------------------------------------*/ +void hostDataXferRestart(PSCCB currSCCB) +{ + ULONG data_count; + UINT sg_index; +#if defined(COMPILER_16_BIT) && !defined(DOS) + ULONG far *sg_ptr; +#else + ULONG *sg_ptr; +#endif + + if (currSCCB->Sccb_XferState & F_SG_XFER) { + + currSCCB->Sccb_XferCnt = 0; + + sg_index = 0xffff; /*Index by long words into sg list. */ + data_count = 0; /*Running count of SG xfer counts. */ + +#if defined(COMPILER_16_BIT) && !defined(DOS) + sg_ptr = (ULONG far *)currSCCB->DataPointer; +#else + sg_ptr = (ULONG *)currSCCB->DataPointer; +#endif + + while (data_count < currSCCB->Sccb_ATC) { + + sg_index++; + data_count += *(sg_ptr+(sg_index * 2)); + } + + if (data_count == currSCCB->Sccb_ATC) { + + currSCCB->Sccb_SGoffset = 0; + sg_index++; + } + + else { + currSCCB->Sccb_SGoffset = data_count - currSCCB->Sccb_ATC; + } + + currSCCB->Sccb_sgseg = (USHORT)sg_index; + } + + else { + currSCCB->Sccb_XferCnt = currSCCB->DataLength - currSCCB->Sccb_ATC; + } +} +#ident "$Id: scam.c 1.16 1997/01/31 02:11:12 mohan Exp $" +/*---------------------------------------------------------------------- + * + * + * Copyright 1995-1996 by Mylex Corporation. All Rights Reserved + * + * This file is available under both the GNU General Public License + * and a BSD-style copyright; see LICENSE.FlashPoint for details. + * + * $Workfile: scam.c $ + * + * Description: Functions relating to handling of the SCAM selection + * and the determination of the SCSI IDs to be assigned + * to all perspective SCSI targets. + * + * $Date: 1997/01/31 02:11:12 $ + * + * $Revision: 1.16 $ + * + *----------------------------------------------------------------------*/ + +/*#include */ + +#if (FW_TYPE==_UCB_MGR_) + /*#include */ +#endif + +/*#include */ +/*#include */ +/*#include */ +/*#include */ +/*#include */ +/*#include */ + + + +/* +extern SCCBMGR_TAR_INFO sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR]; +extern SCCBCARD BL_Card[MAX_CARDS]; +extern SCCBSCAM_INFO scamInfo[MAX_SCSI_TAR]; +extern NVRAMINFO nvRamInfo[MAX_MB_CARDS]; +#if defined(DOS) || defined(OS2) +extern UCHAR temp_id_string[ID_STRING_LENGTH]; +#endif +extern UCHAR scamHAString[]; +*/ +/*--------------------------------------------------------------------- + * + * Function: scini + * + * Description: Setup all data structures necessary for SCAM selection. + * + *---------------------------------------------------------------------*/ + +void scini(UCHAR p_card, UCHAR p_our_id, UCHAR p_power_up) +{ + +#if defined(SCAM_LEV_2) + UCHAR loser,assigned_id; +#endif +#if defined(DOS) + + USHORT p_port; +#else + ULONG p_port; +#endif + + UCHAR i,k,ScamFlg ; + PSCCBcard currCard; + PNVRamInfo pCurrNvRam; + + currCard = &BL_Card[p_card]; + p_port = currCard->ioPort; + pCurrNvRam = currCard->pNvRamInfo; + + + if(pCurrNvRam){ + ScamFlg = pCurrNvRam->niScamConf; + i = pCurrNvRam->niSysConf; + } + else{ + ScamFlg = (UCHAR) utilEERead(p_port, SCAM_CONFIG/2); + i = (UCHAR)(utilEERead(p_port, (SYSTEM_CONFIG/2))); + } + if(!(i & 0x02)) /* check if reset bus in AutoSCSI parameter set */ + return; + + inisci(p_card,p_port, p_our_id); + + /* Force to wait 1 sec after SCSI bus reset. Some SCAM device FW + too slow to return to SCAM selection */ + + /* if (p_power_up) + Wait1Second(p_port); + else + Wait(p_port, TO_250ms); */ + + Wait1Second(p_port); + +#if defined(SCAM_LEV_2) + + if ((ScamFlg & SCAM_ENABLED) && (ScamFlg & SCAM_LEVEL2)) + { + while (!(scarb(p_port,INIT_SELTD))) {} + + scsel(p_port); + + do { + scxferc(p_port,SYNC_PTRN); + scxferc(p_port,DOM_MSTR); + loser = scsendi(p_port,&scamInfo[p_our_id].id_string[0]); + } while ( loser == 0xFF ); + + scbusf(p_port); + + if ((p_power_up) && (!loser)) + { + sresb(p_port,p_card); + Wait(p_port, TO_250ms); + + while (!(scarb(p_port,INIT_SELTD))) {} + + scsel(p_port); + + do { + scxferc(p_port, SYNC_PTRN); + scxferc(p_port, DOM_MSTR); + loser = scsendi(p_port,&scamInfo[p_our_id]. + id_string[0]); + } while ( loser == 0xFF ); + + scbusf(p_port); + } + } + + else + { + loser = FALSE; + } + + + if (!loser) + { + +#endif /* SCAM_LEV_2 */ + + scamInfo[p_our_id].state = ID_ASSIGNED; + + + if (ScamFlg & SCAM_ENABLED) + { + + for (i=0; i < MAX_SCSI_TAR; i++) + { + if ((scamInfo[i].state == ID_UNASSIGNED) || + (scamInfo[i].state == ID_UNUSED)) + { + if (scsell(p_port,i)) + { + scamInfo[i].state = LEGACY; + if ((scamInfo[i].id_string[0] != 0xFF) || + (scamInfo[i].id_string[1] != 0xFA)) + { + + scamInfo[i].id_string[0] = 0xFF; + scamInfo[i].id_string[1] = 0xFA; + if(pCurrNvRam == NULL) + currCard->globalFlags |= F_UPDATE_EEPROM; + } + } + } + } + + sresb(p_port,p_card); + Wait1Second(p_port); + while (!(scarb(p_port,INIT_SELTD))) {} + scsel(p_port); + scasid(p_card, p_port); + } + +#if defined(SCAM_LEV_2) + + } + + else if ((loser) && (ScamFlg & SCAM_ENABLED)) + { + scamInfo[p_our_id].id_string[0] = SLV_TYPE_CODE0; + assigned_id = FALSE; + scwtsel(p_port); + + do { + while (scxferc(p_port,0x00) != SYNC_PTRN) {} + + i = scxferc(p_port,0x00); + if (i == ASSIGN_ID) + { + if (!(scsendi(p_port,&scamInfo[p_our_id].id_string[0]))) + { + i = scxferc(p_port,0x00); + if (scvalq(i)) + { + k = scxferc(p_port,0x00); + + if (scvalq(k)) + { + currCard->ourId = + ((UCHAR)(i<<3)+(k & (UCHAR)7)) & (UCHAR) 0x3F; + inisci(p_card, p_port, p_our_id); + scamInfo[currCard->ourId].state = ID_ASSIGNED; + scamInfo[currCard->ourId].id_string[0] + = SLV_TYPE_CODE0; + assigned_id = TRUE; + } + } + } + } + + else if (i == SET_P_FLAG) + { + if (!(scsendi(p_port, + &scamInfo[p_our_id].id_string[0]))) + scamInfo[p_our_id].id_string[0] |= 0x80; + } + }while (!assigned_id); + + while (scxferc(p_port,0x00) != CFG_CMPLT) {} + } + +#endif /* SCAM_LEV_2 */ + if (ScamFlg & SCAM_ENABLED) + { + scbusf(p_port); + if (currCard->globalFlags & F_UPDATE_EEPROM) + { + scsavdi(p_card, p_port); + currCard->globalFlags &= ~F_UPDATE_EEPROM; + } + } + + +#if defined(DOS) + for (i=0; i < MAX_SCSI_TAR; i++) + { + if (((ScamFlg & SCAM_ENABLED) && (scamInfo[i].state == LEGACY)) + || (i != p_our_id)) + { + scsell(p_port,i); + } + } +#endif + +/* + for (i=0,k=0; i < MAX_SCSI_TAR; i++) + { + if ((scamInfo[i].state == ID_ASSIGNED) || + (scamInfo[i].state == LEGACY)) + k++; + } + + if (k==2) + currCard->globalFlags |= F_SINGLE_DEVICE; + else + currCard->globalFlags &= ~F_SINGLE_DEVICE; +*/ +} + + +/*--------------------------------------------------------------------- + * + * Function: scarb + * + * Description: Gain control of the bus and wait SCAM select time (250ms) + * + *---------------------------------------------------------------------*/ + +#if defined(DOS) +int scarb(USHORT p_port, UCHAR p_sel_type) +#else +int scarb(ULONG p_port, UCHAR p_sel_type) +#endif +{ + if (p_sel_type == INIT_SELTD) + { + + while (RD_HARPOON(p_port+hp_scsisig) & (SCSI_SEL | SCSI_BSY)) {} + + + if (RD_HARPOON(p_port+hp_scsisig) & SCSI_SEL) + return(FALSE); + + if (RD_HARPOON(p_port+hp_scsidata_0) != 00) + return(FALSE); + + WR_HARPOON(p_port+hp_scsisig, (RD_HARPOON(p_port+hp_scsisig) | SCSI_BSY)); + + if (RD_HARPOON(p_port+hp_scsisig) & SCSI_SEL) { + + WR_HARPOON(p_port+hp_scsisig, (RD_HARPOON(p_port+hp_scsisig) & + ~SCSI_BSY)); + return(FALSE); + } + + + WR_HARPOON(p_port+hp_scsisig, (RD_HARPOON(p_port+hp_scsisig) | SCSI_SEL)); + + if (RD_HARPOON(p_port+hp_scsidata_0) != 00) { + + WR_HARPOON(p_port+hp_scsisig, (RD_HARPOON(p_port+hp_scsisig) & + ~(SCSI_BSY | SCSI_SEL))); + return(FALSE); + } + } + + + WR_HARPOON(p_port+hp_clkctrl_0, (RD_HARPOON(p_port+hp_clkctrl_0) + & ~ACTdeassert)); + WR_HARPOON(p_port+hp_scsireset, SCAM_EN); + WR_HARPOON(p_port+hp_scsidata_0, 0x00); +#if defined(WIDE_SCSI) + WR_HARPOON(p_port+hp_scsidata_1, 0x00); +#endif + WR_HARPOON(p_port+hp_portctrl_0, SCSI_BUS_EN); + + WR_HARPOON(p_port+hp_scsisig, (RD_HARPOON(p_port+hp_scsisig) | SCSI_MSG)); + + WR_HARPOON(p_port+hp_scsisig, (RD_HARPOON(p_port+hp_scsisig) + & ~SCSI_BSY)); + + Wait(p_port,TO_250ms); + + return(TRUE); +} + + +/*--------------------------------------------------------------------- + * + * Function: scbusf + * + * Description: Release the SCSI bus and disable SCAM selection. + * + *---------------------------------------------------------------------*/ + +#if defined(DOS) +void scbusf(USHORT p_port) +#else +void scbusf(ULONG p_port) +#endif +{ + WR_HARPOON(p_port+hp_page_ctrl, + (RD_HARPOON(p_port+hp_page_ctrl) | G_INT_DISABLE)); + + + WR_HARPOON(p_port+hp_scsidata_0, 0x00); + + WR_HARPOON(p_port+hp_portctrl_0, (RD_HARPOON(p_port+hp_portctrl_0) + & ~SCSI_BUS_EN)); + + WR_HARPOON(p_port+hp_scsisig, 0x00); + + + WR_HARPOON(p_port+hp_scsireset, (RD_HARPOON(p_port+hp_scsireset) + & ~SCAM_EN)); + + WR_HARPOON(p_port+hp_clkctrl_0, (RD_HARPOON(p_port+hp_clkctrl_0) + | ACTdeassert)); + +#if defined(SCAM_LEV_2) + WRW_HARPOON((p_port+hp_intstat), (BUS_FREE | AUTO_INT | SCAM_SEL)); +#else + WRW_HARPOON((p_port+hp_intstat), (BUS_FREE | AUTO_INT)); +#endif + + WR_HARPOON(p_port+hp_page_ctrl, + (RD_HARPOON(p_port+hp_page_ctrl) & ~G_INT_DISABLE)); +} + + + +/*--------------------------------------------------------------------- + * + * Function: scasid + * + * Description: Assign an ID to all the SCAM devices. + * + *---------------------------------------------------------------------*/ + +#if defined(DOS) +void scasid(UCHAR p_card, USHORT p_port) +#else +void scasid(UCHAR p_card, ULONG p_port) +#endif +{ +#if defined(DOS) || defined(OS2) + /* Use external defined in global space area, instead of Stack + space. WIN/95 DOS doesnot work TINY mode. The OS doesnot intialize + SS equal to DS. Thus the array allocated on stack doesnot get + access correctly */ +#else + UCHAR temp_id_string[ID_STRING_LENGTH]; +#endif + + UCHAR i,k,scam_id; + UCHAR crcBytes[3]; + PNVRamInfo pCurrNvRam; + ushort_ptr pCrcBytes; + + pCurrNvRam = BL_Card[p_card].pNvRamInfo; + + i=FALSE; + + while (!i) + { + + for (k=0; k < ID_STRING_LENGTH; k++) + { + temp_id_string[k] = (UCHAR) 0x00; + } + + scxferc(p_port,SYNC_PTRN); + scxferc(p_port,ASSIGN_ID); + + if (!(sciso(p_port,&temp_id_string[0]))) + { + if(pCurrNvRam){ + pCrcBytes = (ushort_ptr)&crcBytes[0]; + *pCrcBytes = CalcCrc16(&temp_id_string[0]); + crcBytes[2] = CalcLrc(&temp_id_string[0]); + temp_id_string[1] = crcBytes[2]; + temp_id_string[2] = crcBytes[0]; + temp_id_string[3] = crcBytes[1]; + for(k = 4; k < ID_STRING_LENGTH; k++) + temp_id_string[k] = (UCHAR) 0x00; + } + i = scmachid(p_card,temp_id_string); + + if (i == CLR_PRIORITY) + { + scxferc(p_port,MISC_CODE); + scxferc(p_port,CLR_P_FLAG); + i = FALSE; /*Not the last ID yet. */ + } + + else if (i != NO_ID_AVAIL) + { + if (i < 8 ) + scxferc(p_port,ID_0_7); + else + scxferc(p_port,ID_8_F); + + scam_id = (i & (UCHAR) 0x07); + + + for (k=1; k < 0x08; k <<= 1) + if (!( k & i )) + scam_id += 0x08; /*Count number of zeros in DB0-3. */ + + scxferc(p_port,scam_id); + + i = FALSE; /*Not the last ID yet. */ + } + } + + else + { + i = TRUE; + } + + } /*End while */ + + scxferc(p_port,SYNC_PTRN); + scxferc(p_port,CFG_CMPLT); +} + + + + + +/*--------------------------------------------------------------------- + * + * Function: scsel + * + * Description: Select all the SCAM devices. + * + *---------------------------------------------------------------------*/ + +#if defined(DOS) +void scsel(USHORT p_port) +#else +void scsel(ULONG p_port) +#endif +{ + + WR_HARPOON(p_port+hp_scsisig, SCSI_SEL); + scwiros(p_port, SCSI_MSG); + + WR_HARPOON(p_port+hp_scsisig, (SCSI_SEL | SCSI_BSY)); + + + WR_HARPOON(p_port+hp_scsisig, (SCSI_SEL | SCSI_BSY | SCSI_IOBIT | SCSI_CD)); + WR_HARPOON(p_port+hp_scsidata_0, (UCHAR)(RD_HARPOON(p_port+hp_scsidata_0) | + (UCHAR)(BIT(7)+BIT(6)))); + + + WR_HARPOON(p_port+hp_scsisig, (SCSI_BSY | SCSI_IOBIT | SCSI_CD)); + scwiros(p_port, SCSI_SEL); + + WR_HARPOON(p_port+hp_scsidata_0, (UCHAR)(RD_HARPOON(p_port+hp_scsidata_0) & + ~(UCHAR)BIT(6))); + scwirod(p_port, BIT(6)); + + WR_HARPOON(p_port+hp_scsisig, (SCSI_SEL | SCSI_BSY | SCSI_IOBIT | SCSI_CD)); +} + + + +/*--------------------------------------------------------------------- + * + * Function: scxferc + * + * Description: Handshake the p_data (DB4-0) across the bus. + * + *---------------------------------------------------------------------*/ + +#if defined(DOS) +UCHAR scxferc(USHORT p_port, UCHAR p_data) +#else +UCHAR scxferc(ULONG p_port, UCHAR p_data) +#endif +{ + UCHAR curr_data, ret_data; + + curr_data = p_data | BIT(7) | BIT(5); /*Start with DB7 & DB5 asserted. */ + + WR_HARPOON(p_port+hp_scsidata_0, curr_data); + + curr_data &= ~BIT(7); + + WR_HARPOON(p_port+hp_scsidata_0, curr_data); + + scwirod(p_port,BIT(7)); /*Wait for DB7 to be released. */ + while (!(RD_HARPOON(p_port+hp_scsidata_0) & BIT(5))); + + ret_data = (RD_HARPOON(p_port+hp_scsidata_0) & (UCHAR) 0x1F); + + curr_data |= BIT(6); + + WR_HARPOON(p_port+hp_scsidata_0, curr_data); + + curr_data &= ~BIT(5); + + WR_HARPOON(p_port+hp_scsidata_0, curr_data); + + scwirod(p_port,BIT(5)); /*Wait for DB5 to be released. */ + + curr_data &= ~(BIT(4)|BIT(3)|BIT(2)|BIT(1)|BIT(0)); /*Release data bits */ + curr_data |= BIT(7); + + WR_HARPOON(p_port+hp_scsidata_0, curr_data); + + curr_data &= ~BIT(6); + + WR_HARPOON(p_port+hp_scsidata_0, curr_data); + + scwirod(p_port,BIT(6)); /*Wait for DB6 to be released. */ + + return(ret_data); +} + + +/*--------------------------------------------------------------------- + * + * Function: scsendi + * + * Description: Transfer our Identification string to determine if we + * will be the dominant master. + * + *---------------------------------------------------------------------*/ + +#if defined(DOS) +UCHAR scsendi(USHORT p_port, UCHAR p_id_string[]) +#else +UCHAR scsendi(ULONG p_port, UCHAR p_id_string[]) +#endif +{ + UCHAR ret_data,byte_cnt,bit_cnt,defer; + + defer = FALSE; + + for (byte_cnt = 0; byte_cnt < ID_STRING_LENGTH; byte_cnt++) { + + for (bit_cnt = 0x80; bit_cnt != 0 ; bit_cnt >>= 1) { + + if (defer) + ret_data = scxferc(p_port,00); + + else if (p_id_string[byte_cnt] & bit_cnt) + + ret_data = scxferc(p_port,02); + + else { + + ret_data = scxferc(p_port,01); + if (ret_data & 02) + defer = TRUE; + } + + if ((ret_data & 0x1C) == 0x10) + return(0x00); /*End of isolation stage, we won! */ + + if (ret_data & 0x1C) + return(0xFF); + + if ((defer) && (!(ret_data & 0x1F))) + return(0x01); /*End of isolation stage, we lost. */ + + } /*bit loop */ + + } /*byte loop */ + + if (defer) + return(0x01); /*We lost */ + else + return(0); /*We WON! Yeeessss! */ +} + + + +/*--------------------------------------------------------------------- + * + * Function: sciso + * + * Description: Transfer the Identification string. + * + *---------------------------------------------------------------------*/ + +#if defined(DOS) +UCHAR sciso(USHORT p_port, UCHAR p_id_string[]) +#else +UCHAR sciso(ULONG p_port, UCHAR p_id_string[]) +#endif +{ + UCHAR ret_data,the_data,byte_cnt,bit_cnt; + + the_data = 0; + + for (byte_cnt = 0; byte_cnt < ID_STRING_LENGTH; byte_cnt++) { + + for (bit_cnt = 0; bit_cnt < 8; bit_cnt++) { + + ret_data = scxferc(p_port,0); + + if (ret_data & 0xFC) + return(0xFF); + + else { + + the_data <<= 1; + if (ret_data & BIT(1)) { + the_data |= 1; + } + } + + if ((ret_data & 0x1F) == 0) +/* + if(bit_cnt != 0 || bit_cnt != 8) + { + byte_cnt = 0; + bit_cnt = 0; + scxferc(p_port, SYNC_PTRN); + scxferc(p_port, ASSIGN_ID); + continue; + } +*/ + if (byte_cnt) + return(0x00); + else + return(0xFF); + + } /*bit loop */ + + p_id_string[byte_cnt] = the_data; + + } /*byte loop */ + + return(0); +} + + + +/*--------------------------------------------------------------------- + * + * Function: scwirod + * + * Description: Sample the SCSI data bus making sure the signal has been + * deasserted for the correct number of consecutive samples. + * + *---------------------------------------------------------------------*/ + +#if defined(DOS) +void scwirod(USHORT p_port, UCHAR p_data_bit) +#else +void scwirod(ULONG p_port, UCHAR p_data_bit) +#endif +{ + UCHAR i; + + i = 0; + while ( i < MAX_SCSI_TAR ) { + + if (RD_HARPOON(p_port+hp_scsidata_0) & p_data_bit) + + i = 0; + + else + + i++; + + } +} + + + +/*--------------------------------------------------------------------- + * + * Function: scwiros + * + * Description: Sample the SCSI Signal lines making sure the signal has been + * deasserted for the correct number of consecutive samples. + * + *---------------------------------------------------------------------*/ + +#if defined(DOS) +void scwiros(USHORT p_port, UCHAR p_data_bit) +#else +void scwiros(ULONG p_port, UCHAR p_data_bit) +#endif +{ + UCHAR i; + + i = 0; + while ( i < MAX_SCSI_TAR ) { + + if (RD_HARPOON(p_port+hp_scsisig) & p_data_bit) + + i = 0; + + else + + i++; + + } +} + + +/*--------------------------------------------------------------------- + * + * Function: scvalq + * + * Description: Make sure we received a valid data byte. + * + *---------------------------------------------------------------------*/ + +UCHAR scvalq(UCHAR p_quintet) +{ + UCHAR count; + + for (count=1; count < 0x08; count<<=1) { + if (!(p_quintet & count)) + p_quintet -= 0x80; + } + + if (p_quintet & 0x18) + return(FALSE); + + else + return(TRUE); +} + + +/*--------------------------------------------------------------------- + * + * Function: scsell + * + * Description: Select the specified device ID using a selection timeout + * less than 4ms. If somebody responds then it is a legacy + * drive and this ID must be marked as such. + * + *---------------------------------------------------------------------*/ + +#if defined(DOS) +UCHAR scsell(USHORT p_port, UCHAR targ_id) +#else +UCHAR scsell(ULONG p_port, UCHAR targ_id) +#endif +{ +#if defined(DOS) + USHORT i; +#else + ULONG i; +#endif + + WR_HARPOON(p_port+hp_page_ctrl, + (RD_HARPOON(p_port+hp_page_ctrl) | G_INT_DISABLE)); + + ARAM_ACCESS(p_port); + + WR_HARPOON(p_port+hp_addstat,(RD_HARPOON(p_port+hp_addstat) | SCAM_TIMER)); + WR_HARPOON(p_port+hp_seltimeout,TO_4ms); + + + for (i = p_port+CMD_STRT; i < p_port+CMD_STRT+12; i+=2) { + WRW_HARPOON(i, (MPM_OP+ACOMMAND)); + } + WRW_HARPOON(i, (BRH_OP+ALWAYS+ NP)); + + WRW_HARPOON((p_port+hp_intstat), + (RESET | TIMEOUT | SEL | BUS_FREE | AUTO_INT)); + + WR_HARPOON(p_port+hp_select_id, targ_id); + + WR_HARPOON(p_port+hp_portctrl_0, SCSI_PORT); + WR_HARPOON(p_port+hp_autostart_3, (SELECT | CMD_ONLY_STRT)); + WR_HARPOON(p_port+hp_scsictrl_0, (SEL_TAR | ENA_RESEL)); + + + while (!(RDW_HARPOON((p_port+hp_intstat)) & + (RESET | PROG_HLT | TIMEOUT | AUTO_INT))) {} + + if (RDW_HARPOON((p_port+hp_intstat)) & RESET) + Wait(p_port, TO_250ms); + + DISABLE_AUTO(p_port); + + WR_HARPOON(p_port+hp_addstat,(RD_HARPOON(p_port+hp_addstat) & ~SCAM_TIMER)); + WR_HARPOON(p_port+hp_seltimeout,TO_290ms); + + SGRAM_ACCESS(p_port); + + if (RDW_HARPOON((p_port+hp_intstat)) & (RESET | TIMEOUT) ) { + + WRW_HARPOON((p_port+hp_intstat), + (RESET | TIMEOUT | SEL | BUS_FREE | PHASE)); + + WR_HARPOON(p_port+hp_page_ctrl, + (RD_HARPOON(p_port+hp_page_ctrl) & ~G_INT_DISABLE)); + + return(FALSE); /*No legacy device */ + } + + else { + + while(!(RDW_HARPOON((p_port+hp_intstat)) & BUS_FREE)) { + if (RD_HARPOON(p_port+hp_scsisig) & SCSI_REQ) + { + WR_HARPOON(p_port+hp_scsisig, (SCSI_ACK + S_ILL_PH)); + ACCEPT_MSG(p_port); + } + } + + WRW_HARPOON((p_port+hp_intstat), CLR_ALL_INT_1); + + WR_HARPOON(p_port+hp_page_ctrl, + (RD_HARPOON(p_port+hp_page_ctrl) & ~G_INT_DISABLE)); + + return(TRUE); /*Found one of them oldies! */ + } +} + + +/*--------------------------------------------------------------------- + * + * Function: scwtsel + * + * Description: Wait to be selected by another SCAM initiator. + * + *---------------------------------------------------------------------*/ + +#if defined(DOS) +void scwtsel(USHORT p_port) +#else +void scwtsel(ULONG p_port) +#endif +{ + while(!(RDW_HARPOON((p_port+hp_intstat)) & SCAM_SEL)) {} +} + + +/*--------------------------------------------------------------------- + * + * Function: inisci + * + * Description: Setup the data Structure with the info from the EEPROM. + * + *---------------------------------------------------------------------*/ + +#if defined(DOS) +void inisci(UCHAR p_card, USHORT p_port, UCHAR p_our_id) +#else +void inisci(UCHAR p_card, ULONG p_port, UCHAR p_our_id) +#endif +{ + UCHAR i,k,max_id; + USHORT ee_data; + PNVRamInfo pCurrNvRam; + + pCurrNvRam = BL_Card[p_card].pNvRamInfo; + + if (RD_HARPOON(p_port+hp_page_ctrl) & NARROW_SCSI_CARD) + max_id = 0x08; + + else + max_id = 0x10; + + if(pCurrNvRam){ + for(i = 0; i < max_id; i++){ + + for(k = 0; k < 4; k++) + scamInfo[i].id_string[k] = pCurrNvRam->niScamTbl[i][k]; + for(k = 4; k < ID_STRING_LENGTH; k++) + scamInfo[i].id_string[k] = (UCHAR) 0x00; + + if(scamInfo[i].id_string[0] == 0x00) + scamInfo[i].state = ID_UNUSED; /*Default to unused ID. */ + else + scamInfo[i].state = ID_UNASSIGNED; /*Default to unassigned ID. */ + + } + }else { + for (i=0; i < max_id; i++) + { + for (k=0; k < ID_STRING_LENGTH; k+=2) + { + ee_data = utilEERead(p_port, (USHORT)((EE_SCAMBASE/2) + + (USHORT) (i*((USHORT)ID_STRING_LENGTH/2)) + (USHORT)(k/2))); + scamInfo[i].id_string[k] = (UCHAR) ee_data; + ee_data >>= 8; + scamInfo[i].id_string[k+1] = (UCHAR) ee_data; + } + + if ((scamInfo[i].id_string[0] == 0x00) || + (scamInfo[i].id_string[0] == 0xFF)) + + scamInfo[i].state = ID_UNUSED; /*Default to unused ID. */ + + else + scamInfo[i].state = ID_UNASSIGNED; /*Default to unassigned ID. */ + + } + } + for(k = 0; k < ID_STRING_LENGTH; k++) + scamInfo[p_our_id].id_string[k] = scamHAString[k]; + +} + +/*--------------------------------------------------------------------- + * + * Function: scmachid + * + * Description: Match the Device ID string with our values stored in + * the EEPROM. + * + *---------------------------------------------------------------------*/ + +UCHAR scmachid(UCHAR p_card, UCHAR p_id_string[]) +{ + + UCHAR i,k,match; + + + for (i=0; i < MAX_SCSI_TAR; i++) { + +#if !defined(SCAM_LEV_2) + if (scamInfo[i].state == ID_UNASSIGNED) + { +#endif + match = TRUE; + + for (k=0; k < ID_STRING_LENGTH; k++) + { + if (p_id_string[k] != scamInfo[i].id_string[k]) + match = FALSE; + } + + if (match) + { + scamInfo[i].state = ID_ASSIGNED; + return(i); + } + +#if !defined(SCAM_LEV_2) + } +#endif + + } + + + + if (p_id_string[0] & BIT(5)) + i = 8; + else + i = MAX_SCSI_TAR; + + if (((p_id_string[0] & 0x06) == 0x02) || ((p_id_string[0] & 0x06) == 0x04)) + match = p_id_string[1] & (UCHAR) 0x1F; + else + match = 7; + + while (i > 0) + { + i--; + + if (scamInfo[match].state == ID_UNUSED) + { + for (k=0; k < ID_STRING_LENGTH; k++) + { + scamInfo[match].id_string[k] = p_id_string[k]; + } + + scamInfo[match].state = ID_ASSIGNED; + + if(BL_Card[p_card].pNvRamInfo == NULL) + BL_Card[p_card].globalFlags |= F_UPDATE_EEPROM; + return(match); + + } + + + match--; + + if (match == 0xFF) + if (p_id_string[0] & BIT(5)) + match = 7; + else + match = MAX_SCSI_TAR-1; + } + + + + if (p_id_string[0] & BIT(7)) + { + return(CLR_PRIORITY); + } + + + if (p_id_string[0] & BIT(5)) + i = 8; + else + i = MAX_SCSI_TAR; + + if (((p_id_string[0] & 0x06) == 0x02) || ((p_id_string[0] & 0x06) == 0x04)) + match = p_id_string[1] & (UCHAR) 0x1F; + else + match = 7; + + while (i > 0) + { + + i--; + + if (scamInfo[match].state == ID_UNASSIGNED) + { + for (k=0; k < ID_STRING_LENGTH; k++) + { + scamInfo[match].id_string[k] = p_id_string[k]; + } + + scamInfo[match].id_string[0] |= BIT(7); + scamInfo[match].state = ID_ASSIGNED; + if(BL_Card[p_card].pNvRamInfo == NULL) + BL_Card[p_card].globalFlags |= F_UPDATE_EEPROM; + return(match); + + } + + + match--; + + if (match == 0xFF) + if (p_id_string[0] & BIT(5)) + match = 7; + else + match = MAX_SCSI_TAR-1; + } + + return(NO_ID_AVAIL); +} + + +/*--------------------------------------------------------------------- + * + * Function: scsavdi + * + * Description: Save off the device SCAM ID strings. + * + *---------------------------------------------------------------------*/ + +#if defined(DOS) +void scsavdi(UCHAR p_card, USHORT p_port) +#else +void scsavdi(UCHAR p_card, ULONG p_port) +#endif +{ + UCHAR i,k,max_id; + USHORT ee_data,sum_data; + + + sum_data = 0x0000; + + for (i = 1; i < EE_SCAMBASE/2; i++) + { + sum_data += utilEERead(p_port, i); + } + + + utilEEWriteOnOff(p_port,1); /* Enable write access to the EEPROM */ + + if (RD_HARPOON(p_port+hp_page_ctrl) & NARROW_SCSI_CARD) + max_id = 0x08; + + else + max_id = 0x10; + + for (i=0; i < max_id; i++) + { + + for (k=0; k < ID_STRING_LENGTH; k+=2) + { + ee_data = scamInfo[i].id_string[k+1]; + ee_data <<= 8; + ee_data |= scamInfo[i].id_string[k]; + sum_data += ee_data; + utilEEWrite(p_port, ee_data, (USHORT)((EE_SCAMBASE/2) + + (USHORT)(i*((USHORT)ID_STRING_LENGTH/2)) + (USHORT)(k/2))); + } + } + + + utilEEWrite(p_port, sum_data, EEPROM_CHECK_SUM/2); + utilEEWriteOnOff(p_port,0); /* Turn off write access */ +} +#ident "$Id: diagnose.c 1.9 1997/01/31 02:09:48 mohan Exp $" +/*---------------------------------------------------------------------- + * + * + * Copyright 1995-1996 by Mylex Corporation. All Rights Reserved + * + * This file is available under both the GNU General Public License + * and a BSD-style copyright; see LICENSE.FlashPoint for details. + * + * $Workfile: diagnose.c $ + * + * Description: Diagnostic funtions for testing the integrity of + * the HARPOON. + * + * $Date: 1997/01/31 02:09:48 $ + * + * $Revision: 1.9 $ + * + *----------------------------------------------------------------------*/ + +/*#include */ + +#if (FW_TYPE==_UCB_MGR_) + /*#include */ +#endif + +/*#include */ +/*#include */ +/*#include */ +/*#include */ +/*#include */ + +/*--------------------------------------------------------------------- + * + * Function: XbowInit + * + * Description: Setup the Xbow for normal operation. + * + *---------------------------------------------------------------------*/ + +#if defined(DOS) +void XbowInit(USHORT port, UCHAR ScamFlg) +#else +void XbowInit(ULONG port, UCHAR ScamFlg) +#endif +{ +UCHAR i; + + i = RD_HARPOON(port+hp_page_ctrl); + WR_HARPOON(port+hp_page_ctrl, (UCHAR) (i | G_INT_DISABLE)); + + WR_HARPOON(port+hp_scsireset,0x00); + WR_HARPOON(port+hp_portctrl_1,HOST_MODE8); + + WR_HARPOON(port+hp_scsireset,(DMA_RESET | HPSCSI_RESET | PROG_RESET | \ + FIFO_CLR)); + + WR_HARPOON(port+hp_scsireset,0x00); + + WR_HARPOON(port+hp_clkctrl_0,CLKCTRL_DEFAULT); + + WR_HARPOON(port+hp_scsisig,0x00); /* Clear any signals we might */ + WR_HARPOON(port+hp_scsictrl_0,ENA_SCAM_SEL); + + WRW_HARPOON((port+hp_intstat), CLR_ALL_INT); + +#if defined(SCAM_LEV_2) + default_intena = RESET | RSEL | PROG_HLT | TIMEOUT | + BUS_FREE | XFER_CNT_0 | AUTO_INT; + + if ((ScamFlg & SCAM_ENABLED) && (ScamFlg & SCAM_LEVEL2)) + default_intena |= SCAM_SEL; + +#else + default_intena = RESET | RSEL | PROG_HLT | TIMEOUT | + BUS_FREE | XFER_CNT_0 | AUTO_INT; +#endif + WRW_HARPOON((port+hp_intena), default_intena); + + WR_HARPOON(port+hp_seltimeout,TO_290ms); + + /* Turn on SCSI_MODE8 for narrow cards to fix the + strapping issue with the DUAL CHANNEL card */ + if (RD_HARPOON(port+hp_page_ctrl) & NARROW_SCSI_CARD) + WR_HARPOON(port+hp_addstat,SCSI_MODE8); + +#if defined(NO_BIOS_OPTION) + + WR_HARPOON(port+hp_synctarg_0,NARROW_SCSI); + WR_HARPOON(port+hp_synctarg_1,NARROW_SCSI); + WR_HARPOON(port+hp_synctarg_2,NARROW_SCSI); + WR_HARPOON(port+hp_synctarg_3,NARROW_SCSI); + WR_HARPOON(port+hp_synctarg_4,NARROW_SCSI); + WR_HARPOON(port+hp_synctarg_5,NARROW_SCSI); + WR_HARPOON(port+hp_synctarg_6,NARROW_SCSI); + WR_HARPOON(port+hp_synctarg_7,NARROW_SCSI); + WR_HARPOON(port+hp_synctarg_8,NARROW_SCSI); + WR_HARPOON(port+hp_synctarg_9,NARROW_SCSI); + WR_HARPOON(port+hp_synctarg_10,NARROW_SCSI); + WR_HARPOON(port+hp_synctarg_11,NARROW_SCSI); + WR_HARPOON(port+hp_synctarg_12,NARROW_SCSI); + WR_HARPOON(port+hp_synctarg_13,NARROW_SCSI); + WR_HARPOON(port+hp_synctarg_14,NARROW_SCSI); + WR_HARPOON(port+hp_synctarg_15,NARROW_SCSI); + +#endif + WR_HARPOON(port+hp_page_ctrl, i); + +} + + +/*--------------------------------------------------------------------- + * + * Function: BusMasterInit + * + * Description: Initialize the BusMaster for normal operations. + * + *---------------------------------------------------------------------*/ + +#if defined(DOS) +void BusMasterInit(USHORT p_port) +#else +void BusMasterInit(ULONG p_port) +#endif +{ + + + WR_HARPOON(p_port+hp_sys_ctrl, DRVR_RST); + WR_HARPOON(p_port+hp_sys_ctrl, 0x00); + + WR_HARPOON(p_port+hp_host_blk_cnt, XFER_BLK64); + + + WR_HARPOON(p_port+hp_bm_ctrl, (BMCTRL_DEFAULT)); + + WR_HARPOON(p_port+hp_ee_ctrl, (SCSI_TERM_ENA_H)); + + +#if defined(NT) + + WR_HARPOON(p_port+hp_pci_cmd_cfg, (RD_HARPOON(p_port+hp_pci_cmd_cfg) + & ~MEM_SPACE_ENA)); + +#endif + + RD_HARPOON(p_port+hp_int_status); /*Clear interrupts. */ + WR_HARPOON(p_port+hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT)); + WR_HARPOON(p_port+hp_page_ctrl, (RD_HARPOON(p_port+hp_page_ctrl) & + ~SCATTER_EN)); +} + + +/*--------------------------------------------------------------------- + * + * Function: DiagXbow + * + * Description: Test Xbow integrity. Non-zero return indicates an error. + * + *---------------------------------------------------------------------*/ + +#if defined(DOS) +int DiagXbow(USHORT port) +#else +int DiagXbow(ULONG port) +#endif +{ + unsigned char fifo_cnt,loop_cnt; + + unsigned char fifodata[5]; + fifodata[0] = 0x00; + fifodata[1] = 0xFF; + fifodata[2] = 0x55; + fifodata[3] = 0xAA; + fifodata[4] = 0x00; + + + WRW_HARPOON((port+hp_intstat), CLR_ALL_INT); + WRW_HARPOON((port+hp_intena), 0x0000); + + WR_HARPOON(port+hp_seltimeout,TO_5ms); + + WR_HARPOON(port+hp_portctrl_0,START_TO); + + + for(fifodata[4] = 0x01; fifodata[4] != (UCHAR) 0; fifodata[4] = fifodata[4] << 1) { + + WR_HARPOON(port+hp_selfid_0,fifodata[4]); + WR_HARPOON(port+hp_selfid_1,fifodata[4]); + + if ((RD_HARPOON(port+hp_selfid_0) != fifodata[4]) || + (RD_HARPOON(port+hp_selfid_1) != fifodata[4])) + return(1); + } + + + for(loop_cnt = 0; loop_cnt < 4; loop_cnt++) { + + WR_HARPOON(port+hp_portctrl_0,(HOST_PORT | HOST_WRT | START_TO)); + + + for (fifo_cnt = 0; fifo_cnt < FIFO_LEN; fifo_cnt++) { + + WR_HARPOON(port+hp_fifodata_0, fifodata[loop_cnt]); + } + + + if (!(RD_HARPOON(port+hp_xferstat) & FIFO_FULL)) + return(1); + + + WR_HARPOON(port+hp_portctrl_0,(HOST_PORT | START_TO)); + + for (fifo_cnt = 0; fifo_cnt < FIFO_LEN; fifo_cnt++) { + + if (RD_HARPOON(port+hp_fifodata_0) != fifodata[loop_cnt]) + return(1); + } + + + if (!(RD_HARPOON(port+hp_xferstat) & FIFO_EMPTY)) + return(1); + } + + + while(!(RDW_HARPOON((port+hp_intstat)) & TIMEOUT)) {} + + + WR_HARPOON(port+hp_seltimeout,TO_290ms); + + WRW_HARPOON((port+hp_intstat), CLR_ALL_INT); + + WRW_HARPOON((port+hp_intena), default_intena); + + return(0); +} + + +/*--------------------------------------------------------------------- + * + * Function: DiagBusMaster + * + * Description: Test BusMaster integrity. Non-zero return indicates an + * error. + * + *---------------------------------------------------------------------*/ + +#if defined(DOS) +int DiagBusMaster(USHORT port) +#else +int DiagBusMaster(ULONG port) +#endif +{ + UCHAR testdata; + + for(testdata = (UCHAR) 1; testdata != (UCHAR)0; testdata = testdata << 1) { + + WR_HARPOON(port+hp_xfer_cnt_lo,testdata); + WR_HARPOON(port+hp_xfer_cnt_mi,testdata); + WR_HARPOON(port+hp_xfer_cnt_hi,testdata); + WR_HARPOON(port+hp_host_addr_lo,testdata); + WR_HARPOON(port+hp_host_addr_lmi,testdata); + WR_HARPOON(port+hp_host_addr_hmi,testdata); + WR_HARPOON(port+hp_host_addr_hi,testdata); + + if ((RD_HARPOON(port+hp_xfer_cnt_lo) != testdata) || + (RD_HARPOON(port+hp_xfer_cnt_mi) != testdata) || + (RD_HARPOON(port+hp_xfer_cnt_hi) != testdata) || + (RD_HARPOON(port+hp_host_addr_lo) != testdata) || + (RD_HARPOON(port+hp_host_addr_lmi) != testdata) || + (RD_HARPOON(port+hp_host_addr_hmi) != testdata) || + (RD_HARPOON(port+hp_host_addr_hi) != testdata)) + + return(1); + } + RD_HARPOON(port+hp_int_status); /*Clear interrupts. */ + return(0); +} + + + +/*--------------------------------------------------------------------- + * + * Function: DiagEEPROM + * + * Description: Verfiy checksum and 'Key' and initialize the EEPROM if + * neccessary. + * + *---------------------------------------------------------------------*/ + +#if defined(DOS) +void DiagEEPROM(USHORT p_port) +#else +void DiagEEPROM(ULONG p_port) +#endif + +{ + USHORT index,temp,max_wd_cnt; + + if (RD_HARPOON(p_port+hp_page_ctrl) & NARROW_SCSI_CARD) + max_wd_cnt = EEPROM_WD_CNT; + else + max_wd_cnt = EEPROM_WD_CNT * 2; + + temp = utilEERead(p_port, FW_SIGNATURE/2); + + if (temp == 0x4641) { + + for (index = 2; index < max_wd_cnt; index++) { + + temp += utilEERead(p_port, index); + + } + + if (temp == utilEERead(p_port, EEPROM_CHECK_SUM/2)) { + + return; /*EEPROM is Okay so return now! */ + } + } + + + utilEEWriteOnOff(p_port,(UCHAR)1); + + for (index = 0; index < max_wd_cnt; index++) { + + utilEEWrite(p_port, 0x0000, index); + } + + temp = 0; + + utilEEWrite(p_port, 0x4641, FW_SIGNATURE/2); + temp += 0x4641; + utilEEWrite(p_port, 0x3920, MODEL_NUMB_0/2); + temp += 0x3920; + utilEEWrite(p_port, 0x3033, MODEL_NUMB_2/2); + temp += 0x3033; + utilEEWrite(p_port, 0x2020, MODEL_NUMB_4/2); + temp += 0x2020; + utilEEWrite(p_port, 0x70D3, SYSTEM_CONFIG/2); + temp += 0x70D3; + utilEEWrite(p_port, 0x0010, BIOS_CONFIG/2); + temp += 0x0010; + utilEEWrite(p_port, 0x0007, SCAM_CONFIG/2); + temp += 0x0007; + utilEEWrite(p_port, 0x0007, ADAPTER_SCSI_ID/2); + temp += 0x0007; + + utilEEWrite(p_port, 0x0000, IGNORE_B_SCAN/2); + temp += 0x0000; + utilEEWrite(p_port, 0x0000, SEND_START_ENA/2); + temp += 0x0000; + utilEEWrite(p_port, 0x0000, DEVICE_ENABLE/2); + temp += 0x0000; + + utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL01/2); + temp += 0x4242; + utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL23/2); + temp += 0x4242; + utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL45/2); + temp += 0x4242; + utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL67/2); + temp += 0x4242; + utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL89/2); + temp += 0x4242; + utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLab/2); + temp += 0x4242; + utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLcd/2); + temp += 0x4242; + utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLef/2); + temp += 0x4242; + + + utilEEWrite(p_port, 0x6C46, 64/2); /*PRODUCT ID */ + temp += 0x6C46; + utilEEWrite(p_port, 0x7361, 66/2); /* FlashPoint LT */ + temp += 0x7361; + utilEEWrite(p_port, 0x5068, 68/2); + temp += 0x5068; + utilEEWrite(p_port, 0x696F, 70/2); + temp += 0x696F; + utilEEWrite(p_port, 0x746E, 72/2); + temp += 0x746E; + utilEEWrite(p_port, 0x4C20, 74/2); + temp += 0x4C20; + utilEEWrite(p_port, 0x2054, 76/2); + temp += 0x2054; + utilEEWrite(p_port, 0x2020, 78/2); + temp += 0x2020; + + index = ((EE_SCAMBASE/2)+(7*16)); + utilEEWrite(p_port, (0x0700+TYPE_CODE0), index); + temp += (0x0700+TYPE_CODE0); + index++; + utilEEWrite(p_port, 0x5542, index); /*Vendor ID code */ + temp += 0x5542; /* BUSLOGIC */ + index++; + utilEEWrite(p_port, 0x4C53, index); + temp += 0x4C53; + index++; + utilEEWrite(p_port, 0x474F, index); + temp += 0x474F; + index++; + utilEEWrite(p_port, 0x4349, index); + temp += 0x4349; + index++; + utilEEWrite(p_port, 0x5442, index); /*Vendor unique code */ + temp += 0x5442; /* BT- 930 */ + index++; + utilEEWrite(p_port, 0x202D, index); + temp += 0x202D; + index++; + utilEEWrite(p_port, 0x3339, index); + temp += 0x3339; + index++; /*Serial # */ + utilEEWrite(p_port, 0x2030, index); /* 01234567 */ + temp += 0x2030; + index++; + utilEEWrite(p_port, 0x5453, index); + temp += 0x5453; + index++; + utilEEWrite(p_port, 0x5645, index); + temp += 0x5645; + index++; + utilEEWrite(p_port, 0x2045, index); + temp += 0x2045; + index++; + utilEEWrite(p_port, 0x202F, index); + temp += 0x202F; + index++; + utilEEWrite(p_port, 0x4F4A, index); + temp += 0x4F4A; + index++; + utilEEWrite(p_port, 0x204E, index); + temp += 0x204E; + index++; + utilEEWrite(p_port, 0x3539, index); + temp += 0x3539; + + + + utilEEWrite(p_port, temp, EEPROM_CHECK_SUM/2); + + utilEEWriteOnOff(p_port,(UCHAR)0); + +} + +#ident "$Id: utility.c 1.22 1997/01/31 02:12:23 mohan Exp $" +/*---------------------------------------------------------------------- + * + * + * Copyright 1995-1996 by Mylex Corporation. All Rights Reserved + * + * This file is available under both the GNU General Public License + * and a BSD-style copyright; see LICENSE.FlashPoint for details. + * + * $Workfile: utility.c $ + * + * Description: Utility functions relating to queueing and EEPROM + * manipulation and any other garbage functions. + * + * $Date: 1997/01/31 02:12:23 $ + * + * $Revision: 1.22 $ + * + *----------------------------------------------------------------------*/ +/*#include */ + +#if (FW_TYPE==_UCB_MGR_) + /*#include */ +#endif + +/*#include */ +/*#include */ +/*#include */ +/*#include */ +/*#include */ + + +/* +extern SCCBCARD BL_Card[MAX_CARDS]; +extern SCCBMGR_TAR_INFO sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR]; +extern unsigned int SccbGlobalFlags; +*/ + +/*--------------------------------------------------------------------- + * + * Function: Queue Search Select + * + * Description: Try to find a new command to execute. + * + *---------------------------------------------------------------------*/ + +void queueSearchSelect(PSCCBcard pCurrCard, UCHAR p_card) +{ + UCHAR scan_ptr, lun; + PSCCBMgr_tar_info currTar_Info; + PSCCB pOldSccb; + + scan_ptr = pCurrCard->scanIndex; + do + { + currTar_Info = &sccbMgrTbl[p_card][scan_ptr]; + if((pCurrCard->globalFlags & F_CONLUN_IO) && + ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)) + { + if (currTar_Info->TarSelQ_Cnt != 0) + { + + scan_ptr++; + if (scan_ptr == MAX_SCSI_TAR) + scan_ptr = 0; + + for(lun=0; lun < MAX_LUN; lun++) + { + if(currTar_Info->TarLUNBusy[lun] == FALSE) + { + + pCurrCard->currentSCCB = currTar_Info->TarSelQ_Head; + pOldSccb = NULL; + + while((pCurrCard->currentSCCB != NULL) && + (lun != pCurrCard->currentSCCB->Lun)) + { + pOldSccb = pCurrCard->currentSCCB; + pCurrCard->currentSCCB = (PSCCB)(pCurrCard->currentSCCB)-> + Sccb_forwardlink; + } + if(pCurrCard->currentSCCB == NULL) + continue; + if(pOldSccb != NULL) + { + pOldSccb->Sccb_forwardlink = (PSCCB)(pCurrCard->currentSCCB)-> + Sccb_forwardlink; + pOldSccb->Sccb_backlink = (PSCCB)(pCurrCard->currentSCCB)-> + Sccb_backlink; + currTar_Info->TarSelQ_Cnt--; + } + else + { + currTar_Info->TarSelQ_Head = (PSCCB)(pCurrCard->currentSCCB)->Sccb_forwardlink; + + if (currTar_Info->TarSelQ_Head == NULL) + { + currTar_Info->TarSelQ_Tail = NULL; + currTar_Info->TarSelQ_Cnt = 0; + } + else + { + currTar_Info->TarSelQ_Cnt--; + currTar_Info->TarSelQ_Head->Sccb_backlink = (PSCCB)NULL; + } + } + pCurrCard->scanIndex = scan_ptr; + + pCurrCard->globalFlags |= F_NEW_SCCB_CMD; + + break; + } + } + } + + else + { + scan_ptr++; + if (scan_ptr == MAX_SCSI_TAR) { + scan_ptr = 0; + } + } + + } + else + { + if ((currTar_Info->TarSelQ_Cnt != 0) && + (currTar_Info->TarLUNBusy[0] == FALSE)) + { + + pCurrCard->currentSCCB = currTar_Info->TarSelQ_Head; + + currTar_Info->TarSelQ_Head = (PSCCB)(pCurrCard->currentSCCB)->Sccb_forwardlink; + + if (currTar_Info->TarSelQ_Head == NULL) + { + currTar_Info->TarSelQ_Tail = NULL; + currTar_Info->TarSelQ_Cnt = 0; + } + else + { + currTar_Info->TarSelQ_Cnt--; + currTar_Info->TarSelQ_Head->Sccb_backlink = (PSCCB)NULL; + } + + scan_ptr++; + if (scan_ptr == MAX_SCSI_TAR) + scan_ptr = 0; + + pCurrCard->scanIndex = scan_ptr; + + pCurrCard->globalFlags |= F_NEW_SCCB_CMD; + + break; + } + + else + { + scan_ptr++; + if (scan_ptr == MAX_SCSI_TAR) + { + scan_ptr = 0; + } + } + } + } while (scan_ptr != pCurrCard->scanIndex); +} + + +/*--------------------------------------------------------------------- + * + * Function: Queue Select Fail + * + * Description: Add the current SCCB to the head of the Queue. + * + *---------------------------------------------------------------------*/ + +void queueSelectFail(PSCCBcard pCurrCard, UCHAR p_card) +{ + UCHAR thisTarg; + PSCCBMgr_tar_info currTar_Info; + + if (pCurrCard->currentSCCB != NULL) + { + thisTarg = (UCHAR)(((PSCCB)(pCurrCard->currentSCCB))->TargID); + currTar_Info = &sccbMgrTbl[p_card][thisTarg]; + + pCurrCard->currentSCCB->Sccb_backlink = (PSCCB)NULL; + + pCurrCard->currentSCCB->Sccb_forwardlink = currTar_Info->TarSelQ_Head; + + if (currTar_Info->TarSelQ_Cnt == 0) + { + currTar_Info->TarSelQ_Tail = pCurrCard->currentSCCB; + } + + else + { + currTar_Info->TarSelQ_Head->Sccb_backlink = pCurrCard->currentSCCB; + } + + + currTar_Info->TarSelQ_Head = pCurrCard->currentSCCB; + + pCurrCard->currentSCCB = NULL; + currTar_Info->TarSelQ_Cnt++; + } +} +/*--------------------------------------------------------------------- + * + * Function: Queue Command Complete + * + * Description: Call the callback function with the current SCCB. + * + *---------------------------------------------------------------------*/ + +void queueCmdComplete(PSCCBcard pCurrCard, PSCCB p_sccb, UCHAR p_card) +{ + +#if (FW_TYPE==_UCB_MGR_) + + u08bits SCSIcmd; + CALL_BK_FN callback; + PSCCBMgr_tar_info currTar_Info; + + PUCB p_ucb; + p_ucb=p_sccb->Sccb_ucb_ptr; + + SCSIcmd = p_sccb->Cdb[0]; + + + if (!(p_sccb->Sccb_XferState & F_ALL_XFERRED)) + { + + if ((p_ucb->UCB_opcode & OPC_CHK_UNDER_OVER_RUN) && + (p_sccb->HostStatus == SCCB_COMPLETE) && + (p_sccb->TargetStatus != SSCHECK)) + + if ((SCSIcmd == SCSI_READ) || + (SCSIcmd == SCSI_WRITE) || + (SCSIcmd == SCSI_READ_EXTENDED) || + (SCSIcmd == SCSI_WRITE_EXTENDED) || + (SCSIcmd == SCSI_WRITE_AND_VERIFY) || + (SCSIcmd == SCSI_START_STOP_UNIT) || + (pCurrCard->globalFlags & F_NO_FILTER) + ) + p_sccb->HostStatus = SCCB_DATA_UNDER_RUN; + } + + p_ucb->UCB_status=SCCB_SUCCESS; + + if ((p_ucb->UCB_hbastat=p_sccb->HostStatus) || (p_ucb->UCB_scsistat=p_sccb->TargetStatus)) + { + p_ucb->UCB_status=SCCB_ERROR; + } + + if ((p_sccb->OperationCode == RESIDUAL_SG_COMMAND) || + (p_sccb->OperationCode == RESIDUAL_COMMAND)) + { + + utilUpdateResidual(p_sccb); + + p_ucb->UCB_datalen=p_sccb->DataLength; + } + + pCurrCard->cmdCounter--; + if (!pCurrCard->cmdCounter) + { + + if (pCurrCard->globalFlags & F_GREEN_PC) + { + WR_HARPOON(pCurrCard->ioPort+hp_clkctrl_0,(PWR_DWN | CLKCTRL_DEFAULT)); + WR_HARPOON(pCurrCard->ioPort+hp_sys_ctrl, STOP_CLK); + } + + WR_HARPOON(pCurrCard->ioPort+hp_semaphore, + (RD_HARPOON(pCurrCard->ioPort+hp_semaphore) & ~SCCB_MGR_ACTIVE)); + } + + if(pCurrCard->discQCount != 0) + { + currTar_Info = &sccbMgrTbl[p_card][p_sccb->TargID]; + if(((pCurrCard->globalFlags & F_CONLUN_IO) && + ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) + { + pCurrCard->discQCount--; + pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[p_sccb->Lun]] = NULL; + } + else + { + if(p_sccb->Sccb_tag) + { + pCurrCard->discQCount--; + pCurrCard->discQ_Tbl[p_sccb->Sccb_tag] = NULL; + }else + { + pCurrCard->discQCount--; + pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[0]] = NULL; + } + } + + } + callback = (CALL_BK_FN)p_ucb->UCB_callback; + callback(p_ucb); + pCurrCard->globalFlags |= F_NEW_SCCB_CMD; + pCurrCard->currentSCCB = NULL; +} + + + + +#else + + UCHAR i, SCSIcmd; + CALL_BK_FN callback; + PSCCBMgr_tar_info currTar_Info; + + SCSIcmd = p_sccb->Cdb[0]; + + + if (!(p_sccb->Sccb_XferState & F_ALL_XFERRED)) { + + if ((p_sccb->ControlByte & (SCCB_DATA_XFER_OUT | SCCB_DATA_XFER_IN)) && + (p_sccb->HostStatus == SCCB_COMPLETE) && + (p_sccb->TargetStatus != SSCHECK)) + + if ((SCSIcmd == SCSI_READ) || + (SCSIcmd == SCSI_WRITE) || + (SCSIcmd == SCSI_READ_EXTENDED) || + (SCSIcmd == SCSI_WRITE_EXTENDED) || + (SCSIcmd == SCSI_WRITE_AND_VERIFY) || + (SCSIcmd == SCSI_START_STOP_UNIT) || + (pCurrCard->globalFlags & F_NO_FILTER) + ) + p_sccb->HostStatus = SCCB_DATA_UNDER_RUN; + } + + + if(p_sccb->SccbStatus == SCCB_IN_PROCESS) + { + if (p_sccb->HostStatus || p_sccb->TargetStatus) + p_sccb->SccbStatus = SCCB_ERROR; + else + p_sccb->SccbStatus = SCCB_SUCCESS; + } + + if (p_sccb->Sccb_XferState & F_AUTO_SENSE) { + + p_sccb->CdbLength = p_sccb->Save_CdbLen; + for (i=0; i < 6; i++) { + p_sccb->Cdb[i] = p_sccb->Save_Cdb[i]; + } + } + + if ((p_sccb->OperationCode == RESIDUAL_SG_COMMAND) || + (p_sccb->OperationCode == RESIDUAL_COMMAND)) { + + utilUpdateResidual(p_sccb); + } + + pCurrCard->cmdCounter--; + if (!pCurrCard->cmdCounter) { + + if (pCurrCard->globalFlags & F_GREEN_PC) { + WR_HARPOON(pCurrCard->ioPort+hp_clkctrl_0,(PWR_DWN | CLKCTRL_DEFAULT)); + WR_HARPOON(pCurrCard->ioPort+hp_sys_ctrl, STOP_CLK); + } + + WR_HARPOON(pCurrCard->ioPort+hp_semaphore, + (RD_HARPOON(pCurrCard->ioPort+hp_semaphore) & ~SCCB_MGR_ACTIVE)); + + } + + if(pCurrCard->discQCount != 0) + { + currTar_Info = &sccbMgrTbl[p_card][p_sccb->TargID]; + if(((pCurrCard->globalFlags & F_CONLUN_IO) && + ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) + { + pCurrCard->discQCount--; + pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[p_sccb->Lun]] = NULL; + } + else + { + if(p_sccb->Sccb_tag) + { + pCurrCard->discQCount--; + pCurrCard->discQ_Tbl[p_sccb->Sccb_tag] = NULL; + }else + { + pCurrCard->discQCount--; + pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[0]] = NULL; + } + } + + } + + callback = (CALL_BK_FN)p_sccb->SccbCallback; + callback(p_sccb); + pCurrCard->globalFlags |= F_NEW_SCCB_CMD; + pCurrCard->currentSCCB = NULL; +} +#endif /* ( if FW_TYPE==...) */ + + +/*--------------------------------------------------------------------- + * + * Function: Queue Disconnect + * + * Description: Add SCCB to our disconnect array. + * + *---------------------------------------------------------------------*/ +void queueDisconnect(PSCCB p_sccb, UCHAR p_card) +{ + PSCCBMgr_tar_info currTar_Info; + + currTar_Info = &sccbMgrTbl[p_card][p_sccb->TargID]; + + if(((BL_Card[p_card].globalFlags & F_CONLUN_IO) && + ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) + { + BL_Card[p_card].discQ_Tbl[currTar_Info->LunDiscQ_Idx[p_sccb->Lun]] = p_sccb; + } + else + { + if (p_sccb->Sccb_tag) + { + BL_Card[p_card].discQ_Tbl[p_sccb->Sccb_tag] = p_sccb; + sccbMgrTbl[p_card][p_sccb->TargID].TarLUNBusy[0] = FALSE; + sccbMgrTbl[p_card][p_sccb->TargID].TarTagQ_Cnt++; + }else + { + BL_Card[p_card].discQ_Tbl[currTar_Info->LunDiscQ_Idx[0]] = p_sccb; + } + } + BL_Card[p_card].currentSCCB = NULL; +} + + +/*--------------------------------------------------------------------- + * + * Function: Queue Flush SCCB + * + * Description: Flush all SCCB's back to the host driver for this target. + * + *---------------------------------------------------------------------*/ + +void queueFlushSccb(UCHAR p_card, UCHAR error_code) +{ + UCHAR qtag,thisTarg; + PSCCB currSCCB; + PSCCBMgr_tar_info currTar_Info; + + currSCCB = BL_Card[p_card].currentSCCB; + if(currSCCB != NULL) + { + thisTarg = (UCHAR)currSCCB->TargID; + currTar_Info = &sccbMgrTbl[p_card][thisTarg]; + + for (qtag=0; qtagTargID == thisTarg)) + { + + BL_Card[p_card].discQ_Tbl[qtag]->HostStatus = (UCHAR)error_code; + + queueCmdComplete(&BL_Card[p_card],BL_Card[p_card].discQ_Tbl[qtag], p_card); + + BL_Card[p_card].discQ_Tbl[qtag] = NULL; + currTar_Info->TarTagQ_Cnt--; + + } + } + } + +} + +/*--------------------------------------------------------------------- + * + * Function: Queue Flush Target SCCB + * + * Description: Flush all SCCB's back to the host driver for this target. + * + *---------------------------------------------------------------------*/ + +void queueFlushTargSccb(UCHAR p_card, UCHAR thisTarg, UCHAR error_code) +{ + UCHAR qtag; + PSCCBMgr_tar_info currTar_Info; + + currTar_Info = &sccbMgrTbl[p_card][thisTarg]; + + for (qtag=0; qtagTargID == thisTarg)) + { + + BL_Card[p_card].discQ_Tbl[qtag]->HostStatus = (UCHAR)error_code; + + queueCmdComplete(&BL_Card[p_card],BL_Card[p_card].discQ_Tbl[qtag], p_card); + + BL_Card[p_card].discQ_Tbl[qtag] = NULL; + currTar_Info->TarTagQ_Cnt--; + + } + } + +} + + + + + +void queueAddSccb(PSCCB p_SCCB, UCHAR p_card) +{ + PSCCBMgr_tar_info currTar_Info; + currTar_Info = &sccbMgrTbl[p_card][p_SCCB->TargID]; + + p_SCCB->Sccb_forwardlink = NULL; + + p_SCCB->Sccb_backlink = currTar_Info->TarSelQ_Tail; + + if (currTar_Info->TarSelQ_Cnt == 0) { + + currTar_Info->TarSelQ_Head = p_SCCB; + } + + else { + + currTar_Info->TarSelQ_Tail->Sccb_forwardlink = p_SCCB; + } + + + currTar_Info->TarSelQ_Tail = p_SCCB; + currTar_Info->TarSelQ_Cnt++; +} + + +/*--------------------------------------------------------------------- + * + * Function: Queue Find SCCB + * + * Description: Search the target select Queue for this SCCB, and + * remove it if found. + * + *---------------------------------------------------------------------*/ + +UCHAR queueFindSccb(PSCCB p_SCCB, UCHAR p_card) +{ + PSCCB q_ptr; + PSCCBMgr_tar_info currTar_Info; + + currTar_Info = &sccbMgrTbl[p_card][p_SCCB->TargID]; + + q_ptr = currTar_Info->TarSelQ_Head; + + while(q_ptr != NULL) { + + if (q_ptr == p_SCCB) { + + + if (currTar_Info->TarSelQ_Head == q_ptr) { + + currTar_Info->TarSelQ_Head = q_ptr->Sccb_forwardlink; + } + + if (currTar_Info->TarSelQ_Tail == q_ptr) { + + currTar_Info->TarSelQ_Tail = q_ptr->Sccb_backlink; + } + + if (q_ptr->Sccb_forwardlink != NULL) { + q_ptr->Sccb_forwardlink->Sccb_backlink = q_ptr->Sccb_backlink; + } + + if (q_ptr->Sccb_backlink != NULL) { + q_ptr->Sccb_backlink->Sccb_forwardlink = q_ptr->Sccb_forwardlink; + } + + currTar_Info->TarSelQ_Cnt--; + + return(TRUE); + } + + else { + q_ptr = q_ptr->Sccb_forwardlink; + } + } + + + return(FALSE); + +} + + +/*--------------------------------------------------------------------- + * + * Function: Utility Update Residual Count + * + * Description: Update the XferCnt to the remaining byte count. + * If we transferred all the data then just write zero. + * If Non-SG transfer then report Total Cnt - Actual Transfer + * Cnt. For SG transfers add the count fields of all + * remaining SG elements, as well as any partial remaining + * element. + * + *---------------------------------------------------------------------*/ + +void utilUpdateResidual(PSCCB p_SCCB) +{ + ULONG partial_cnt; + UINT sg_index; +#if defined(COMPILER_16_BIT) && !defined(DOS) + ULONG far *sg_ptr; +#else + ULONG *sg_ptr; +#endif + + if (p_SCCB->Sccb_XferState & F_ALL_XFERRED) { + + p_SCCB->DataLength = 0x0000; + } + + else if (p_SCCB->Sccb_XferState & F_SG_XFER) { + + partial_cnt = 0x0000; + + sg_index = p_SCCB->Sccb_sgseg; + +#if defined(COMPILER_16_BIT) && !defined(DOS) + sg_ptr = (ULONG far *)p_SCCB->DataPointer; +#else + sg_ptr = (ULONG *)p_SCCB->DataPointer; +#endif + + if (p_SCCB->Sccb_SGoffset) { + + partial_cnt = p_SCCB->Sccb_SGoffset; + sg_index++; + } + + while ( ((ULONG)sg_index * (ULONG)SG_ELEMENT_SIZE) < + p_SCCB->DataLength ) { + + partial_cnt += *(sg_ptr+(sg_index * 2)); + sg_index++; + } + + p_SCCB->DataLength = partial_cnt; + } + + else { + + p_SCCB->DataLength -= p_SCCB->Sccb_ATC; + } +} + + +/*--------------------------------------------------------------------- + * + * Function: Wait 1 Second + * + * Description: Wait for 1 second. + * + *---------------------------------------------------------------------*/ + +#if defined(DOS) +void Wait1Second(USHORT p_port) +#else +void Wait1Second(ULONG p_port) +#endif +{ + UCHAR i; + + for(i=0; i < 4; i++) { + + Wait(p_port, TO_250ms); + + if ((RD_HARPOON(p_port+hp_scsictrl_0) & SCSI_RST)) + break; + + if((RDW_HARPOON((p_port+hp_intstat)) & SCAM_SEL)) + break; + } +} + + +/*--------------------------------------------------------------------- + * + * Function: Wait + * + * Description: Wait the desired delay. + * + *---------------------------------------------------------------------*/ + +#if defined(DOS) +void Wait(USHORT p_port, UCHAR p_delay) +#else +void Wait(ULONG p_port, UCHAR p_delay) +#endif +{ + UCHAR old_timer; + UCHAR green_flag; + + old_timer = RD_HARPOON(p_port+hp_seltimeout); + + green_flag=RD_HARPOON(p_port+hp_clkctrl_0); + WR_HARPOON(p_port+hp_clkctrl_0, CLKCTRL_DEFAULT); + + WR_HARPOON(p_port+hp_seltimeout,p_delay); + WRW_HARPOON((p_port+hp_intstat), TIMEOUT); + WRW_HARPOON((p_port+hp_intena), (default_intena & ~TIMEOUT)); + + + WR_HARPOON(p_port+hp_portctrl_0, + (RD_HARPOON(p_port+hp_portctrl_0) | START_TO)); + + while (!(RDW_HARPOON((p_port+hp_intstat)) & TIMEOUT)) { + + if ((RD_HARPOON(p_port+hp_scsictrl_0) & SCSI_RST)) + break; + + if ((RDW_HARPOON((p_port+hp_intstat)) & SCAM_SEL)) + break; + } + + WR_HARPOON(p_port+hp_portctrl_0, + (RD_HARPOON(p_port+hp_portctrl_0) & ~START_TO)); + + WRW_HARPOON((p_port+hp_intstat), TIMEOUT); + WRW_HARPOON((p_port+hp_intena), default_intena); + + WR_HARPOON(p_port+hp_clkctrl_0,green_flag); + + WR_HARPOON(p_port+hp_seltimeout,old_timer); +} + + +/*--------------------------------------------------------------------- + * + * Function: Enable/Disable Write to EEPROM + * + * Description: The EEPROM must first be enabled for writes + * A total of 9 clocks are needed. + * + *---------------------------------------------------------------------*/ + +#if defined(DOS) +void utilEEWriteOnOff(USHORT p_port,UCHAR p_mode) +#else +void utilEEWriteOnOff(ULONG p_port,UCHAR p_mode) +#endif +{ + UCHAR ee_value; + + ee_value = (UCHAR)(RD_HARPOON(p_port+hp_ee_ctrl) & (EXT_ARB_ACK | SCSI_TERM_ENA_H)); + + if (p_mode) + + utilEESendCmdAddr(p_port, EWEN, EWEN_ADDR); + + else + + + utilEESendCmdAddr(p_port, EWDS, EWDS_ADDR); + + WR_HARPOON(p_port+hp_ee_ctrl, (ee_value | SEE_MS)); /*Turn off CS */ + WR_HARPOON(p_port+hp_ee_ctrl, ee_value); /*Turn off Master Select */ +} + + +/*--------------------------------------------------------------------- + * + * Function: Write EEPROM + * + * Description: Write a word to the EEPROM at the specified + * address. + * + *---------------------------------------------------------------------*/ + +#if defined(DOS) +void utilEEWrite(USHORT p_port, USHORT ee_data, USHORT ee_addr) +#else +void utilEEWrite(ULONG p_port, USHORT ee_data, USHORT ee_addr) +#endif +{ + + UCHAR ee_value; + USHORT i; + + ee_value = (UCHAR)((RD_HARPOON(p_port+hp_ee_ctrl) & (EXT_ARB_ACK | SCSI_TERM_ENA_H))| + (SEE_MS | SEE_CS)); + + + + utilEESendCmdAddr(p_port, EE_WRITE, ee_addr); + + + ee_value |= (SEE_MS + SEE_CS); + + for(i = 0x8000; i != 0; i>>=1) { + + if (i & ee_data) + ee_value |= SEE_DO; + else + ee_value &= ~SEE_DO; + + WR_HARPOON(p_port+hp_ee_ctrl, ee_value); + ee_value |= SEE_CLK; /* Clock data! */ + WR_HARPOON(p_port+hp_ee_ctrl, ee_value); + ee_value &= ~SEE_CLK; + WR_HARPOON(p_port+hp_ee_ctrl, ee_value); + } + ee_value &= (EXT_ARB_ACK | SCSI_TERM_ENA_H); + WR_HARPOON(p_port+hp_ee_ctrl, (ee_value | SEE_MS)); + + Wait(p_port, TO_10ms); + + WR_HARPOON(p_port+hp_ee_ctrl, (ee_value | SEE_MS | SEE_CS)); /* Set CS to EEPROM */ + WR_HARPOON(p_port+hp_ee_ctrl, (ee_value | SEE_MS)); /* Turn off CS */ + WR_HARPOON(p_port+hp_ee_ctrl, ee_value); /* Turn off Master Select */ +} + + +/*--------------------------------------------------------------------- + * + * Function: Read EEPROM + * + * Description: Read a word from the EEPROM at the desired + * address. + * + *---------------------------------------------------------------------*/ + +#if defined(DOS) +USHORT utilEERead(USHORT p_port, USHORT ee_addr) +#else +USHORT utilEERead(ULONG p_port, USHORT ee_addr) +#endif +{ + + UCHAR ee_value; + USHORT i, ee_data; + + ee_value = (UCHAR)((RD_HARPOON(p_port+hp_ee_ctrl) & (EXT_ARB_ACK | SCSI_TERM_ENA_H))| + (SEE_MS | SEE_CS)); + + + utilEESendCmdAddr(p_port, EE_READ, ee_addr); + + + ee_value |= (SEE_MS + SEE_CS); + ee_data = 0; + + for(i = 1; i <= 16; i++) { + + ee_value |= SEE_CLK; /* Clock data! */ + WR_HARPOON(p_port+hp_ee_ctrl, ee_value); + ee_value &= ~SEE_CLK; + WR_HARPOON(p_port+hp_ee_ctrl, ee_value); + + ee_data <<= 1; + + if (RD_HARPOON(p_port+hp_ee_ctrl) & SEE_DI) + ee_data |= 1; + } + + ee_value &= ~(SEE_MS + SEE_CS); + WR_HARPOON(p_port+hp_ee_ctrl, (ee_value | SEE_MS)); /*Turn off CS */ + WR_HARPOON(p_port+hp_ee_ctrl, ee_value); /*Turn off Master Select */ + + return(ee_data); +} + + +/*--------------------------------------------------------------------- + * + * Function: Send EE command and Address to the EEPROM + * + * Description: Transfers the correct command and sends the address + * to the eeprom. + * + *---------------------------------------------------------------------*/ + +#if defined(DOS) +void utilEESendCmdAddr(USHORT p_port, UCHAR ee_cmd, USHORT ee_addr) +#else +void utilEESendCmdAddr(ULONG p_port, UCHAR ee_cmd, USHORT ee_addr) +#endif +{ + UCHAR ee_value; + UCHAR narrow_flg; + + USHORT i; + + + narrow_flg= (UCHAR)(RD_HARPOON(p_port+hp_page_ctrl) & NARROW_SCSI_CARD); + + + ee_value = SEE_MS; + WR_HARPOON(p_port+hp_ee_ctrl, ee_value); + + ee_value |= SEE_CS; /* Set CS to EEPROM */ + WR_HARPOON(p_port+hp_ee_ctrl, ee_value); + + + for(i = 0x04; i != 0; i>>=1) { + + if (i & ee_cmd) + ee_value |= SEE_DO; + else + ee_value &= ~SEE_DO; + + WR_HARPOON(p_port+hp_ee_ctrl, ee_value); + ee_value |= SEE_CLK; /* Clock data! */ + WR_HARPOON(p_port+hp_ee_ctrl, ee_value); + ee_value &= ~SEE_CLK; + WR_HARPOON(p_port+hp_ee_ctrl, ee_value); + } + + + if (narrow_flg) + i = 0x0080; + + else + i = 0x0200; + + + while (i != 0) { + + if (i & ee_addr) + ee_value |= SEE_DO; + else + ee_value &= ~SEE_DO; + + WR_HARPOON(p_port+hp_ee_ctrl, ee_value); + ee_value |= SEE_CLK; /* Clock data! */ + WR_HARPOON(p_port+hp_ee_ctrl, ee_value); + ee_value &= ~SEE_CLK; + WR_HARPOON(p_port+hp_ee_ctrl, ee_value); + + i >>= 1; + } +} + +USHORT CalcCrc16(UCHAR buffer[]) +{ + USHORT crc=0; + int i,j; + USHORT ch; + for (i=0; i < ID_STRING_LENGTH; i++) + { + ch = (USHORT) buffer[i]; + for(j=0; j < 8; j++) + { + if ((crc ^ ch) & 1) + crc = (crc >> 1) ^ CRCMASK; + else + crc >>= 1; + ch >>= 1; + } + } + return(crc); +} + +UCHAR CalcLrc(UCHAR buffer[]) +{ + int i; + UCHAR lrc; + lrc = 0; + for(i = 0; i < ID_STRING_LENGTH; i++) + lrc ^= buffer[i]; + return(lrc); +} + + + +#endif /* CONFIG_SCSI_OMIT_FLASHPOINT */ diff -u --recursive --new-file v2.1.27/linux/drivers/scsi/LICENSE.FlashPoint linux/drivers/scsi/LICENSE.FlashPoint --- v2.1.27/linux/drivers/scsi/LICENSE.FlashPoint Wed Dec 31 16:00:00 1969 +++ linux/drivers/scsi/LICENSE.FlashPoint Sun Feb 23 16:14:00 1997 @@ -0,0 +1,60 @@ + FlashPoint Driver Developer's Kit + Version 1.0 + + Copyright 1995-1996 by Mylex Corporation + All Rights Reserved + +This program is free software; you may redistribute and/or modify it under +the terms of either: + + a) the GNU General Public License as published by the Free Software + Foundation; either version 2, or (at your option) any later version, + + or + + b) the "BSD-style License" included below. + +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 either the GNU General Public +License or the BSD-style License below 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. + +The BSD-style License is as follows: + +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 this LICENSE.FlashPoint + file, without modification, this list of conditions, and the following + disclaimer. The following copyright notice must appear immediately at + the beginning of all source files: + + Copyright 1995-1996 by Mylex Corporation. All Rights Reserved + + This file is available under both the GNU General Public License + and a BSD-style copyright; see LICENSE.FlashPoint for details. + +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. The name of Mylex Corporation may not be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY MYLEX CORP. ``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 AUTHOR 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. diff -u --recursive --new-file v2.1.27/linux/drivers/scsi/Makefile linux/drivers/scsi/Makefile --- v2.1.27/linux/drivers/scsi/Makefile Fri Jan 24 09:35:50 1997 +++ linux/drivers/scsi/Makefile Fri Feb 28 15:15:42 1997 @@ -381,6 +381,12 @@ include $(TOPDIR)/Rules.make +BusLogic.o: BusLogic.c FlashPoint.c + $(CC) $(CFLAGS) -c BusLogic.c -o BusLogic.O + $(CC) $(CFLAGS) -c FlashPoint.c -o FlashPoint.O + $(LD) -r -o BusLogic.o BusLogic.O FlashPoint.O + rm -f BusLogic.O FlashPoint.O + aha152x.o: aha152x.c $(CC) $(CFLAGS) $(AHA152X) -c aha152x.c diff -u --recursive --new-file v2.1.27/linux/drivers/scsi/README.BusLogic linux/drivers/scsi/README.BusLogic --- v2.1.27/linux/drivers/scsi/README.BusLogic Wed Jul 17 11:22:13 1996 +++ linux/drivers/scsi/README.BusLogic Sun Feb 23 16:14:00 1997 @@ -1,9 +1,10 @@ - BusLogic MultiMaster SCSI Driver for Linux + BusLogic MultiMaster and FlashPoint SCSI Driver for Linux - Version 1.2.6 for Linux 1.2.13 - Version 2.0.6 for Linux 2.0.4 + Version 2.0.7 for Linux 2.0 - 17 July 1996 + PRODUCTION RELEASE + + 23 February 1997 Leonard N. Zubkoff Dandelion Digital @@ -18,10 +19,15 @@ adapters which share a common programming interface across a diverse collection of bus architectures by virtue of their MultiMaster ASIC technology. This driver supports all present BusLogic MultiMaster Host Adapters, and should -support any future MultiMaster designs with little or no modification. Host -adapters based on the new FlashPoint architecture are not supported by this -driver; consult the README.FlashPoint file for information about a program to -upgrade Linux users from the unsupported FlashPoint LT to the supported BT-948. +support any future MultiMaster designs with little or no modification. More +recently, BusLogic has introduced the FlashPoint Host Adapters, which are less +costly and rely on the host CPU, rather than including an onboard processor. +Mylex/BusLogic has recently provided me with the FlashPoint Driver Developer's +Kit, which comprises documentation and freely redistributable source code for +the FlashPoint SCCB Manager. The SCCB Manager is the library of code that runs +on the host CPU and performs functions analogous to the firmware on the +MultiMaster Host Adapters. Thanks to their having provided the SCCB Manager, +this driver now supports the FlashPoint Host Adapters as well. My primary goals in writing this completely new BusLogic driver for Linux are to achieve the full performance that BusLogic SCSI Host Adapters and modern @@ -112,26 +118,23 @@ o Robustness Features The driver implements extensive error recovery procedures. When the higher - level parts of the SCSI subsystem request that a command be reset, action is - taken to restore proper operation of the host adapter and SCSI bus. On Linux - 1.2.13, by default a full host adapter hard reset and SCSI bus reset is - performed. On Linux 2.0.x, by default a selection is made between a full - host adapter hard reset and SCSI bus reset versus sending a bus device reset - message to the individual target device based on the recommendation of the - SCSI subsystem. Error recovery strategies are selectable from the kernel - command line individually for each target device, and also include sending a - bus device reset to the specific target device associated with the command - being reset, as well as suppressing error recovery entirely to avoid - perturbing an improperly functioning device. If the bus device reset error - recovery strategy is selected and sending a bus device reset does not restore - correct operation, the next command that is reset will force a full host - adapter hard reset and SCSI bus reset. SCSI bus resets caused by other - devices and detected by the host adapter are also handled by issuing a hard - reset to the host adapter and full re-initialization. Finally, if tagged - queuing is active and more than one command reset occurs in a 10 minute - interval, or if a command reset occurs within the first 10 minutes of - operation, then tagged queuing will be disabled for that target device. - These error recovery options should improve overall system robustness by + level parts of the SCSI subsystem request that a timed out command be reset, + a selection is made between a full host adapter hard reset and SCSI bus reset + versus sending a bus device reset message to the individual target device + based on the recommendation of the SCSI subsystem. Error recovery strategies + are selectable from the kernel command line individually for each target + device, and also include sending a bus device reset to the specific target + device associated with the command being reset, as well as suppressing error + recovery entirely to avoid perturbing an improperly functioning device. If + the bus device reset error recovery strategy is selected and sending a bus + device reset does not restore correct operation, the next command that is + reset will force a full host adapter hard reset and SCSI bus reset. SCSI bus + resets caused by other devices and detected by the host adapter are also + handled by issuing a hard reset to the host adapter and re-initialization. + Finally, if tagged queuing is active and more than one command reset occurs + in a 10 minute interval, or if a command reset occurs within the first 10 + minutes of operation, then tagged queuing will be disabled for that target + device. These error recovery options improve overall system robustness by preventing individual errant devices from causing the system as a whole to lock up or crash, and thereby allowing a clean shutdown and restart after the offending component is removed. @@ -155,13 +158,16 @@ used to disable the ISA compatible I/O port entirely as it is not necessary. The ISA compatible I/O port is disabled by default on the BT-948/958/958D. +o /proc File System Support + + Copies of the host adapter configuration information together with data + transfer and error recovery statistics are now available through the + /proc/scsi/BusLogic/ interface. + o Shared Interrupts Support On systems that support shared interrupts, any number of BusLogic Host - Adapters may share the same interrupt request channel, and in fact it is more - efficient if they do so. The driver scans all known BusLogic Host Adapters - whenever an interrupt is handled on an interrupt channel assigned to any - BusLogic Host Adapter. + Adapters may share the same interrupt request channel. o Wide SCSI Support @@ -181,48 +187,50 @@ Host Adapter not in the following table contact the author beforehand to verify that it is or will be supported. -"W" Series Host Adapters: +FlashPoint Series PCI Host Adapters: + +FlashPoint LT (BT-930) Ultra Fast Single-ended SCSI-2 +FlashPoint DL (BT-932) Dual Channel Ultra Fast Single-ended SCSI-2 +FlashPoint LW (BT-950) Ultra Wide Single-ended SCSI-2 +FlashPoint DW (BT-952) Dual Channel Ultra Wide Single-ended SCSI-2 + +MultiMaster "W" Series Host Adapters: + +BT-948 PCI Ultra Fast Single-ended SCSI-2 +BT-958 PCI Ultra Wide Single-ended SCSI-2 +BT-958D PCI Ultra Wide Differential SCSI-2 + +MultiMaster "C" Series Host Adapters: + +BT-946C PCI Fast Single-ended SCSI-2 +BT-956C PCI Fast Wide Single-ended SCSI-2 +BT-956CD PCI Fast Wide Differential SCSI-2 +BT-445C VLB Fast Single-ended SCSI-2 +BT-747C EISA Fast Single-ended SCSI-2 +BT-757C EISA Fast Wide Single-ended SCSI-2 +BT-757CD EISA Fast Wide Differential SCSI-2 +BT-545C ISA Fast Single-ended SCSI-2 +BT-540CF ISA Fast Single-ended SCSI-2 + +MultiMaster "S" Series Host Adapters: + +BT-445S VLB Fast Single-ended SCSI-2 +BT-747S EISA Fast Single-ended SCSI-2 +BT-747D EISA Fast Differential SCSI-2 +BT-757S EISA Fast Wide Single-ended SCSI-2 +BT-757D EISA Fast Wide Differential SCSI-2 +BT-545S ISA Fast Single-ended SCSI-2 +BT-542D ISA Fast Differential SCSI-2 +BT-742A EISA Single-ended SCSI-2 (742A revision H) +BT-542B ISA Single-ended SCSI-2 (542B revision H) + +MultiMaster "A" Series Host Adapters: -BT-948 PCI Ultra Fast Single-ended SCSI-2 -BT-958 PCI Ultra Wide Single-ended SCSI-2 -BT-958D PCI Ultra Wide Differential SCSI-2 - -"C" Series Host Adapters: - -BT-946C PCI Fast Single-ended SCSI-2 -BT-956C PCI Fast Wide Single-ended SCSI-2 -BT-956CD PCI Fast Wide Differential SCSI-2 -BT-445C VLB Fast Single-ended SCSI-2 -BT-747C EISA Fast Single-ended SCSI-2 -BT-757C EISA Fast Wide Single-ended SCSI-2 -BT-757CD EISA Fast Wide Differential SCSI-2 -BT-545C ISA Fast Single-ended SCSI-2 -BT-540CF ISA Fast Single-ended SCSI-2 - -"S" Series Host Adapters: - -BT-445S VLB Fast Single-ended SCSI-2 -BT-747S EISA Fast Single-ended SCSI-2 -BT-747D EISA Fast Differential SCSI-2 -BT-757S EISA Fast Wide Single-ended SCSI-2 -BT-757D EISA Fast Wide Differential SCSI-2 -BT-545S ISA Fast Single-ended SCSI-2 -BT-542D ISA Fast Differential SCSI-2 -BT-742A EISA Single-ended SCSI-2 (742A revision H) -BT-542B ISA Single-ended SCSI-2 (542B revision H) - -"A" Series Host Adapters: - -BT-742A EISA Single-ended SCSI-2 (742A revisions A - G) -BT-542B ISA Single-ended SCSI-2 (542B revisions A - G) - -The FlashPoint LT, also known as the BT-930 Ultra, implements a different host -interface and is not supported by this driver. Consult the README.FlashPoint -file for information about a program to upgrade Linux users from the -unsupported FlashPoint LT to the supported BT-948. +BT-742A EISA Single-ended SCSI-2 (742A revisions A - G) +BT-542B ISA Single-ended SCSI-2 (542B revisions A - G) -AMI FastDisk Host Adapters that are true BusLogic clones are supported by this -driver. +AMI FastDisk Host Adapters that are true BusLogic MultiMaster clones are also +supported by this driver. BT-948/958/958D INSTALLATION NOTES @@ -285,6 +293,45 @@ may be found in the comments before BusLogic_Setup in the kernel source code file "BusLogic.c". The following examples may be useful as a starting point: + "BusLogic=NoProbe" + + No probing of any kind is to be performed, and hence no BusLogic Host + Adapters will be detected. + + "BusLogic=NoProbeISA" + + No probing of the standard ISA I/O Addresses will be done, and hence only + PCI Host Adapters will be detected. + + "BusLogic=NoProbePCI" + + No interrogation of PCI Configuration Space will be made, and hence only + ISA Multimaster Host Adapters will be detected, as well as PCI Multimaster + Host Adapters that have their ISA Compatible I/O Port set to "Primary" or + "Alternate". + + "BusLogic=NoSortPCI" + + PCI MultiMaster Host Adapters will be enumerated in the order provided by + the PCI BIOS, ignoring any setting of the AutoSCSI "Use Bus And Device # + For PCI Scanning Seq." option. + + "BusLogic=MultiMasterFirst" + + By default, if both FlashPoint and PCI MultiMaster Host Adapters are + present, this driver will probe for PCI MultiMaster Host Adapters first + unless the BIOS primary disk is not controlled by the first PCI MultiMaster + Host Adapter, in which case FlashPoint Host Adapters will be probed first. + This option forces MultiMaster Host Adapters to be probed first. + + "BusLogic=FlashPointFirst" + + By default, if both FlashPoint and PCI MultiMaster Host Adapters are + present, this driver will probe for PCI MultiMaster Host Adapters first + unless the BIOS primary disk is not controlled by the first PCI MultiMaster + Host Adapter, in which case FlashPoint Host Adapters will be probed first. + This option forces FlashPoint Host Adapters to be probed first. + "BusLogic=0x330" This command line limits probing to the single I/O port at 0x330. @@ -295,10 +342,11 @@ which also disables tagged queuing. It may be useful if problems arise during installation on a system with a flaky SCSI configuration. In cases of a marginal SCSI configuration it may also be beneficial to disable fast - transfers and/or synchronous negotiation using AutoSCSI on "W" and "C" - series controllers. Disconnect/reconnect may also be disabled for fast - devices such as disk drives, but should not be disabled for tape drives or - other devices where a single command may take over a second to execute. + transfers and/or synchronous negotiation using AutoSCSI on FlashPoint and + "W" and "C" series MultiMaster host adapters. Disconnect/reconnect may + also be disabled for fast devices such as disk drives, but should not be + disabled for tape drives or other devices where a single command may take + over a second to execute. "BusLogic=0,0,30" @@ -325,21 +373,16 @@ INSTALLATION -This distribution was prepared for Linux kernel version 1.2.13 -(BusLogic-1.2.6.tar.gz) or Linux kernel version 2.0.4 (BusLogic-2.0.6.tar.gz). -Installation in later versions will probably be successful as well, though -BusLogic.patch may not be required. Installation in earlier versions is not -recommended. - -To install the BusLogic SCSI driver, you may use the following commands, -replacing "/usr/src" with wherever you keep your Linux kernel source tree -(substitute "1.2" or "2.0" for "x.y" in the tar command as appropriate): +This distribution was prepared for Linux kernel version 2.0.29, but should be +compatible with 2.0.4 or any later 2.0 series kernel. + +To install the new BusLogic SCSI driver, you may use the following commands, +replacing "/usr/src" with wherever you keep your Linux kernel source tree: cd /usr/src - tar -xvzf BusLogic-x.y.6.tar.gz - mv README.* BusLogic.[ch] linux/drivers/scsi - patch -p < BusLogic.patch (on Linux 1.2.13 only) - patch -p < BusLogic.elf_patch (on Linux 1.2.13 ELF systems only) + tar -xvzf BusLogic-2.0.7.tar.gz + mv README.* LICENSE.* BusLogic.[ch] FlashPoint.c linux/drivers/scsi + patch -p < BusLogic.patch cd linux make config make depend diff -u --recursive --new-file v2.1.27/linux/drivers/scsi/README.FlashPoint linux/drivers/scsi/README.FlashPoint --- v2.1.27/linux/drivers/scsi/README.FlashPoint Tue Oct 29 04:55:15 1996 +++ linux/drivers/scsi/README.FlashPoint Sun Feb 23 16:14:00 1997 @@ -1,7 +1,5 @@ -The BusLogic FlashPoint SCSI host adapters are now supported on Linux 2.0.x. -See http://www.dandelion.com/Linux/ for the beta test BusLogic driver which -includes FlashPoint support. The upgrade program described below will remain -available through the end of 1996. +The BusLogic FlashPoint SCSI Host Adapters are now supported on Linux. The +upgrade program described below will remain available through March 1997. diff -u --recursive --new-file v2.1.27/linux/drivers/scsi/aha1542.c linux/drivers/scsi/aha1542.c --- v2.1.27/linux/drivers/scsi/aha1542.c Thu Nov 7 01:25:56 1996 +++ linux/drivers/scsi/aha1542.c Fri Feb 28 15:15:42 1997 @@ -13,6 +13,9 @@ * controller). * Modified by Matti Aarnio * Accept parameters from LILO cmd-line. -- 1-Oct-94 + * Modified by Mike McLagan + * Recognise extended mode on AHA1542CP, different bit than 1542CF + * 1-Jan-97 */ #include @@ -813,7 +816,9 @@ mbenable_cmd[0]=CMD_MBENABLE; mbenable_cmd[1]=0; mbenable_cmd[2]=mbenable_result[1]; - if(mbenable_result[1] & 1) retval = BIOS_TRANSLATION_25563; + + if(mbenable_result[1] & 0x03) retval = BIOS_TRANSLATION_25563; + aha1542_out(base,mbenable_cmd,3); WAIT(INTRFLAGS(base),INTRMASK,HACC,0); }; diff -u --recursive --new-file v2.1.27/linux/drivers/scsi/scsi_ioctl.c linux/drivers/scsi/scsi_ioctl.c --- v2.1.27/linux/drivers/scsi/scsi_ioctl.c Fri Feb 7 04:34:19 1997 +++ linux/drivers/scsi/scsi_ioctl.c Fri Feb 28 15:15:42 1997 @@ -247,8 +247,12 @@ retries = 1; break; case START_STOP: + timeout = 2 * 60 * HZ; /* 2 minutes */ + retries = 1; + break; case MOVE_MEDIUM: - timeout = 60 * HZ; /* 60 seconds */ + case READ_ELEMENT_STATUS: + timeout = 5 * 60 * HZ; /* 5 minutes */ retries = 1; break; default: diff -u --recursive --new-file v2.1.27/linux/drivers/scsi/sd.c linux/drivers/scsi/sd.c --- v2.1.27/linux/drivers/scsi/sd.c Sun Jan 26 02:07:20 1997 +++ linux/drivers/scsi/sd.c Fri Feb 28 15:15:42 1997 @@ -1210,6 +1210,7 @@ printk ("scsi : deleting disk entry.\n"); rscsi_disks[i].device = NULL; sd_template.nr_dev--; + sd_gendisk.nr_real--; return i; } } diff -u --recursive --new-file v2.1.27/linux/drivers/scsi/st.c linux/drivers/scsi/st.c --- v2.1.27/linux/drivers/scsi/st.c Sun Jan 26 02:07:23 1997 +++ linux/drivers/scsi/st.c Fri Feb 28 15:15:42 1997 @@ -629,7 +629,6 @@ if ((STp->buffer)->last_result_fatal != 0) { if ((SCpnt->sense_buffer[0] & 0x70) == 0x70 && (SCpnt->sense_buffer[2] & 0x0f) == NO_TAPE) { - printk(KERN_NOTICE "st%d: No tape.\n", dev); STp->ready = ST_NO_TAPE; } else STp->ready = ST_NOT_READY; diff -u --recursive --new-file v2.1.27/linux/fs/proc/Makefile linux/fs/proc/Makefile --- v2.1.27/linux/fs/proc/Makefile Sun Jan 26 02:07:45 1997 +++ linux/fs/proc/Makefile Fri Feb 28 15:00:55 1997 @@ -8,7 +8,8 @@ # Note 2! The CFLAGS definitions are now in the main makefile... O_TARGET := proc.o -O_OBJS := inode.o root.o base.o mem.o link.o fd.o array.o kmsg.o net.o scsi.o +O_OBJS := inode.o root.o base.o generic.o mem.o link.o fd.o array.o \ + kmsg.o net.o scsi.o proc_tty.o OX_OBJS := procfs_syms.o M_OBJS := diff -u --recursive --new-file v2.1.27/linux/fs/proc/generic.c linux/fs/proc/generic.c --- v2.1.27/linux/fs/proc/generic.c Wed Dec 31 16:00:00 1969 +++ linux/fs/proc/generic.c Fri Feb 28 15:00:55 1997 @@ -0,0 +1,195 @@ +/* + * proc/fs/generic.c --- generic routines for the proc-fs + * + * This file contains generic proc-fs routines for handling + * directories and files. + * + * Copyright (C) 1991, 1992 Linus Torvalds. + * Copyright (C) 1997 Theodore Ts'o + */ + +#include + +#include +#include +#include +#include +#include +#include + +static long proc_file_read(struct inode * inode, struct file * file, + char * buf, unsigned long nbytes); +static long proc_file_write(struct inode * inode, struct file * file, + const char * buffer, unsigned long count); +static long long proc_file_lseek(struct inode * inode, struct file * file, + long long offset, int orig); + +static struct file_operations proc_file_operations = { + proc_file_lseek, /* lseek */ + proc_file_read, /* read */ + proc_file_write, /* write */ + NULL, /* readdir */ + NULL, /* poll */ + NULL, /* ioctl */ + NULL, /* mmap */ + NULL, /* no special open code */ + NULL, /* no special release code */ + NULL /* can't fsync */ +}; + +/* + * proc files can do almost nothing.. + */ +struct inode_operations proc_file_inode_operations = { + &proc_file_operations, /* default scsi directory file-ops */ + NULL, /* create */ + NULL, /* lookup */ + NULL, /* link */ + NULL, /* unlink */ + NULL, /* symlink */ + NULL, /* mkdir */ + NULL, /* rmdir */ + NULL, /* mknod */ + NULL, /* rename */ + NULL, /* readlink */ + NULL, /* follow_link */ + NULL, /* readpage */ + NULL, /* writepage */ + NULL, /* bmap */ + NULL, /* truncate */ + NULL /* permission */ +}; + +#ifndef MIN +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +/* 4K page size but our output routines use some slack for overruns */ +#define PROC_BLOCK_SIZE (3*1024) + +static long proc_file_read(struct inode * inode, struct file * file, + char * buf, unsigned long nbytes) +{ + char *page; + int retval=0; + int n; + char *start; + struct proc_dir_entry * dp; + + if (nbytes < 0) + return -EINVAL; + dp = (struct proc_dir_entry *) inode->u.generic_ip; + if (!(page = (char*) __get_free_page(GFP_KERNEL))) + return -ENOMEM; + + while (nbytes > 0) + { + n = MIN(PROC_BLOCK_SIZE, nbytes); + + if (dp->get_info) { + /* + * Handle backwards compatibility with the old net + * routines. + * + * XXX What gives with the file->f_flags & O_ACCMODE + * test? Seems stupid to me.... + */ + n = dp->get_info(page, &start, file->f_pos, n, + (file->f_flags & O_ACCMODE) == O_RDWR); + } else if (dp->read_proc) { + n = dp->read_proc(page, &start, file->f_pos, + n, dp->data); + } else + break; + + if (n == 0) + break; /* End of file */ + if (n < 0) { + if (retval == 0) + retval = n; + break; + } + + n -= copy_to_user(buf, start, n); + if (n == 0) { + if (retval == 0) + retval = -EFAULT; + break; + } + + file->f_pos += n; /* Move down the file */ + nbytes -= n; + buf += n; + retval += n; + } + free_page((unsigned long) page); + return retval; +} + +static long +proc_file_write(struct inode * inode, struct file * file, + const char * buffer, unsigned long count) +{ + struct proc_dir_entry * dp; + char *page; + + if (count < 0) + return -EINVAL; + dp = (struct proc_dir_entry *) inode->u.generic_ip; + if (!(page = (char*) __get_free_page(GFP_KERNEL))) + return -ENOMEM; + + if (!dp->write_proc) + return -EIO; + + return dp->write_proc(file, buffer, count, dp->data); +} + + + +static long long proc_file_lseek(struct inode * inode, struct file * file, + long long offset, int orig) +{ + switch (orig) { + case 0: + file->f_pos = offset; + return(file->f_pos); + case 1: + file->f_pos += offset; + return(file->f_pos); + case 2: + return(-EINVAL); + default: + return(-EINVAL); + } +} + +struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode, + struct proc_dir_entry *parent) +{ + struct proc_dir_entry *ent; + + ent = kmalloc(sizeof(struct proc_dir_entry), GFP_KERNEL); + if (!ent) + return NULL; + memset(ent, 0, sizeof(struct proc_dir_entry)); + + if (mode == S_IFDIR) + mode |= S_IRUGO | S_IXUGO; + else if (mode == 0) + mode = S_IFREG | S_IRUGO; + + ent->name = name; + ent->namelen = strlen(ent->name); + ent->mode = mode; + if (S_ISDIR(mode)) + ent->nlink = 2; + else + ent->nlink = 1; + + if (parent) + proc_register(parent, ent); + + return ent; +} + diff -u --recursive --new-file v2.1.27/linux/fs/proc/inode.c linux/fs/proc/inode.c --- v2.1.27/linux/fs/proc/inode.c Thu Dec 19 01:03:36 1996 +++ linux/fs/proc/inode.c Fri Feb 28 15:00:55 1997 @@ -81,6 +81,7 @@ struct inode * proc_get_inode(struct super_block * s, int ino, struct proc_dir_entry * de) { struct inode * inode = iget(s, ino); + struct task_struct *p; #ifdef CONFIG_SUN_OPENPROMFS_MODULE if ((inode->i_ino >= PROC_OPENPROM_FIRST) @@ -106,6 +107,14 @@ de->fill_inode(inode); } } + /* + * Fixup the root inode's nlink value + */ + if (inode->i_ino == PROC_ROOT_INO) { + for_each_task(p) + if (p && p->pid) + inode->i_nlink++; + } return inode; } @@ -162,92 +171,19 @@ inode->i_nlink = 1; inode->i_size = 0; pid = ino >> 16; + if (!pid) + return; p = task[0]; for (i = 0; i < NR_TASKS ; i++) if ((p = task[i]) && (p->pid == pid)) break; if (!p || i >= NR_TASKS) return; - if (ino == PROC_ROOT_INO) { - inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO; - inode->i_nlink = 2; - for (i = 1 ; i < NR_TASKS ; i++) - if (task[i]) - inode->i_nlink++; - return; - } - if (!pid) { - switch (ino) { - case PROC_KMSG: - inode->i_mode = S_IFREG | S_IRUSR; - inode->i_op = &proc_kmsg_inode_operations; - break; - case PROC_NET: - inode->i_nlink = 2; - break; - case PROC_SCSI: - inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO; - inode->i_nlink = 2; - inode->i_op = &proc_scsi_inode_operations; - break; - case PROC_KCORE: - inode->i_mode = S_IFREG | S_IRUSR; - inode->i_op = &proc_kcore_inode_operations; - inode->i_size = (MAP_NR(high_memory) << PAGE_SHIFT) + PAGE_SIZE; - break; - case PROC_PROFILE: - inode->i_mode = S_IFREG | S_IRUGO | S_IWUSR; - inode->i_op = &proc_profile_inode_operations; - inode->i_size = (1+prof_len) * sizeof(unsigned long); - break; - default: - inode->i_mode = S_IFREG | S_IRUGO; - inode->i_op = &proc_array_inode_operations; - break; - } - return; - } ino &= 0x0000ffff; if (ino == PROC_PID_INO || p->dumpable) { inode->i_uid = p->euid; inode->i_gid = p->egid; - } - switch (ino) { - case PROC_PID_INO: - inode->i_nlink = 4; - return; - case PROC_PID_MEM: - inode->i_op = &proc_mem_inode_operations; - inode->i_mode = S_IFREG | S_IRUSR | S_IWUSR; - return; - case PROC_PID_CWD: - case PROC_PID_ROOT: - case PROC_PID_EXE: - inode->i_op = &proc_link_inode_operations; - inode->i_size = 64; - inode->i_mode = S_IFLNK | S_IRWXU; - return; - case PROC_PID_FD: - inode->i_mode = S_IFDIR | S_IRUSR | S_IXUSR; - inode->i_op = &proc_fd_inode_operations; - inode->i_nlink = 2; - return; - case PROC_PID_ENVIRON: - inode->i_mode = S_IFREG | S_IRUSR; - inode->i_op = &proc_array_inode_operations; - return; - case PROC_PID_CMDLINE: - case PROC_PID_STATUS: - case PROC_PID_STAT: - case PROC_PID_STATM: - inode->i_mode = S_IFREG | S_IRUGO; - inode->i_op = &proc_array_inode_operations; - return; - case PROC_PID_MAPS: - inode->i_mode = S_IFIFO | S_IRUGO; - inode->i_op = &proc_arraylong_inode_operations; - return; } switch (ino >> 8) { case PROC_PID_FD_DIR: diff -u --recursive --new-file v2.1.27/linux/fs/proc/proc_tty.c linux/fs/proc/proc_tty.c --- v2.1.27/linux/fs/proc/proc_tty.c Wed Dec 31 16:00:00 1969 +++ linux/fs/proc/proc_tty.c Fri Feb 28 15:00:55 1997 @@ -0,0 +1,183 @@ +/* + * proc_tty.c -- handles /proc/tty + * + * Copyright 1997, Theodore Ts'o + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +extern struct tty_driver *tty_drivers; /* linked list of tty drivers */ +extern struct tty_ldisc ldiscs[]; + + +static int tty_drivers_read_proc(char *page, char **start, off_t off, + int count, void *data); +static int tty_ldiscs_read_proc(char *page, char **start, off_t off, + int count, void *data); + +/* + * The /proc/tty directory inodes... + */ +static struct proc_dir_entry *proc_tty, *proc_tty_ldisc, *proc_tty_driver; + +/* + * This is the handler for /proc/tty/drivers + */ +static int tty_drivers_read_proc(char *page, char **start, off_t off, + int count, void *data) +{ + int len = 0; + off_t begin = 0; + struct tty_driver *p; + char range[20], deftype[20]; + char *type; + + for (p = tty_drivers; p; p = p->next) { + if (p->num > 1) + sprintf(range, "%d-%d", p->minor_start, + p->minor_start + p->num - 1); + else + sprintf(range, "%d", p->minor_start); + switch (p->type) { + case TTY_DRIVER_TYPE_SYSTEM: + if (p->subtype == SYSTEM_TYPE_TTY) + type = "system:/dev/tty"; + else if (p->subtype == SYSTEM_TYPE_CONSOLE) + type = "system:console"; + else + type = "system"; + break; + case TTY_DRIVER_TYPE_CONSOLE: + type = "console"; + break; + case TTY_DRIVER_TYPE_SERIAL: + if (p->subtype == 2) + type = "serial:callout"; + else + type = "serial"; + break; + case TTY_DRIVER_TYPE_PTY: + if (p->subtype == PTY_TYPE_MASTER) + type = "pty:master"; + else if (p->subtype == PTY_TYPE_SLAVE) + type = "pty:slave"; + else + type = "pty"; + break; + default: + sprintf(deftype, "type:%d.%d", p->type, p->subtype); + type = deftype; + break; + } + len += sprintf(page+len, "%-20s /dev/%-8s %3d %7s %s\n", + p->driver_name ? p->driver_name : "", + p->name, p->major, range, type); + if (len+begin > off+count) + break; + if (len+begin < off) { + begin += len; + len = 0; + } + } + if (off >= len+begin) + return 0; + *start = page + (begin-off); + return ((count < begin+len-off) ? count : begin+len-off); +} + +/* + * This is the handler for /proc/tty/ldiscs + */ +static int tty_ldiscs_read_proc(char *page, char **start, off_t off, + int count, void *data) +{ + int i; + int len = 0; + off_t begin = 0; + + for (i=0; i < NR_LDISCS; i++) { + if (!(ldiscs[i].flags & LDISC_FLAG_DEFINED)) + continue; + len += sprintf(page+len, "%-10s %2d\n", + ldiscs[i].name ? ldiscs[i].name : "???", i); + if (len+begin > off+count) + break; + if (len+begin < off) { + begin += len; + len = 0; + } + } + if (off >= len+begin) + return 0; + *start = page + (begin-off); + return ((count < begin+len-off) ? count : begin+len-off); +} + +/* + * Thsi function is called by register_tty_driver() to handle + * registering the driver's /proc handler into /proc/tty/driver/ + */ +void proc_tty_register_driver(struct tty_driver *driver) +{ + struct proc_dir_entry *ent; + + if ((!driver->read_proc && !driver->write_proc) || + !driver->driver_name || + driver->proc_entry) + return; + + ent = create_proc_entry(driver->driver_name, 0, proc_tty_driver); + if (!ent) + return; + ent->read_proc = driver->read_proc; + ent->write_proc = driver->write_proc; + ent->data = driver; + + driver->proc_entry = ent; +} + +/* + * This function is called by unregister_tty_driver() + */ +void proc_tty_unregister_driver(struct tty_driver *driver) +{ + struct proc_dir_entry *ent; + + ent = driver->proc_entry; + if (!ent) + return; + + proc_unregister(proc_tty_driver, ent->low_ino); + + driver->proc_entry = 0; + kfree(ent); +} + +/* + * Called by proc_root_init() to initialize the /proc/tty subtree + */ +void proc_tty_init(void) +{ + struct proc_dir_entry *ent; + + proc_tty = create_proc_entry("tty", S_IFDIR, &proc_root); + if (!proc_tty) + return; + proc_tty_ldisc = create_proc_entry("ldisc", S_IFDIR, proc_tty); + proc_tty_driver = create_proc_entry("driver", S_IFDIR, proc_tty); + + ent = create_proc_entry("ldiscs", 0, proc_tty); + ent->read_proc = tty_ldiscs_read_proc; + + ent = create_proc_entry("drivers", 0, proc_tty); + ent->read_proc = tty_drivers_read_proc; +} + diff -u --recursive --new-file v2.1.27/linux/fs/proc/root.c linux/fs/proc/root.c --- v2.1.27/linux/fs/proc/root.c Wed Jan 29 03:32:21 1997 +++ linux/fs/proc/root.c Fri Feb 28 15:00:55 1997 @@ -299,13 +299,41 @@ extern void openpromfs_init (void); #endif /* CONFIG_SUN_OPENPROMFS */ +static int make_inode_number(void) +{ + int i = find_first_zero_bit((void *) proc_alloc_map, PROC_NDYNAMIC); + if (i<0 || i>=PROC_NDYNAMIC) + return -1; + set_bit(i, (void *) proc_alloc_map); + return PROC_DYNAMIC_FIRST + i; +} + int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp) { + int i; + + if (dp->low_ino == 0) { + i = make_inode_number(); + if (i < 0) + return -EAGAIN; + dp->low_ino = i; + } dp->next = dir->subdir; dp->parent = dir; dir->subdir = dp; - if (S_ISDIR(dp->mode)) + if (S_ISDIR(dp->mode)) { + if (dp->ops == NULL) + dp->ops = &proc_dir_inode_operations; dir->nlink++; + } else { + if (dp->ops == NULL) + dp->ops = &proc_file_inode_operations; + } + /* + * kludge until we fixup the md device driver + */ + if (dp->low_ino == PROC_MD) + dp->ops = &proc_array_inode_operations; return 0; } @@ -330,28 +358,16 @@ return -EINVAL; } -static int make_inode_number(void) -{ - int i = find_first_zero_bit((void *) proc_alloc_map, PROC_NDYNAMIC); - if (i<0 || i>=PROC_NDYNAMIC) - return -1; - set_bit(i, (void *) proc_alloc_map); - return PROC_DYNAMIC_FIRST + i; -} - int proc_register_dynamic(struct proc_dir_entry * dir, struct proc_dir_entry * dp) { - int i = make_inode_number(); - if (i < 0) - return -EAGAIN; - dp->low_ino = i; - dp->next = dir->subdir; - dp->parent = dir; - dir->subdir = dp; - if (S_ISDIR(dp->mode)) - dir->nlink++; - return 0; + /* + * Make sure we use a dynamically allocated inode. + * In the future, all procedures should just call + * proc_register.... + */ + dp->low_ino = 0; + return proc_register(dir, dp); } /* @@ -404,38 +420,46 @@ static struct proc_dir_entry proc_root_loadavg = { PROC_LOADAVG, 7, "loadavg", S_IFREG | S_IRUGO, 1, 0, 0, + 0, &proc_array_inode_operations }; static struct proc_dir_entry proc_root_uptime = { PROC_UPTIME, 6, "uptime", S_IFREG | S_IRUGO, 1, 0, 0, + 0, &proc_array_inode_operations }; static struct proc_dir_entry proc_root_meminfo = { PROC_MEMINFO, 7, "meminfo", S_IFREG | S_IRUGO, 1, 0, 0, + 0, &proc_array_inode_operations }; static struct proc_dir_entry proc_root_kmsg = { PROC_KMSG, 4, "kmsg", S_IFREG | S_IRUSR, 1, 0, 0, + 0, &proc_kmsg_inode_operations }; static struct proc_dir_entry proc_root_version = { PROC_VERSION, 7, "version", S_IFREG | S_IRUGO, 1, 0, 0, + 0, &proc_array_inode_operations }; #ifdef CONFIG_PCI static struct proc_dir_entry proc_root_pci = { PROC_PCI, 3, "pci", S_IFREG | S_IRUGO, 1, 0, 0, + 0, &proc_array_inode_operations }; #endif #ifdef CONFIG_ZORRO static struct proc_dir_entry proc_root_zorro = { PROC_ZORRO, 5, "zorro", S_IFREG | S_IRUGO, 1, 0, 0, + 0, &proc_array_inode_operations }; #endif static struct proc_dir_entry proc_root_cpuinfo = { PROC_CPUINFO, 7, "cpuinfo", S_IFREG | S_IRUGO, 1, 0, 0, + 0, &proc_array_inode_operations }; static struct proc_dir_entry proc_root_self = { PROC_SELF, 4, "self", @@ -446,81 +470,99 @@ static struct proc_dir_entry proc_root_malloc = { PROC_MALLOC, 6, "malloc", S_IFREG | S_IRUGO, 1, 0, 0, + 0, &proc_array_inode_operations }; #endif static struct proc_dir_entry proc_root_kcore = { PROC_KCORE, 5, "kcore", S_IFREG | S_IRUSR, 1, 0, 0, + 0, &proc_kcore_inode_operations }; #ifdef CONFIG_MODULES static struct proc_dir_entry proc_root_modules = { PROC_MODULES, 7, "modules", S_IFREG | S_IRUGO, 1, 0, 0, + 0, &proc_array_inode_operations }; static struct proc_dir_entry proc_root_ksyms = { PROC_KSYMS, 5, "ksyms", S_IFREG | S_IRUGO, 1, 0, 0, + 0, &proc_array_inode_operations }; #endif static struct proc_dir_entry proc_root_stat = { PROC_STAT, 4, "stat", S_IFREG | S_IRUGO, 1, 0, 0, + 0, &proc_array_inode_operations }; static struct proc_dir_entry proc_root_devices = { PROC_DEVICES, 7, "devices", S_IFREG | S_IRUGO, 1, 0, 0, + 0, &proc_array_inode_operations }; static struct proc_dir_entry proc_root_interrupts = { PROC_INTERRUPTS, 10,"interrupts", S_IFREG | S_IRUGO, 1, 0, 0, + 0, &proc_array_inode_operations }; #ifdef __SMP_PROF__ static struct proc_dir_entry proc_root_smp = { PROC_SMP_PROF, 3,"smp", S_IFREG | S_IRUGO, 1, 0, 0, + 0, &proc_array_inode_operations }; #endif static struct proc_dir_entry proc_root_filesystems = { PROC_FILESYSTEMS, 11,"filesystems", S_IFREG | S_IRUGO, 1, 0, 0, + 0, &proc_array_inode_operations }; static struct proc_dir_entry proc_root_dma = { PROC_DMA, 3, "dma", S_IFREG | S_IRUGO, 1, 0, 0, + 0, &proc_array_inode_operations }; static struct proc_dir_entry proc_root_ioports = { PROC_IOPORTS, 7, "ioports", S_IFREG | S_IRUGO, 1, 0, 0, + 0, &proc_array_inode_operations }; static struct proc_dir_entry proc_root_cmdline = { PROC_CMDLINE, 7, "cmdline", S_IFREG | S_IRUGO, 1, 0, 0, + 0, &proc_array_inode_operations }; #ifdef CONFIG_RTC static struct proc_dir_entry proc_root_rtc = { PROC_RTC, 3, "rtc", S_IFREG | S_IRUGO, 1, 0, 0, + 0, &proc_array_inode_operations }; #endif static struct proc_dir_entry proc_root_locks = { PROC_LOCKS, 5, "locks", S_IFREG | S_IRUGO, 1, 0, 0, + 0, &proc_array_inode_operations }; static struct proc_dir_entry proc_root_mounts = { PROC_MTAB, 6, "mounts", S_IFREG | S_IRUGO, 1, 0, 0, + 0, &proc_array_inode_operations }; static struct proc_dir_entry proc_root_swaps = { PROC_SWAP, 5, "swaps", S_IFREG | S_IRUGO, 1, 0, 0, + 0, &proc_array_inode_operations }; static struct proc_dir_entry proc_root_profile = { PROC_PROFILE, 7, "profile", S_IFREG | S_IRUGO | S_IWUSR, 1, 0, 0, + 0, &proc_profile_inode_operations }; static struct proc_dir_entry proc_root_slab = { PROC_SLABINFO, 8, "slabinfo", S_IFREG | S_IRUGO, 1, 0, 0, + 0, &proc_array_inode_operations }; void proc_root_init(void) @@ -555,6 +597,7 @@ proc_register(&proc_root, &proc_root_malloc); #endif proc_register(&proc_root, &proc_root_kcore); + proc_root_kcore.size = (MAP_NR(high_memory) << PAGE_SHIFT) + PAGE_SIZE; #ifdef CONFIG_MODULES proc_register(&proc_root, &proc_root_modules); @@ -589,7 +632,10 @@ if (prof_shift) { proc_register(&proc_root, &proc_root_profile); + proc_root_profile.size = (1+prof_len) * sizeof(unsigned long); } + + proc_tty_init(); } @@ -666,8 +712,17 @@ { unsigned int pid, c; int i, ino, retval; + struct task_struct *p; dir->i_count++; + + if (dir->i_ino == PROC_ROOT_INO) { /* check for safety... */ + dir->i_nlink = proc_root.nlink; + for_each_task(p) + if (p && p->pid) + dir->i_nlink++; + } + retval = proc_lookup(dir, name, len, result); if (retval != -ENOENT) { iput(dir); diff -u --recursive --new-file v2.1.27/linux/include/asm-alpha/checksum.h linux/include/asm-alpha/checksum.h --- v2.1.27/linux/include/asm-alpha/checksum.h Thu Feb 6 02:44:41 1997 +++ linux/include/asm-alpha/checksum.h Thu Feb 27 14:15:47 1997 @@ -53,7 +53,7 @@ * this is a new version of the above that records errors it finds in *errp, * but continues and zeros the rest of the buffer. */ -unsigned int csum_partial_copy_from_user(int *errp, char *src, char *dst, int len, unsigned int sum); +unsigned int csum_partial_copy_from_user(char *src, char *dst, int len, unsigned int sum, int *errp); /* * this routine is used for miscellaneous IP-like checksums, mainly diff -u --recursive --new-file v2.1.27/linux/include/asm-i386/termbits.h linux/include/asm-i386/termbits.h --- v2.1.27/linux/include/asm-i386/termbits.h Thu Feb 6 02:53:33 1997 +++ linux/include/asm-i386/termbits.h Fri Feb 28 15:00:53 1997 @@ -122,6 +122,7 @@ #define B230400 0010003 #define B460800 0010004 #define CIBAUD 002003600000 /* input baud rate (not used) */ +#define CMSPAR 010000000000 /* mark or space (stick) parity */ #define CRTSCTS 020000000000 /* flow control */ /* c_lflag bits */ diff -u --recursive --new-file v2.1.27/linux/include/asm-i386/termios.h linux/include/asm-i386/termios.h --- v2.1.27/linux/include/asm-i386/termios.h Thu Feb 6 02:53:33 1997 +++ linux/include/asm-i386/termios.h Fri Feb 28 15:00:53 1997 @@ -33,6 +33,8 @@ #define TIOCM_DSR 0x100 #define TIOCM_CD TIOCM_CAR #define TIOCM_RI TIOCM_RNG +#define TIOCM_OUT1 0x2000 +#define TIOCM_OUT2 0x4000 /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ diff -u --recursive --new-file v2.1.27/linux/include/linux/proc_fs.h linux/include/linux/proc_fs.h --- v2.1.27/linux/include/linux/proc_fs.h Fri Feb 7 05:54:55 1997 +++ linux/include/linux/proc_fs.h Fri Feb 28 15:41:58 1997 @@ -223,6 +223,10 @@ void (*fill_inode)(struct inode *); struct proc_dir_entry *next, *parent, *subdir; void *data; + int (*read_proc)(char *page, char **start, off_t off, + int count, void *data); + int (*write_proc)(struct file *file, const char *buffer, + unsigned long count, void *data); }; extern int (* dispatch_scsi_info_ptr) (int ino, char *buffer, char **start, @@ -327,6 +331,7 @@ extern int proc_openprom_unregdev(struct openpromfs_dev *); extern struct inode_operations proc_dir_inode_operations; +extern struct inode_operations proc_file_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; @@ -344,3 +349,16 @@ extern struct inode_operations proc_ringbuf_inode_operations; #endif #endif + +/* + * generic.c + */ +struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode, + struct proc_dir_entry *parent); + +/* + * proc_tty.c + */ +extern void proc_tty_init(void); +extern void proc_tty_register_driver(struct tty_driver *driver); +extern void proc_tty_unregister_driver(struct tty_driver *driver); diff -u --recursive --new-file v2.1.27/linux/include/linux/serial.h linux/include/linux/serial.h --- v2.1.27/linux/include/linux/serial.h Thu Feb 6 02:53:43 1997 +++ linux/include/linux/serial.h Fri Feb 28 15:40:33 1997 @@ -123,7 +123,10 @@ */ struct serial_icounter_struct { int cts, dsr, rng, dcd; - int reserved[16]; + int rx, tx; + int frame, overrun, parity, brk; + int buf_overrun; + int reserved[9]; }; @@ -144,7 +147,9 @@ * Counters of the input lines (CTS, DSR, RI, CD) interrupts */ struct async_icount { - __u32 cts, dsr, rng, dcd; + __u32 cts, dsr, rng, dcd, tx, rx; + __u32 frame, parity, overrun, brk; + __u32 buf_overrun; }; struct serial_state { @@ -178,6 +183,7 @@ int read_status_mask; int ignore_status_mask; int timeout; + int quot; int x_char; /* xon/xoff character */ int close_delay; unsigned short closing_wait; @@ -235,5 +241,6 @@ /* Export to allow PCMCIA to use this - Dave Hinds */ extern int register_serial(struct serial_struct *req); extern void unregister_serial(int line); + #endif /* __KERNEL__ */ #endif /* _LINUX_SERIAL_H */ diff -u --recursive --new-file v2.1.27/linux/include/linux/tty.h linux/include/linux/tty.h --- v2.1.27/linux/include/linux/tty.h Thu Feb 6 02:53:33 1997 +++ linux/include/linux/tty.h Fri Feb 28 15:41:53 1997 @@ -328,13 +328,8 @@ extern int n_tty_ioctl(struct tty_struct * tty, struct file * file, unsigned int cmd, unsigned long arg); -/* serial.c */ +/* pcxx.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); extern int pcxe_open(struct tty_struct *tty, struct file *filp); /* console.c */ diff -u --recursive --new-file v2.1.27/linux/include/linux/tty_driver.h linux/include/linux/tty_driver.h --- v2.1.27/linux/include/linux/tty_driver.h Thu Feb 6 02:53:33 1997 +++ linux/include/linux/tty_driver.h Fri Feb 28 15:41:53 1997 @@ -107,6 +107,7 @@ struct tty_driver { int magic; /* magic number for this structure */ + const char *driver_name; const char *name; int name_base; /* offset of printed name */ short major; /* major device number */ @@ -117,6 +118,7 @@ struct termios init_termios; /* Initial termios */ int flags; /* tty driver flags */ int *refcount; /* for loadable tty drivers */ + struct proc_dir_entry *proc_entry; /* /proc fs entry */ struct tty_driver *other; /* only used for the PTY driver */ /* @@ -150,6 +152,10 @@ void (*set_ldisc)(struct tty_struct *tty); void (*wait_until_sent)(struct tty_struct *tty, int timeout); void (*send_xchar)(struct tty_struct *tty, char ch); + int (*read_proc)(char *page, char **start, off_t off, + int count, void *data); + int (*write_proc)(struct file *file, const char *buffer, + unsigned long count, void *data); /* * linked list pointers @@ -196,5 +202,9 @@ /* pty subtypes (magic, used by tty_io.c) */ #define PTY_TYPE_MASTER 0x0001 #define PTY_TYPE_SLAVE 0x0002 + +/* serial subtype definitions */ +#define SERIAL_TYPE_NORMAL 1 +#define SERIAL_TYPE_CALLOUT 2 #endif /* #ifdef _LINUX_TTY_DRIVER_H */ diff -u --recursive --new-file v2.1.27/linux/include/linux/tty_ldisc.h linux/include/linux/tty_ldisc.h --- v2.1.27/linux/include/linux/tty_ldisc.h Thu Feb 6 02:53:33 1997 +++ linux/include/linux/tty_ldisc.h Fri Feb 28 15:41:53 1997 @@ -102,6 +102,7 @@ struct tty_ldisc { int magic; + char *name; int num; int flags; /*